aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/cpu
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-28 14:06:39 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-28 14:06:39 -0400
commitf28e71617ddaf2483e3e5c5237103484a303743f (patch)
tree67627d2d8ddbf6a4449371e9261d796c013b1fa1 /arch/i386/kernel/cpu
parentdc6a78f1af10d28fb8c395034ae1e099b85c05b0 (diff)
parenta39727f212426b9d5f9267b3318a2afaf9922d3b (diff)
Merge ../linux-2.6/
Conflicts: drivers/scsi/aacraid/comminit.c Fixed up by removing the now renamed CONFIG_IOMMU option from aacraid Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'arch/i386/kernel/cpu')
-rw-r--r--arch/i386/kernel/cpu/amd.c22
-rw-r--r--arch/i386/kernel/cpu/common.c25
-rw-r--r--arch/i386/kernel/cpu/cyrix.c2
-rw-r--r--arch/i386/kernel/cpu/intel.c6
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c123
-rw-r--r--arch/i386/kernel/cpu/proc.c8
6 files changed, 144 insertions, 42 deletions
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 786d1a57048b..e6a2d6b80cda 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -224,22 +224,26 @@ static void __init init_amd(struct cpuinfo_x86 *c)
224 224
225#ifdef CONFIG_X86_HT 225#ifdef CONFIG_X86_HT
226 /* 226 /*
227 * On a AMD dual core setup the lower bits of the APIC id 227 * On a AMD multi core setup the lower bits of the APIC id
228 * distingush the cores. Assumes number of cores is a power 228 * distingush the cores.
229 * of two.
230 */ 229 */
231 if (c->x86_max_cores > 1) { 230 if (c->x86_max_cores > 1) {
232 int cpu = smp_processor_id(); 231 int cpu = smp_processor_id();
233 unsigned bits = 0; 232 unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf;
234 while ((1 << bits) < c->x86_max_cores) 233
235 bits++; 234 if (bits == 0) {
236 cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1); 235 while ((1 << bits) < c->x86_max_cores)
237 phys_proc_id[cpu] >>= bits; 236 bits++;
237 }
238 c->cpu_core_id = c->phys_proc_id & ((1<<bits)-1);
239 c->phys_proc_id >>= bits;
238 printk(KERN_INFO "CPU %d(%d) -> Core %d\n", 240 printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
239 cpu, c->x86_max_cores, cpu_core_id[cpu]); 241 cpu, c->x86_max_cores, c->cpu_core_id);
240 } 242 }
241#endif 243#endif
242 244
245 if (cpuid_eax(0x80000000) >= 0x80000006)
246 num_cache_leaves = 3;
243} 247}
244 248
245static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) 249static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 44f2c5f2dda1..70c87de582c7 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -294,7 +294,7 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
294 if (c->x86 >= 0x6) 294 if (c->x86 >= 0x6)
295 c->x86_model += ((tfms >> 16) & 0xF) << 4; 295 c->x86_model += ((tfms >> 16) & 0xF) << 4;
296 c->x86_mask = tfms & 15; 296 c->x86_mask = tfms & 15;
297#ifdef CONFIG_SMP 297#ifdef CONFIG_X86_HT
298 c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0); 298 c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
299#else 299#else
300 c->apicid = (ebx >> 24) & 0xFF; 300 c->apicid = (ebx >> 24) & 0xFF;
@@ -319,7 +319,7 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
319 early_intel_workaround(c); 319 early_intel_workaround(c);
320 320
321#ifdef CONFIG_X86_HT 321#ifdef CONFIG_X86_HT
322 phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; 322 c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
323#endif 323#endif
324} 324}
325 325
@@ -477,11 +477,9 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
477{ 477{
478 u32 eax, ebx, ecx, edx; 478 u32 eax, ebx, ecx, edx;
479 int index_msb, core_bits; 479 int index_msb, core_bits;
480 int cpu = smp_processor_id();
481 480
482 cpuid(1, &eax, &ebx, &ecx, &edx); 481 cpuid(1, &eax, &ebx, &ecx, &edx);
483 482
484
485 if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) 483 if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
486 return; 484 return;
487 485
@@ -492,16 +490,17 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
492 } else if (smp_num_siblings > 1 ) { 490 } else if (smp_num_siblings > 1 ) {
493 491
494 if (smp_num_siblings > NR_CPUS) { 492 if (smp_num_siblings > NR_CPUS) {
495 printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); 493 printk(KERN_WARNING "CPU: Unsupported number of the "
494 "siblings %d", smp_num_siblings);
496 smp_num_siblings = 1; 495 smp_num_siblings = 1;
497 return; 496 return;
498 } 497 }
499 498
500 index_msb = get_count_order(smp_num_siblings); 499 index_msb = get_count_order(smp_num_siblings);
501 phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); 500 c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
502 501
503 printk(KERN_INFO "CPU: Physical Processor ID: %d\n", 502 printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
504 phys_proc_id[cpu]); 503 c->phys_proc_id);
505 504
506 smp_num_siblings = smp_num_siblings / c->x86_max_cores; 505 smp_num_siblings = smp_num_siblings / c->x86_max_cores;
507 506
@@ -509,12 +508,12 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
509 508
510 core_bits = get_count_order(c->x86_max_cores); 509 core_bits = get_count_order(c->x86_max_cores);
511 510
512 cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) & 511 c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
513 ((1 << core_bits) - 1); 512 ((1 << core_bits) - 1);
514 513
515 if (c->x86_max_cores > 1) 514 if (c->x86_max_cores > 1)
516 printk(KERN_INFO "CPU: Processor Core ID: %d\n", 515 printk(KERN_INFO "CPU: Processor Core ID: %d\n",
517 cpu_core_id[cpu]); 516 c->cpu_core_id);
518 } 517 }
519} 518}
520#endif 519#endif
@@ -613,6 +612,12 @@ void __cpuinit cpu_init(void)
613 set_in_cr4(X86_CR4_TSD); 612 set_in_cr4(X86_CR4_TSD);
614 } 613 }
615 614
615 /* The CPU hotplug case */
616 if (cpu_gdt_descr->address) {
617 gdt = (struct desc_struct *)cpu_gdt_descr->address;
618 memset(gdt, 0, PAGE_SIZE);
619 goto old_gdt;
620 }
616 /* 621 /*
617 * This is a horrible hack to allocate the GDT. The problem 622 * This is a horrible hack to allocate the GDT. The problem
618 * is that cpu_init() is called really early for the boot CPU 623 * is that cpu_init() is called really early for the boot CPU
@@ -631,7 +636,7 @@ void __cpuinit cpu_init(void)
631 local_irq_enable(); 636 local_irq_enable();
632 } 637 }
633 } 638 }
634 639old_gdt:
635 /* 640 /*
636 * Initialize the per-CPU GDT with the boot GDT, 641 * Initialize the per-CPU GDT with the boot GDT,
637 * and set up the GDT descriptor: 642 * and set up the GDT descriptor:
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index fc32c8028e24..f03b7f94c304 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -354,7 +354,7 @@ static void __init init_nsc(struct cpuinfo_x86 *c)
354 * This function only handles the GX processor, and kicks every 354 * This function only handles the GX processor, and kicks every
355 * thing else to the Cyrix init function above - that should 355 * thing else to the Cyrix init function above - that should
356 * cover any processors that might have been branded differently 356 * cover any processors that might have been branded differently
357 * after NSC aquired Cyrix. 357 * after NSC acquired Cyrix.
358 * 358 *
359 * If this breaks your GX1 horribly, please e-mail 359 * If this breaks your GX1 horribly, please e-mail
360 * info-linux@ldcmail.amd.com to tell us. 360 * info-linux@ldcmail.amd.com to tell us.
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index 5386b29bb5a5..10afc645c540 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -122,6 +122,12 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
122 122
123 select_idle_routine(c); 123 select_idle_routine(c);
124 l2 = init_intel_cacheinfo(c); 124 l2 = init_intel_cacheinfo(c);
125 if (c->cpuid_level > 9 ) {
126 unsigned eax = cpuid_eax(10);
127 /* Check for version and the number of counters */
128 if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
129 set_bit(X86_FEATURE_ARCH_PERFMON, c->x86_capability);
130 }
125 131
126 /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */ 132 /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
127 if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) 133 if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index c8547a6fa7e6..e9f0b928b0a9 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -4,6 +4,7 @@
4 * Changes: 4 * Changes:
5 * Venkatesh Pallipadi : Adding cache identification through cpuid(4) 5 * Venkatesh Pallipadi : Adding cache identification through cpuid(4)
6 * Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure. 6 * Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
7 * Andi Kleen : CPUID4 emulation on AMD.
7 */ 8 */
8 9
9#include <linux/init.h> 10#include <linux/init.h>
@@ -130,25 +131,111 @@ struct _cpuid4_info {
130 cpumask_t shared_cpu_map; 131 cpumask_t shared_cpu_map;
131}; 132};
132 133
133static unsigned short num_cache_leaves; 134unsigned short num_cache_leaves;
135
136/* AMD doesn't have CPUID4. Emulate it here to report the same
137 information to the user. This makes some assumptions about the machine:
138 No L3, L2 not shared, no SMT etc. that is currently true on AMD CPUs.
139
140 In theory the TLBs could be reported as fake type (they are in "dummy").
141 Maybe later */
142union l1_cache {
143 struct {
144 unsigned line_size : 8;
145 unsigned lines_per_tag : 8;
146 unsigned assoc : 8;
147 unsigned size_in_kb : 8;
148 };
149 unsigned val;
150};
151
152union l2_cache {
153 struct {
154 unsigned line_size : 8;
155 unsigned lines_per_tag : 4;
156 unsigned assoc : 4;
157 unsigned size_in_kb : 16;
158 };
159 unsigned val;
160};
161
162static const unsigned short assocs[] = {
163 [1] = 1, [2] = 2, [4] = 4, [6] = 8,
164 [8] = 16,
165 [0xf] = 0xffff // ??
166 };
167static const unsigned char levels[] = { 1, 1, 2 };
168static const unsigned char types[] = { 1, 2, 3 };
169
170static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
171 union _cpuid4_leaf_ebx *ebx,
172 union _cpuid4_leaf_ecx *ecx)
173{
174 unsigned dummy;
175 unsigned line_size, lines_per_tag, assoc, size_in_kb;
176 union l1_cache l1i, l1d;
177 union l2_cache l2;
178
179 eax->full = 0;
180 ebx->full = 0;
181 ecx->full = 0;
182
183 cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val);
184 cpuid(0x80000006, &dummy, &dummy, &l2.val, &dummy);
185
186 if (leaf > 2 || !l1d.val || !l1i.val || !l2.val)
187 return;
188
189 eax->split.is_self_initializing = 1;
190 eax->split.type = types[leaf];
191 eax->split.level = levels[leaf];
192 eax->split.num_threads_sharing = 0;
193 eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1;
194
195 if (leaf <= 1) {
196 union l1_cache *l1 = leaf == 0 ? &l1d : &l1i;
197 assoc = l1->assoc;
198 line_size = l1->line_size;
199 lines_per_tag = l1->lines_per_tag;
200 size_in_kb = l1->size_in_kb;
201 } else {
202 assoc = l2.assoc;
203 line_size = l2.line_size;
204 lines_per_tag = l2.lines_per_tag;
205 /* cpu_data has errata corrections for K7 applied */
206 size_in_kb = current_cpu_data.x86_cache_size;
207 }
208
209 if (assoc == 0xf)
210 eax->split.is_fully_associative = 1;
211 ebx->split.coherency_line_size = line_size - 1;
212 ebx->split.ways_of_associativity = assocs[assoc] - 1;
213 ebx->split.physical_line_partition = lines_per_tag - 1;
214 ecx->split.number_of_sets = (size_in_kb * 1024) / line_size /
215 (ebx->split.ways_of_associativity + 1) - 1;
216}
134 217
135static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) 218static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
136{ 219{
137 unsigned int eax, ebx, ecx, edx; 220 union _cpuid4_leaf_eax eax;
138 union _cpuid4_leaf_eax cache_eax; 221 union _cpuid4_leaf_ebx ebx;
222 union _cpuid4_leaf_ecx ecx;
223 unsigned edx;
139 224
140 cpuid_count(4, index, &eax, &ebx, &ecx, &edx); 225 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
141 cache_eax.full = eax; 226 amd_cpuid4(index, &eax, &ebx, &ecx);
142 if (cache_eax.split.type == CACHE_TYPE_NULL) 227 else
228 cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
229 if (eax.split.type == CACHE_TYPE_NULL)
143 return -EIO; /* better error ? */ 230 return -EIO; /* better error ? */
144 231
145 this_leaf->eax.full = eax; 232 this_leaf->eax = eax;
146 this_leaf->ebx.full = ebx; 233 this_leaf->ebx = ebx;
147 this_leaf->ecx.full = ecx; 234 this_leaf->ecx = ecx;
148 this_leaf->size = (this_leaf->ecx.split.number_of_sets + 1) * 235 this_leaf->size = (ecx.split.number_of_sets + 1) *
149 (this_leaf->ebx.split.coherency_line_size + 1) * 236 (ebx.split.coherency_line_size + 1) *
150 (this_leaf->ebx.split.physical_line_partition + 1) * 237 (ebx.split.physical_line_partition + 1) *
151 (this_leaf->ebx.split.ways_of_associativity + 1); 238 (ebx.split.ways_of_associativity + 1);
152 return 0; 239 return 0;
153} 240}
154 241
@@ -174,7 +261,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
174 unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */ 261 unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
175 unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */ 262 unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
176 unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb; 263 unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
177#ifdef CONFIG_SMP 264#ifdef CONFIG_X86_HT
178 unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data); 265 unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data);
179#endif 266#endif
180 267
@@ -296,14 +383,14 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
296 383
297 if (new_l2) { 384 if (new_l2) {
298 l2 = new_l2; 385 l2 = new_l2;
299#ifdef CONFIG_SMP 386#ifdef CONFIG_X86_HT
300 cpu_llc_id[cpu] = l2_id; 387 cpu_llc_id[cpu] = l2_id;
301#endif 388#endif
302 } 389 }
303 390
304 if (new_l3) { 391 if (new_l3) {
305 l3 = new_l3; 392 l3 = new_l3;
306#ifdef CONFIG_SMP 393#ifdef CONFIG_X86_HT
307 cpu_llc_id[cpu] = l3_id; 394 cpu_llc_id[cpu] = l3_id;
308#endif 395#endif
309 } 396 }
@@ -642,7 +729,7 @@ static void __cpuexit cache_remove_dev(struct sys_device * sys_dev)
642 return; 729 return;
643} 730}
644 731
645static int cacheinfo_cpu_callback(struct notifier_block *nfb, 732static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
646 unsigned long action, void *hcpu) 733 unsigned long action, void *hcpu)
647{ 734{
648 unsigned int cpu = (unsigned long)hcpu; 735 unsigned int cpu = (unsigned long)hcpu;
@@ -660,7 +747,7 @@ static int cacheinfo_cpu_callback(struct notifier_block *nfb,
660 return NOTIFY_OK; 747 return NOTIFY_OK;
661} 748}
662 749
663static struct notifier_block cacheinfo_cpu_notifier = 750static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier =
664{ 751{
665 .notifier_call = cacheinfo_cpu_callback, 752 .notifier_call = cacheinfo_cpu_callback,
666}; 753};
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index a19fcb262dbb..f54a15268ed7 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -18,7 +18,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
18 * applications want to get the raw CPUID data, they should access 18 * applications want to get the raw CPUID data, they should access
19 * /dev/cpu/<cpu_nr>/cpuid instead. 19 * /dev/cpu/<cpu_nr>/cpuid instead.
20 */ 20 */
21 static char *x86_cap_flags[] = { 21 static const char * const x86_cap_flags[] = {
22 /* Intel-defined */ 22 /* Intel-defined */
23 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", 23 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
24 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", 24 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
@@ -62,7 +62,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
62 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 62 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
63 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 63 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
64 }; 64 };
65 static char *x86_power_flags[] = { 65 static const char * const x86_power_flags[] = {
66 "ts", /* temperature sensor */ 66 "ts", /* temperature sensor */
67 "fid", /* frequency id control */ 67 "fid", /* frequency id control */
68 "vid", /* voltage id control */ 68 "vid", /* voltage id control */
@@ -109,9 +109,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
109 seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); 109 seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
110#ifdef CONFIG_X86_HT 110#ifdef CONFIG_X86_HT
111 if (c->x86_max_cores * smp_num_siblings > 1) { 111 if (c->x86_max_cores * smp_num_siblings > 1) {
112 seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); 112 seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
113 seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n])); 113 seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n]));
114 seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]); 114 seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
115 seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); 115 seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
116 } 116 }
117#endif 117#endif