diff options
author | avg <avg@FreeBSD.org> | 2016-04-12 13:30:39 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2016-04-12 13:30:39 +0000 |
commit | f7d20d373434d068dcb6a6c509c1658cf683c026 (patch) | |
tree | ad17502d1ace83c7947422a7127a812817e2b2a0 /sys/x86 | |
parent | 3478256ec241901437844ce52380f29a9bed6beb (diff) | |
download | FreeBSD-src-f7d20d373434d068dcb6a6c509c1658cf683c026.zip FreeBSD-src-f7d20d373434d068dcb6a6c509c1658cf683c026.tar.gz |
re-enable AMD Topology extension on certain models if disabled by BIOS
Some BIOSes disable AMD Topology extension on AMD Family 15h notebook
processors. We re-enable the extension, so that we can properly discover
core and cache topology. Linux seems to do the same.
Reported by: Johannes Dieterich <dieterich.joh@gmail.com>
Reviewed by: jhb, kib
Tested by: Johannes Dieterich <dieterich.joh@gmail.com>
(earlier version)
MFC after: 3 weeks
Differential Revision: https://reviews.freebsd.org/D5883
Diffstat (limited to 'sys/x86')
-rw-r--r-- | sys/x86/include/specialreg.h | 1 | ||||
-rw-r--r-- | sys/x86/include/x86_var.h | 2 | ||||
-rw-r--r-- | sys/x86/x86/identcpu.c | 39 |
3 files changed, 29 insertions, 13 deletions
diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h index c2d2c59..5f71b2d 100644 --- a/sys/x86/include/specialreg.h +++ b/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 diff --git a/sys/x86/include/x86_var.h b/sys/x86/include/x86_var.h index 46ce1a0..07e9d80 100644 --- a/sys/x86/include/x86_var.h +++ b/sys/x86/include/x86_var.h @@ -103,7 +103,7 @@ void dump_drop_page(vm_paddr_t); 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); diff --git a/sys/x86/x86/identcpu.c b/sys/x86/x86/identcpu.c index bc232a2..41ba36a 100644 --- a/sys/x86/x86/identcpu.c +++ b/sys/x86/x86/identcpu.c @@ -1342,23 +1342,22 @@ identify_hypervisor(void) } } -/* - * 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 @@ intel_fix_cpuid(void) 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_cpu(void) identify_hypervisor(); cpu_vendor_id = find_cpu_vendor_id(); - if (intel_fix_cpuid()) { + if (fix_cpuid()) { do_cpuid(0, regs); cpu_high = regs[0]; } |