diff options
author | avg <avg@FreeBSD.org> | 2016-05-04 11:53:30 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2016-05-04 11:53:30 +0000 |
commit | ecc2c61c9002a9159aba3f4c8215b793d08b91a4 (patch) | |
tree | 3a57b68dbab06b46f754d58ca510091a3c71685c /sys | |
parent | 246db7e3b0b035080c9ec0255d09e867658de98f (diff) | |
download | FreeBSD-src-ecc2c61c9002a9159aba3f4c8215b793d08b91a4.zip FreeBSD-src-ecc2c61c9002a9159aba3f4c8215b793d08b91a4.tar.gz |
MFC r297857: re-enable AMD Topology extension on certain models if
disabled by BIOS
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/amd64/mp_machdep.c | 2 | ||||
-rw-r--r-- | sys/amd64/include/md_var.h | 2 | ||||
-rw-r--r-- | sys/i386/i386/mp_machdep.c | 2 | ||||
-rw-r--r-- | sys/i386/include/md_var.h | 2 | ||||
-rw-r--r-- | sys/x86/include/specialreg.h | 1 | ||||
-rw-r--r-- | sys/x86/x86/identcpu.c | 39 |
6 files changed, 32 insertions, 16 deletions
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 43bb023..c18042b 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -682,7 +682,7 @@ init_secondary(void) 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); diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index cc95db1..36a6d7f 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -112,7 +112,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); void fpstate_drop(struct thread *td); int is_physical_memory(vm_paddr_t addr); diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index 7b27265..8b5be80 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -684,7 +684,7 @@ init_secondary(void) 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; diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index 892b30a..76254c2 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -116,7 +116,7 @@ void fillw(int /*u_short*/ pat, void *base, size_t cnt); void fill_based_sd(struct segment_descriptor *sdp, uint32_t base); void initializecpu(void); void initializecpucache(void); -bool intel_fix_cpuid(void); +bool fix_cpuid(void); void i686_pagezero(void *addr); void sse2_pagezero(void *addr); void init_AMD_Elan_sc520(void); diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h index 3846efc..3e04273 100644 --- a/sys/x86/include/specialreg.h +++ b/sys/x86/include/specialreg.h @@ -821,6 +821,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/x86/identcpu.c b/sys/x86/x86/identcpu.c index 69a978f..b6c7f95 100644 --- a/sys/x86/x86/identcpu.c +++ b/sys/x86/x86/identcpu.c @@ -1304,23 +1304,22 @@ identify_hypervisor(void) } #endif -/* - * 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; @@ -1328,6 +1327,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); } @@ -1367,7 +1382,7 @@ identify_cpu(void) #endif cpu_vendor_id = find_cpu_vendor_id(); - if (intel_fix_cpuid()) { + if (fix_cpuid()) { do_cpuid(0, regs); cpu_high = regs[0]; } |