Module Name:    src
Committed By:   dsl
Date:           Sun Feb 23 12:56:40 UTC 2014

Modified Files:
        src/sys/arch/amd64/amd64: machdep.c
        src/sys/arch/i386/i386: machdep.c
        src/sys/arch/x86/include: cpu.h
        src/sys/arch/x86/x86: fpu.c identcpu.c x86_machdep.c

Log Message:
Determine whether the cpu supports xsave (and hence AVX).
The result is only written to sysctl nodes at the moment.
I see:
machdep.fpu_save = 3 (implies xsaveopt)
machdep.xsave_size = 832
machdep.xsave_features = 7
Completely common up the i386 and amd64 machdep sysctl creation.


To generate a diff of this commit:
cvs rdiff -u -r1.206 -r1.207 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.750 -r1.751 src/sys/arch/i386/i386/machdep.c
cvs rdiff -u -r1.64 -r1.65 src/sys/arch/x86/include/cpu.h
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/x86/x86/fpu.c
cvs rdiff -u -r1.40 -r1.41 src/sys/arch/x86/x86/identcpu.c
cvs rdiff -u -r1.61 -r1.62 src/sys/arch/x86/x86/x86_machdep.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/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.206 src/sys/arch/amd64/amd64/machdep.c:1.207
--- src/sys/arch/amd64/amd64/machdep.c:1.206	Thu Feb 20 18:19:09 2014
+++ src/sys/arch/amd64/amd64/machdep.c	Sun Feb 23 12:56:40 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.206 2014/02/20 18:19:09 dsl Exp $	*/
+/*	$NetBSD: machdep.c,v 1.207 2014/02/23 12:56:40 dsl Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -111,7 +111,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.206 2014/02/20 18:19:09 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.207 2014/02/23 12:56:40 dsl Exp $");
 
 /* #define XENDEBUG_LOW  */
 
@@ -511,27 +511,6 @@ cpu_init_tss(struct cpu_info *ci)
 	ci->ci_tss_sel = tss_alloc(tss);
 }
 
-SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
-{
-	x86_sysctl_machdep_setup(clog);
-
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT | CTLFLAG_IMMEDIATE,
-		       CTLTYPE_INT, "fpu_present", NULL,
-		       NULL, 1, NULL, 0,
-		       CTL_MACHDEP, CPU_FPU_PRESENT, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT | CTLFLAG_IMMEDIATE,
-		       CTLTYPE_INT, "sse", NULL,
-		       NULL, 1, NULL, 0,
-		       CTL_MACHDEP, CPU_SSE, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT | CTLFLAG_IMMEDIATE,
-		       CTLTYPE_INT, "sse2", NULL,
-		       NULL, 1, NULL, 0,
-		       CTL_MACHDEP, CPU_SSE2, CTL_EOL);
-}
-
 void
 buildcontext(struct lwp *l, void *catcher, void *f)
 {

Index: src/sys/arch/i386/i386/machdep.c
diff -u src/sys/arch/i386/i386/machdep.c:1.750 src/sys/arch/i386/i386/machdep.c:1.751
--- src/sys/arch/i386/i386/machdep.c:1.750	Thu Feb 20 18:19:10 2014
+++ src/sys/arch/i386/i386/machdep.c	Sun Feb 23 12:56:40 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.750 2014/02/20 18:19:10 dsl Exp $	*/
+/*	$NetBSD: machdep.c,v 1.751 2014/02/23 12:56:40 dsl Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.750 2014/02/20 18:19:10 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.751 2014/02/23 12:56:40 dsl Exp $");
 
 #include "opt_beep.h"
 #include "opt_compat_ibcs2.h"
@@ -590,47 +590,6 @@ cpu_init_tss(struct cpu_info *ci)
 }
 #endif /* XEN */
 
-/*
- * machine dependent system variables.
- */
-SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
-{
-	x86_sysctl_machdep_setup(clog);
-
-#ifndef XEN
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_INT, "biosbasemem", NULL,
-		       NULL, 0, &biosbasemem, 0,
-		       CTL_MACHDEP, CPU_BIOSBASEMEM, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_INT, "biosextmem", NULL,
-		       NULL, 0, &biosextmem, 0,
-		       CTL_MACHDEP, CPU_BIOSEXTMEM, CTL_EOL);
-#endif /* XEN */
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_INT, "osfxsr", NULL,
-		       NULL, 0, &i386_use_fxsave, 0,
-		       CTL_MACHDEP, CPU_OSFXSR, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_INT, "fpu_present", NULL,
-		       NULL, 0, &i386_fpu_present, 0,
-		       CTL_MACHDEP, CPU_FPU_PRESENT, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_INT, "sse", NULL,
-		       NULL, 0, &i386_has_sse, 0,
-		       CTL_MACHDEP, CPU_SSE, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_INT, "sse2", NULL,
-		       NULL, 0, &i386_has_sse2, 0,
-		       CTL_MACHDEP, CPU_SSE2, CTL_EOL);
-}
-
 void *
 getframe(struct lwp *l, int sig, int *onstack)
 {

Index: src/sys/arch/x86/include/cpu.h
diff -u src/sys/arch/x86/include/cpu.h:1.64 src/sys/arch/x86/include/cpu.h:1.65
--- src/sys/arch/x86/include/cpu.h:1.64	Sat Feb 22 17:48:08 2014
+++ src/sys/arch/x86/include/cpu.h	Sun Feb 23 12:56:40 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.64 2014/02/22 17:48:08 dsl Exp $	*/
+/*	$NetBSD: cpu.h,v 1.65 2014/02/23 12:56:40 dsl Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -382,6 +382,14 @@ extern int i386_has_sse2;
 #define	i386_has_sse2		1
 #endif
 
+extern int x86_fpu_save;
+#define	FPU_SAVE_FSAVE		0
+#define	FPU_SAVE_FXSAVE		1
+#define	FPU_SAVE_XSAVE		2
+#define	FPU_SAVE_XSAVEOPT	3
+extern unsigned int x86_xsave_size;
+extern uint64_t x86_xsave_features;
+
 extern void (*x86_cpu_idle)(void);
 #define	cpu_idle() (*x86_cpu_idle)()
 

Index: src/sys/arch/x86/x86/fpu.c
diff -u src/sys/arch/x86/x86/fpu.c:1.6 src/sys/arch/x86/x86/fpu.c:1.7
--- src/sys/arch/x86/x86/fpu.c:1.6	Sat Feb 15 22:20:42 2014
+++ src/sys/arch/x86/x86/fpu.c	Sun Feb 23 12:56:40 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: fpu.c,v 1.6 2014/02/15 22:20:42 dsl Exp $	*/
+/*	$NetBSD: fpu.c,v 1.7 2014/02/23 12:56:40 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.  All
@@ -100,7 +100,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.6 2014/02/15 22:20:42 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.7 2014/02/23 12:56:40 dsl Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -241,34 +241,11 @@ static const uint8_t fpetable[128] = {
 void
 fpuinit(struct cpu_info *ci)
 {
+	if (!i386_fpu_present)
+		return;
+
 	clts();
 	fninit();
-
-#if defined(__i386__) && !defined(XEN)
-	{
-		uint16_t control;
-
-		/* Read the default control word */
-		fnstcw(&control); 
-
-		if (control != __INITIAL_NPXCW__) {
-			/* Must be a 486SX, trap FP instructions */
-			lcr0((rcr0() & ~CR0_MP) | CR0_EM);
-			aprint_normal_dev(ci->ci_dev, "no fpu (control %x)\n",
-			    control);
-			i386_fpu_present = 0;
-			return;
-		}
-
-		if (npx586bug1(4195835, 3145727) != 0) {
-			/* NB 120+MHz cpus are not affected */
-			i386_fpu_fdivbug = 1;
-			aprint_normal_dev(ci->ci_dev,
-			    "WARNING: Pentium FDIV bug detected!\n");
-		}
-	}
-#endif
-
 	stts();
 }
 

Index: src/sys/arch/x86/x86/identcpu.c
diff -u src/sys/arch/x86/x86/identcpu.c:1.40 src/sys/arch/x86/x86/identcpu.c:1.41
--- src/sys/arch/x86/x86/identcpu.c:1.40	Sat Feb 22 17:48:08 2014
+++ src/sys/arch/x86/x86/identcpu.c	Sun Feb 23 12:56:40 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: identcpu.c,v 1.40 2014/02/22 17:48:08 dsl Exp $	*/
+/*	$NetBSD: identcpu.c,v 1.41 2014/02/23 12:56:40 dsl Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.40 2014/02/22 17:48:08 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.41 2014/02/23 12:56:40 dsl Exp $");
 
 #include "opt_xen.h"
 
@@ -60,6 +60,10 @@ static const struct x86_cache_info amd_c
 int cpu_vendor;
 char cpu_brand_string[49];
 
+int x86_fpu_save = FPU_SAVE_FSAVE;
+unsigned int x86_xsave_size = 0;
+uint64_t x86_xsave_features = 0;
+
 /*
  * Info for CTL_HW
  */
@@ -677,6 +681,85 @@ cpu_probe_vortex86(struct cpu_info *ci)
 #undef PCI_MODE1_DATA_REG
 }
 
+#if !defined(__i386__) || defined(XEN)
+#define cpu_probe_old_fpu(ci)
+#else
+static void
+cpu_probe_old_fpu(struct cpu_info *ci)
+{
+	uint16_t control;
+
+	/* Check that there really is an fpu (496SX) */
+	clts();
+	fninit();
+	/* Read default control word */
+	fnstcw(&control);
+	if (control != __INITIAL_NPXCW__) {
+		/* Must be a 486SX, trap FP instructions */
+		lcr0((rcr0() & ~CR0_MP) | CR0_EM);
+		i386_fpu_present = 0;
+		return;
+	}
+
+	/* Check for 'FDIV' bug on the original Pentium */
+	if (npx586bug1(4195835, 3145727) != 0)
+		/* NB 120+MHz cpus are not affected */
+		i386_fpu_fdivbug = 1;
+
+	stts();
+}
+#endif
+
+static void
+cpu_probe_fpu(struct cpu_info *ci)
+{
+	u_int descs[4];
+
+#ifdef i386 /* amd64 always has fxsave, sse and sse2 */
+	/* If we have FXSAVE/FXRESTOR, use them. */
+	if ((ci->ci_feat_val[0] & CPUID_FXSR) == 0) {
+		i386_use_fxsave = 0;
+		/* Allow for no fpu even if cpuid is supported */
+		cpu_probe_old_fpu(ci);
+		return;
+	}
+
+	i386_use_fxsave = 1;
+	/*
+	 * If we have SSE/SSE2, enable XMM exceptions, and
+	 * notify userland.
+	 */
+	if (ci->ci_feat_val[0] & CPUID_SSE)
+		i386_has_sse = 1;
+	if (ci->ci_feat_val[0] & CPUID_SSE2)
+		i386_has_sse2 = 1;
+#else
+	/*
+	 * For amd64 i386_use_fxsave, i386_has_sse and i386_has_sse2 are
+	 * #defined to 1.
+	 */
+#endif	/* i386 */
+
+	x86_fpu_save = FPU_SAVE_FXSAVE;
+
+	/* See if xsave (for AVX is supported) */
+	if ((ci->ci_feat_val[1] & CPUID2_XSAVE) == 0)
+		return;
+
+	x86_fpu_save = FPU_SAVE_XSAVE;
+
+	/* xsaveopt ought to be faster than xsave */
+	x86_cpuid2(0xd, 1, descs);
+	if (descs[0] & CPUID_PES1_XSAVEOPT)
+		x86_fpu_save = FPU_SAVE_XSAVEOPT;
+
+	/* Get features and maximum size of the save area */
+	x86_cpuid(0xd, descs);
+	/* XXX these probably ought to be per-cpu */
+	x86_xsave_size = descs[2];
+	x86_xsave_features = (uint64_t)descs[3] << 32 | descs[0];
+}
+
 void
 cpu_probe(struct cpu_info *ci)
 {
@@ -688,8 +771,11 @@ cpu_probe(struct cpu_info *ci)
 	cpu_vendor = i386_nocpuid_cpus[cputype << 1];
 	cpu_class = i386_nocpuid_cpus[(cputype << 1) + 1];
 
-	if (cpuid_level < 0)
+	if (cpuid_level < 0) {
+		/* cpuid instruction not supported */
+		cpu_probe_old_fpu(ci);
 		return;
+	}
 
 	for (i = 0; i < __arraycount(ci->ci_feat_val); i++) {
 		ci->ci_feat_val[i] = 0;
@@ -779,6 +865,8 @@ cpu_probe(struct cpu_info *ci)
 	cpu_probe_geode(ci);
 	cpu_probe_vortex86(ci);
 
+	cpu_probe_fpu(ci);
+
 	x86_cpu_topology(ci);
 
 	if (cpu_vendor != CPUVENDOR_AMD && (ci->ci_feat_val[0] & CPUID_TM) &&
@@ -812,6 +900,7 @@ cpu_probe(struct cpu_info *ci)
 	}
 }
 
+/* Write what we know about the cpu to the console... */
 void
 cpu_identify(struct cpu_info *ci)
 {
@@ -840,51 +929,36 @@ cpu_identify(struct cpu_info *ci)
 		aprint_error("WARNING: BUGGY CYRIX CACHE\n");
 	}
 
-	if ((cpu_vendor == CPUVENDOR_AMD) /* check enablement of an */
-	  && (device_unit(ci->ci_dev) == 0) /* AMD feature only once */
-	  && ((cpu_feature[3] & CPUID_SVM) == CPUID_SVM)
-#if defined(XEN) && !defined(DOM0OPS)
-	  && (false)  /* on Xen rdmsr is for Dom0 only */
-#endif
-	  )
-	{
+#if !defined(XEN) || defined(DOM0OPS)       /* on Xen rdmsr is for Dom0 only */
+	if (cpu_vendor == CPUVENDOR_AMD     /* check enablement of an */
+	    && device_unit(ci->ci_dev) == 0 /* AMD feature only once */
+	    && ((cpu_feature[3] & CPUID_SVM) == CPUID_SVM)) {
 		uint64_t val;
 
 		val = rdmsr(MSR_VMCR);
 		if (((val & VMCR_SVMED) == VMCR_SVMED)
-		  && ((val & VMCR_LOCK) == VMCR_LOCK))
-		{
+		    && ((val & VMCR_LOCK) == VMCR_LOCK)) {
 			aprint_normal_dev(ci->ci_dev,
 				"SVM disabled by the BIOS\n");
 		}
 	}
+#endif
+
+#ifdef i386
+	if (i386_fpu_present == 0)
+		aprint_normal_dev(ci->ci_dev, "no fpu\n");
+
+	if (i386_fpu_fdivbug == 1)
+		aprint_normal_dev(ci->ci_dev,
+		    "WARNING: Pentium FDIV bug detected!\n");
 
-#ifdef i386 /* XXX for now */
 	if (cpu_vendor == CPUVENDOR_TRANSMETA) {
 		u_int descs[4];
 		x86_cpuid(0x80860000, descs);
 		if (descs[0] >= 0x80860007)
+			/* Create longrun sysctls */
 			tmx86_init_longrun();
 	}
-
-	/* If we have FXSAVE/FXRESTOR, use them. */
-	if (cpu_feature[0] & CPUID_FXSR) {
-		i386_use_fxsave = 1;
-		/*
-		 * If we have SSE/SSE2, enable XMM exceptions, and
-		 * notify userland.
-		 */
-		if (cpu_feature[0] & CPUID_SSE)
-			i386_has_sse = 1;
-		if (cpu_feature[0] & CPUID_SSE2)
-			i386_has_sse2 = 1;
-	} else {
-		i386_use_fxsave = 0;
-	}
-#else
-	/*
-	 * i386_use_fxsave, i386_has_sse and i386_has_sse2 are
-	 * #defined to 1.
-	 */
 #endif	/* i386 */
+
 }

Index: src/sys/arch/x86/x86/x86_machdep.c
diff -u src/sys/arch/x86/x86/x86_machdep.c:1.61 src/sys/arch/x86/x86/x86_machdep.c:1.62
--- src/sys/arch/x86/x86/x86_machdep.c:1.61	Sat Oct  5 16:50:31 2013
+++ src/sys/arch/x86/x86/x86_machdep.c	Sun Feb 23 12:56:40 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: x86_machdep.c,v 1.61 2013/10/05 16:50:31 rmind Exp $	*/
+/*	$NetBSD: x86_machdep.c,v 1.62 2014/02/23 12:56:40 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi,
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.61 2013/10/05 16:50:31 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.62 2014/02/23 12:56:40 dsl Exp $");
 
 #include "opt_modular.h"
 #include "opt_physmem.h"
@@ -1055,8 +1055,18 @@ sysctl_machdep_diskinfo(SYSCTLFN_ARGS)
         return sysctl_lookup(SYSCTLFN_CALL(&node));
 }
 
-void
-x86_sysctl_machdep_setup(struct sysctllog **clog) {
+static void
+const_sysctl(struct sysctllog **clog, const char *name, u_quad_t value, int tag)
+{
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT | CTLFLAG_IMMEDIATE,
+		       CTLTYPE_QUAD, name, NULL,
+		       NULL, value, NULL, 0,
+		       CTL_MACHDEP, tag, CTL_EOL);
+}
+
+SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
+{
 	extern uint64_t tsc_freq;
 	extern int sparse_dump;
 
@@ -1081,6 +1091,7 @@ x86_sysctl_machdep_setup(struct sysctllo
 		       CTLTYPE_STRUCT, "diskinfo", NULL,
 		       sysctl_machdep_diskinfo, 0, NULL, 0,
 		       CTL_MACHDEP, CPU_DISKINFO, CTL_EOL);
+
 	sysctl_createv(clog, 0, NULL, NULL, 
 	    	       CTLFLAG_PERMANENT,
 		       CTLTYPE_STRING, "cpu_brand", NULL,
@@ -1102,4 +1113,19 @@ x86_sysctl_machdep_setup(struct sysctllo
 		       SYSCTL_DESCR("Whether the kernel uses PAE"),
 		       NULL, 0, &use_pae, 0,
 		       CTL_MACHDEP, CTL_CREATE, CTL_EOL);
+
+	/* None of these can ever change once the system has booted */
+	const_sysctl(clog, "fpu_present", i386_fpu_present, CPU_FPU_PRESENT);
+	const_sysctl(clog, "osfxsr", i386_use_fxsave, CPU_OSFXSR);
+	const_sysctl(clog, "sse", i386_has_sse, CPU_SSE);
+	const_sysctl(clog, "sse2", i386_has_sse2, CPU_SSE2);
+
+	const_sysctl(clog, "fpu_save", x86_fpu_save, CTL_CREATE);
+	const_sysctl(clog, "xsave_size", x86_xsave_size, CTL_CREATE);
+	const_sysctl(clog, "xsave_features", x86_xsave_features, CTL_CREATE);
+
+#ifndef XEN
+	const_sysctl(clog, "biosbasemem", biosbasemem, CPU_BIOSBASEMEM);
+	const_sysctl(clog, "biosextmem", biosextmem, CPU_BIOSEXTMEM);
+#endif
 }

Reply via email to