summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2005-07-18 14:55:55 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2005-07-18 14:55:55 +0000
commit266c19464df004208d3eb2fc4d421579a43b28cd (patch)
tree4ca1713dce4f02ca0a126ee79a5db91f52e43cc3 /sys/arch
parent4f3dde2f262f2e950cc96b19ae8c092398b83d74 (diff)
save/restore fpu for the signal handler call in the trampoline.
modeled after sparc together w/ deraadt@; deraadt@ ok
Diffstat (limited to 'sys/arch')
-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.c24
-rw-r--r--sys/arch/i386/include/frame.h3
4 files changed, 47 insertions, 10 deletions
diff --git a/sys/arch/i386/i386/genassym.cf b/sys/arch/i386/i386/genassym.cf
index 95c33aa1d58..f4db5a69833 100644
--- a/sys/arch/i386/i386/genassym.cf
+++ b/sys/arch/i386/i386/genassym.cf
@@ -1,4 +1,4 @@
-# $OpenBSD: genassym.cf,v 1.20 2005/05/21 19:13:55 brad Exp $
+# $OpenBSD: genassym.cf,v 1.21 2005/07/18 14:55:49 mickey Exp $
#
# Copyright (c) 1982, 1990 The Regents of the University of California.
# All rights reserved.
@@ -133,6 +133,7 @@ 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 724f4325bdb..370bb730027 100644
--- a/sys/arch/i386/i386/locore.s
+++ b/sys/arch/i386/i386/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.90 2005/05/29 03:20:38 deraadt Exp $ */
+/* $OpenBSD: locore.s,v 1.91 2005/07/18 14:55:49 mickey Exp $ */
/* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */
/*-
@@ -736,8 +736,29 @@ NENTRY(proc_trampoline)
* Signal trampoline; copied to top of user stack.
*/
NENTRY(sigcode)
- call *SIGF_HANDLER(%esp)
- leal SIGF_SC(%esp),%eax # scp (the call may have clobbered the
+ 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
# 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 66b3c7f69a3..c658f2f8ee4 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.321 2005/06/26 19:23:53 deraadt Exp $ */
+/* $OpenBSD: machdep.c,v 1.322 2005/07/18 14:55:49 mickey Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -2054,11 +2054,15 @@ sendsig(catcher, sig, mask, code, type, val)
int type;
union sigval val;
{
+#ifdef I686_CPU
+ extern char sigcode, sigcode_xmm;
+#endif
struct proc *p = curproc;
struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map);
struct trapframe *tf = p->p_md.md_regs;
struct sigframe *fp, frame;
struct sigacts *psp = p->p_sigacts;
+ register_t sp;
int oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
/*
@@ -2071,13 +2075,19 @@ sendsig(catcher, sig, mask, code, type, val)
*/
if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
(psp->ps_sigonstack & sigmask(sig))) {
- fp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
- psp->ps_sigstk.ss_size - sizeof(struct sigframe));
+ sp = (long)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size;
psp->ps_sigstk.ss_flags |= SS_ONSTACK;
- } else {
- fp = (struct sigframe *)tf->tf_esp - 1;
+ } else
+ sp = tf->tf_esp;
+
+ frame.sf_fpstate = NULL;
+ if (p->p_md.md_flags & MDP_USEDFPU) {
+ sp -= sizeof(union savefpu);
+ sp &= ~0xf; /* foe XMM regs */
+ frame.sf_fpstate = (void *)sp;
}
+ fp = (struct sigframe *)sp - 1;
frame.sf_scp = &fp->sf_sc;
frame.sf_sip = NULL;
frame.sf_handler = catcher;
@@ -2146,6 +2156,10 @@ sendsig(catcher, sig, mask, code, type, val)
tf->tf_eip = p->p_sigcode;
tf->tf_cs = pmap->pm_hiexec > I386_MAX_EXE_ADDR ?
GSEL(GUCODE1_SEL, SEL_UPL) : GSEL(GUCODE_SEL, SEL_UPL);
+#ifdef I686_CPU
+ if (i386_use_fxsave)
+ tf->tf_eip += &sigcode_xmm - &sigcode;
+#endif
tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
tf->tf_esp = (int)fp;
tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
diff --git a/sys/arch/i386/include/frame.h b/sys/arch/i386/include/frame.h
index cbe9a1a805d..85141665ec2 100644
--- a/sys/arch/i386/include/frame.h
+++ b/sys/arch/i386/include/frame.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: frame.h,v 1.6 2004/07/02 16:29:55 niklas Exp $ */
+/* $OpenBSD: frame.h,v 1.7 2005/07/18 14:55:54 mickey Exp $ */
/* $NetBSD: frame.h,v 1.12 1995/10/11 04:20:08 mycroft Exp $ */
/*-
@@ -121,4 +121,5 @@ struct sigframe {
sig_t sf_handler;
struct sigcontext sf_sc;
siginfo_t sf_si;
+ void *sf_fpstate;
};