git: 83f24cffba42 - stable/14 - powerpc: keep the VSX halves of the FPRs across back-to-back signals

From: Piotr Kubaj <pkubaj_at_FreeBSD.org>
Date: Sun, 25 Oct 2026 10:16:31 UTC
The branch stable/14 has been updated by pkubaj:

URL: https://cgit.FreeBSD.org/src/commit/?id=83f24cffba426fcdfce5de114048e666c62f15ea

commit 83f24cffba426fcdfce5de114048e666c62f15ea
Author:     Piotr Kubaj <pkubaj@FreeBSD.org>
AuthorDate: 2026-10-15 19:18:16 +0000
Commit:     Piotr Kubaj <pkubaj@FreeBSD.org>
CommitDate: 2026-10-25 10:16:18 +0000

    powerpc: keep the VSX halves of the FPRs across back-to-back signals
    
    grab_mcontext() only put the second halves of vs0-31 into the context
    while the thread owned the VSX unit, but sigreturn(2) gives ownership
    up so that the next use reloads the registers lazily. A signal that
    arrives right after a sigreturn, like one the handler's mask was
    holding back, got a context without them and its own sigreturn then
    zeroed them in the PCB.
    
    The halves saved in the PCB are current whenever the FP state is, since
    VSX instructions can't run without PCB_VSX and save_fpu() stores them
    in that case, so export them together with the FP registers.
    
    Reviewed by:    jhibbits
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D60754
    
    (cherry picked from commit 64b2fea9a2f90c2cc6097ed2d69acbfeeb13058d)
    (cherry picked from commit 0e9af9fb72884e77de79e37069a162e1563ca86b)
---
 sys/powerpc/powerpc/exec_machdep.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c
index 3f7318ef6a50..e0e20f7cddf8 100644
--- a/sys/powerpc/powerpc/exec_machdep.c
+++ b/sys/powerpc/powerpc/exec_machdep.c
@@ -422,13 +422,21 @@ grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
 		for (i = 0; i < 32; i++)
 			memcpy(&mcp->mc_fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
 			    sizeof(double));
-	}
 
-	if (pcb->pcb_flags & PCB_VSX) {
-		mcp->mc_flags |= _MC_VS_VALID;
-		for (i = 0; i < 32; i++)
-			memcpy(&mcp->mc_vsxfpreg[i],
-			    &pcb->pcb_fpu.fpr[i].vsr[2], sizeof(double));
+		/*
+		 * The second halves of VSR0-31 in the PCB are current
+		 * whenever the FP state is: VSX instructions cannot run
+		 * without PCB_VSX, and save_fpu() stores them when it is
+		 * set.  Export them regardless of whether the thread owns
+		 * VSX at this moment, or a signal delivered right after a
+		 * sigreturn loses them.
+		 */
+		if (cpu_features & PPC_FEATURE_HAS_VSX) {
+			mcp->mc_flags |= _MC_VS_VALID;
+			for (i = 0; i < 32; i++)
+				memcpy(&mcp->mc_vsxfpreg[i],
+				    &pcb->pcb_fpu.fpr[i].vsr[2], sizeof(double));
+		}
 	}
 
 	/*