> Date: Fri, 22 Jun 2018 17:16:14 +0200 (CEST)
> From: Mark Kettenis <[email protected]>
>
> It takes the alpha/hppa/mips64 approach of storing the state in struct
> sigcontext instead of using a pointer. Using unsigned int and
> unsigned long long instead of uint32_t and uint64_t here to avoid
> having to include other headers. But I suppose I could include
> include <sys/_types.h> and use __uint32_t and __uint64_t if people
> prefer that.
>
> This is an ABI break. Code that plays tricks with sigcontext, like
> copying structs around or looks at the internals will have to be
> recompiled. But we don't really support that, so I'm inclined to just
> go aead.
>
> This fixes the corruption in ksh/sh that is currently preventing snaps
> from being built. At least in combination with the setjmp fix I
> mailed out wednesday and Dale's ast fix.
>
> ok?
Better diff that gives the signal handler a clean FPU state and make
sure we reset the FPU state if the signal handler was the first to use
the FPU. This no longer calls vfp_discard(). Instead it just sets
pcb_fpcpu to NULL. That is enough to force reloading of the FPU
state.
ok?
Index: arch/arm/arm/sig_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/arm/arm/sig_machdep.c,v
retrieving revision 1.16
diff -u -p -r1.16 sig_machdep.c
--- arch/arm/arm/sig_machdep.c 12 Apr 2018 17:13:43 -0000 1.16
+++ arch/arm/arm/sig_machdep.c 22 Jun 2018 22:10:19 -0000
@@ -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 retu
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 retu
/* 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, r
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) {
@@ -227,6 +239,18 @@ sys_sigreturn(struct proc *p, void *v, r
/* 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);
}
Index: arch/arm/include/signal.h
===================================================================
RCS file: /cvs/src/sys/arch/arm/include/signal.h,v
retrieving revision 1.9
diff -u -p -r1.9 signal.h
--- arch/arm/include/signal.h 10 May 2016 18:39:43 -0000 1.9
+++ arch/arm/include/signal.h 22 Jun 2018 22:10:19 -0000
@@ -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 */