diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-09-14 11:26:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-14 11:26:53 -0400 |
commit | f81b691a3df09806385ea413c3a2ee094c705ca3 (patch) | |
tree | 01c0d6d319fcbddc98171d06cfe8e742cd270455 /arch/x86/kernel | |
parent | 110e0358e7dfd9cc56d47077068f3680dae10b56 (diff) | |
parent | adee14b2e1557d0a8559f29681732d05a89dfc35 (diff) |
Merge commit 'v2.6.27-rc6' into x86/pat
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/alternative.c | 36 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/amd.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/centaur.c | 11 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 34 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common_64.c | 74 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 109 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/cpufreq/powernow-k8.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/cyrix.c | 32 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/feature_names.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_64.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 18 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/generic.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/cpuid.c | 15 | ||||
-rw-r--r-- | arch/x86/kernel/e820.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/genx2apic_uv_x.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/hpet.c | 19 | ||||
-rw-r--r-- | arch/x86/kernel/io_delay.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/msr.c | 38 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 16 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/tsc.c | 240 |
21 files changed, 467 insertions, 223 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 2763cb37b553..65a0c1b48696 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -145,35 +145,25 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = { | |||
145 | extern char __vsyscall_0; | 145 | extern char __vsyscall_0; |
146 | const unsigned char *const *find_nop_table(void) | 146 | const unsigned char *const *find_nop_table(void) |
147 | { | 147 | { |
148 | return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || | 148 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && |
149 | boot_cpu_data.x86 < 6 ? k8_nops : p6_nops; | 149 | boot_cpu_has(X86_FEATURE_NOPL)) |
150 | return p6_nops; | ||
151 | else | ||
152 | return k8_nops; | ||
150 | } | 153 | } |
151 | 154 | ||
152 | #else /* CONFIG_X86_64 */ | 155 | #else /* CONFIG_X86_64 */ |
153 | 156 | ||
154 | static const struct nop { | ||
155 | int cpuid; | ||
156 | const unsigned char *const *noptable; | ||
157 | } noptypes[] = { | ||
158 | { X86_FEATURE_K8, k8_nops }, | ||
159 | { X86_FEATURE_K7, k7_nops }, | ||
160 | { X86_FEATURE_P4, p6_nops }, | ||
161 | { X86_FEATURE_P3, p6_nops }, | ||
162 | { -1, NULL } | ||
163 | }; | ||
164 | |||
165 | const unsigned char *const *find_nop_table(void) | 157 | const unsigned char *const *find_nop_table(void) |
166 | { | 158 | { |
167 | const unsigned char *const *noptable = intel_nops; | 159 | if (boot_cpu_has(X86_FEATURE_K8)) |
168 | int i; | 160 | return k8_nops; |
169 | 161 | else if (boot_cpu_has(X86_FEATURE_K7)) | |
170 | for (i = 0; noptypes[i].cpuid >= 0; i++) { | 162 | return k7_nops; |
171 | if (boot_cpu_has(noptypes[i].cpuid)) { | 163 | else if (boot_cpu_has(X86_FEATURE_NOPL)) |
172 | noptable = noptypes[i].noptable; | 164 | return p6_nops; |
173 | break; | 165 | else |
174 | } | 166 | return intel_nops; |
175 | } | ||
176 | return noptable; | ||
177 | } | 167 | } |
178 | 168 | ||
179 | #endif /* CONFIG_X86_64 */ | 169 | #endif /* CONFIG_X86_64 */ |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index cae9cabc3031..18514ed26104 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -31,6 +31,11 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) | |||
31 | if (c->x86_power & (1<<8)) | 31 | if (c->x86_power & (1<<8)) |
32 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | 32 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); |
33 | } | 33 | } |
34 | |||
35 | /* Set MTRR capability flag if appropriate */ | ||
36 | if (c->x86_model == 13 || c->x86_model == 9 || | ||
37 | (c->x86_model == 8 && c->x86_mask >= 8)) | ||
38 | set_cpu_cap(c, X86_FEATURE_K6_MTRR); | ||
34 | } | 39 | } |
35 | 40 | ||
36 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) | 41 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) |
@@ -166,10 +171,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) | |||
166 | mbytes); | 171 | mbytes); |
167 | } | 172 | } |
168 | 173 | ||
169 | /* Set MTRR capability flag if appropriate */ | ||
170 | if (c->x86_model == 13 || c->x86_model == 9 || | ||
171 | (c->x86_model == 8 && c->x86_mask >= 8)) | ||
172 | set_cpu_cap(c, X86_FEATURE_K6_MTRR); | ||
173 | break; | 174 | break; |
174 | } | 175 | } |
175 | 176 | ||
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index e0f45edd6a55..a0534c04d38a 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c | |||
@@ -314,6 +314,16 @@ enum { | |||
314 | EAMD3D = 1<<20, | 314 | EAMD3D = 1<<20, |
315 | }; | 315 | }; |
316 | 316 | ||
317 | static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) | ||
318 | { | ||
319 | switch (c->x86) { | ||
320 | case 5: | ||
321 | /* Emulate MTRRs using Centaur's MCR. */ | ||
322 | set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR); | ||
323 | break; | ||
324 | } | ||
325 | } | ||
326 | |||
317 | static void __cpuinit init_centaur(struct cpuinfo_x86 *c) | 327 | static void __cpuinit init_centaur(struct cpuinfo_x86 *c) |
318 | { | 328 | { |
319 | 329 | ||
@@ -462,6 +472,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) | |||
462 | static struct cpu_dev centaur_cpu_dev __cpuinitdata = { | 472 | static struct cpu_dev centaur_cpu_dev __cpuinitdata = { |
463 | .c_vendor = "Centaur", | 473 | .c_vendor = "Centaur", |
464 | .c_ident = { "CentaurHauls" }, | 474 | .c_ident = { "CentaurHauls" }, |
475 | .c_early_init = early_init_centaur, | ||
465 | .c_init = init_centaur, | 476 | .c_init = init_centaur, |
466 | .c_size_cache = centaur_size_cache, | 477 | .c_size_cache = centaur_size_cache, |
467 | }; | 478 | }; |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 80ab20d4fa39..8aab8517642e 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/mtrr.h> | 13 | #include <asm/mtrr.h> |
14 | #include <asm/mce.h> | 14 | #include <asm/mce.h> |
15 | #include <asm/pat.h> | 15 | #include <asm/pat.h> |
16 | #include <asm/asm.h> | ||
16 | #ifdef CONFIG_X86_LOCAL_APIC | 17 | #ifdef CONFIG_X86_LOCAL_APIC |
17 | #include <asm/mpspec.h> | 18 | #include <asm/mpspec.h> |
18 | #include <asm/apic.h> | 19 | #include <asm/apic.h> |
@@ -334,11 +335,40 @@ static void __init early_cpu_detect(void) | |||
334 | 335 | ||
335 | get_cpu_vendor(c, 1); | 336 | get_cpu_vendor(c, 1); |
336 | 337 | ||
338 | early_get_cap(c); | ||
339 | |||
337 | if (c->x86_vendor != X86_VENDOR_UNKNOWN && | 340 | if (c->x86_vendor != X86_VENDOR_UNKNOWN && |
338 | cpu_devs[c->x86_vendor]->c_early_init) | 341 | cpu_devs[c->x86_vendor]->c_early_init) |
339 | cpu_devs[c->x86_vendor]->c_early_init(c); | 342 | cpu_devs[c->x86_vendor]->c_early_init(c); |
343 | } | ||
340 | 344 | ||
341 | early_get_cap(c); | 345 | /* |
346 | * The NOPL instruction is supposed to exist on all CPUs with | ||
347 | * family >= 6, unfortunately, that's not true in practice because | ||
348 | * of early VIA chips and (more importantly) broken virtualizers that | ||
349 | * are not easy to detect. Hence, probe for it based on first | ||
350 | * principles. | ||
351 | */ | ||
352 | static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) | ||
353 | { | ||
354 | const u32 nopl_signature = 0x888c53b1; /* Random number */ | ||
355 | u32 has_nopl = nopl_signature; | ||
356 | |||
357 | clear_cpu_cap(c, X86_FEATURE_NOPL); | ||
358 | if (c->x86 >= 6) { | ||
359 | asm volatile("\n" | ||
360 | "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ | ||
361 | "2:\n" | ||
362 | " .section .fixup,\"ax\"\n" | ||
363 | "3: xor %0,%0\n" | ||
364 | " jmp 2b\n" | ||
365 | " .previous\n" | ||
366 | _ASM_EXTABLE(1b,3b) | ||
367 | : "+a" (has_nopl)); | ||
368 | |||
369 | if (has_nopl == nopl_signature) | ||
370 | set_cpu_cap(c, X86_FEATURE_NOPL); | ||
371 | } | ||
342 | } | 372 | } |
343 | 373 | ||
344 | static void __cpuinit generic_identify(struct cpuinfo_x86 *c) | 374 | static void __cpuinit generic_identify(struct cpuinfo_x86 *c) |
@@ -395,8 +425,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) | |||
395 | } | 425 | } |
396 | 426 | ||
397 | init_scattered_cpuid_features(c); | 427 | init_scattered_cpuid_features(c); |
428 | detect_nopl(c); | ||
398 | } | 429 | } |
399 | |||
400 | } | 430 | } |
401 | 431 | ||
402 | static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) | 432 | static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) |
diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index dd6e3f15017e..a11f5d4477cd 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/mtrr.h> | 18 | #include <asm/mtrr.h> |
19 | #include <asm/mce.h> | 19 | #include <asm/mce.h> |
20 | #include <asm/pat.h> | 20 | #include <asm/pat.h> |
21 | #include <asm/asm.h> | ||
21 | #include <asm/numa.h> | 22 | #include <asm/numa.h> |
22 | #ifdef CONFIG_X86_LOCAL_APIC | 23 | #ifdef CONFIG_X86_LOCAL_APIC |
23 | #include <asm/mpspec.h> | 24 | #include <asm/mpspec.h> |
@@ -215,6 +216,39 @@ static void __init early_cpu_support_print(void) | |||
215 | } | 216 | } |
216 | } | 217 | } |
217 | 218 | ||
219 | /* | ||
220 | * The NOPL instruction is supposed to exist on all CPUs with | ||
221 | * family >= 6, unfortunately, that's not true in practice because | ||
222 | * of early VIA chips and (more importantly) broken virtualizers that | ||
223 | * are not easy to detect. Hence, probe for it based on first | ||
224 | * principles. | ||
225 | * | ||
226 | * Note: no 64-bit chip is known to lack these, but put the code here | ||
227 | * for consistency with 32 bits, and to make it utterly trivial to | ||
228 | * diagnose the problem should it ever surface. | ||
229 | */ | ||
230 | static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) | ||
231 | { | ||
232 | const u32 nopl_signature = 0x888c53b1; /* Random number */ | ||
233 | u32 has_nopl = nopl_signature; | ||
234 | |||
235 | clear_cpu_cap(c, X86_FEATURE_NOPL); | ||
236 | if (c->x86 >= 6) { | ||
237 | asm volatile("\n" | ||
238 | "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ | ||
239 | "2:\n" | ||
240 | " .section .fixup,\"ax\"\n" | ||
241 | "3: xor %0,%0\n" | ||
242 | " jmp 2b\n" | ||
243 | " .previous\n" | ||
244 | _ASM_EXTABLE(1b,3b) | ||
245 | : "+a" (has_nopl)); | ||
246 | |||
247 | if (has_nopl == nopl_signature) | ||
248 | set_cpu_cap(c, X86_FEATURE_NOPL); | ||
249 | } | ||
250 | } | ||
251 | |||
218 | static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c); | 252 | static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c); |
219 | 253 | ||
220 | void __init early_cpu_init(void) | 254 | void __init early_cpu_init(void) |
@@ -313,6 +347,8 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) | |||
313 | c->x86_phys_bits = eax & 0xff; | 347 | c->x86_phys_bits = eax & 0xff; |
314 | } | 348 | } |
315 | 349 | ||
350 | detect_nopl(c); | ||
351 | |||
316 | if (c->x86_vendor != X86_VENDOR_UNKNOWN && | 352 | if (c->x86_vendor != X86_VENDOR_UNKNOWN && |
317 | cpu_devs[c->x86_vendor]->c_early_init) | 353 | cpu_devs[c->x86_vendor]->c_early_init) |
318 | cpu_devs[c->x86_vendor]->c_early_init(c); | 354 | cpu_devs[c->x86_vendor]->c_early_init(c); |
@@ -493,17 +529,20 @@ void pda_init(int cpu) | |||
493 | /* others are initialized in smpboot.c */ | 529 | /* others are initialized in smpboot.c */ |
494 | pda->pcurrent = &init_task; | 530 | pda->pcurrent = &init_task; |
495 | pda->irqstackptr = boot_cpu_stack; | 531 | pda->irqstackptr = boot_cpu_stack; |
532 | pda->irqstackptr += IRQSTACKSIZE - 64; | ||
496 | } else { | 533 | } else { |
497 | pda->irqstackptr = (char *) | 534 | if (!pda->irqstackptr) { |
498 | __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); | 535 | pda->irqstackptr = (char *) |
499 | if (!pda->irqstackptr) | 536 | __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); |
500 | panic("cannot allocate irqstack for cpu %d", cpu); | 537 | if (!pda->irqstackptr) |
538 | panic("cannot allocate irqstack for cpu %d", | ||
539 | cpu); | ||
540 | pda->irqstackptr += IRQSTACKSIZE - 64; | ||
541 | } | ||
501 | 542 | ||
502 | if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) | 543 | if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) |
503 | pda->nodenumber = cpu_to_node(cpu); | 544 | pda->nodenumber = cpu_to_node(cpu); |
504 | } | 545 | } |
505 | |||
506 | pda->irqstackptr += IRQSTACKSIZE-64; | ||
507 | } | 546 | } |
508 | 547 | ||
509 | char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + | 548 | char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + |
@@ -601,19 +640,22 @@ void __cpuinit cpu_init(void) | |||
601 | /* | 640 | /* |
602 | * set up and load the per-CPU TSS | 641 | * set up and load the per-CPU TSS |
603 | */ | 642 | */ |
604 | for (v = 0; v < N_EXCEPTION_STACKS; v++) { | 643 | if (!orig_ist->ist[0]) { |
605 | static const unsigned int order[N_EXCEPTION_STACKS] = { | 644 | static const unsigned int order[N_EXCEPTION_STACKS] = { |
606 | [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, | 645 | [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, |
607 | [DEBUG_STACK - 1] = DEBUG_STACK_ORDER | 646 | [DEBUG_STACK - 1] = DEBUG_STACK_ORDER |
608 | }; | 647 | }; |
609 | if (cpu) { | 648 | for (v = 0; v < N_EXCEPTION_STACKS; v++) { |
610 | estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); | 649 | if (cpu) { |
611 | if (!estacks) | 650 | estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); |
612 | panic("Cannot allocate exception stack %ld %d\n", | 651 | if (!estacks) |
613 | v, cpu); | 652 | panic("Cannot allocate exception " |
653 | "stack %ld %d\n", v, cpu); | ||
654 | } | ||
655 | estacks += PAGE_SIZE << order[v]; | ||
656 | orig_ist->ist[v] = t->x86_tss.ist[v] = | ||
657 | (unsigned long)estacks; | ||
614 | } | 658 | } |
615 | estacks += PAGE_SIZE << order[v]; | ||
616 | orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks; | ||
617 | } | 659 | } |
618 | 660 | ||
619 | t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap); | 661 | t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap); |
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 4e7271999a74..84bb395038d8 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c | |||
@@ -737,63 +737,44 @@ static int find_psb_table(struct powernow_k8_data *data) | |||
737 | #ifdef CONFIG_X86_POWERNOW_K8_ACPI | 737 | #ifdef CONFIG_X86_POWERNOW_K8_ACPI |
738 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) | 738 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) |
739 | { | 739 | { |
740 | if (!data->acpi_data->state_count || (cpu_family == CPU_HW_PSTATE)) | 740 | if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) |
741 | return; | 741 | return; |
742 | 742 | ||
743 | data->irt = (data->acpi_data->states[index].control >> IRT_SHIFT) & IRT_MASK; | 743 | data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK; |
744 | data->rvo = (data->acpi_data->states[index].control >> RVO_SHIFT) & RVO_MASK; | 744 | data->rvo = (data->acpi_data.states[index].control >> RVO_SHIFT) & RVO_MASK; |
745 | data->exttype = (data->acpi_data->states[index].control >> EXT_TYPE_SHIFT) & EXT_TYPE_MASK; | 745 | data->exttype = (data->acpi_data.states[index].control >> EXT_TYPE_SHIFT) & EXT_TYPE_MASK; |
746 | data->plllock = (data->acpi_data->states[index].control >> PLL_L_SHIFT) & PLL_L_MASK; | 746 | data->plllock = (data->acpi_data.states[index].control >> PLL_L_SHIFT) & PLL_L_MASK; |
747 | data->vidmvs = 1 << ((data->acpi_data->states[index].control >> MVS_SHIFT) & MVS_MASK); | 747 | data->vidmvs = 1 << ((data->acpi_data.states[index].control >> MVS_SHIFT) & MVS_MASK); |
748 | data->vstable = (data->acpi_data->states[index].control >> VST_SHIFT) & VST_MASK; | 748 | data->vstable = (data->acpi_data.states[index].control >> VST_SHIFT) & VST_MASK; |
749 | } | ||
750 | |||
751 | |||
752 | static struct acpi_processor_performance *acpi_perf_data; | ||
753 | static int preregister_valid; | ||
754 | |||
755 | static int powernow_k8_cpu_preinit_acpi(void) | ||
756 | { | ||
757 | acpi_perf_data = alloc_percpu(struct acpi_processor_performance); | ||
758 | if (!acpi_perf_data) | ||
759 | return -ENODEV; | ||
760 | |||
761 | if (acpi_processor_preregister_performance(acpi_perf_data)) | ||
762 | return -ENODEV; | ||
763 | else | ||
764 | preregister_valid = 1; | ||
765 | return 0; | ||
766 | } | 749 | } |
767 | 750 | ||
768 | static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) | 751 | static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) |
769 | { | 752 | { |
770 | struct cpufreq_frequency_table *powernow_table; | 753 | struct cpufreq_frequency_table *powernow_table; |
771 | int ret_val; | 754 | int ret_val; |
772 | int cpu = 0; | ||
773 | 755 | ||
774 | data->acpi_data = percpu_ptr(acpi_perf_data, cpu); | 756 | if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { |
775 | if (acpi_processor_register_performance(data->acpi_data, data->cpu)) { | ||
776 | dprintk("register performance failed: bad ACPI data\n"); | 757 | dprintk("register performance failed: bad ACPI data\n"); |
777 | return -EIO; | 758 | return -EIO; |
778 | } | 759 | } |
779 | 760 | ||
780 | /* verify the data contained in the ACPI structures */ | 761 | /* verify the data contained in the ACPI structures */ |
781 | if (data->acpi_data->state_count <= 1) { | 762 | if (data->acpi_data.state_count <= 1) { |
782 | dprintk("No ACPI P-States\n"); | 763 | dprintk("No ACPI P-States\n"); |
783 | goto err_out; | 764 | goto err_out; |
784 | } | 765 | } |
785 | 766 | ||
786 | if ((data->acpi_data->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || | 767 | if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || |
787 | (data->acpi_data->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { | 768 | (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { |
788 | dprintk("Invalid control/status registers (%x - %x)\n", | 769 | dprintk("Invalid control/status registers (%x - %x)\n", |
789 | data->acpi_data->control_register.space_id, | 770 | data->acpi_data.control_register.space_id, |
790 | data->acpi_data->status_register.space_id); | 771 | data->acpi_data.status_register.space_id); |
791 | goto err_out; | 772 | goto err_out; |
792 | } | 773 | } |
793 | 774 | ||
794 | /* fill in data->powernow_table */ | 775 | /* fill in data->powernow_table */ |
795 | powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) | 776 | powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) |
796 | * (data->acpi_data->state_count + 1)), GFP_KERNEL); | 777 | * (data->acpi_data.state_count + 1)), GFP_KERNEL); |
797 | if (!powernow_table) { | 778 | if (!powernow_table) { |
798 | dprintk("powernow_table memory alloc failure\n"); | 779 | dprintk("powernow_table memory alloc failure\n"); |
799 | goto err_out; | 780 | goto err_out; |
@@ -806,12 +787,12 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) | |||
806 | if (ret_val) | 787 | if (ret_val) |
807 | goto err_out_mem; | 788 | goto err_out_mem; |
808 | 789 | ||
809 | powernow_table[data->acpi_data->state_count].frequency = CPUFREQ_TABLE_END; | 790 | powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END; |
810 | powernow_table[data->acpi_data->state_count].index = 0; | 791 | powernow_table[data->acpi_data.state_count].index = 0; |
811 | data->powernow_table = powernow_table; | 792 | data->powernow_table = powernow_table; |
812 | 793 | ||
813 | /* fill in data */ | 794 | /* fill in data */ |
814 | data->numps = data->acpi_data->state_count; | 795 | data->numps = data->acpi_data.state_count; |
815 | if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu) | 796 | if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu) |
816 | print_basics(data); | 797 | print_basics(data); |
817 | powernow_k8_acpi_pst_values(data, 0); | 798 | powernow_k8_acpi_pst_values(data, 0); |
@@ -819,31 +800,16 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) | |||
819 | /* notify BIOS that we exist */ | 800 | /* notify BIOS that we exist */ |
820 | acpi_processor_notify_smm(THIS_MODULE); | 801 | acpi_processor_notify_smm(THIS_MODULE); |
821 | 802 | ||
822 | /* determine affinity, from ACPI if available */ | ||
823 | if (preregister_valid) { | ||
824 | if ((data->acpi_data->shared_type == CPUFREQ_SHARED_TYPE_ALL) || | ||
825 | (data->acpi_data->shared_type == CPUFREQ_SHARED_TYPE_ANY)) | ||
826 | data->starting_core_affinity = data->acpi_data->shared_cpu_map; | ||
827 | else | ||
828 | data->starting_core_affinity = cpumask_of_cpu(data->cpu); | ||
829 | } else { | ||
830 | /* best guess from family if not */ | ||
831 | if (cpu_family == CPU_HW_PSTATE) | ||
832 | data->starting_core_affinity = cpumask_of_cpu(data->cpu); | ||
833 | else | ||
834 | data->starting_core_affinity = per_cpu(cpu_core_map, data->cpu); | ||
835 | } | ||
836 | |||
837 | return 0; | 803 | return 0; |
838 | 804 | ||
839 | err_out_mem: | 805 | err_out_mem: |
840 | kfree(powernow_table); | 806 | kfree(powernow_table); |
841 | 807 | ||
842 | err_out: | 808 | err_out: |
843 | acpi_processor_unregister_performance(data->acpi_data, data->cpu); | 809 | acpi_processor_unregister_performance(&data->acpi_data, data->cpu); |
844 | 810 | ||
845 | /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */ | 811 | /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */ |
846 | data->acpi_data->state_count = 0; | 812 | data->acpi_data.state_count = 0; |
847 | 813 | ||
848 | return -ENODEV; | 814 | return -ENODEV; |
849 | } | 815 | } |
@@ -855,10 +821,10 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpuf | |||
855 | rdmsr(MSR_PSTATE_CUR_LIMIT, hi, lo); | 821 | rdmsr(MSR_PSTATE_CUR_LIMIT, hi, lo); |
856 | data->max_hw_pstate = (hi & HW_PSTATE_MAX_MASK) >> HW_PSTATE_MAX_SHIFT; | 822 | data->max_hw_pstate = (hi & HW_PSTATE_MAX_MASK) >> HW_PSTATE_MAX_SHIFT; |
857 | 823 | ||
858 | for (i = 0; i < data->acpi_data->state_count; i++) { | 824 | for (i = 0; i < data->acpi_data.state_count; i++) { |
859 | u32 index; | 825 | u32 index; |
860 | 826 | ||
861 | index = data->acpi_data->states[i].control & HW_PSTATE_MASK; | 827 | index = data->acpi_data.states[i].control & HW_PSTATE_MASK; |
862 | if (index > data->max_hw_pstate) { | 828 | if (index > data->max_hw_pstate) { |
863 | printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index); | 829 | printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index); |
864 | printk(KERN_ERR PFX "Please report to BIOS manufacturer\n"); | 830 | printk(KERN_ERR PFX "Please report to BIOS manufacturer\n"); |
@@ -874,7 +840,7 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpuf | |||
874 | 840 | ||
875 | powernow_table[i].index = index; | 841 | powernow_table[i].index = index; |
876 | 842 | ||
877 | powernow_table[i].frequency = data->acpi_data->states[i].core_frequency * 1000; | 843 | powernow_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000; |
878 | } | 844 | } |
879 | return 0; | 845 | return 0; |
880 | } | 846 | } |
@@ -883,16 +849,16 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpuf | |||
883 | { | 849 | { |
884 | int i; | 850 | int i; |
885 | int cntlofreq = 0; | 851 | int cntlofreq = 0; |
886 | for (i = 0; i < data->acpi_data->state_count; i++) { | 852 | for (i = 0; i < data->acpi_data.state_count; i++) { |
887 | u32 fid; | 853 | u32 fid; |
888 | u32 vid; | 854 | u32 vid; |
889 | 855 | ||
890 | if (data->exttype) { | 856 | if (data->exttype) { |
891 | fid = data->acpi_data->states[i].status & EXT_FID_MASK; | 857 | fid = data->acpi_data.states[i].status & EXT_FID_MASK; |
892 | vid = (data->acpi_data->states[i].status >> VID_SHIFT) & EXT_VID_MASK; | 858 | vid = (data->acpi_data.states[i].status >> VID_SHIFT) & EXT_VID_MASK; |
893 | } else { | 859 | } else { |
894 | fid = data->acpi_data->states[i].control & FID_MASK; | 860 | fid = data->acpi_data.states[i].control & FID_MASK; |
895 | vid = (data->acpi_data->states[i].control >> VID_SHIFT) & VID_MASK; | 861 | vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK; |
896 | } | 862 | } |
897 | 863 | ||
898 | dprintk(" %d : fid 0x%x, vid 0x%x\n", i, fid, vid); | 864 | dprintk(" %d : fid 0x%x, vid 0x%x\n", i, fid, vid); |
@@ -933,10 +899,10 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpuf | |||
933 | cntlofreq = i; | 899 | cntlofreq = i; |
934 | } | 900 | } |
935 | 901 | ||
936 | if (powernow_table[i].frequency != (data->acpi_data->states[i].core_frequency * 1000)) { | 902 | if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { |
937 | printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n", | 903 | printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n", |
938 | powernow_table[i].frequency, | 904 | powernow_table[i].frequency, |
939 | (unsigned int) (data->acpi_data->states[i].core_frequency * 1000)); | 905 | (unsigned int) (data->acpi_data.states[i].core_frequency * 1000)); |
940 | powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; | 906 | powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; |
941 | continue; | 907 | continue; |
942 | } | 908 | } |
@@ -946,12 +912,11 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpuf | |||
946 | 912 | ||
947 | static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) | 913 | static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) |
948 | { | 914 | { |
949 | if (data->acpi_data->state_count) | 915 | if (data->acpi_data.state_count) |
950 | acpi_processor_unregister_performance(data->acpi_data, data->cpu); | 916 | acpi_processor_unregister_performance(&data->acpi_data, data->cpu); |
951 | } | 917 | } |
952 | 918 | ||
953 | #else | 919 | #else |
954 | static int powernow_k8_cpu_preinit_acpi(void) { return -ENODEV; } | ||
955 | static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { return -ENODEV; } | 920 | static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { return -ENODEV; } |
956 | static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) { return; } | 921 | static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) { return; } |
957 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { return; } | 922 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { return; } |
@@ -1136,7 +1101,7 @@ static int powernowk8_verify(struct cpufreq_policy *pol) | |||
1136 | static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | 1101 | static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) |
1137 | { | 1102 | { |
1138 | struct powernow_k8_data *data; | 1103 | struct powernow_k8_data *data; |
1139 | cpumask_t oldmask = CPU_MASK_ALL; | 1104 | cpumask_t oldmask; |
1140 | int rc; | 1105 | int rc; |
1141 | 1106 | ||
1142 | if (!cpu_online(pol->cpu)) | 1107 | if (!cpu_online(pol->cpu)) |
@@ -1209,7 +1174,10 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
1209 | /* run on any CPU again */ | 1174 | /* run on any CPU again */ |
1210 | set_cpus_allowed_ptr(current, &oldmask); | 1175 | set_cpus_allowed_ptr(current, &oldmask); |
1211 | 1176 | ||
1212 | pol->cpus = data->starting_core_affinity; | 1177 | if (cpu_family == CPU_HW_PSTATE) |
1178 | pol->cpus = cpumask_of_cpu(pol->cpu); | ||
1179 | else | ||
1180 | pol->cpus = per_cpu(cpu_core_map, pol->cpu); | ||
1213 | data->available_cores = &(pol->cpus); | 1181 | data->available_cores = &(pol->cpus); |
1214 | 1182 | ||
1215 | /* Take a crude guess here. | 1183 | /* Take a crude guess here. |
@@ -1332,7 +1300,6 @@ static int __cpuinit powernowk8_init(void) | |||
1332 | } | 1300 | } |
1333 | 1301 | ||
1334 | if (supported_cpus == num_online_cpus()) { | 1302 | if (supported_cpus == num_online_cpus()) { |
1335 | powernow_k8_cpu_preinit_acpi(); | ||
1336 | printk(KERN_INFO PFX "Found %d %s " | 1303 | printk(KERN_INFO PFX "Found %d %s " |
1337 | "processors (%d cpu cores) (" VERSION ")\n", | 1304 | "processors (%d cpu cores) (" VERSION ")\n", |
1338 | num_online_nodes(), | 1305 | num_online_nodes(), |
@@ -1349,10 +1316,6 @@ static void __exit powernowk8_exit(void) | |||
1349 | dprintk("exit\n"); | 1316 | dprintk("exit\n"); |
1350 | 1317 | ||
1351 | cpufreq_unregister_driver(&cpufreq_amd64_driver); | 1318 | cpufreq_unregister_driver(&cpufreq_amd64_driver); |
1352 | |||
1353 | #ifdef CONFIG_X86_POWERNOW_K8_ACPI | ||
1354 | free_percpu(acpi_perf_data); | ||
1355 | #endif | ||
1356 | } | 1319 | } |
1357 | 1320 | ||
1358 | MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com>"); | 1321 | MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com>"); |
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h index a62612cd4be8..ab48cfed4d96 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h | |||
@@ -33,13 +33,12 @@ struct powernow_k8_data { | |||
33 | #ifdef CONFIG_X86_POWERNOW_K8_ACPI | 33 | #ifdef CONFIG_X86_POWERNOW_K8_ACPI |
34 | /* the acpi table needs to be kept. it's only available if ACPI was | 34 | /* the acpi table needs to be kept. it's only available if ACPI was |
35 | * used to determine valid frequency/vid/fid states */ | 35 | * used to determine valid frequency/vid/fid states */ |
36 | struct acpi_processor_performance *acpi_data; | 36 | struct acpi_processor_performance acpi_data; |
37 | #endif | 37 | #endif |
38 | /* we need to keep track of associated cores, but let cpufreq | 38 | /* we need to keep track of associated cores, but let cpufreq |
39 | * handle hotplug events - so just point at cpufreq pol->cpus | 39 | * handle hotplug events - so just point at cpufreq pol->cpus |
40 | * structure */ | 40 | * structure */ |
41 | cpumask_t *available_cores; | 41 | cpumask_t *available_cores; |
42 | cpumask_t starting_core_affinity; | ||
43 | }; | 42 | }; |
44 | 43 | ||
45 | 44 | ||
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index e710a21bb6e8..898a5a2002ed 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c | |||
@@ -15,13 +15,11 @@ | |||
15 | /* | 15 | /* |
16 | * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU | 16 | * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU |
17 | */ | 17 | */ |
18 | static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) | 18 | static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) |
19 | { | 19 | { |
20 | unsigned char ccr2, ccr3; | 20 | unsigned char ccr2, ccr3; |
21 | unsigned long flags; | ||
22 | 21 | ||
23 | /* we test for DEVID by checking whether CCR3 is writable */ | 22 | /* we test for DEVID by checking whether CCR3 is writable */ |
24 | local_irq_save(flags); | ||
25 | ccr3 = getCx86(CX86_CCR3); | 23 | ccr3 = getCx86(CX86_CCR3); |
26 | setCx86(CX86_CCR3, ccr3 ^ 0x80); | 24 | setCx86(CX86_CCR3, ccr3 ^ 0x80); |
27 | getCx86(0xc0); /* dummy to change bus */ | 25 | getCx86(0xc0); /* dummy to change bus */ |
@@ -44,9 +42,16 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) | |||
44 | *dir0 = getCx86(CX86_DIR0); | 42 | *dir0 = getCx86(CX86_DIR0); |
45 | *dir1 = getCx86(CX86_DIR1); | 43 | *dir1 = getCx86(CX86_DIR1); |
46 | } | 44 | } |
47 | local_irq_restore(flags); | ||
48 | } | 45 | } |
49 | 46 | ||
47 | static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) | ||
48 | { | ||
49 | unsigned long flags; | ||
50 | |||
51 | local_irq_save(flags); | ||
52 | __do_cyrix_devid(dir0, dir1); | ||
53 | local_irq_restore(flags); | ||
54 | } | ||
50 | /* | 55 | /* |
51 | * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in | 56 | * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in |
52 | * order to identify the Cyrix CPU model after we're out of setup.c | 57 | * order to identify the Cyrix CPU model after we're out of setup.c |
@@ -161,6 +166,24 @@ static void __cpuinit geode_configure(void) | |||
161 | local_irq_restore(flags); | 166 | local_irq_restore(flags); |
162 | } | 167 | } |
163 | 168 | ||
169 | static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c) | ||
170 | { | ||
171 | unsigned char dir0, dir0_msn, dir1 = 0; | ||
172 | |||
173 | __do_cyrix_devid(&dir0, &dir1); | ||
174 | dir0_msn = dir0 >> 4; /* identifies CPU "family" */ | ||
175 | |||
176 | switch (dir0_msn) { | ||
177 | case 3: /* 6x86/6x86L */ | ||
178 | /* Emulate MTRRs using Cyrix's ARRs. */ | ||
179 | set_cpu_cap(c, X86_FEATURE_CYRIX_ARR); | ||
180 | break; | ||
181 | case 5: /* 6x86MX/M II */ | ||
182 | /* Emulate MTRRs using Cyrix's ARRs. */ | ||
183 | set_cpu_cap(c, X86_FEATURE_CYRIX_ARR); | ||
184 | break; | ||
185 | } | ||
186 | } | ||
164 | 187 | ||
165 | static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) | 188 | static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) |
166 | { | 189 | { |
@@ -416,6 +439,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c) | |||
416 | static struct cpu_dev cyrix_cpu_dev __cpuinitdata = { | 439 | static struct cpu_dev cyrix_cpu_dev __cpuinitdata = { |
417 | .c_vendor = "Cyrix", | 440 | .c_vendor = "Cyrix", |
418 | .c_ident = { "CyrixInstead" }, | 441 | .c_ident = { "CyrixInstead" }, |
442 | .c_early_init = early_init_cyrix, | ||
419 | .c_init = init_cyrix, | 443 | .c_init = init_cyrix, |
420 | .c_identify = cyrix_identify, | 444 | .c_identify = cyrix_identify, |
421 | }; | 445 | }; |
diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c index e43ad4ad4cba..c9017799497c 100644 --- a/arch/x86/kernel/cpu/feature_names.c +++ b/arch/x86/kernel/cpu/feature_names.c | |||
@@ -39,7 +39,8 @@ const char * const x86_cap_flags[NCAPINTS*32] = { | |||
39 | NULL, NULL, NULL, NULL, | 39 | NULL, NULL, NULL, NULL, |
40 | "constant_tsc", "up", NULL, "arch_perfmon", | 40 | "constant_tsc", "up", NULL, "arch_perfmon", |
41 | "pebs", "bts", NULL, NULL, | 41 | "pebs", "bts", NULL, NULL, |
42 | "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 42 | "rep_good", NULL, NULL, NULL, |
43 | "nopl", NULL, NULL, NULL, | ||
43 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 44 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
44 | 45 | ||
45 | /* Intel-defined (#2) */ | 46 | /* Intel-defined (#2) */ |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 65a339678ece..726a5fcdf341 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c | |||
@@ -759,6 +759,7 @@ static struct sysdev_class mce_sysclass = { | |||
759 | }; | 759 | }; |
760 | 760 | ||
761 | DEFINE_PER_CPU(struct sys_device, device_mce); | 761 | DEFINE_PER_CPU(struct sys_device, device_mce); |
762 | void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu) __cpuinitdata; | ||
762 | 763 | ||
763 | /* Why are there no generic functions for this? */ | 764 | /* Why are there no generic functions for this? */ |
764 | #define ACCESSOR(name, var, start) \ | 765 | #define ACCESSOR(name, var, start) \ |
@@ -883,9 +884,13 @@ static int __cpuinit mce_cpu_callback(struct notifier_block *nfb, | |||
883 | case CPU_ONLINE: | 884 | case CPU_ONLINE: |
884 | case CPU_ONLINE_FROZEN: | 885 | case CPU_ONLINE_FROZEN: |
885 | mce_create_device(cpu); | 886 | mce_create_device(cpu); |
887 | if (threshold_cpu_callback) | ||
888 | threshold_cpu_callback(action, cpu); | ||
886 | break; | 889 | break; |
887 | case CPU_DEAD: | 890 | case CPU_DEAD: |
888 | case CPU_DEAD_FROZEN: | 891 | case CPU_DEAD_FROZEN: |
892 | if (threshold_cpu_callback) | ||
893 | threshold_cpu_callback(action, cpu); | ||
889 | mce_remove_device(cpu); | 894 | mce_remove_device(cpu); |
890 | break; | 895 | break; |
891 | } | 896 | } |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index 88736cadbaa6..5eb390a4b2e9 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c | |||
@@ -628,6 +628,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) | |||
628 | deallocate_threshold_block(cpu, bank); | 628 | deallocate_threshold_block(cpu, bank); |
629 | 629 | ||
630 | free_out: | 630 | free_out: |
631 | kobject_del(b->kobj); | ||
631 | kobject_put(b->kobj); | 632 | kobject_put(b->kobj); |
632 | kfree(b); | 633 | kfree(b); |
633 | per_cpu(threshold_banks, cpu)[bank] = NULL; | 634 | per_cpu(threshold_banks, cpu)[bank] = NULL; |
@@ -645,14 +646,11 @@ static void threshold_remove_device(unsigned int cpu) | |||
645 | } | 646 | } |
646 | 647 | ||
647 | /* get notified when a cpu comes on/off */ | 648 | /* get notified when a cpu comes on/off */ |
648 | static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb, | 649 | static void __cpuinit amd_64_threshold_cpu_callback(unsigned long action, |
649 | unsigned long action, void *hcpu) | 650 | unsigned int cpu) |
650 | { | 651 | { |
651 | /* cpu was unsigned int to begin with */ | ||
652 | unsigned int cpu = (unsigned long)hcpu; | ||
653 | |||
654 | if (cpu >= NR_CPUS) | 652 | if (cpu >= NR_CPUS) |
655 | goto out; | 653 | return; |
656 | 654 | ||
657 | switch (action) { | 655 | switch (action) { |
658 | case CPU_ONLINE: | 656 | case CPU_ONLINE: |
@@ -666,14 +664,8 @@ static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb, | |||
666 | default: | 664 | default: |
667 | break; | 665 | break; |
668 | } | 666 | } |
669 | out: | ||
670 | return NOTIFY_OK; | ||
671 | } | 667 | } |
672 | 668 | ||
673 | static struct notifier_block threshold_cpu_notifier __cpuinitdata = { | ||
674 | .notifier_call = threshold_cpu_callback, | ||
675 | }; | ||
676 | |||
677 | static __init int threshold_init_device(void) | 669 | static __init int threshold_init_device(void) |
678 | { | 670 | { |
679 | unsigned lcpu = 0; | 671 | unsigned lcpu = 0; |
@@ -684,7 +676,7 @@ static __init int threshold_init_device(void) | |||
684 | if (err) | 676 | if (err) |
685 | return err; | 677 | return err; |
686 | } | 678 | } |
687 | register_hotcpu_notifier(&threshold_cpu_notifier); | 679 | threshold_cpu_callback = amd_64_threshold_cpu_callback; |
688 | return 0; | 680 | return 0; |
689 | } | 681 | } |
690 | 682 | ||
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 43102e03e2d1..cb7d3b6a80eb 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c | |||
@@ -401,7 +401,12 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, | |||
401 | tmp |= ~((1<<(hi - 1)) - 1); | 401 | tmp |= ~((1<<(hi - 1)) - 1); |
402 | 402 | ||
403 | if (tmp != mask_lo) { | 403 | if (tmp != mask_lo) { |
404 | WARN_ON("mtrr: your BIOS has set up an incorrect mask, fixing it up.\n"); | 404 | static int once = 1; |
405 | |||
406 | if (once) { | ||
407 | printk(KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n"); | ||
408 | once = 0; | ||
409 | } | ||
405 | mask_lo = tmp; | 410 | mask_lo = tmp; |
406 | } | 411 | } |
407 | } | 412 | } |
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 14b11b3be31c..8e9cd6a8ec12 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c | |||
@@ -89,6 +89,8 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, | |||
89 | struct cpuid_regs cmd; | 89 | struct cpuid_regs cmd; |
90 | int cpu = iminor(file->f_path.dentry->d_inode); | 90 | int cpu = iminor(file->f_path.dentry->d_inode); |
91 | u64 pos = *ppos; | 91 | u64 pos = *ppos; |
92 | ssize_t bytes = 0; | ||
93 | int err = 0; | ||
92 | 94 | ||
93 | if (count % 16) | 95 | if (count % 16) |
94 | return -EINVAL; /* Invalid chunk size */ | 96 | return -EINVAL; /* Invalid chunk size */ |
@@ -96,14 +98,19 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, | |||
96 | for (; count; count -= 16) { | 98 | for (; count; count -= 16) { |
97 | cmd.eax = pos; | 99 | cmd.eax = pos; |
98 | cmd.ecx = pos >> 32; | 100 | cmd.ecx = pos >> 32; |
99 | smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1); | 101 | err = smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1); |
100 | if (copy_to_user(tmp, &cmd, 16)) | 102 | if (err) |
101 | return -EFAULT; | 103 | break; |
104 | if (copy_to_user(tmp, &cmd, 16)) { | ||
105 | err = -EFAULT; | ||
106 | break; | ||
107 | } | ||
102 | tmp += 16; | 108 | tmp += 16; |
109 | bytes += 16; | ||
103 | *ppos = ++pos; | 110 | *ppos = ++pos; |
104 | } | 111 | } |
105 | 112 | ||
106 | return tmp - buf; | 113 | return bytes ? bytes : err; |
107 | } | 114 | } |
108 | 115 | ||
109 | static int cpuid_open(struct inode *inode, struct file *file) | 116 | static int cpuid_open(struct inode *inode, struct file *file) |
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 9af89078f7bb..66e48aa2dd1b 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -1203,7 +1203,7 @@ static int __init parse_memmap_opt(char *p) | |||
1203 | if (!p) | 1203 | if (!p) |
1204 | return -EINVAL; | 1204 | return -EINVAL; |
1205 | 1205 | ||
1206 | if (!strcmp(p, "exactmap")) { | 1206 | if (!strncmp(p, "exactmap", 8)) { |
1207 | #ifdef CONFIG_CRASH_DUMP | 1207 | #ifdef CONFIG_CRASH_DUMP |
1208 | /* | 1208 | /* |
1209 | * If we are doing a crash dump, we still need to know | 1209 | * If we are doing a crash dump, we still need to know |
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 2d7e307c7779..bfa837cb16be 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c | |||
@@ -293,7 +293,9 @@ static __init void uv_rtc_init(void) | |||
293 | sn_rtc_cycles_per_second = ticks_per_sec; | 293 | sn_rtc_cycles_per_second = ticks_per_sec; |
294 | } | 294 | } |
295 | 295 | ||
296 | static __init void uv_system_init(void) | 296 | static bool uv_system_inited; |
297 | |||
298 | void __init uv_system_init(void) | ||
297 | { | 299 | { |
298 | union uvh_si_addr_map_config_u m_n_config; | 300 | union uvh_si_addr_map_config_u m_n_config; |
299 | union uvh_node_id_u node_id; | 301 | union uvh_node_id_u node_id; |
@@ -383,6 +385,7 @@ static __init void uv_system_init(void) | |||
383 | map_mmr_high(max_pnode); | 385 | map_mmr_high(max_pnode); |
384 | map_config_high(max_pnode); | 386 | map_config_high(max_pnode); |
385 | map_mmioh_high(max_pnode); | 387 | map_mmioh_high(max_pnode); |
388 | uv_system_inited = true; | ||
386 | } | 389 | } |
387 | 390 | ||
388 | /* | 391 | /* |
@@ -391,8 +394,7 @@ static __init void uv_system_init(void) | |||
391 | */ | 394 | */ |
392 | void __cpuinit uv_cpu_init(void) | 395 | void __cpuinit uv_cpu_init(void) |
393 | { | 396 | { |
394 | if (!uv_node_to_blade) | 397 | BUG_ON(!uv_system_inited); |
395 | uv_system_init(); | ||
396 | 398 | ||
397 | uv_blade_info[uv_numa_blade_id()].nr_online_cpus++; | 399 | uv_blade_info[uv_numa_blade_id()].nr_online_cpus++; |
398 | 400 | ||
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 59fd3b6b1303..73deaffadd03 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -210,8 +210,8 @@ static void hpet_legacy_clockevent_register(void) | |||
210 | /* Calculate the min / max delta */ | 210 | /* Calculate the min / max delta */ |
211 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, | 211 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, |
212 | &hpet_clockevent); | 212 | &hpet_clockevent); |
213 | hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30, | 213 | /* 5 usec minimum reprogramming delta. */ |
214 | &hpet_clockevent); | 214 | hpet_clockevent.min_delta_ns = 5000; |
215 | 215 | ||
216 | /* | 216 | /* |
217 | * Start hpet with the boot cpu mask and make it | 217 | * Start hpet with the boot cpu mask and make it |
@@ -270,15 +270,22 @@ static void hpet_legacy_set_mode(enum clock_event_mode mode, | |||
270 | } | 270 | } |
271 | 271 | ||
272 | static int hpet_legacy_next_event(unsigned long delta, | 272 | static int hpet_legacy_next_event(unsigned long delta, |
273 | struct clock_event_device *evt) | 273 | struct clock_event_device *evt) |
274 | { | 274 | { |
275 | unsigned long cnt; | 275 | u32 cnt; |
276 | 276 | ||
277 | cnt = hpet_readl(HPET_COUNTER); | 277 | cnt = hpet_readl(HPET_COUNTER); |
278 | cnt += delta; | 278 | cnt += (u32) delta; |
279 | hpet_writel(cnt, HPET_T0_CMP); | 279 | hpet_writel(cnt, HPET_T0_CMP); |
280 | 280 | ||
281 | return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0) ? -ETIME : 0; | 281 | /* |
282 | * We need to read back the CMP register to make sure that | ||
283 | * what we wrote hit the chip before we compare it to the | ||
284 | * counter. | ||
285 | */ | ||
286 | WARN_ON((u32)hpet_readl(HPET_T0_CMP) != cnt); | ||
287 | |||
288 | return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; | ||
282 | } | 289 | } |
283 | 290 | ||
284 | /* | 291 | /* |
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c index 1c3a66a67f83..720d2607aacb 100644 --- a/arch/x86/kernel/io_delay.c +++ b/arch/x86/kernel/io_delay.c | |||
@@ -92,6 +92,14 @@ static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = { | |||
92 | DMI_MATCH(DMI_BOARD_NAME, "30BF") | 92 | DMI_MATCH(DMI_BOARD_NAME, "30BF") |
93 | } | 93 | } |
94 | }, | 94 | }, |
95 | { | ||
96 | .callback = dmi_io_delay_0xed_port, | ||
97 | .ident = "Presario F700", | ||
98 | .matches = { | ||
99 | DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), | ||
100 | DMI_MATCH(DMI_BOARD_NAME, "30D3") | ||
101 | } | ||
102 | }, | ||
95 | { } | 103 | { } |
96 | }; | 104 | }; |
97 | 105 | ||
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index e43938086885..2e2af5d18191 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c | |||
@@ -72,21 +72,28 @@ static ssize_t msr_read(struct file *file, char __user *buf, | |||
72 | u32 data[2]; | 72 | u32 data[2]; |
73 | u32 reg = *ppos; | 73 | u32 reg = *ppos; |
74 | int cpu = iminor(file->f_path.dentry->d_inode); | 74 | int cpu = iminor(file->f_path.dentry->d_inode); |
75 | int err; | 75 | int err = 0; |
76 | ssize_t bytes = 0; | ||
76 | 77 | ||
77 | if (count % 8) | 78 | if (count % 8) |
78 | return -EINVAL; /* Invalid chunk size */ | 79 | return -EINVAL; /* Invalid chunk size */ |
79 | 80 | ||
80 | for (; count; count -= 8) { | 81 | for (; count; count -= 8) { |
81 | err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]); | 82 | err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]); |
82 | if (err) | 83 | if (err) { |
83 | return -EIO; | 84 | if (err == -EFAULT) /* Fix idiotic error code */ |
84 | if (copy_to_user(tmp, &data, 8)) | 85 | err = -EIO; |
85 | return -EFAULT; | 86 | break; |
87 | } | ||
88 | if (copy_to_user(tmp, &data, 8)) { | ||
89 | err = -EFAULT; | ||
90 | break; | ||
91 | } | ||
86 | tmp += 2; | 92 | tmp += 2; |
93 | bytes += 8; | ||
87 | } | 94 | } |
88 | 95 | ||
89 | return ((char __user *)tmp) - buf; | 96 | return bytes ? bytes : err; |
90 | } | 97 | } |
91 | 98 | ||
92 | static ssize_t msr_write(struct file *file, const char __user *buf, | 99 | static ssize_t msr_write(struct file *file, const char __user *buf, |
@@ -96,21 +103,28 @@ static ssize_t msr_write(struct file *file, const char __user *buf, | |||
96 | u32 data[2]; | 103 | u32 data[2]; |
97 | u32 reg = *ppos; | 104 | u32 reg = *ppos; |
98 | int cpu = iminor(file->f_path.dentry->d_inode); | 105 | int cpu = iminor(file->f_path.dentry->d_inode); |
99 | int err; | 106 | int err = 0; |
107 | ssize_t bytes = 0; | ||
100 | 108 | ||
101 | if (count % 8) | 109 | if (count % 8) |
102 | return -EINVAL; /* Invalid chunk size */ | 110 | return -EINVAL; /* Invalid chunk size */ |
103 | 111 | ||
104 | for (; count; count -= 8) { | 112 | for (; count; count -= 8) { |
105 | if (copy_from_user(&data, tmp, 8)) | 113 | if (copy_from_user(&data, tmp, 8)) { |
106 | return -EFAULT; | 114 | err = -EFAULT; |
115 | break; | ||
116 | } | ||
107 | err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); | 117 | err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); |
108 | if (err) | 118 | if (err) { |
109 | return -EIO; | 119 | if (err == -EFAULT) /* Fix idiotic error code */ |
120 | err = -EIO; | ||
121 | break; | ||
122 | } | ||
110 | tmp += 2; | 123 | tmp += 2; |
124 | bytes += 8; | ||
111 | } | 125 | } |
112 | 126 | ||
113 | return ((char __user *)tmp) - buf; | 127 | return bytes ? bytes : err; |
114 | } | 128 | } |
115 | 129 | ||
116 | static int msr_open(struct inode *inode, struct file *file) | 130 | static int msr_open(struct inode *inode, struct file *file) |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index a4656adab53b..362d4e7f2d38 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -604,14 +604,6 @@ void __init setup_arch(char **cmdline_p) | |||
604 | early_cpu_init(); | 604 | early_cpu_init(); |
605 | early_ioremap_init(); | 605 | early_ioremap_init(); |
606 | 606 | ||
607 | #if defined(CONFIG_VMI) && defined(CONFIG_X86_32) | ||
608 | /* | ||
609 | * Must be before kernel pagetables are setup | ||
610 | * or fixmap area is touched. | ||
611 | */ | ||
612 | vmi_init(); | ||
613 | #endif | ||
614 | |||
615 | ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev); | 607 | ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev); |
616 | screen_info = boot_params.screen_info; | 608 | screen_info = boot_params.screen_info; |
617 | edid_info = boot_params.edid_info; | 609 | edid_info = boot_params.edid_info; |
@@ -678,6 +670,14 @@ void __init setup_arch(char **cmdline_p) | |||
678 | 670 | ||
679 | parse_early_param(); | 671 | parse_early_param(); |
680 | 672 | ||
673 | #if defined(CONFIG_VMI) && defined(CONFIG_X86_32) | ||
674 | /* | ||
675 | * Must be before kernel pagetables are setup | ||
676 | * or fixmap area is touched. | ||
677 | */ | ||
678 | vmi_init(); | ||
679 | #endif | ||
680 | |||
681 | /* after early param, so could get panic from serial */ | 681 | /* after early param, so could get panic from serial */ |
682 | reserve_early_setup_data(); | 682 | reserve_early_setup_data(); |
683 | 683 | ||
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index e139e617f422..7985c5b3f916 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -1221,6 +1221,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
1221 | printk(KERN_INFO "CPU%d: ", 0); | 1221 | printk(KERN_INFO "CPU%d: ", 0); |
1222 | print_cpu_info(&cpu_data(0)); | 1222 | print_cpu_info(&cpu_data(0)); |
1223 | setup_boot_clock(); | 1223 | setup_boot_clock(); |
1224 | |||
1225 | if (is_uv_system()) | ||
1226 | uv_system_init(); | ||
1224 | out: | 1227 | out: |
1225 | preempt_enable(); | 1228 | preempt_enable(); |
1226 | } | 1229 | } |
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 46af71676738..8f98e9de1b82 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
@@ -122,80 +122,216 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet) | |||
122 | return ULLONG_MAX; | 122 | return ULLONG_MAX; |
123 | } | 123 | } |
124 | 124 | ||
125 | /** | 125 | /* |
126 | * native_calibrate_tsc - calibrate the tsc on boot | 126 | * Try to calibrate the TSC against the Programmable |
127 | * Interrupt Timer and return the frequency of the TSC | ||
128 | * in kHz. | ||
129 | * | ||
130 | * Return ULONG_MAX on failure to calibrate. | ||
127 | */ | 131 | */ |
128 | unsigned long native_calibrate_tsc(void) | 132 | static unsigned long pit_calibrate_tsc(void) |
129 | { | 133 | { |
130 | unsigned long flags; | 134 | u64 tsc, t1, t2, delta; |
131 | u64 tsc1, tsc2, tr1, tr2, delta, pm1, pm2, hpet1, hpet2; | 135 | unsigned long tscmin, tscmax; |
132 | int hpet = is_hpet_enabled(); | 136 | int pitcnt; |
133 | unsigned int tsc_khz_val = 0; | ||
134 | |||
135 | local_irq_save(flags); | ||
136 | |||
137 | tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL); | ||
138 | 137 | ||
138 | /* Set the Gate high, disable speaker */ | ||
139 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); | 139 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); |
140 | 140 | ||
141 | /* | ||
142 | * Setup CTC channel 2* for mode 0, (interrupt on terminal | ||
143 | * count mode), binary count. Set the latch register to 50ms | ||
144 | * (LSB then MSB) to begin countdown. | ||
145 | */ | ||
141 | outb(0xb0, 0x43); | 146 | outb(0xb0, 0x43); |
142 | outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42); | 147 | outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42); |
143 | outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42); | 148 | outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42); |
144 | tr1 = get_cycles(); | ||
145 | while ((inb(0x61) & 0x20) == 0); | ||
146 | tr2 = get_cycles(); | ||
147 | 149 | ||
148 | tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL); | 150 | tsc = t1 = t2 = get_cycles(); |
149 | 151 | ||
150 | local_irq_restore(flags); | 152 | pitcnt = 0; |
153 | tscmax = 0; | ||
154 | tscmin = ULONG_MAX; | ||
155 | while ((inb(0x61) & 0x20) == 0) { | ||
156 | t2 = get_cycles(); | ||
157 | delta = t2 - tsc; | ||
158 | tsc = t2; | ||
159 | if ((unsigned long) delta < tscmin) | ||
160 | tscmin = (unsigned int) delta; | ||
161 | if ((unsigned long) delta > tscmax) | ||
162 | tscmax = (unsigned int) delta; | ||
163 | pitcnt++; | ||
164 | } | ||
151 | 165 | ||
152 | /* | 166 | /* |
153 | * Preset the result with the raw and inaccurate PIT | 167 | * Sanity checks: |
154 | * calibration value | 168 | * |
169 | * If we were not able to read the PIT more than 5000 | ||
170 | * times, then we have been hit by a massive SMI | ||
171 | * | ||
172 | * If the maximum is 10 times larger than the minimum, | ||
173 | * then we got hit by an SMI as well. | ||
155 | */ | 174 | */ |
156 | delta = (tr2 - tr1); | 175 | if (pitcnt < 5000 || tscmax > 10 * tscmin) |
176 | return ULONG_MAX; | ||
177 | |||
178 | /* Calculate the PIT value */ | ||
179 | delta = t2 - t1; | ||
157 | do_div(delta, 50); | 180 | do_div(delta, 50); |
158 | tsc_khz_val = delta; | 181 | return delta; |
182 | } | ||
183 | |||
184 | |||
185 | /** | ||
186 | * native_calibrate_tsc - calibrate the tsc on boot | ||
187 | */ | ||
188 | unsigned long native_calibrate_tsc(void) | ||
189 | { | ||
190 | u64 tsc1, tsc2, delta, pm1, pm2, hpet1, hpet2; | ||
191 | unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; | ||
192 | unsigned long flags; | ||
193 | int hpet = is_hpet_enabled(), i; | ||
194 | |||
195 | /* | ||
196 | * Run 5 calibration loops to get the lowest frequency value | ||
197 | * (the best estimate). We use two different calibration modes | ||
198 | * here: | ||
199 | * | ||
200 | * 1) PIT loop. We set the PIT Channel 2 to oneshot mode and | ||
201 | * load a timeout of 50ms. We read the time right after we | ||
202 | * started the timer and wait until the PIT count down reaches | ||
203 | * zero. In each wait loop iteration we read the TSC and check | ||
204 | * the delta to the previous read. We keep track of the min | ||
205 | * and max values of that delta. The delta is mostly defined | ||
206 | * by the IO time of the PIT access, so we can detect when a | ||
207 | * SMI/SMM disturbance happend between the two reads. If the | ||
208 | * maximum time is significantly larger than the minimum time, | ||
209 | * then we discard the result and have another try. | ||
210 | * | ||
211 | * 2) Reference counter. If available we use the HPET or the | ||
212 | * PMTIMER as a reference to check the sanity of that value. | ||
213 | * We use separate TSC readouts and check inside of the | ||
214 | * reference read for a SMI/SMM disturbance. We dicard | ||
215 | * disturbed values here as well. We do that around the PIT | ||
216 | * calibration delay loop as we have to wait for a certain | ||
217 | * amount of time anyway. | ||
218 | */ | ||
219 | for (i = 0; i < 5; i++) { | ||
220 | unsigned long tsc_pit_khz; | ||
221 | |||
222 | /* | ||
223 | * Read the start value and the reference count of | ||
224 | * hpet/pmtimer when available. Then do the PIT | ||
225 | * calibration, which will take at least 50ms, and | ||
226 | * read the end value. | ||
227 | */ | ||
228 | local_irq_save(flags); | ||
229 | tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL); | ||
230 | tsc_pit_khz = pit_calibrate_tsc(); | ||
231 | tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL); | ||
232 | local_irq_restore(flags); | ||
233 | |||
234 | /* Pick the lowest PIT TSC calibration so far */ | ||
235 | tsc_pit_min = min(tsc_pit_min, tsc_pit_khz); | ||
236 | |||
237 | /* hpet or pmtimer available ? */ | ||
238 | if (!hpet && !pm1 && !pm2) | ||
239 | continue; | ||
240 | |||
241 | /* Check, whether the sampling was disturbed by an SMI */ | ||
242 | if (tsc1 == ULLONG_MAX || tsc2 == ULLONG_MAX) | ||
243 | continue; | ||
244 | |||
245 | tsc2 = (tsc2 - tsc1) * 1000000LL; | ||
246 | |||
247 | if (hpet) { | ||
248 | if (hpet2 < hpet1) | ||
249 | hpet2 += 0x100000000ULL; | ||
250 | hpet2 -= hpet1; | ||
251 | tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); | ||
252 | do_div(tsc1, 1000000); | ||
253 | } else { | ||
254 | if (pm2 < pm1) | ||
255 | pm2 += (u64)ACPI_PM_OVRRUN; | ||
256 | pm2 -= pm1; | ||
257 | tsc1 = pm2 * 1000000000LL; | ||
258 | do_div(tsc1, PMTMR_TICKS_PER_SEC); | ||
259 | } | ||
260 | |||
261 | do_div(tsc2, tsc1); | ||
262 | tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Now check the results. | ||
267 | */ | ||
268 | if (tsc_pit_min == ULONG_MAX) { | ||
269 | /* PIT gave no useful value */ | ||
270 | printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n"); | ||
271 | |||
272 | /* We don't have an alternative source, disable TSC */ | ||
273 | if (!hpet && !pm1 && !pm2) { | ||
274 | printk("TSC: No reference (HPET/PMTIMER) available\n"); | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /* The alternative source failed as well, disable TSC */ | ||
279 | if (tsc_ref_min == ULONG_MAX) { | ||
280 | printk(KERN_WARNING "TSC: HPET/PMTIMER calibration " | ||
281 | "failed due to SMI disturbance.\n"); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /* Use the alternative source */ | ||
286 | printk(KERN_INFO "TSC: using %s reference calibration\n", | ||
287 | hpet ? "HPET" : "PMTIMER"); | ||
288 | |||
289 | return tsc_ref_min; | ||
290 | } | ||
159 | 291 | ||
160 | /* hpet or pmtimer available ? */ | 292 | /* We don't have an alternative source, use the PIT calibration value */ |
161 | if (!hpet && !pm1 && !pm2) { | 293 | if (!hpet && !pm1 && !pm2) { |
162 | printk(KERN_INFO "TSC calibrated against PIT\n"); | 294 | printk(KERN_INFO "TSC: Using PIT calibration value\n"); |
163 | goto out; | 295 | return tsc_pit_min; |
164 | } | 296 | } |
165 | 297 | ||
166 | /* Check, whether the sampling was disturbed by an SMI */ | 298 | /* The alternative source failed, use the PIT calibration value */ |
167 | if (tsc1 == ULLONG_MAX || tsc2 == ULLONG_MAX) { | 299 | if (tsc_ref_min == ULONG_MAX) { |
168 | printk(KERN_WARNING "TSC calibration disturbed by SMI, " | 300 | printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed due " |
169 | "using PIT calibration result\n"); | 301 | "to SMI disturbance. Using PIT calibration\n"); |
170 | goto out; | 302 | return tsc_pit_min; |
171 | } | 303 | } |
172 | 304 | ||
173 | tsc2 = (tsc2 - tsc1) * 1000000LL; | 305 | /* Check the reference deviation */ |
174 | 306 | delta = ((u64) tsc_pit_min) * 100; | |
175 | if (hpet) { | 307 | do_div(delta, tsc_ref_min); |
176 | printk(KERN_INFO "TSC calibrated against HPET\n"); | 308 | |
177 | if (hpet2 < hpet1) | 309 | /* |
178 | hpet2 += 0x100000000ULL; | 310 | * If both calibration results are inside a 5% window, the we |
179 | hpet2 -= hpet1; | 311 | * use the lower frequency of those as it is probably the |
180 | tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); | 312 | * closest estimate. |
181 | do_div(tsc1, 1000000); | 313 | */ |
182 | } else { | 314 | if (delta >= 95 && delta <= 105) { |
183 | printk(KERN_INFO "TSC calibrated against PM_TIMER\n"); | 315 | printk(KERN_INFO "TSC: PIT calibration confirmed by %s.\n", |
184 | if (pm2 < pm1) | 316 | hpet ? "HPET" : "PMTIMER"); |
185 | pm2 += (u64)ACPI_PM_OVRRUN; | 317 | printk(KERN_INFO "TSC: using %s calibration value\n", |
186 | pm2 -= pm1; | 318 | tsc_pit_min <= tsc_ref_min ? "PIT" : |
187 | tsc1 = pm2 * 1000000000LL; | 319 | hpet ? "HPET" : "PMTIMER"); |
188 | do_div(tsc1, PMTMR_TICKS_PER_SEC); | 320 | return tsc_pit_min <= tsc_ref_min ? tsc_pit_min : tsc_ref_min; |
189 | } | 321 | } |
190 | 322 | ||
191 | do_div(tsc2, tsc1); | 323 | printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n", |
192 | tsc_khz_val = tsc2; | 324 | hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min); |
193 | 325 | ||
194 | out: | 326 | /* |
195 | return tsc_khz_val; | 327 | * The calibration values differ too much. In doubt, we use |
328 | * the PIT value as we know that there are PMTIMERs around | ||
329 | * running at double speed. | ||
330 | */ | ||
331 | printk(KERN_INFO "TSC: Using PIT calibration value\n"); | ||
332 | return tsc_pit_min; | ||
196 | } | 333 | } |
197 | 334 | ||
198 | |||
199 | #ifdef CONFIG_X86_32 | 335 | #ifdef CONFIG_X86_32 |
200 | /* Only called from the Powernow K7 cpu freq driver */ | 336 | /* Only called from the Powernow K7 cpu freq driver */ |
201 | int recalibrate_cpu_khz(void) | 337 | int recalibrate_cpu_khz(void) |
@@ -314,7 +450,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | |||
314 | mark_tsc_unstable("cpufreq changes"); | 450 | mark_tsc_unstable("cpufreq changes"); |
315 | } | 451 | } |
316 | 452 | ||
317 | set_cyc2ns_scale(tsc_khz_ref, freq->cpu); | 453 | set_cyc2ns_scale(tsc_khz, freq->cpu); |
318 | 454 | ||
319 | return 0; | 455 | return 0; |
320 | } | 456 | } |
@@ -325,6 +461,10 @@ static struct notifier_block time_cpufreq_notifier_block = { | |||
325 | 461 | ||
326 | static int __init cpufreq_tsc(void) | 462 | static int __init cpufreq_tsc(void) |
327 | { | 463 | { |
464 | if (!cpu_has_tsc) | ||
465 | return 0; | ||
466 | if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | ||
467 | return 0; | ||
328 | cpufreq_register_notifier(&time_cpufreq_notifier_block, | 468 | cpufreq_register_notifier(&time_cpufreq_notifier_block, |
329 | CPUFREQ_TRANSITION_NOTIFIER); | 469 | CPUFREQ_TRANSITION_NOTIFIER); |
330 | return 0; | 470 | return 0; |