From: Prarit Bhargava <prarit@redhat.com> Date: Thu, 16 Sep 2010 15:13:59 -0400 Subject: [misc] x86: fix cpuid_level on Intel pre-model 13 cpus Message-id: <20100916151359.5672.71172.sendpatchset@prarit.bos.redhat.com> Patchwork-id: 28259 O-Subject: [RHEL5.6 BZ 606851 PATCH V3] x86_64, i386: Fix cpuid_level on Intel pre-model 13 processors Bugzilla: 606851 RH-Acked-by: Dean Nelson <dnelson@redhat.com> Backport linux-2.6 commit 99fb4d349db7e7dacb2099c5cc320a9e2d31c1ef We do not see a boot hang, but the incorrect setting of the cpuid_level has other ramifications for the processors. For example, the siblings, core id, cpu cores, and acpid values are not populated in /proc/cpuinfo. Successfully tested by me. Resolves BZ 606851. Signed-off-by: Jarod Wilson <jarod@redhat.com> diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 447afef..4435d9b 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -280,6 +280,22 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c) (int *)&c->x86_vendor_id[4]); get_cpu_vendor(c, 0); + + /* Unmask CPUID levels if masked: */ + if ((c->x86_vendor == X86_VENDOR_INTEL) && + (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd))) { + u64 misc_enable; + + rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable); + + if (misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) { + misc_enable &= + ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID; + wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable); + c->cpuid_level = cpuid_eax(0); + } + } + /* Initialize the standard set of capabilities */ /* Note that the vendor-specific code below might override */ diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index bf5f428..f4a441a 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -1174,6 +1174,20 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) get_cpu_vendor(c); + /* Unmask CPUID levels if masked: */ + if ((c->x86_vendor == X86_VENDOR_INTEL) && + (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd))) { + u64 misc_enable; + + rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable); + + if (misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) { + misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID; + wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable); + c->cpuid_level = cpuid_eax(0); + } + } + /* Initialize the standard set of capabilities */ /* Note that the vendor-specific code below might override */ diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h index 2b3e1d5..249b0c7 100644 --- a/include/asm-i386/msr.h +++ b/include/asm-i386/msr.h @@ -134,6 +134,8 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val) #define MSR_IA32_THERM_STATUS 0x19c #define MSR_IA32_MISC_ENABLE 0x1a0 +#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << 22) + #define MSR_IA32_TEMPERATURE_TARGET 0x1a2 #define MSR_IA32_DEBUGCTLMSR 0x1d9 diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h index 80964f5..cf716ff 100644 --- a/include/asm-x86_64/msr.h +++ b/include/asm-x86_64/msr.h @@ -337,6 +337,8 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) #define MSR_IA32_THERM_STATUS 0x19c #define MSR_IA32_MISC_ENABLE 0x1a0 +#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << 22) + #define MSR_IA32_TEMPERATURE_TARGET 0x1a2 #define MSR_IA32_DEBUGCTLMSR 0x1d9