summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Xu <davidxu@FreeBSD.org>2005-07-10 23:31:11 +0000
committerDavid Xu <davidxu@FreeBSD.org>2005-07-10 23:31:11 +0000
commit740fd64d65cc70e1bfd61ab9e8061eb2d1f39c5d (patch)
treee1deb69e9ef98abe6e3de57b17a8192575186ef3
parent5305063bdf10c069cd1fdb9fd0860a42b1d70008 (diff)
Notes
-rw-r--r--sys/alpha/alpha/vm_machdep.c3
-rw-r--r--sys/amd64/amd64/sys_machdep.c51
-rw-r--r--sys/amd64/amd64/vm_machdep.c6
-rw-r--r--sys/arm/arm/vm_machdep.c3
-rw-r--r--sys/i386/i386/vm_machdep.c3
-rw-r--r--sys/ia64/ia64/vm_machdep.c3
-rw-r--r--sys/kern/kern_thr.c7
-rw-r--r--sys/powerpc/aim/vm_machdep.c3
-rw-r--r--sys/powerpc/powerpc/vm_machdep.c3
-rw-r--r--sys/sparc64/sparc64/vm_machdep.c3
-rw-r--r--sys/sys/proc.h2
11 files changed, 65 insertions, 22 deletions
diff --git a/sys/alpha/alpha/vm_machdep.c b/sys/alpha/alpha/vm_machdep.c
index f8e90287fc80..cfbdf2c1d21f 100644
--- a/sys/alpha/alpha/vm_machdep.c
+++ b/sys/alpha/alpha/vm_machdep.c
@@ -360,7 +360,7 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
tf->tf_regs[FRAME_FLAGS] = 0; /* full restore */
}
-void
+int
cpu_set_user_tls(struct thread *td, void *tls_base)
{
@@ -368,6 +368,7 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
td->td_pcb->pcb_hw.apcb_unique = (unsigned long)tls_base;
else
alpha_pal_wrunique((uintptr_t)tls_base);
+ return (0);
}
/*
diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index 25fbb6f0d04f..7f022d00bcce 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -42,6 +42,10 @@ __FBSDID("$FreeBSD$");
#include <machine/sysarch.h>
#include <machine/pcb.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/vmparam.h>
+
#ifndef _SYS_SYSPROTO_H_
struct sysarch_args {
int op;
@@ -57,6 +61,7 @@ sysarch(td, uap)
int error = 0;
struct pcb *pcb = curthread->td_pcb;
uint32_t i386base;
+ uint64_t a64base;
switch(uap->op) {
case I386_GET_FSBASE:
@@ -65,9 +70,12 @@ sysarch(td, uap)
break;
case I386_SET_FSBASE:
error = copyin(uap->parms, &i386base, sizeof(i386base));
- pcb->pcb_fsbase = i386base;
- if (!error)
- wrmsr(MSR_FSBASE, pcb->pcb_fsbase);
+ if (!error) {
+ critical_enter();
+ wrmsr(MSR_FSBASE, i386base);
+ pcb->pcb_fsbase = i386base;
+ critical_exit();
+ }
break;
case I386_GET_GSBASE:
i386base = pcb->pcb_gsbase;
@@ -75,18 +83,29 @@ sysarch(td, uap)
break;
case I386_SET_GSBASE:
error = copyin(uap->parms, &i386base, sizeof(i386base));
- pcb->pcb_gsbase = i386base;
- if (!error)
- wrmsr(MSR_KGSBASE, pcb->pcb_gsbase);
+ if (!error) {
+ critical_enter();
+ wrmsr(MSR_KGSBASE, i386base);
+ pcb->pcb_gsbase = i386base;
+ critical_exit();
+ }
break;
case AMD64_GET_FSBASE:
error = copyout(&pcb->pcb_fsbase, uap->parms, sizeof(pcb->pcb_fsbase));
break;
case AMD64_SET_FSBASE:
- error = copyin(uap->parms, &pcb->pcb_fsbase, sizeof(pcb->pcb_fsbase));
- if (!error)
- wrmsr(MSR_FSBASE, pcb->pcb_fsbase);
+ error = copyin(uap->parms, &a64base, sizeof(a64base));
+ if (!error) {
+ if (a64base < VM_MAXUSER_ADDRESS) {
+ critical_enter();
+ wrmsr(MSR_FSBASE, a64base);
+ pcb->pcb_fsbase = a64base;
+ critical_exit();
+ } else {
+ error = EINVAL;
+ }
+ }
break;
case AMD64_GET_GSBASE:
@@ -94,9 +113,17 @@ sysarch(td, uap)
break;
case AMD64_SET_GSBASE:
- error = copyin(uap->parms, &pcb->pcb_gsbase, sizeof(pcb->pcb_gsbase));
- if (!error)
- wrmsr(MSR_KGSBASE, pcb->pcb_gsbase);
+ error = copyin(uap->parms, &a64base, sizeof(a64base));
+ if (!error) {
+ if (a64base < VM_MAXUSER_ADDRESS) {
+ critical_enter();
+ wrmsr(MSR_KGSBASE, a64base);
+ pcb->pcb_gsbase = a64base;
+ critical_exit();
+ } else {
+ error = EINVAL;
+ }
+ }
break;
default:
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index 5acc1c04a481..424adafc5bb3 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -341,10 +341,13 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
td->td_frame->tf_rdi = (register_t)arg;
}
-void
+int
cpu_set_user_tls(struct thread *td, void *tls_base)
{
+ if ((u_int64_t)tls_base >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+
if (td == curthread) {
critical_enter();
td->td_pcb->pcb_fsbase = (register_t)tls_base;
@@ -353,6 +356,7 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
} else {
td->td_pcb->pcb_fsbase = (register_t)tls_base;
}
+ return (0);
}
#ifdef SMP
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index 6c0760e72f3b..154958dab969 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -297,7 +297,7 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
tf->tf_spsr = PSR_USR32_MODE;
}
-void
+int
cpu_set_user_tls(struct thread *td, void *tls_base)
{
@@ -308,6 +308,7 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
*(void **)ARM_TP_ADDRESS = tls_base;
critical_exit();
}
+ return (0);
}
void
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 7a9837d53fbd..9ad7891ff293 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -472,7 +472,7 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
(int)arg);
}
-void
+int
cpu_set_user_tls(struct thread *td, void *tls_base)
{
struct segment_descriptor sd;
@@ -503,6 +503,7 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
load_gs(GSEL(GUGS_SEL, SEL_UPL));
}
critical_exit();
+ return (0);
}
/*
diff --git a/sys/ia64/ia64/vm_machdep.c b/sys/ia64/ia64/vm_machdep.c
index f7d63014452f..685aece38ee7 100644
--- a/sys/ia64/ia64/vm_machdep.c
+++ b/sys/ia64/ia64/vm_machdep.c
@@ -209,10 +209,11 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
}
}
-void
+int
cpu_set_user_tls(struct thread *td, void *tls_base)
{
td->td_frame->tf_special.tp = (unsigned long)tls_base;
+ return (0);
}
/*
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 4a552a22623d..0e8b3e81f69f 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -176,7 +176,12 @@ create_thread(struct thread *td, mcontext_t *ctx,
/* Set upcall address to user thread entry function. */
cpu_set_upcall_kse(newtd, start_func, arg, &stack);
/* Setup user TLS address and TLS pointer register. */
- cpu_set_user_tls(newtd, tls_base);
+ error = cpu_set_user_tls(newtd, tls_base);
+ if (error != 0) {
+ thread_free(newtd);
+ crfree(td->td_ucred);
+ return (error);
+ }
}
if ((td->td_proc->p_flag & P_HADTHREADS) == 0) {
diff --git a/sys/powerpc/aim/vm_machdep.c b/sys/powerpc/aim/vm_machdep.c
index 60274f32d70e..4b896eaf7e42 100644
--- a/sys/powerpc/aim/vm_machdep.c
+++ b/sys/powerpc/aim/vm_machdep.c
@@ -355,9 +355,10 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
td->td_retval[1] = 0;
}
-void
+int
cpu_set_user_tls(struct thread *td, void *tls_base)
{
td->td_frame->fixreg[2] = (register_t)tls_base;
+ return (0);
}
diff --git a/sys/powerpc/powerpc/vm_machdep.c b/sys/powerpc/powerpc/vm_machdep.c
index 60274f32d70e..4b896eaf7e42 100644
--- a/sys/powerpc/powerpc/vm_machdep.c
+++ b/sys/powerpc/powerpc/vm_machdep.c
@@ -355,9 +355,10 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
td->td_retval[1] = 0;
}
-void
+int
cpu_set_user_tls(struct thread *td, void *tls_base)
{
td->td_frame->fixreg[2] = (register_t)tls_base;
+ return (0);
}
diff --git a/sys/sparc64/sparc64/vm_machdep.c b/sys/sparc64/sparc64/vm_machdep.c
index 20bf46b5ed9c..9dd80fdb8a55 100644
--- a/sys/sparc64/sparc64/vm_machdep.c
+++ b/sys/sparc64/sparc64/vm_machdep.c
@@ -196,13 +196,14 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
td->td_retval[1] = tf->tf_out[1];
}
-void
+int
cpu_set_user_tls(struct thread *td, void *tls_base)
{
if (td == curthread)
flushw();
td->td_frame->tf_global[7] = (uint64_t) tls_base;
+ return (0);
}
/*
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index b165c071aa44..a408ecccb670 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -897,7 +897,7 @@ void kse_GC(void);
void kseinit(void);
void cpu_set_upcall(struct thread *td, struct thread *td0);
void cpu_set_upcall_kse(struct thread *, void (*)(void *), void *, stack_t *);
-void cpu_set_user_tls(struct thread *, void *tls_base);
+int cpu_set_user_tls(struct thread *, void *tls_base);
void cpu_thread_clean(struct thread *);
void cpu_thread_exit(struct thread *);
void cpu_thread_setup(struct thread *td);