summaryrefslogtreecommitdiffstats
path: root/sys/amd64/ia32
diff options
context:
space:
mode:
Diffstat (limited to 'sys/amd64/ia32')
-rw-r--r--sys/amd64/ia32/ia32_signal.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c
index 30074e8..ae5978e 100644
--- a/sys/amd64/ia32/ia32_signal.c
+++ b/sys/amd64/ia32/ia32_signal.c
@@ -558,3 +558,44 @@ freebsd32_sigreturn(td, uap)
PROC_UNLOCK(p);
return (EJUSTRETURN);
}
+
+/*
+ * Clear registers on exec
+ */
+void
+ia32_setregs(td, entry, stack, ps_strings)
+ struct thread *td;
+ u_long entry;
+ u_long stack;
+ u_long ps_strings;
+{
+ struct trapframe *regs = td->td_frame;
+ struct pcb *pcb = td->td_pcb;
+
+ wrmsr(MSR_FSBASE, 0);
+ wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */
+ pcb->pcb_fsbase = 0;
+ pcb->pcb_gsbase = 0;
+ load_ds(_udatasel);
+ load_es(_udatasel);
+ load_fs(_udatasel);
+ load_gs(_udatasel);
+ pcb->pcb_ds = _udatasel;
+ pcb->pcb_es = _udatasel;
+ pcb->pcb_fs = _udatasel;
+ pcb->pcb_gs = _udatasel;
+
+ bzero((char *)regs, sizeof(struct trapframe));
+ regs->tf_rip = entry;
+ regs->tf_rsp = stack;
+ regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
+ regs->tf_ss = _udatasel;
+ regs->tf_cs = _ucode32sel;
+ regs->tf_rbx = ps_strings;
+ load_cr0(rcr0() | CR0_MP | CR0_TS);
+ fpstate_drop(td);
+
+ /* Return via doreti so that we can change to a different %cs */
+ pcb->pcb_flags |= PCB_FULLCTX;
+ td->td_retval[1] = 0;
+}
OpenPOWER on IntegriCloud