summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-07-05 11:29:22 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-07-05 11:29:22 +0000
commitdd20fbc75da7e37108120a7081fd24bb9241d9a0 (patch)
treea0e53f01f96fcf631d0a9cd902e1241e01610453
parent58db0d0707cdad9d85f3ed6c40f7cb071445daa4 (diff)
Save FPU state to PCB before running a signal handler. This doesn't
completely fix the case where the FPU is used in a signal handler but it is part of the solution and makes sure the processor mode check in sys_sigreturn() passes if the process was using the FPU when the signal happened.
-rw-r--r--sys/arch/powerpc64/powerpc64/machdep.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/sys/arch/powerpc64/powerpc64/machdep.c b/sys/arch/powerpc64/powerpc64/machdep.c
index bad24026422..c131fda5324 100644
--- a/sys/arch/powerpc64/powerpc64/machdep.c
+++ b/sys/arch/powerpc64/powerpc64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.42 2020/07/05 10:34:08 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.43 2020/07/05 11:29:21 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -671,6 +671,7 @@ void
sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip)
{
struct proc *p = curproc;
+ struct pcb *pcb = &p->p_addr->u_pcb;
struct trapframe *tf = p->p_md.md_regs;
struct sigframe *fp, frame;
struct sigacts *psp = p->p_p->ps_sigacts;
@@ -687,6 +688,13 @@ sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip)
fp = (struct sigframe *)(STACKALIGN(fp - 1) - 288);
+ /* Save FPU state to PCB if necessary. */
+ if (pcb->pcb_flags & (PCB_FP|PCB_VEC|PCB_VSX) &&
+ tf->srr1 & (PSL_FP|PSL_VEC|PSL_VSX)) {
+ tf->srr1 &= ~(PSL_FP|PSL_VEC|PSL_VSX);
+ save_vsx(p);
+ }
+
/* Build stack frame for signal trampoline. */
memset(&frame, 0, sizeof(frame));
frame.sf_signum = sig;