diff options
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 9d92e19039f0..bcd200839c90 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
| @@ -737,6 +737,59 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, | |||
| 737 | } | 737 | } |
| 738 | #endif | 738 | #endif |
| 739 | 739 | ||
| 740 | static void __cpuinit cpu_detect_tlb_amd(struct cpuinfo_x86 *c) | ||
| 741 | { | ||
| 742 | u32 ebx, eax, ecx, edx; | ||
| 743 | u16 mask = 0xfff; | ||
| 744 | |||
| 745 | if (c->x86 < 0xf) | ||
| 746 | return; | ||
| 747 | |||
| 748 | if (c->extended_cpuid_level < 0x80000006) | ||
| 749 | return; | ||
| 750 | |||
| 751 | cpuid(0x80000006, &eax, &ebx, &ecx, &edx); | ||
| 752 | |||
| 753 | tlb_lld_4k[ENTRIES] = (ebx >> 16) & mask; | ||
| 754 | tlb_lli_4k[ENTRIES] = ebx & mask; | ||
| 755 | |||
| 756 | /* | ||
| 757 | * K8 doesn't have 2M/4M entries in the L2 TLB so read out the L1 TLB | ||
| 758 | * characteristics from the CPUID function 0x80000005 instead. | ||
| 759 | */ | ||
| 760 | if (c->x86 == 0xf) { | ||
| 761 | cpuid(0x80000005, &eax, &ebx, &ecx, &edx); | ||
| 762 | mask = 0xff; | ||
| 763 | } | ||
| 764 | |||
| 765 | /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ | ||
| 766 | if (!((eax >> 16) & mask)) { | ||
| 767 | u32 a, b, c, d; | ||
| 768 | |||
| 769 | cpuid(0x80000005, &a, &b, &c, &d); | ||
| 770 | tlb_lld_2m[ENTRIES] = (a >> 16) & 0xff; | ||
| 771 | } else { | ||
| 772 | tlb_lld_2m[ENTRIES] = (eax >> 16) & mask; | ||
| 773 | } | ||
| 774 | |||
| 775 | /* a 4M entry uses two 2M entries */ | ||
| 776 | tlb_lld_4m[ENTRIES] = tlb_lld_2m[ENTRIES] >> 1; | ||
| 777 | |||
| 778 | /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ | ||
| 779 | if (!(eax & mask)) { | ||
| 780 | /* Erratum 658 */ | ||
| 781 | if (c->x86 == 0x15 && c->x86_model <= 0x1f) { | ||
| 782 | tlb_lli_2m[ENTRIES] = 1024; | ||
| 783 | } else { | ||
| 784 | cpuid(0x80000005, &eax, &ebx, &ecx, &edx); | ||
| 785 | tlb_lli_2m[ENTRIES] = eax & 0xff; | ||
| 786 | } | ||
| 787 | } else | ||
| 788 | tlb_lli_2m[ENTRIES] = eax & mask; | ||
| 789 | |||
| 790 | tlb_lli_4m[ENTRIES] = tlb_lli_2m[ENTRIES] >> 1; | ||
| 791 | } | ||
| 792 | |||
| 740 | static const struct cpu_dev __cpuinitconst amd_cpu_dev = { | 793 | static const struct cpu_dev __cpuinitconst amd_cpu_dev = { |
| 741 | .c_vendor = "AMD", | 794 | .c_vendor = "AMD", |
| 742 | .c_ident = { "AuthenticAMD" }, | 795 | .c_ident = { "AuthenticAMD" }, |
| @@ -756,6 +809,7 @@ static const struct cpu_dev __cpuinitconst amd_cpu_dev = { | |||
| 756 | .c_size_cache = amd_size_cache, | 809 | .c_size_cache = amd_size_cache, |
| 757 | #endif | 810 | #endif |
| 758 | .c_early_init = early_init_amd, | 811 | .c_early_init = early_init_amd, |
| 812 | .c_detect_tlb = cpu_detect_tlb_amd, | ||
| 759 | .c_bsp_init = bsp_init_amd, | 813 | .c_bsp_init = bsp_init_amd, |
| 760 | .c_init = init_amd, | 814 | .c_init = init_amd, |
| 761 | .c_x86_vendor = X86_VENDOR_AMD, | 815 | .c_x86_vendor = X86_VENDOR_AMD, |
