|
@@ -491,6 +491,147 @@ static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned i
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+#define TLB_INST_4K 0x01
|
|
|
|
+#define TLB_INST_4M 0x02
|
|
|
|
+#define TLB_INST_2M_4M 0x03
|
|
|
|
+
|
|
|
|
+#define TLB_INST_ALL 0x05
|
|
|
|
+#define TLB_INST_1G 0x06
|
|
|
|
+
|
|
|
|
+#define TLB_DATA_4K 0x11
|
|
|
|
+#define TLB_DATA_4M 0x12
|
|
|
|
+#define TLB_DATA_2M_4M 0x13
|
|
|
|
+#define TLB_DATA_4K_4M 0x14
|
|
|
|
+
|
|
|
|
+#define TLB_DATA_1G 0x16
|
|
|
|
+
|
|
|
|
+#define TLB_DATA0_4K 0x21
|
|
|
|
+#define TLB_DATA0_4M 0x22
|
|
|
|
+#define TLB_DATA0_2M_4M 0x23
|
|
|
|
+
|
|
|
|
+#define STLB_4K 0x41
|
|
|
|
+
|
|
|
|
+static const struct _tlb_table intel_tlb_table[] __cpuinitconst = {
|
|
|
|
+ { 0x01, TLB_INST_4K, 32, " TLB_INST 4 KByte pages, 4-way set associative" },
|
|
|
|
+ { 0x02, TLB_INST_4M, 2, " TLB_INST 4 MByte pages, full associative" },
|
|
|
|
+ { 0x03, TLB_DATA_4K, 64, " TLB_DATA 4 KByte pages, 4-way set associative" },
|
|
|
|
+ { 0x04, TLB_DATA_4M, 8, " TLB_DATA 4 MByte pages, 4-way set associative" },
|
|
|
|
+ { 0x05, TLB_DATA_4M, 32, " TLB_DATA 4 MByte pages, 4-way set associative" },
|
|
|
|
+ { 0x0b, TLB_INST_4M, 4, " TLB_INST 4 MByte pages, 4-way set associative" },
|
|
|
|
+ { 0x4f, TLB_INST_4K, 32, " TLB_INST 4 KByte pages */" },
|
|
|
|
+ { 0x50, TLB_INST_ALL, 64, " TLB_INST 4 KByte and 2-MByte or 4-MByte pages" },
|
|
|
|
+ { 0x51, TLB_INST_ALL, 128, " TLB_INST 4 KByte and 2-MByte or 4-MByte pages" },
|
|
|
|
+ { 0x52, TLB_INST_ALL, 256, " TLB_INST 4 KByte and 2-MByte or 4-MByte pages" },
|
|
|
|
+ { 0x55, TLB_INST_2M_4M, 7, " TLB_INST 2-MByte or 4-MByte pages, fully associative" },
|
|
|
|
+ { 0x56, TLB_DATA0_4M, 16, " TLB_DATA0 4 MByte pages, 4-way set associative" },
|
|
|
|
+ { 0x57, TLB_DATA0_4K, 16, " TLB_DATA0 4 KByte pages, 4-way associative" },
|
|
|
|
+ { 0x59, TLB_DATA0_4K, 16, " TLB_DATA0 4 KByte pages, fully associative" },
|
|
|
|
+ { 0x5a, TLB_DATA0_2M_4M, 32, " TLB_DATA0 2-MByte or 4 MByte pages, 4-way set associative" },
|
|
|
|
+ { 0x5b, TLB_DATA_4K_4M, 64, " TLB_DATA 4 KByte and 4 MByte pages" },
|
|
|
|
+ { 0x5c, TLB_DATA_4K_4M, 128, " TLB_DATA 4 KByte and 4 MByte pages" },
|
|
|
|
+ { 0x5d, TLB_DATA_4K_4M, 256, " TLB_DATA 4 KByte and 4 MByte pages" },
|
|
|
|
+ { 0xb0, TLB_INST_4K, 128, " TLB_INST 4 KByte pages, 4-way set associative" },
|
|
|
|
+ { 0xb1, TLB_INST_2M_4M, 4, " TLB_INST 2M pages, 4-way, 8 entries or 4M pages, 4-way entries" },
|
|
|
|
+ { 0xb2, TLB_INST_4K, 64, " TLB_INST 4KByte pages, 4-way set associative" },
|
|
|
|
+ { 0xb3, TLB_DATA_4K, 128, " TLB_DATA 4 KByte pages, 4-way set associative" },
|
|
|
|
+ { 0xb4, TLB_DATA_4K, 256, " TLB_DATA 4 KByte pages, 4-way associative" },
|
|
|
|
+ { 0xba, TLB_DATA_4K, 64, " TLB_DATA 4 KByte pages, 4-way associative" },
|
|
|
|
+ { 0xc0, TLB_DATA_4K_4M, 8, " TLB_DATA 4 KByte and 4 MByte pages, 4-way associative" },
|
|
|
|
+ { 0xca, STLB_4K, 512, " STLB 4 KByte pages, 4-way associative" },
|
|
|
|
+ { 0x00, 0, 0 }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static void __cpuinit intel_tlb_lookup(const unsigned char desc)
|
|
|
|
+{
|
|
|
|
+ unsigned char k;
|
|
|
|
+ if (desc == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ /* look up this descriptor in the table */
|
|
|
|
+ for (k = 0; intel_tlb_table[k].descriptor != desc && \
|
|
|
|
+ intel_tlb_table[k].descriptor != 0; k++)
|
|
|
|
+ ;
|
|
|
|
+
|
|
|
|
+ if (intel_tlb_table[k].tlb_type == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ switch (intel_tlb_table[k].tlb_type) {
|
|
|
|
+ case STLB_4K:
|
|
|
|
+ if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ break;
|
|
|
|
+ case TLB_INST_ALL:
|
|
|
|
+ if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ if (tlb_lli_2m[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lli_2m[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ if (tlb_lli_4m[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lli_4m[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ break;
|
|
|
|
+ case TLB_INST_4K:
|
|
|
|
+ if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ break;
|
|
|
|
+ case TLB_INST_4M:
|
|
|
|
+ if (tlb_lli_4m[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lli_4m[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ break;
|
|
|
|
+ case TLB_INST_2M_4M:
|
|
|
|
+ if (tlb_lli_2m[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lli_2m[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ if (tlb_lli_4m[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lli_4m[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ break;
|
|
|
|
+ case TLB_DATA_4K:
|
|
|
|
+ case TLB_DATA0_4K:
|
|
|
|
+ if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ break;
|
|
|
|
+ case TLB_DATA_4M:
|
|
|
|
+ case TLB_DATA0_4M:
|
|
|
|
+ if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ break;
|
|
|
|
+ case TLB_DATA_2M_4M:
|
|
|
|
+ case TLB_DATA0_2M_4M:
|
|
|
|
+ if (tlb_lld_2m[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lld_2m[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ break;
|
|
|
|
+ case TLB_DATA_4K_4M:
|
|
|
|
+ if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries)
|
|
|
|
+ tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void __cpuinit intel_detect_tlb(struct cpuinfo_x86 *c)
|
|
|
|
+{
|
|
|
|
+ int i, j, n;
|
|
|
|
+ unsigned int regs[4];
|
|
|
|
+ unsigned char *desc = (unsigned char *)regs;
|
|
|
|
+ /* Number of times to iterate */
|
|
|
|
+ n = cpuid_eax(2) & 0xFF;
|
|
|
|
+
|
|
|
|
+ for (i = 0 ; i < n ; i++) {
|
|
|
|
+ cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]);
|
|
|
|
+
|
|
|
|
+ /* If bit 31 is set, this is an unknown format */
|
|
|
|
+ for (j = 0 ; j < 3 ; j++)
|
|
|
|
+ if (regs[j] & (1 << 31))
|
|
|
|
+ regs[j] = 0;
|
|
|
|
+
|
|
|
|
+ /* Byte 0 is level count, not a descriptor */
|
|
|
|
+ for (j = 1 ; j < 16 ; j++)
|
|
|
|
+ intel_tlb_lookup(desc[j]);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct cpu_dev __cpuinitconst intel_cpu_dev = {
|
|
static const struct cpu_dev __cpuinitconst intel_cpu_dev = {
|
|
.c_vendor = "Intel",
|
|
.c_vendor = "Intel",
|
|
.c_ident = { "GenuineIntel" },
|
|
.c_ident = { "GenuineIntel" },
|
|
@@ -546,6 +687,7 @@ static const struct cpu_dev __cpuinitconst intel_cpu_dev = {
|
|
},
|
|
},
|
|
.c_size_cache = intel_size_cache,
|
|
.c_size_cache = intel_size_cache,
|
|
#endif
|
|
#endif
|
|
|
|
+ .c_detect_tlb = intel_detect_tlb,
|
|
.c_early_init = early_init_intel,
|
|
.c_early_init = early_init_intel,
|
|
.c_init = init_intel,
|
|
.c_init = init_intel,
|
|
.c_x86_vendor = X86_VENDOR_INTEL,
|
|
.c_x86_vendor = X86_VENDOR_INTEL,
|