Index: sys/amd64/amd64/mp_machdep.c =================================================================== --- sys/amd64/amd64/mp_machdep.c +++ sys/amd64/amd64/mp_machdep.c @@ -247,7 +247,7 @@ wrmsr(MSR_FSBASE, 0); /* User value */ wrmsr(MSR_GSBASE, (u_int64_t)pc); wrmsr(MSR_KGSBASE, (u_int64_t)pc); /* XXX User value while we're in the kernel */ - intel_fix_cpuid(); + fix_cpuid(); lidt(&r_idt); Index: sys/i386/i386/mp_machdep.c =================================================================== --- sys/i386/i386/mp_machdep.c +++ sys/i386/i386/mp_machdep.c @@ -242,7 +242,7 @@ pc->pc_prvspace = pc; pc->pc_curthread = 0; - intel_fix_cpuid(); + fix_cpuid(); gdt_segs[GPRIV_SEL].ssd_base = (int) pc; gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss; Index: sys/x86/include/specialreg.h =================================================================== --- sys/x86/include/specialreg.h +++ sys/x86/include/specialreg.h @@ -816,6 +816,7 @@ #define MSR_P_STATE_CONFIG(n) (0xc0010064 + (n)) /* P-state Config */ #define MSR_SMM_ADDR 0xc0010112 /* SMM TSEG base address */ #define MSR_SMM_MASK 0xc0010113 /* SMM TSEG address mask */ +#define MSR_EXTFEATURES 0xc0011005 /* Extended CPUID Features override */ #define MSR_IC_CFG 0xc0011021 /* Instruction Cache Configuration */ #define MSR_K8_UCODE_UPDATE 0xc0010020 /* update microcode */ #define MSR_MC0_CTL_MASK 0xc0010044 Index: sys/x86/include/x86_var.h =================================================================== --- sys/x86/include/x86_var.h +++ sys/x86/include/x86_var.h @@ -103,7 +103,7 @@ void identify_cpu(void); void initializecpu(void); void initializecpucache(void); -bool intel_fix_cpuid(void); +bool fix_cpuid(void); void fillw(int /*u_short*/ pat, void *base, size_t cnt); int is_physical_memory(vm_paddr_t addr); int isa_nmi(int cd); Index: sys/x86/x86/identcpu.c =================================================================== --- sys/x86/x86/identcpu.c +++ sys/x86/x86/identcpu.c @@ -1342,23 +1342,22 @@ } } -/* - * Clear "Limit CPUID Maxval" bit and return true if the caller should - * get the largest standard CPUID function number again if it is set - * from BIOS. It is necessary for probing correct CPU topology later - * and for the correct operation of the AVX-aware userspace. - */ bool -intel_fix_cpuid(void) +fix_cpuid(void) { uint64_t msr; - if (cpu_vendor_id != CPU_VENDOR_INTEL) - return (false); - if ((CPUID_TO_FAMILY(cpu_id) == 0xf && + /* + * Clear "Limit CPUID Maxval" bit and return true if the caller should + * get the largest standard CPUID function number again if it is set + * from BIOS. It is necessary for probing correct CPU topology later + * and for the correct operation of the AVX-aware userspace. + */ + if (cpu_vendor_id == CPU_VENDOR_INTEL && + ((CPUID_TO_FAMILY(cpu_id) == 0xf && CPUID_TO_MODEL(cpu_id) >= 0x3) || (CPUID_TO_FAMILY(cpu_id) == 0x6 && - CPUID_TO_MODEL(cpu_id) >= 0xe)) { + CPUID_TO_MODEL(cpu_id) >= 0xe))) { msr = rdmsr(MSR_IA32_MISC_ENABLE); if ((msr & IA32_MISC_EN_LIMCPUID) != 0) { msr &= ~IA32_MISC_EN_LIMCPUID; @@ -1366,6 +1365,22 @@ return (true); } } + + /* + * Re-enable AMD Topology Extension that could be disabled by BIOS + * on some notebook processors. Without the extension it's really + * hard to determine the correct CPU cache topology. + * See BIOS and Kernel Developer’s Guide (BKDG) for AMD Family 15h + * Models 60h-6Fh Processors, Publication # 50742. + */ + if (cpu_vendor_id == CPU_VENDOR_AMD && CPUID_TO_FAMILY(cpu_id) == 0x15) { + msr = rdmsr(MSR_EXTFEATURES); + if ((msr & ((uint64_t)1 << 54)) == 0) { + msr |= (uint64_t)1 << 54; + wrmsr(MSR_EXTFEATURES, msr); + return (true); + } + } return (false); } @@ -1403,7 +1418,7 @@ identify_hypervisor(); cpu_vendor_id = find_cpu_vendor_id(); - if (intel_fix_cpuid()) { + if (fix_cpuid()) { do_cpuid(0, regs); cpu_high = regs[0]; }