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;

Reply via email to