On Tue, 2 Feb 2016, Philip Guenther wrote:
...
> Currently we seem to assume that the presence of certain CPU features like
> AVX implies that CPUID supports the related leaf; that BIOS option breaks
> that assumption, resulting in the bogus fpu_save_len sizing you hit.
> From the dmesg you posted I see it also explains the bogus mwait sizing
> that has been reported by some others. Your machine will perform better
> with that option off; I guess we should add check to the code to catch
> this sort of setup by checking the cpuid_level variable before using the
> higher CPUID leafs.
Revised version that switches a few places to check cpuid_level instead of
calling CPUID(0) again and similar for using curcpu()->ci_pnfeatset
instead of calling CPUID(0x80000000) once identifycpu() sets that, and add
a check of ci->ci_pnfeatset before using CPUID(CPUID_AMD_SVM_CAP) in the
vmm bits.
ok?
Philip Guenther
Index: i386/i386/cpu.c
===================================================================
RCS file: /data/src/openbsd/src/sys/arch/i386/i386/cpu.c,v
retrieving revision 1.70
diff -u -p -r1.70 cpu.c
--- i386/i386/cpu.c 27 Dec 2015 04:31:34 -0000 1.70
+++ i386/i386/cpu.c 2 Feb 2016 16:54:09 -0000
@@ -784,7 +784,7 @@ cpu_init_mwait(struct device *dv)
{
unsigned int smallest, largest, extensions, c_substates;
- if ((cpu_ecxfeature & CPUIDECX_MWAIT) == 0)
+ if ((cpu_ecxfeature & CPUIDECX_MWAIT) == 0 || cpuid_level < 0x5)
return;
/* get the monitor granularity */
Index: amd64/amd64/amd64_mem.c
===================================================================
RCS file: /data/src/openbsd/src/sys/arch/amd64/amd64/amd64_mem.c,v
retrieving revision 1.11
diff -u -p -r1.11 amd64_mem.c
--- amd64/amd64/amd64_mem.c 14 Mar 2015 03:38:46 -0000 1.11
+++ amd64/amd64/amd64_mem.c 2 Feb 2016 17:37:55 -0000
@@ -583,8 +583,7 @@ mrinit(struct mem_range_softc *sc)
* If CPUID does not support leaf function 0x80000008, use the
* default a 36-bit address size.
*/
- CPUID(0x80000000, regs[0], regs[1], regs[2], regs[3]);
- if (regs[0] >= 0x80000008) {
+ if (curcpu()->ci_pnfeatset >= 0x80000008) {
CPUID(0x80000008, regs[0], regs[1], regs[2], regs[3]);
if (regs[0] & 0xff) {
mtrrmask = (1ULL << (regs[0] & 0xff)) - 1;
Index: amd64/amd64/cacheinfo.c
===================================================================
RCS file: /data/src/openbsd/src/sys/arch/amd64/amd64/cacheinfo.c,v
retrieving revision 1.7
diff -u -p -r1.7 cacheinfo.c
--- amd64/amd64/cacheinfo.c 13 Nov 2015 07:52:20 -0000 1.7
+++ amd64/amd64/cacheinfo.c 2 Feb 2016 17:36:11 -0000
@@ -159,7 +159,6 @@ amd_cpu_cacheinfo(struct cpu_info *ci)
struct x86_cache_info *cai;
int family, model;
u_int descs[4];
- u_int lfunc;
family = ci->ci_family;
model = ci->ci_model;
@@ -171,15 +170,9 @@ amd_cpu_cacheinfo(struct cpu_info *ci)
return;
/*
- * Determine the largest extended function value.
- */
- CPUID(0x80000000, descs[0], descs[1], descs[2], descs[3]);
- lfunc = descs[0];
-
- /*
* Determine L1 cache/TLB info.
*/
- if (lfunc < 0x80000005) {
+ if (ci->ci_pnfeatset < 0x80000005) {
/* No L1 cache info available. */
return;
}
@@ -228,7 +221,7 @@ amd_cpu_cacheinfo(struct cpu_info *ci)
/*
* Determine L2 cache/TLB info.
*/
- if (lfunc < 0x80000006) {
+ if (ci->ci_pnfeatset < 0x80000006) {
/* No L2 cache info available. */
return;
}
Index: amd64/amd64/cpu.c
===================================================================
RCS file: /data/src/openbsd/src/sys/arch/amd64/amd64/cpu.c,v
retrieving revision 1.94
diff -u -p -r1.94 cpu.c
--- amd64/amd64/cpu.c 27 Dec 2015 04:31:34 -0000 1.94
+++ amd64/amd64/cpu.c 2 Feb 2016 17:03:04 -0000
@@ -282,7 +282,7 @@ cpu_init_mwait(struct cpu_softc *sc)
{
unsigned int smallest, largest, extensions, c_substates;
- if ((cpu_ecxfeature & CPUIDECX_MWAIT) == 0)
+ if ((cpu_ecxfeature & CPUIDECX_MWAIT) == 0 || cpuid_level < 0x5)
return;
/* get the monitor granularity */
@@ -505,7 +505,7 @@ cpu_init(struct cpu_info *ci)
cr4 |= CR4_OSXSAVE;
lcr4(cr4);
- if (cpu_ecxfeature & CPUIDECX_XSAVE) {
+ if ((cpu_ecxfeature & CPUIDECX_XSAVE) && cpuid_level >= 0xd) {
u_int32_t eax, ebx, ecx, edx;
xsave_mask = XCR0_X87 | XCR0_SSE;
Index: amd64/amd64/identcpu.c
===================================================================
RCS file: /data/src/openbsd/src/sys/arch/amd64/amd64/identcpu.c,v
retrieving revision 1.71
diff -u -p -r1.71 identcpu.c
--- amd64/amd64/identcpu.c 27 Dec 2015 04:31:34 -0000 1.71
+++ amd64/amd64/identcpu.c 2 Feb 2016 17:35:36 -0000
@@ -700,8 +700,7 @@ cpu_topology(struct cpu_info *ci)
u_int32_t smt_mask = 0, core_mask, pkg_mask = 0;
/* We need at least apicid at CPUID 1 */
- CPUID(0, eax, ebx, ecx, edx);
- if (eax < 1)
+ if (cpuid_level < 1)
goto no_topology;
/* Initial apicid */
@@ -710,8 +709,7 @@ cpu_topology(struct cpu_info *ci)
if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
/* We need at least apicid at CPUID 0x80000008 */
- CPUID(0x80000000, eax, ebx, ecx, edx);
- if (eax < 0x80000008)
+ if (ci->ci_pnfeatset < 0x80000008)
goto no_topology;
CPUID(0x80000008, eax, ebx, ecx, edx);
@@ -727,8 +725,7 @@ cpu_topology(struct cpu_info *ci)
ci->ci_pkg_id >>= core_bits;
} else if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
/* We only support leaf 1/4 detection */
- CPUID(0, eax, ebx, ecx, edx);
- if (eax < 4)
+ if (cpuid_level < 4)
goto no_topology;
/* Get max_apicid */
CPUID(1, eax, ebx, ecx, edx);
@@ -858,7 +855,8 @@ cpu_check_vmm_cap(struct cpu_info *ci)
/*
* Check for SVM Nested Paging
*/
- if (ci->ci_vmm_flags & CI_VMM_SVM) {
+ if ((ci->ci_vmm_flags & CI_VMM_SVM) &&
+ ci->ci_pnfeatset >= CPUID_AMD_SVM_CAP) {
CPUID(CPUID_AMD_SVM_CAP, dummy, dummy, dummy, cap);
if (cap & AMD_SVM_NESTED_PAGING_CAP)
ci->ci_vmm_flags |= CI_VMM_RVI;