Module Name: src
Committed By: skrll
Date: Sat Jan 25 17:30:56 UTC 2014
Modified Files:
src/sys/arch/arm/vfp: vfp_init.c
Log Message:
Improve PCU/VFP handling to the point that the atf tests don't trigger
KASSERTs on the Raspberry PI and its arm1176jzf-s.
XXX Need to emulate bounce instructions to get correct exception codes,
XXX etc.
To generate a diff of this commit:
cvs rdiff -u -r1.32 -r1.33 src/sys/arch/arm/vfp/vfp_init.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/vfp/vfp_init.c
diff -u src/sys/arch/arm/vfp/vfp_init.c:1.32 src/sys/arch/arm/vfp/vfp_init.c:1.33
--- src/sys/arch/arm/vfp/vfp_init.c:1.32 Fri Jan 24 08:26:39 2014
+++ src/sys/arch/arm/vfp/vfp_init.c Sat Jan 25 17:30:56 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: vfp_init.c,v 1.32 2014/01/24 08:26:39 skrll Exp $ */
+/* $NetBSD: vfp_init.c,v 1.33 2014/01/25 17:30:56 skrll Exp $ */
/*
* Copyright (c) 2008 ARM Ltd
@@ -407,14 +407,18 @@ vfp_handler(u_int address, u_int insn, t
vfpevent_fpe.ev_count++;
- pcu_save(&arm_vfp_ops);
-
/*
* Need the clear the exception condition so any signal
- * can run.
+ * and future use can proceed.
*/
armreg_fpexc_write(fpexc & ~(VFP_FPEXC_EX|VFP_FPEXC_FSUM));
+ pcu_save(&arm_vfp_ops);
+
+ /*
+ * XXX Need to emulate bounce instructions here to get correct
+ * XXX exception codes, etc.
+ */
KSI_INIT_TRAP(&ksi);
ksi.ksi_signo = SIGFPE;
if (fpexc & VFP_FPEXC_IXF)
@@ -499,6 +503,7 @@ vfp_state_load(lwp_t *l, u_int flags)
* a trap to use it again" event.
*/
if (__predict_false((flags & PCU_LOADED) == 0)) {
+ KASSERT(flags & PCU_RELOAD);
vfpevent_use.ev_count++;
pcb->pcb_vfp.vfp_fpscr =
(VFP_FPSCR_DN | VFP_FPSCR_FZ | VFP_FPSCR_RN); /* Runfast */
@@ -506,21 +511,24 @@ vfp_state_load(lwp_t *l, u_int flags)
vfpevent_reuse.ev_count++;
}
- if (fregs->vfp_fpexc & VFP_FPEXC_EN) {
+ uint32_t fpexc = armreg_fpexc_read();
+ if (flags & PCU_RELOAD) {
+ bool enabled = fregs->vfp_fpexc & VFP_FPEXC_EN;
+
/*
- * If we think the VFP is enabled, it must have be disabled by
- * vfp_state_release for another LWP so we can just restore
- * FPEXC and return since our VFP state is still loaded.
+ * Load and Enable the VFP (so that we can write the
+ * registers).
*/
+ fregs->vfp_fpexc |= VFP_FPEXC_EN;
armreg_fpexc_write(fregs->vfp_fpexc);
- return;
- }
-
- /* Load and Enable the VFP (so that we can write the registers). */
- if (flags & PCU_RELOAD) {
- uint32_t fpexc = armreg_fpexc_read();
- KDASSERT((fpexc & VFP_FPEXC_EX) == 0);
- armreg_fpexc_write(fpexc | VFP_FPEXC_EN);
+ if (enabled) {
+ /*
+ * If we think the VFP is enabled, it must have be
+ * disabled by vfp_state_release for another LWP so
+ * we can now just return.
+ */
+ return;
+ }
load_vfpregs(fregs);
armreg_fpscr_write(fregs->vfp_fpscr);
@@ -531,11 +539,13 @@ vfp_state_load(lwp_t *l, u_int flags)
if (fregs->vfp_fpexc & VFP_FPEXC_FP2V)
armreg_fpinst_write(fregs->vfp_fpinst);
}
+ } else {
+ /*
+ * If the VFP is already enabled we must be bouncing an
+ * instruction.
+ */
+ armreg_fpexc_write(fpexc | VFP_FPEXC_EN);
}
-
- /* Finally, restore the FPEXC but don't enable the VFP. */
- fregs->vfp_fpexc |= VFP_FPEXC_EN;
- armreg_fpexc_write(fregs->vfp_fpexc);
}
void
@@ -543,6 +553,12 @@ vfp_state_save(lwp_t *l, u_int flags)
{
struct pcb * const pcb = lwp_getpcb(l);
uint32_t fpexc = armreg_fpexc_read();
+
+ /*
+ * Enable the VFP (so we can read the registers).
+ * Make sure the exception bit is cleared so that we can
+ * safely dump the registers.
+ */
armreg_fpexc_write((fpexc | VFP_FPEXC_EN) & ~VFP_FPEXC_EX);
if (flags & PCU_KERNEL) {
@@ -556,11 +572,6 @@ vfp_state_save(lwp_t *l, u_int flags)
struct vfpreg * const fregs = &pcb->pcb_vfp;
- /*
- * Enable the VFP (so we can read the registers).
- * Make sure the exception bit is cleared so that we can
- * safely dump the registers.
- */
fregs->vfp_fpexc = fpexc;
if (fpexc & VFP_FPEXC_EX) {
/* Need to save the exception handling state */
@@ -572,7 +583,7 @@ vfp_state_save(lwp_t *l, u_int flags)
save_vfpregs(fregs);
/* Disable the VFP. */
- armreg_fpexc_write(fpexc);
+ armreg_fpexc_write(fpexc & ~VFP_FPEXC_EN);
}
void