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