From 82ca37398f696d0ccdcb227598b11494babe14db Mon Sep 17 00:00:00 2001 From: matt Date: Mon, 3 Mar 2014 08:45:18 +0000 Subject: [PATCH] Query the media and vfp feature registers to determine what our default mode should be and what bits in the fpscr can be changed. Print what features are supported: vfp0 at cpu0: NEON MPE (VFP 3.0+), rounding, NaN propogation, denormals --- sys/arch/arm/arm32/sys_machdep.c | 7 ++--- sys/arch/arm/vfp/vfp_init.c | 46 +++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/sys/arch/arm/arm32/sys_machdep.c b/sys/arch/arm/arm32/sys_machdep.c index 3af0c1088576..98aaff4b1c0e 100644 --- a/sys/arch/arm/arm32/sys_machdep.c +++ b/sys/arch/arm/arm32/sys_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: sys_machdep.c,v 1.19 2013/08/23 14:39:50 matt Exp $ */ +/* $NetBSD: sys_machdep.c,v 1.20 2014/03/03 08:45:18 matt Exp $ */ /* * Copyright (c) 1995-1997 Mark Brinicombe. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.19 2013/08/23 14:39:50 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.20 2014/03/03 08:45:18 matt Exp $"); #include #include @@ -106,11 +106,12 @@ arm32_vfp_fpscr(struct lwp *l, const void *uap, register_t *retval) retval[0] = pcb->pcb_vfp.vfp_fpscr; if (uap) { + extern uint32_t vfp_fpscr_changable; struct arm_vfp_fpscr_args ua; int error; if ((error = copyin(uap, &ua, sizeof(ua))) != 0) return (error); - if (((ua.fpscr_clear|ua.fpscr_set) & ~VFP_FPSCR_RMODE) != 0) + if ((ua.fpscr_clear|ua.fpscr_set) & ~vfp_fpscr_changable) return EINVAL; pcb->pcb_vfp.vfp_fpscr &= ~ua.fpscr_clear; pcb->pcb_vfp.vfp_fpscr |= ua.fpscr_set; diff --git a/sys/arch/arm/vfp/vfp_init.c b/sys/arch/arm/vfp/vfp_init.c index 20c654d9faab..987e5a760644 100644 --- a/sys/arch/arm/vfp/vfp_init.c +++ b/sys/arch/arm/vfp/vfp_init.c @@ -1,4 +1,4 @@ -/* $NetBSD: vfp_init.c,v 1.33 2014/01/25 17:30:56 skrll Exp $ */ +/* $NetBSD: vfp_init.c,v 1.34 2014/03/03 08:45:18 matt Exp $ */ /* * Copyright (c) 2008 ARM Ltd @@ -148,6 +148,11 @@ struct evcnt vfpevent_use; struct evcnt vfpevent_reuse; struct evcnt vfpevent_fpe; +/* determine what bits can be changed */ +uint32_t vfp_fpscr_changable = VFP_FPSCR_CSUM; +/* default to run fast */ +uint32_t vfp_fpscr_default = (VFP_FPSCR_DN | VFP_FPSCR_FZ | VFP_FPSCR_RN); + /* * Used to test for a VFP. The following function is installed as a coproc10 * handler on the undefined instruction vector and then we issue a VFP @@ -208,10 +213,8 @@ vfp_fpscr_handler(u_int address, u_int insn, trapframe_t *frame, int fault_code) if (insn & 0x00100000) { *regp = pcb->pcb_vfp.vfp_fpscr; } else { - register_t tmp = *regp; - if (!(cpu_media_and_vfp_features[0] & ARM_MVFR0_EXCEPT_MASK)) - tmp &= ~VFP_FPSCR_ESUM; - pcb->pcb_vfp.vfp_fpscr = tmp; + pcb->pcb_vfp.vfp_fpscr &= ~vfp_fpscr_changable; + pcb->pcb_vfp.vfp_fpscr |= *regp & vfp_fpscr_changable; } vfp_fpscr_ev.ev_count++; @@ -345,14 +348,34 @@ vfp_attach(void) cpu_media_and_vfp_features[0] = armreg_mvfr0_read(); cpu_media_and_vfp_features[1] = armreg_mvfr1_read(); if (fpsid != 0) { - aprint_normal("vfp%d at %s: %s\n", + uint32_t f0 = armreg_mvfr0_read(); + uint32_t f1 = armreg_mvfr0_read(); + aprint_normal("vfp%d at %s: %s%s%s%s%s\n", device_unit(curcpu()->ci_dev), device_xname(curcpu()->ci_dev), - model); + model, + ((f0 & ARM_MVFR0_ROUNDING_MASK) ? ", rounding" : ""), + ((f0 & ARM_MVFR0_EXCEPT_MASK) ? ", exceptions" : ""), + ((f1 & ARM_MVFR1_D_NAN_MASK) ? ", NaN propogation" : ""), + ((f1 & ARM_MVFR1_FTZ_MASK) ? ", denormals" : "")); aprint_verbose("vfp%d: mvfr: [0]=%#x [1]=%#x\n", - device_unit(curcpu()->ci_dev), - cpu_media_and_vfp_features[0], - cpu_media_and_vfp_features[1]); + device_unit(curcpu()->ci_dev), f0, f1); + if (cpu_media_and_vfp_features[0] & ARM_MVFR0_ROUNDING_MASK) { + vfp_fpscr_changable |= VFP_FPSCR_RMODE; + } + if (cpu_media_and_vfp_features[0] & ARM_MVFR0_EXCEPT_MASK) { + vfp_fpscr_changable |= VFP_FPSCR_ESUM; + } + // If hardware supports propogation of NaNs, select it. + if (cpu_media_and_vfp_features[1] & ARM_MVFR1_D_NAN_MASK) { + vfp_fpscr_default &= ~VFP_FPSCR_DN; + vfp_fpscr_changable |= VFP_FPSCR_DN; + } + // If hardware supports denormalized numbers, use it. + if (cpu_media_and_vfp_features[1] & ARM_MVFR1_FTZ_MASK) { + vfp_fpscr_default &= ~VFP_FPSCR_FZ; + vfp_fpscr_changable |= VFP_FPSCR_FZ; + } } evcnt_attach_dynamic(&vfpevent_use, EVCNT_TYPE_MISC, NULL, "VFP", "coproc use"); @@ -505,8 +528,7 @@ vfp_state_load(lwp_t *l, u_int flags) 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 */ + pcb->pcb_vfp.vfp_fpscr = vfp_fpscr_default; } else { vfpevent_reuse.ev_count++; }