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 | |
| 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')
| -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) |
