diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2005-07-18 14:55:55 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2005-07-18 14:55:55 +0000 |
commit | 266c19464df004208d3eb2fc4d421579a43b28cd (patch) | |
tree | 4ca1713dce4f02ca0a126ee79a5db91f52e43cc3 /sys/arch | |
parent | 4f3dde2f262f2e950cc96b19ae8c092398b83d74 (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.cf | 3 | ||||
-rw-r--r-- | sys/arch/i386/i386/locore.s | 27 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 24 | ||||
-rw-r--r-- | sys/arch/i386/include/frame.h | 3 |
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; }; |