aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2021-03-23 18:23:47 +0000
committerAndrew Turner <andrew@FreeBSD.org>2021-04-08 07:51:26 +0000
commitd6a53211a716c987de76294cff32b652fe38bb09 (patch)
tree3f7452673ab909b0f3cff66e6ec516c5a1a6b914
parent15dc713ceb57d0d61c1dc54b1d550da42d250730 (diff)
downloadsrc-d6a53211a716c987de76294cff32b652fe38bb09.tar.gz
src-d6a53211a716c987de76294cff32b652fe38bb09.zip
Discard the arm64 VFP state before resetting it
When resetting the VFP state we need to discard any old state so we don't try to save it on a context switch. Move this first so resetting the pcb is safe to perform outside a critical section. Reviewed by: arichardson Sponsored by: Innovate UK Differential Revision: https://reviews.freebsd.org/D29401
-rw-r--r--sys/arm64/arm64/vfp.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/sys/arm64/arm64/vfp.c b/sys/arm64/arm64/vfp.c
index 4935946d2430..9de27349fb8d 100644
--- a/sys/arm64/arm64/vfp.c
+++ b/sys/arm64/arm64/vfp.c
@@ -208,7 +208,15 @@ vfp_save_state(struct thread *td, struct pcb *pcb)
void
vfp_reset_state(struct thread *td, struct pcb *pcb)
{
+ /* Discard the threads VFP state before resetting it */
critical_enter();
+ vfp_discard(td);
+ critical_exit();
+
+ /*
+ * Clear the thread state. The VFP is disabled and is not the current
+ * VFP thread so we won't change any of these on context switch.
+ */
bzero(&pcb->pcb_fpustate.vfp_regs, sizeof(pcb->pcb_fpustate.vfp_regs));
KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
("pcb_fpusaved should point to pcb_fpustate."));
@@ -216,8 +224,6 @@ vfp_reset_state(struct thread *td, struct pcb *pcb)
pcb->pcb_fpustate.vfp_fpsr = 0;
pcb->pcb_vfpcpu = UINT_MAX;
pcb->pcb_fpflags = 0;
- vfp_discard(td);
- critical_exit();
}
void