diff options
| author | dsl <dsl@NetBSD.org> | 2014-02-23 12:56:40 +0000 |
|---|---|---|
| committer | dsl <dsl@NetBSD.org> | 2014-02-23 12:56:40 +0000 |
| commit | 2dfd01904dd1c6ab754dc2e88be3a1fa3feaa2b2 (patch) | |
| tree | db753ff7863a0ca1eca8a57c63e5836d337605c0 /sys | |
| parent | a682083b2a7e09e019a1a3457914177a6b45cf91 (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.c | 25 | ||||
| -rw-r--r-- | sys/arch/i386/i386/machdep.c | 45 | ||||
| -rw-r--r-- | sys/arch/x86/include/cpu.h | 10 | ||||
| -rw-r--r-- | sys/arch/x86/x86/fpu.c | 33 | ||||
| -rw-r--r-- | sys/arch/x86/x86/identcpu.c | 142 | ||||
| -rw-r--r-- | sys/arch/x86/x86/x86_machdep.c | 34 |
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 } |
