summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2006-09-17 14:54:14 +0000
committerdavidxu <davidxu@FreeBSD.org>2006-09-17 14:54:14 +0000
commit4254dacbf5cff0f4e4c7f21833c8620c8d66e4c5 (patch)
tree387405b3f59f48f25a5c509046b03ed0bf4a6bdc
parent710a642f7a2c6d9d8683559d0a28398ef6c469ba (diff)
downloadFreeBSD-src-4254dacbf5cff0f4e4c7f21833c8620c8d66e4c5.zip
FreeBSD-src-4254dacbf5cff0f4e4c7f21833c8620c8d66e4c5.tar.gz
Make cpu_set_upcall_kse() and cpu_set_user_tls() work for 32bit process.
-rw-r--r--sys/amd64/amd64/vm_machdep.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index 1acd2e9..afe70a0 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include "opt_isa.h"
#include "opt_cpu.h"
+#include "opt_compat.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -69,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
+#include <machine/specialreg.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -79,6 +81,12 @@ __FBSDID("$FreeBSD$");
#include <amd64/isa/isa.h>
+#ifdef COMPAT_IA32
+
+extern struct sysentvec ia32_freebsd_sysvec;
+
+#endif
+
static void cpu_reset_real(void);
#ifdef SMP
static void cpu_reset_proxy(void);
@@ -320,6 +328,28 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
*/
cpu_thread_clean(td);
+#ifdef COMPAT_IA32
+ if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) {
+ /*
+ * Set the trap frame to point at the beginning of the uts
+ * function.
+ */
+ td->td_frame->tf_rbp = 0;
+ td->td_frame->tf_rsp =
+ (((uintptr_t)stack->ss_sp + stack->ss_size - 4) & ~0x0f) - 4;
+ td->td_frame->tf_rip = (uintptr_t)entry;
+
+ /*
+ * Pass the address of the mailbox for this kse to the uts
+ * function as a parameter on the stack.
+ */
+ suword32((void *)(td->td_frame->tf_rsp + sizeof(int32_t)),
+ (uint32_t)(uintptr_t)arg);
+
+ return;
+ }
+#endif
+
/*
* Set the trap frame to point at the beginning of the uts
* function.
@@ -344,6 +374,19 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
if ((u_int64_t)tls_base >= VM_MAXUSER_ADDRESS)
return (EINVAL);
+#ifdef COMPAT_IA32
+ if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) {
+ if (td == curthread) {
+ critical_enter();
+ td->td_pcb->pcb_gsbase = (register_t)tls_base;
+ wrmsr(MSR_KGSBASE, td->td_pcb->pcb_gsbase);
+ critical_exit();
+ } else {
+ td->td_pcb->pcb_gsbase = (register_t)tls_base;
+ }
+ return (0);
+ }
+#endif
if (td == curthread) {
critical_enter();
td->td_pcb->pcb_fsbase = (register_t)tls_base;
OpenPOWER on IntegriCloud