git: 95dd6974b591 - main - Always read the VFP regs in the arm64 fill_fpregs

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Wed, 18 Jan 2023 09:39:48 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=95dd6974b591ce76bf8d29adcc0dd01b4b281ffd

commit 95dd6974b591ce76bf8d29adcc0dd01b4b281ffd
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2023-01-18 09:30:20 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2023-01-18 09:31:35 +0000

    Always read the VFP regs in the arm64 fill_fpregs
    
    The PCB_FP_STARTED is used to indicate that the current VFP context
    has been used since either 1. the start of the thread, or 2. exiting
    a kernel FP context.
    
    When case 2 was added to the kernel this could cause incorrect results
    to be returned when a thread exits the kernel FP context and fill_fpregs
    is called before it has restored the VFP state, e.g. by trappin on a
    userspace VFP instruction.
    
    In both of the cases the base save area is still valid so reduce the
    use of the PCB_FP_STARTED flag check to help decide if we need to
    store the current threads VFP state.
    
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D37994
---
 sys/arm64/arm64/exec_machdep.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/sys/arm64/arm64/exec_machdep.c b/sys/arm64/arm64/exec_machdep.c
index 6109a866a2d0..12c23149ec7f 100644
--- a/sys/arm64/arm64/exec_machdep.c
+++ b/sys/arm64/arm64/exec_machdep.c
@@ -153,16 +153,17 @@ fill_fpregs(struct thread *td, struct fpreg *regs)
 		 */
 		if (td == curthread)
 			vfp_save_state(td, pcb);
+	}
 
-		KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
-		    ("Called fill_fpregs while the kernel is using the VFP"));
-		memcpy(regs->fp_q, pcb->pcb_fpustate.vfp_regs,
-		    sizeof(regs->fp_q));
-		regs->fp_cr = pcb->pcb_fpustate.vfp_fpcr;
-		regs->fp_sr = pcb->pcb_fpustate.vfp_fpsr;
-	} else
+	KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
+	    ("Called fill_fpregs while the kernel is using the VFP"));
+	memcpy(regs->fp_q, pcb->pcb_fpustate.vfp_regs,
+	    sizeof(regs->fp_q));
+	regs->fp_cr = pcb->pcb_fpustate.vfp_fpcr;
+	regs->fp_sr = pcb->pcb_fpustate.vfp_fpsr;
+#else
+	memset(regs, 0, sizeof(*regs));
 #endif
-		memset(regs, 0, sizeof(*regs));
 	return (0);
 }