diff options
author | 2018-06-23 22:15:14 +0000 | |
---|---|---|
committer | 2018-06-23 22:15:14 +0000 | |
commit | 74f6b3c1e3aba38f8feec08c2adb8e8ca18686b6 (patch) | |
tree | a0f47643146a177da4d759dde84f665cd9985b84 | |
parent | Add -z notext and -z norelro to prevent fatal warnings with ld.lld(1). (diff) | |
download | wireguard-openbsd-74f6b3c1e3aba38f8feec08c2adb8e8ca18686b6.tar.xz wireguard-openbsd-74f6b3c1e3aba38f8feec08c2adb8e8ca18686b6.zip |
Save and restore FPU registers around signal handlers.
Fixes the random crashes in sh(1).
ok guenther@
-rw-r--r-- | sys/arch/arm/arm/sig_machdep.c | 30 | ||||
-rw-r--r-- | sys/arch/arm/include/signal.h | 6 |
2 files changed, 32 insertions, 4 deletions
diff --git a/sys/arch/arm/arm/sig_machdep.c b/sys/arch/arm/arm/sig_machdep.c index 8808158457a..4c7b9789b0e 100644 --- a/sys/arch/arm/arm/sig_machdep.c +++ b/sys/arch/arm/arm/sig_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sig_machdep.c,v 1.16 2018/04/12 17:13:43 deraadt Exp $ */ +/* $OpenBSD: sig_machdep.c,v 1.17 2018/06/23 22:15:14 kettenis Exp $ */ /* $NetBSD: sig_machdep.c,v 1.22 2003/10/08 00:28:41 thorpej Exp $ */ /* @@ -51,11 +51,11 @@ #include <sys/systm.h> #include <sys/user.h> -#include <arm/armreg.h> - #include <machine/cpu.h> #include <machine/frame.h> #include <machine/pcb.h> + +#include <arm/armreg.h> #include <arm/cpufunc.h> #include <uvm/uvm_extern.h> @@ -80,6 +80,7 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, union sigval val) { struct proc *p = curproc; + struct pcb *pcb = &p->p_addr->u_pcb; struct trapframe *tf; struct sigframe *fp, frame; struct sigacts *psp = p->p_p->ps_sigacts; @@ -130,6 +131,16 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, /* Save signal mask. */ frame.sf_sc.sc_mask = returnmask; + /* Save FPU registers. */ + frame.sf_sc.sc_fpused = pcb->pcb_flags & PCB_FPU; + if (frame.sf_sc.sc_fpused) { + frame.sf_sc.sc_fpscr = pcb->pcb_fpstate.fp_scr; + memcpy(&frame.sf_sc.sc_fpreg, &pcb->pcb_fpstate.fp_reg, + sizeof(pcb->pcb_fpstate.fp_reg)); + pcb->pcb_flags &= ~PCB_FPU; + pcb->pcb_fpcpu = NULL; + } + if (psp->ps_siginfo & sigmask(sig)) { frame.sf_sip = &fp->sf_si; initsiginfo(&frame.sf_si, sig, code, type, val); @@ -176,6 +187,7 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval) syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; struct sigcontext ksc, *scp = SCARG(uap, sigcntxp); + struct pcb *pcb = &p->p_addr->u_pcb; struct trapframe *tf; if (PROC_PC(p) != p->p_p->ps_sigcoderet) { @@ -228,5 +240,17 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval) /* Restore signal mask. */ p->p_sigmask = ksc.sc_mask & ~sigcantmask; + /* Restore FPU registers. */ + if (ksc.sc_fpused) { + pcb->pcb_fpstate.fp_scr = ksc.sc_fpscr; + memcpy(&pcb->pcb_fpstate.fp_reg, &ksc.sc_fpreg, + sizeof(pcb->pcb_fpstate.fp_reg)); + pcb->pcb_flags |= PCB_FPU; + pcb->pcb_fpcpu = NULL; + } else { + pcb->pcb_flags &= ~PCB_FPU; + pcb->pcb_fpcpu = NULL; + } + return (EJUSTRETURN); } diff --git a/sys/arch/arm/include/signal.h b/sys/arch/arm/include/signal.h index 773fdc89dc0..38303b02aa7 100644 --- a/sys/arch/arm/include/signal.h +++ b/sys/arch/arm/include/signal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: signal.h,v 1.9 2016/05/10 18:39:43 deraadt Exp $ */ +/* $OpenBSD: signal.h,v 1.10 2018/06/23 22:15:14 kettenis Exp $ */ /* $NetBSD: signal.h,v 1.5 2003/10/18 17:57:21 briggs Exp $ */ /* @@ -82,6 +82,10 @@ struct sigcontext { unsigned int sc_usr_lr; unsigned int sc_svc_lr; unsigned int sc_pc; + + unsigned int sc_fpused; + unsigned int sc_fpscr; + unsigned long long sc_fpreg[32]; }; #endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ #endif /* !_LOCORE */ |