Module Name:    src
Committed By:   matt
Date:           Mon Mar  3 08:45:18 UTC 2014

Modified Files:
        src/sys/arch/arm/arm32: sys_machdep.c
        src/sys/arch/arm/vfp: vfp_init.c

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/arm/arm32/sys_machdep.c
cvs rdiff -u -r1.33 -r1.34 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/arm32/sys_machdep.c
diff -u src/sys/arch/arm/arm32/sys_machdep.c:1.19 src/sys/arch/arm/arm32/sys_machdep.c:1.20
--- src/sys/arch/arm/arm32/sys_machdep.c:1.19	Fri Aug 23 14:39:50 2013
+++ src/sys/arch/arm/arm32/sys_machdep.c	Mon Mar  3 08:45:18 2014
@@ -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 <sys/cdefs.h>
-__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 <sys/param.h>
 #include <sys/systm.h>
@@ -106,11 +106,12 @@ arm32_vfp_fpscr(struct lwp *l, const voi
 
 	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;

Index: src/sys/arch/arm/vfp/vfp_init.c
diff -u src/sys/arch/arm/vfp/vfp_init.c:1.33 src/sys/arch/arm/vfp/vfp_init.c:1.34
--- src/sys/arch/arm/vfp/vfp_init.c:1.33	Sat Jan 25 17:30:56 2014
+++ src/sys/arch/arm/vfp/vfp_init.c	Mon Mar  3 08:45:18 2014
@@ -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 i
 	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++;
 	}

Reply via email to