summaryrefslogtreecommitdiffstats
path: root/sys/x86
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2016-04-12 13:30:39 +0000
committeravg <avg@FreeBSD.org>2016-04-12 13:30:39 +0000
commitf7d20d373434d068dcb6a6c509c1658cf683c026 (patch)
treead17502d1ace83c7947422a7127a812817e2b2a0 /sys/x86
parent3478256ec241901437844ce52380f29a9bed6beb (diff)
downloadFreeBSD-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.h1
-rw-r--r--sys/x86/include/x86_var.h2
-rw-r--r--sys/x86/x86/identcpu.c39
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];
}
OpenPOWER on IntegriCloud