aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <borislav.petkov@amd.com>2012-08-06 13:00:38 -0400
committerH. Peter Anvin <hpa@zytor.com>2012-08-06 22:18:34 -0400
commitb46882e4c4de4813947fce940fe74af794a1eb72 (patch)
tree786c342272340043c3415b9348fe6fcc3366f9bf
parent5b556332c3ab19e6375836d35ca658776e9ba0f6 (diff)
x86, cpu: Add AMD TLB size detection
Read I- and DTLB entries count from CPUID on AMD. Handle all the different family-specific cases. Signed-off-by: Borislav Petkov <borislav.petkov@amd.com> Link: http://lkml.kernel.org/r/1344272439-29080-4-git-send-email-bp@amd64.org Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/x86/kernel/cpu/amd.c54
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
740static 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
740static const struct cpu_dev __cpuinitconst amd_cpu_dev = { 793static 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,