Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2150

kernel-2.6.18-238.el5.src.rpm

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