grml...
[seabios.git] / src / mtrr.c
index 7d1df097e85bbdbc040a704e247db6976c106a3b..ec3be4f3aa66fcf76eed22183ab87ce30ed92dbe 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "util.h" // dprintf
 #include "biosvar.h" // GET_EBDA
+#include "xen.h" // usingXen
 
 #define MSR_MTRRcap                    0x000000fe
 #define MSR_MTRRfix64K_00000           0x00000250
@@ -32,7 +33,7 @@
 
 void mtrr_setup(void)
 {
-    if (CONFIG_COREBOOT)
+    if (!CONFIG_MTRR_INIT || CONFIG_COREBOOT || usingXen())
         return;
 
     u32 eax, ebx, ecx, edx, cpuid_features;
@@ -44,50 +45,54 @@ void mtrr_setup(void)
 
     dprintf(3, "init mtrr\n");
 
-    int i, vcnt, fix, wc;
-    u32 mtrr_cap;
-    union {
-        u8 valb[8];
-        u64 val;
-    } u;
-
-    mtrr_cap = rdmsr(MSR_MTRRcap);
-    vcnt = mtrr_cap & 0xff;
-    fix = mtrr_cap & 0x100;
-    wc = mtrr_cap & 0x400;
+    u32 mtrr_cap = rdmsr(MSR_MTRRcap);
+    int vcnt = mtrr_cap & 0xff;
+    int fix = mtrr_cap & 0x100;
     if (!vcnt || !fix)
        return;
 
-    // Fixed MTRRs
+    // Disable MTRRs
+    wrmsr_smp(MSR_MTRRdefType, 0);
+
+    // Set fixed MTRRs
+    union u64b {
+        u8 valb[8];
+        u64 val;
+    } u;
     u.val = 0;
-    for (i = 0; i < 8; ++i)
+    int i;
+    for (i = 0; i < 8; i++)
         if (RamSize >= 65536 * (i + 1))
             u.valb[i] = MTRR_MEMTYPE_WB;
     wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
     u.val = 0;
-    for (i = 0; i < 8; ++i)
-        if (RamSize >= 65536 * 8 + 16384 * (i + 1))
+    for (i = 0; i < 8; i++)
+        if (RamSize >= 0x80000 + 16384 * (i + 1))
             u.valb[i] = MTRR_MEMTYPE_WB;
     wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
-    wrmsr_smp(MSR_MTRRfix16K_A0000, 0);
-    wrmsr_smp(MSR_MTRRfix4K_C0000, 0);
-    wrmsr_smp(MSR_MTRRfix4K_C8000, 0);
-    wrmsr_smp(MSR_MTRRfix4K_D0000, 0);
-    wrmsr_smp(MSR_MTRRfix4K_D8000, 0);
-    wrmsr_smp(MSR_MTRRfix4K_E0000, 0);
-    wrmsr_smp(MSR_MTRRfix4K_E8000, 0);
-    wrmsr_smp(MSR_MTRRfix4K_F0000, 0);
-    wrmsr_smp(MSR_MTRRfix4K_F8000, 0);
+    wrmsr_smp(MSR_MTRRfix16K_A0000, 0);   // 0xA0000-0xC0000 is uncached
+    int j;
+    for (j = 0; j < 8; j++) {
+        u.val = 0;
+        for (i = 0; i < 8; i++)
+            if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1))
+                u.valb[i] = MTRR_MEMTYPE_WP;
+        wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val);
+    }
 
-    // Variable MTRRs
+    // Set variable MTRRs
     int phys_bits = 36;
     cpuid(0x80000000u, &eax, &ebx, &ecx, &edx);
     if (eax >= 0x80000008) {
-            /* Get physical bits from leaf 0x80000008 (if available) */
-            cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
-            phys_bits = eax & 0xff;
+        /* Get physical bits from leaf 0x80000008 (if available) */
+        cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
+        phys_bits = eax & 0xff;
     }
     u64 phys_mask = ((1ull << phys_bits) - 1);
+    for (i=0; i<vcnt; i++) {
+        wrmsr_smp(MTRRphysBase_MSR(i), 0);
+        wrmsr_smp(MTRRphysMask_MSR(i), 0);
+    }
     /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
     wrmsr_smp(MTRRphysBase_MSR(0), BUILD_MAX_HIGHMEM | MTRR_MEMTYPE_UC);
     wrmsr_smp(MTRRphysMask_MSR(0)