From 89e2fce3e51a331df7ad94fb1badc8032734b421 Mon Sep 17 00:00:00 2001 From: luporl Date: Thu, 14 Feb 2019 15:15:32 +0000 Subject: [PATCH] [PPC64] Fix mismatch between thread flags and MSR When sigreturn() restored a thread's context, SRR1 was being restored to its previous value, but pcb_flags was not being touched. This could cause a mismatch between the thread's MSR and its pcb_flags. For instance, when the thread used the FPU for the first time inside the signal handler, sigreturn() would clear SRR1, but not pcb_flags. Then, the thread would return with the FPU bit cleared in MSR and, the next time it tried to use the FPU, it would fail on a KASSERT that checked if the FPU was disabled. This change clears the FPU bit in both pcb_flags and frame->srr1, as the code that restores the context expects to use the FPU trap to re-enable it. PR: 234539 Reported by: sbruno Reviewed by: jhibbits, sbruno Differential Revision: https://reviews.freebsd.org/D19166 --- sys/powerpc/powerpc/exec_machdep.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index 4cb9fb8bbae5..3ae1640b2642 100644 --- a/sys/powerpc/powerpc/exec_machdep.c +++ b/sys/powerpc/powerpc/exec_machdep.c @@ -474,6 +474,10 @@ set_mcontext(struct thread *td, mcontext_t *mcp) else tf->fixreg[2] = tls; + /* Disable FPU */ + tf->srr1 &= ~PSL_FP; + pcb->pcb_flags &= ~PCB_FPU; + if (mcp->mc_flags & _MC_FP_VALID) { /* enable_fpu() will happen lazily on a fault */ pcb->pcb_flags |= PCB_FPREGS;