diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-09-14 05:33:15 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-14 08:09:13 -0400 |
commit | aef93c8bd506a78983d91cd576a97fee6e934ac1 (patch) | |
tree | ecefbd11687673a0c5234450a421beef29adb214 /arch/x86/kernel/cpu | |
parent | e38e05a85828dac23540cd007df5f20985388afc (diff) |
x86: identify_cpu_without_cpuid v2
Krzysztof found some old cyrix cpu where an mtrr-alike cpu feature was
not detected properly.
this one is based on Krzysztof' patch, and we call ->c_identify() in
early_identify_cpu.
need to call c_identify() for cpus without cpuid even earlier ...
v2: Krzysztof point out need to give cyrix another chance about cpuid
checking again, after ->c_identify() enables cpuid for it
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Cc: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 57 |
1 files changed, 40 insertions, 17 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 9a57106c1995..f5f25b85be95 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -485,6 +485,33 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) | |||
485 | c->x86_power = cpuid_edx(0x80000007); | 485 | c->x86_power = cpuid_edx(0x80000007); |
486 | 486 | ||
487 | } | 487 | } |
488 | |||
489 | static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c) | ||
490 | { | ||
491 | #ifdef CONFIG_X86_32 | ||
492 | int i; | ||
493 | |||
494 | /* | ||
495 | * First of all, decide if this is a 486 or higher | ||
496 | * It's a 486 if we can modify the AC flag | ||
497 | */ | ||
498 | if (flag_is_changeable_p(X86_EFLAGS_AC)) | ||
499 | c->x86 = 4; | ||
500 | else | ||
501 | c->x86 = 3; | ||
502 | |||
503 | for (i = 0; i < X86_VENDOR_NUM; i++) | ||
504 | if (cpu_devs[i] && cpu_devs[i]->c_identify) { | ||
505 | c->x86_vendor_id[0] = 0; | ||
506 | cpu_devs[i]->c_identify(c); | ||
507 | if (c->x86_vendor_id[0]) { | ||
508 | get_cpu_vendor(c); | ||
509 | break; | ||
510 | } | ||
511 | } | ||
512 | #endif | ||
513 | } | ||
514 | |||
488 | /* | 515 | /* |
489 | * Do minimum CPU detection early. | 516 | * Do minimum CPU detection early. |
490 | * Fields really needed: vendor, cpuid_level, family, model, mask, | 517 | * Fields really needed: vendor, cpuid_level, family, model, mask, |
@@ -503,13 +530,16 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) | |||
503 | #endif | 530 | #endif |
504 | c->x86_cache_alignment = c->x86_clflush_size; | 531 | c->x86_cache_alignment = c->x86_clflush_size; |
505 | 532 | ||
506 | if (!have_cpuid_p()) | ||
507 | return; | ||
508 | |||
509 | memset(&c->x86_capability, 0, sizeof c->x86_capability); | 533 | memset(&c->x86_capability, 0, sizeof c->x86_capability); |
510 | |||
511 | c->extended_cpuid_level = 0; | 534 | c->extended_cpuid_level = 0; |
512 | 535 | ||
536 | if (!have_cpuid_p()) | ||
537 | identify_cpu_without_cpuid(c); | ||
538 | |||
539 | /* cyrix could have cpuid enabled via c_identify()*/ | ||
540 | if (!have_cpuid()) | ||
541 | return; | ||
542 | |||
513 | cpu_detect(c); | 543 | cpu_detect(c); |
514 | 544 | ||
515 | get_cpu_vendor(c); | 545 | get_cpu_vendor(c); |
@@ -583,10 +613,14 @@ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) | |||
583 | 613 | ||
584 | static void __cpuinit generic_identify(struct cpuinfo_x86 *c) | 614 | static void __cpuinit generic_identify(struct cpuinfo_x86 *c) |
585 | { | 615 | { |
616 | c->extended_cpuid_level = 0; | ||
617 | |||
586 | if (!have_cpuid_p()) | 618 | if (!have_cpuid_p()) |
587 | return; | 619 | identify_cpu_without_cpuid(c); |
588 | 620 | ||
589 | c->extended_cpuid_level = 0; | 621 | /* cyrix could have cpuid enabled via c_identify()*/ |
622 | if (!have_cpuid()) | ||
623 | return; | ||
590 | 624 | ||
591 | cpu_detect(c); | 625 | cpu_detect(c); |
592 | 626 | ||
@@ -639,17 +673,6 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) | |||
639 | c->x86_cache_alignment = c->x86_clflush_size; | 673 | c->x86_cache_alignment = c->x86_clflush_size; |
640 | memset(&c->x86_capability, 0, sizeof c->x86_capability); | 674 | memset(&c->x86_capability, 0, sizeof c->x86_capability); |
641 | 675 | ||
642 | if (!have_cpuid_p()) { | ||
643 | /* | ||
644 | * First of all, decide if this is a 486 or higher | ||
645 | * It's a 486 if we can modify the AC flag | ||
646 | */ | ||
647 | if (flag_is_changeable_p(X86_EFLAGS_AC)) | ||
648 | c->x86 = 4; | ||
649 | else | ||
650 | c->x86 = 3; | ||
651 | } | ||
652 | |||
653 | generic_identify(c); | 676 | generic_identify(c); |
654 | 677 | ||
655 | if (this_cpu->c_identify) | 678 | if (this_cpu->c_identify) |