git: 95dd6974b591 - main - Always read the VFP regs in the arm64 fill_fpregs
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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);
}