summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2004-02-13 03:37:11 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2004-02-13 03:37:11 +0000
commit9a6d8430061e2c9cc91086acaf739146bdb99a7e (patch)
tree497ef2f1c6d30ddc365b02d098ab51e4bdc15bac /sys/arch/amd64
parent64b425b69d7ce5f938212239c7e464017642976c (diff)
save/restore fpu state around the signal handler. skip a gap on unempty stack per abi. form drahn@ and deraadt@
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/amd64/machdep.c28
-rw-r--r--sys/arch/amd64/include/signal.h1
2 files changed, 22 insertions, 7 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 7571f885d92..4ea8fd9fcec 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.4 2004/02/13 00:05:52 mickey Exp $ */
+/* $OpenBSD: machdep.c,v 1.5 2004/02/13 03:37:10 mickey Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -598,12 +598,10 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
p->p_comm, p->p_pid, sig, catcher);
#endif
- if (p->p_md.md_flags & MDP_USEDFPU)
- fpusave_proc(p, 1);
-
bcopy(tf, &ksc, sizeof(*tf));
ksc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
ksc.sc_mask = mask;
+ ksc.sc_fpstate = NULL;
/* Allocate space for the signal handler context. */
if ((psp->ps_flags & SAS_ALTSTACK) && !ksc.sc_onstack &&
@@ -611,10 +609,20 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
sp = (register_t)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size;
psp->ps_sigstk.ss_flags |= SS_ONSTACK;
} else
- sp = tf->tf_rsp;
+ sp = tf->tf_rsp - 128;
sp &= ~15ULL; /* just in case */
sss = (sizeof(ksc) + 15) & ~15;
+
+ if (p->p_md.md_flags & MDP_USEDFPU) {
+ fpusave_proc(p, 1);
+ sp -= sizeof(struct fxsave64);
+ ksc.sc_fpstate = (struct fxsave64 *)sp;
+ if (copyout(&p->p_addr->u_pcb.pcb_savefpu.fp_fxsave,
+ (void *)sp, sizeof(struct fxsave64)))
+ sigexit(p, SIGILL);
+ }
+
sip = 0;
if (psp->ps_siginfo & sigmask(sig)) {
sip = sp - ((sizeof(ksi) + 15) & ~15);
@@ -680,14 +688,20 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
#endif
-
- if (copyin((caddr_t)scp, &ksc, sizeof ksc))
+ if ((error = copyin((caddr_t)scp, &ksc, sizeof ksc)))
return (error);
if (((ksc.sc_rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 ||
!USERMODE(ksc.sc_cs, ksc.sc_eflags))
return (EINVAL);
+ if (p->p_md.md_flags & MDP_USEDFPU)
+ fpusave_proc(p, 0);
+
+ if (ksc.sc_fpstate && (error = copyin(ksc.sc_fpstate,
+ &p->p_addr->u_pcb.pcb_savefpu.fp_fxsave, sizeof (struct fxsave64))))
+ return (error);
+
ksc.sc_trapno = tf->tf_trapno;
ksc.sc_err = tf->tf_err;
bcopy(&ksc, tf, sizeof(*tf));
diff --git a/sys/arch/amd64/include/signal.h b/sys/arch/amd64/include/signal.h
index 79227ad5f6e..cfe62913156 100644
--- a/sys/arch/amd64/include/signal.h
+++ b/sys/arch/amd64/include/signal.h
@@ -79,6 +79,7 @@ struct sigcontext {
long sc_rsp;
long sc_ss;
+ struct fxsave64 *sc_fpstate;
int sc_onstack;
int sc_mask;
};