diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2010-07-03 04:54:33 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2010-07-03 04:54:33 +0000 |
commit | 705b0f3878354b438472892e238e4d05423c56ca (patch) | |
tree | d52482e213791d7c06620c188b058cf88196ee61 /sys/arch/i386 | |
parent | 1df4f9d5fc0dabecca2ff9680db469442a1cfc73 (diff) |
Make the kernel responsible for saving the FPU state before running
signal handlers. Breaks ABI for applications that copy around struct
sigcontext to implement cooperative threading. Other applications
shoouldn't notice the difference.
ok guenther@, deraadt@
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/i386/genassym.cf | 3 | ||||
-rw-r--r-- | sys/arch/i386/i386/locore.s | 27 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 37 | ||||
-rw-r--r-- | sys/arch/i386/include/frame.h | 3 | ||||
-rw-r--r-- | sys/arch/i386/include/signal.h | 4 |
5 files changed, 36 insertions, 38 deletions
diff --git a/sys/arch/i386/i386/genassym.cf b/sys/arch/i386/i386/genassym.cf index 678ce236452..1f95c15ad01 100644 --- a/sys/arch/i386/i386/genassym.cf +++ b/sys/arch/i386/i386/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.30 2010/04/01 19:48:50 kettenis Exp $ +# $OpenBSD: genassym.cf,v 1.31 2010/07/03 04:54:32 kettenis Exp $ # # Copyright (c) 1982, 1990 The Regents of the University of California. # All rights reserved. @@ -136,7 +136,6 @@ member if_ppl struct sigframe SIGF_ member HANDLER sf_handler member SC sf_sc -member FPSTATE sf_fpstate struct sigcontext # mbuf fields diff --git a/sys/arch/i386/i386/locore.s b/sys/arch/i386/i386/locore.s index 3a9f2d2dabd..3eedfb20b5b 100644 --- a/sys/arch/i386/i386/locore.s +++ b/sys/arch/i386/i386/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.129 2010/05/09 12:03:16 kettenis Exp $ */ +/* $OpenBSD: locore.s,v 1.130 2010/07/03 04:54:32 kettenis Exp $ */ /* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */ /*- @@ -639,29 +639,8 @@ NENTRY(proc_trampoline) * Signal trampoline; copied to top of user stack. */ NENTRY(sigcode) - movl SIGF_FPSTATE(%esp),%esi # FPU state area if need saving - testl %esi,%esi - jz 1f - fnsave (%esi) -1: call *SIGF_HANDLER(%esp) - testl %esi,%esi - jz 2f - frstor (%esi) - jmp 2f - - .globl _C_LABEL(sigcode_xmm) -_C_LABEL(sigcode_xmm): - movl SIGF_FPSTATE(%esp),%esi # FPU state area if need saving - testl %esi,%esi - jz 1f - fxsave (%esi) - fninit -1: call *SIGF_HANDLER(%esp) - testl %esi,%esi - jz 2f - fxrstor (%esi) - -2: leal SIGF_SC(%esp),%eax # scp (the call may have clobbered the + call *SIGF_HANDLER(%esp) + leal SIGF_SC(%esp),%eax # scp (the call may have clobbered the # copy at SIGF_SCP(%esp)) pushl %eax pushl %eax # junk to fake return address diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 73f461160d9..409ecde3841 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.476 2010/07/01 23:05:50 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.477 2010/07/03 04:54:32 kettenis Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -2178,8 +2178,8 @@ void sendsig(sig_t catcher, int sig, int mask, u_long code, int type, union sigval val) { - extern char sigcode, sigcode_xmm; struct proc *p = curproc; + union savefpu *sfp = &p->p_addr->u_pcb.pcb_savefpu; struct trapframe *tf = p->p_md.md_regs; struct sigframe *fp, frame; struct sigacts *psp = p->p_sigacts; @@ -2201,11 +2201,23 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, } else sp = tf->tf_esp; - frame.sf_fpstate = NULL; + frame.sf_sc.sc_fpstate = NULL; if (p->p_md.md_flags & MDP_USEDFPU) { + npxsave_proc(p, 1); sp -= sizeof(union savefpu); sp &= ~0xf; /* for XMM regs */ - frame.sf_fpstate = (void *)sp; + frame.sf_sc.sc_fpstate = (void *)sp; + if (copyout(&p->p_addr->u_pcb.pcb_savefpu, + (void *)sp, sizeof(union savefpu))) + sigexit(p, SIGILL); + + /* Signal handlers get a completely clean FP state */ + p->p_md.md_flags &= ~MDP_USEDFPU; + if (i386_use_fxsave) { + sfp->sv_xmm.sv_env.en_cw = __OpenBSD_NPXCW__; + sfp->sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__; + } else + sfp->sv_87.sv_env.en_cw = __OpenBSD_NPXCW__; } fp = (struct sigframe *)sp - 1; @@ -2276,8 +2288,6 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_eip = p->p_sigcode; tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); - if (i386_use_fxsave) - tf->tf_eip += &sigcode_xmm - &sigcode; tf->tf_eflags &= ~(PSL_T|PSL_D|PSL_VM|PSL_AC); tf->tf_esp = (int)fp; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); @@ -2300,9 +2310,8 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval) syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; struct sigcontext *scp, context; - struct trapframe *tf; - - tf = p->p_md.md_regs; + struct trapframe *tf = p->p_md.md_regs; + int error; /* * The trampoline code hands us the context. @@ -2354,6 +2363,16 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval) tf->tf_esp = context.sc_esp; tf->tf_ss = context.sc_ss; + if (p->p_md.md_flags & MDP_USEDFPU) + npxsave_proc(p, 0); + + if (context.sc_fpstate) { + if ((error = copyin(context.sc_fpstate, + &p->p_addr->u_pcb.pcb_savefpu, sizeof (union savefpu)))) + return (error); + p->p_md.md_flags |= MDP_USEDFPU; + } + if (context.sc_onstack & 01) p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; else diff --git a/sys/arch/i386/include/frame.h b/sys/arch/i386/include/frame.h index cc1263e57c8..a1bc4ceba8a 100644 --- a/sys/arch/i386/include/frame.h +++ b/sys/arch/i386/include/frame.h @@ -1,4 +1,4 @@ -/* $OpenBSD: frame.h,v 1.9 2007/10/10 15:53:52 art Exp $ */ +/* $OpenBSD: frame.h,v 1.10 2010/07/03 04:54:32 kettenis Exp $ */ /* $NetBSD: frame.h,v 1.12 1995/10/11 04:20:08 mycroft Exp $ */ /*- @@ -122,6 +122,5 @@ struct sigframe { sig_t sf_handler; struct sigcontext sf_sc; siginfo_t sf_si; - void *sf_fpstate; }; #endif diff --git a/sys/arch/i386/include/signal.h b/sys/arch/i386/include/signal.h index 8229bd26c5c..ed3fb62bbb8 100644 --- a/sys/arch/i386/include/signal.h +++ b/sys/arch/i386/include/signal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: signal.h,v 1.6 2006/01/08 14:20:17 millert Exp $ */ +/* $OpenBSD: signal.h,v 1.7 2010/07/03 04:54:32 kettenis Exp $ */ /* $NetBSD: signal.h,v 1.6 1996/01/08 13:51:43 mycroft Exp $ */ /* @@ -78,6 +78,8 @@ struct sigcontext { int sc_trapno; /* XXX should be above */ int sc_err; + + union savefpu *sc_fpstate; }; #define sc_sp sc_esp |