Skip to contentSkip to conversation

New version of early CPU detect

PATCH In review Andi Kleen 2 participants 5 messages Apr 23, 2004 – Jun 21, 2004

lore
Share & tools
lore

Andi Kleen

author
#0 lore raw

PATCH 1/1 New version of early CPU detect

We still need some kind of early CPU detection, e.g. for the AMD768 workaround and for the slab allocator to size its slabs correctly for the cache line. Also some other code already had private early CPU routines.

This patch takes a new approach compared to the previous patch which caused Andrew so much grief. It only fills in a few selected fields in boot_cpu_data (only the data needed to identify the CPU type and the cache alignment). In particular the feature masks are not filled in, and the other fields are also not touched to prevent unwanted side effects.

Also convert the ppro workaround to use standard cpu data now.

Please consider applying to -mm.

I'm not sure if slab still has the necessary support to use the cache line size early; previously Manfred showed some serious memory saving with this for kernels that are compiled for a bigger cache line size than the CPU (is often the case on distribution kernels). This code could be reenable now with this patch.

-Andi

arch/i386/kernel/cpu/common.c renamed from arch/i386/kernel/cpu/common.c-o +44 -5
diff -u linux-2.6.5-i386/arch/i386/kernel/cpu/common.c-o linux-2.6.5-i386/arch/i386/kernel/cpu/common.c
@@ -137,8 +137,7 @@
 }
 
 
-
-void __init get_cpu_vendor(struct cpuinfo_x86 *c)
+void __init get_cpu_vendor(struct cpuinfo_x86 *c, int early)
 {
 	char *v = c->x86_vendor_id;
 	int i;
@@ -149,7 +148,8 @@
 			    (cpu_devs[i]->c_ident[1] && 
 			     !strcmp(v,cpu_devs[i]->c_ident[1]))) {
 				c->x86_vendor = i;
-				this_cpu = cpu_devs[i];
+				if (!early) 
+					this_cpu = cpu_devs[i];
 				break;
 			}
 		}
@@ -193,6 +193,44 @@
 	return flag_is_changeable_p(X86_EFLAGS_ID);
 }
 
+/* Do minimum CPU detection early. 
+   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
+   The others are not touched to avoid unwanted side effects. */
+void __init early_cpu_detect(void) 
+{ 
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+
+	if (!have_cpuid_p())
+		return;
+
+	/* Get vendor name */
+	cpuid(0x00000000, &c->cpuid_level,
+	      (int *)&c->x86_vendor_id[0],
+	      (int *)&c->x86_vendor_id[8],
+	      (int *)&c->x86_vendor_id[4]);
+	
+	get_cpu_vendor(c, 1);
+
+	c->x86 = 4;
+	c->x86_cache_alignment = 32;
+
+	if (c->cpuid_level >= 0x00000001) {
+		u32 junk, tfms, cap0, misc;
+		cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
+		c->x86 = (tfms >> 8) & 15;
+		c->x86_model = (tfms >> 4) & 15;
+		if (c->x86 == 0xf) {
+			c->x86 += (tfms >> 20) & 0xff;
+			c->x86_model += ((tfms >> 16) & 0xF) << 4;
+		} 
+		c->x86_mask = tfms & 15;
+		if (cap0 & (1<<19)) 
+			c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
+	}
+
+	early_intel_workaround(c); 
+} 
+
 void __init generic_identify(struct cpuinfo_x86 * c)
 {
 	u32 tfms, xlvl;
@@ -205,7 +243,7 @@
 		      (int *)&c->x86_vendor_id[8],
 		      (int *)&c->x86_vendor_id[4]);
 		
-		get_cpu_vendor(c);
+		get_cpu_vendor(c, 0);
 		/* Initialize the standard set of capabilities */
 		/* Note that the vendor-specific code below might override */
 	
@@ -383,7 +421,6 @@
  
 void __init dodgy_tsc(void)
 {
-	get_cpu_vendor(&boot_cpu_data);
 	if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) ||
 	    ( boot_cpu_data.x86_vendor == X86_VENDOR_NSC   ))
 		cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data);
@@ -431,9 +468,11 @@
 extern int rise_init_cpu(void);
 extern int nexgen_init_cpu(void);
 extern int umc_init_cpu(void);
+void early_cpu_detect(void);
 
 void __init early_cpu_init(void)
 {
+	early_cpu_detect();
 	intel_cpu_init();
 	cyrix_init_cpu();
 	nsc_init_cpu();
arch/i386/kernel/cpu/cpu.h renamed from arch/i386/kernel/cpu/cpu.h-o +3 -0
diff -u linux-2.6.5-i386/arch/i386/kernel/cpu/cpu.h-o linux-2.6.5-i386/arch/i386/kernel/cpu/cpu.h
@@ -26,3 +26,6 @@
 
 extern void generic_identify(struct cpuinfo_x86 * c);
 extern int have_cpuid_p(void);
+
+extern void early_intel_workaround(struct cpuinfo_x86 *c);
+
arch/i386/kernel/cpu/intel.c renamed from arch/i386/kernel/cpu/intel.c-o +14 -33

62 lines not on this page · raw message

#1 lore raw

2.6.7 shows K7 with Pentium Pro erratum [Re: New version of early CPU detect]

Quoted 1 line · Andi Kleen

We still need some kind of early CPU detection, e.g. for the AMD768 workaround

This is an old post with a patch which seems to be responsible for what I am seeing on an aging machine:

Quoted 4 lines
Quoted 4 lines

Pentium Pro with Errata#50 detected. Taking evasive action.
Memory: 255808k/262144k available (2445k kernel code, 5600k reserved, 667k data, 148k init, 0k highmem) Checking if this processor honours the WP bit even in supervisor mode... Ok. Calibrating delay loop... 1077.24 BogoMIPS

...

Quoted 8 lines
Quoted 8 lines
CPU:     After generic identify, caps: 0081f9ff c0c1f9ff 00000000 00000000
CPU:     After vendor identify, caps: 0081f9ff c0c1f9ff 00000000 00000000
CPU: L1 I Cache: 64K (64 bytes/line), D cache 64K (64 bytes/line)
CPU: L2 Cache: 512K (64 bytes/line)
CPU:     After all inits, caps: 0081f9ff c0c1f9ff 00000000 00000020

Intel machine check architecture supported.
Intel machine check reporting enabled on CPU#0.
CPU: AMD-K7(tm) Processor stepping 02

So, it's a K7-550 with a Pentium Pro erratum... I'm not quite sure it's right :)

As it is, the family/model numbers seems to match, but it's obviously an AMD product..

processor : 0
vendor_id : AuthenticAMD
cpu family : 6
model : 1
model name : AMD-K7(tm) Processor
stepping : 2
cpu MHz : 551.261
cache size : 512 KB
...
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 sep mtrr pge mca cmov pat mmx syscall mmxext 3dnowext 3dnow
bogomips : 1077.24

The parts of the patch to point to this misdetection:

Quoted 1 line

+++ linux-2.6.5-i386/arch/i386/kernel/cpu/common.c 2004-04-21 17:05:06.000000000 +0200

...

Quoted 7 lines

void __init early_cpu_init(void)
{

arch/i386/kernel/cpu/common.c renamed from arch/i386/kernel/cpu/common.c-o +2 -0
+	early_cpu_detect();
 	intel_cpu_init();
 	cyrix_init_cpu();
 
+++ linux-2.6.5-i386/arch/i386/kernel/cpu/intel.c	2004-04-21 17:06:00.000000000 +0200

...

Quoted 7 lines
arch/i386/kernel/cpu/intel.c renamed from arch/i386/kernel/cpu/intel.c-o +5 -0
+	/* Uses data from early_cpu_detect now */
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+	    boot_cpu_data.x86 == 6 &&
+	    boot_cpu_data.x86_model == 1 && 
+	    boot_cpu_data.x86_mask < 8) { 
 		printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n");
 		return 1;
Signature · 1 line
Janos | romfs is at http://romfs.sourceforge.net/ | Don't talk about silence.
author
#2 lore raw

Re: 2.6.7 shows K7 with Pentium Pro erratum [Re: New version of early CPU detect]

Quoted 3 lines · On Mon, 21 Jun 2004 14:04:16 +0200 Janos Farkas…

As it is, the family/model numbers seems to match, but it's obviously an AMD product..

Does this patch fix the problem?

-Andi

arch/i386/kernel/cpu/common.c renamed from arch/i386/kernel/cpu/common.c-o +2 -1
diff -u linux-2.6.7-work/arch/i386/kernel/cpu/common.c-o linux-2.6.7-work/arch/i386/kernel/cpu/common.c
@@ -143,8 +143,9 @@
 	char *v = c->x86_vendor_id;
 	int i;
 
+	c->x86_vendor = X86_VENDOR_UNKNOWN;
 	for (i = 0; i < X86_VENDOR_NUM; i++) {
-		if (cpu_devs[i]) {
+		if (cpu_devs[i] || early) {
 			if (!strcmp(v,cpu_devs[i]->c_ident[0]) ||
 			    (cpu_devs[i]->c_ident[1] && 
 			     !strcmp(v,cpu_devs[i]->c_ident[1]))) {
author
#3 lore raw

Re: 2.6.7 shows K7 with Pentium Pro erratum [Re: New version of early CPU detect] II

In reply to Janos Farkas

On Mon, 21 Jun 2004 14:04:16 +0200
Janos Farkas <[email protected]> wrote:
[...]

Please ignore the previous patch I sent. This patch should actually fix it.

arch/i386/kernel/cpu/common.c renamed from arch/i386/kernel/cpu/common.c-o +1 -1
diff -u linux-2.6.7-work/arch/i386/kernel/cpu/common.c-o linux-2.6.7-work/arch/i386/kernel/cpu/common.c
@@ -473,7 +473,6 @@
 
 void __init early_cpu_init(void)
 {
-	early_cpu_detect();
 	intel_cpu_init();
 	cyrix_init_cpu();
 	nsc_init_cpu();
@@ -483,6 +482,7 @@
 	rise_init_cpu();
 	nexgen_init_cpu();
 	umc_init_cpu();
+	early_cpu_detect();
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
 	/* pse is not compatible with on-the-fly unmapping,
#4 lore raw

Re: 2.6.7 shows K7 with Pentium Pro erratum [Re: New version of early CPU detect] II

Quoted 3 lines · Andi Kleen

Please ignore the previous patch I sent. This patch should actually fix it.

+++ linux-2.6.7-work/arch/i386/kernel/cpu/common.c 2004-06-21 17:30:57.000000000 +0200

...

arch/i386/kernel/cpu/common.c line 485

Quoted 5 lines
arch/i386/kernel/cpu/common.c renamed from arch/i386/kernel/cpu/common.c-o +1 -0
@@ -483,6 +482,7 @@
 	rise_init_cpu();
 	nexgen_init_cpu();
 	umc_init_cpu();
+	early_cpu_detect();

Yup, it does! Thanks!

Signature · 1 line
Janos | romfs is at http://romfs.sourceforge.net/ | Don't talk about silence.