diff options
author | kib <kib@FreeBSD.org> | 2015-08-17 18:33:16 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2015-08-17 18:33:16 +0000 |
commit | 70c41a2cb18dc2517295e70fd25b8fe5cbadcd4c (patch) | |
tree | 847cc97358e20533e88fe4b2bcc2227de12541ba /sys/x86 | |
parent | f69a7374f02c3d824c60751d6975726b9fb789c1 (diff) | |
download | FreeBSD-src-70c41a2cb18dc2517295e70fd25b8fe5cbadcd4c.zip FreeBSD-src-70c41a2cb18dc2517295e70fd25b8fe5cbadcd4c.tar.gz |
MFC r286228:
Clear the IA32_MISC_ENABLE MSR bit on APs.
Diffstat (limited to 'sys/x86')
-rw-r--r-- | sys/x86/x86/identcpu.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/sys/x86/x86/identcpu.c b/sys/x86/x86/identcpu.c index f61035c..8e5f5c3 100644 --- a/sys/x86/x86/identcpu.c +++ b/sys/x86/x86/identcpu.c @@ -1297,6 +1297,33 @@ 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) +{ + uint64_t msr; + + if (cpu_vendor_id != CPU_VENDOR_INTEL) + return (false); + if ((CPUID_TO_FAMILY(cpu_id) == 0xf && + CPUID_TO_MODEL(cpu_id) >= 0x3) || + (CPUID_TO_FAMILY(cpu_id) == 0x6 && + CPUID_TO_MODEL(cpu_id) >= 0xe)) { + msr = rdmsr(MSR_IA32_MISC_ENABLE); + if ((msr & IA32_MISC_EN_LIMCPUID) != 0) { + msr &= ~IA32_MISC_EN_LIMCPUID; + wrmsr(MSR_IA32_MISC_ENABLE, msr); + return (true); + } + } + return (false); +} + +/* * Final stage of CPU identification. */ #ifdef __i386__ @@ -1332,22 +1359,9 @@ identify_cpu(void) #endif cpu_vendor_id = find_cpu_vendor_id(); - /* - * Clear "Limit CPUID Maxval" bit and get the largest standard CPUID - * function number again if it is set from BIOS. It is necessary - * for probing correct CPU topology later. - * XXX This is only done on the BSP package. - */ - if (cpu_vendor_id == CPU_VENDOR_INTEL && cpu_high > 0 && cpu_high < 4 && - ((CPUID_TO_FAMILY(cpu_id) == 0xf && CPUID_TO_MODEL(cpu_id) >= 0x3) || - (CPUID_TO_FAMILY(cpu_id) == 0x6 && CPUID_TO_MODEL(cpu_id) >= 0xe))) { - uint64_t msr; - msr = rdmsr(MSR_IA32_MISC_ENABLE); - if ((msr & 0x400000ULL) != 0) { - wrmsr(MSR_IA32_MISC_ENABLE, msr & ~0x400000ULL); - do_cpuid(0, regs); - cpu_high = regs[0]; - } + if (intel_fix_cpuid()) { + do_cpuid(0, regs); + cpu_high = regs[0]; } if (cpu_high >= 5 && (cpu_feature2 & CPUID2_MON) != 0) { |