> Date: Tue, 2 Feb 2016 09:43:54 -0800
> From: Philip Guenther <[email protected]>
>
> 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?
ok kettenis@
> 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;
>
>