summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authordsl <dsl@NetBSD.org>2014-02-23 12:56:40 +0000
committerdsl <dsl@NetBSD.org>2014-02-23 12:56:40 +0000
commit2dfd01904dd1c6ab754dc2e88be3a1fa3feaa2b2 (patch)
treedb753ff7863a0ca1eca8a57c63e5836d337605c0 /sys
parenta682083b2a7e09e019a1a3457914177a6b45cf91 (diff)
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.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/amd64/machdep.c25
-rw-r--r--sys/arch/i386/i386/machdep.c45
-rw-r--r--sys/arch/x86/include/cpu.h10
-rw-r--r--sys/arch/x86/x86/fpu.c33
-rw-r--r--sys/arch/x86/x86/identcpu.c142
-rw-r--r--sys/arch/x86/x86/x86_machdep.c34
6 files changed, 156 insertions, 133 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index d9c923e07db..98d33602a03 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -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)
{
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index 69fafb79730..e8dd87527d7 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -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)
{
diff --git a/sys/arch/x86/include/cpu.h b/sys/arch/x86/include/cpu.h
index fadec2bf3fc..48a6b752fdc 100644
--- a/sys/arch/x86/include/cpu.h
+++ b/sys/arch/x86/include/cpu.h
@@ -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)()
diff --git a/sys/arch/x86/x86/fpu.c b/sys/arch/x86/x86/fpu.c
index 0b90543385c..f346ca89880 100644
--- a/sys/arch/x86/x86/fpu.c
+++ b/sys/arch/x86/x86/fpu.c
@@ -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();
}
diff --git a/sys/arch/x86/x86/identcpu.c b/sys/arch/x86/x86/identcpu.c
index 93fd5b12ab9..638f23485c5 100644
--- a/sys/arch/x86/x86/identcpu.c
+++ b/sys/arch/x86/x86/identcpu.c
@@ -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_cpuid_l3cache_assoc_info[] =
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 */
+
}
diff --git a/sys/arch/x86/x86/x86_machdep.c b/sys/arch/x86/x86/x86_machdep.c
index fc0b56b1dc5..621f883f2d7 100644
--- a/sys/arch/x86/x86/x86_machdep.c
+++ b/sys/arch/x86/x86/x86_machdep.c
@@ -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 sysctllog **clog) {
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 sysctllog **clog) {
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
}