summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2010-07-03 04:54:33 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2010-07-03 04:54:33 +0000
commit705b0f3878354b438472892e238e4d05423c56ca (patch)
treed52482e213791d7c06620c188b058cf88196ee61 /sys/arch/i386
parent1df4f9d5fc0dabecca2ff9680db469442a1cfc73 (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.cf3
-rw-r--r--sys/arch/i386/i386/locore.s27
-rw-r--r--sys/arch/i386/i386/machdep.c37
-rw-r--r--sys/arch/i386/include/frame.h3
-rw-r--r--sys/arch/i386/include/signal.h4
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