X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fmtrr.c;h=ec3be4f3aa66fcf76eed22183ab87ce30ed92dbe;hb=refs%2Fheads%2Fcoreboot;hp=d14a25c4ba683e969046b7bd83213bf942e5eaad;hpb=b1b7c2a1c3b940b787fdb5da67fc37003e9d7b0e;p=seabios.git diff --git a/src/mtrr.c b/src/mtrr.c index d14a25c..ec3be4f 100644 --- a/src/mtrr.c +++ b/src/mtrr.c @@ -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 @@ -24,66 +25,79 @@ #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) -static u64 rdmsr(unsigned index) -{ - unsigned long long ret; - - asm ("rdmsr" : "=A"(ret) : "c"(index)); - return ret; -} - -static void wrmsr(unsigned index, u64 val) -{ - asm volatile ("wrmsr" : : "c"(index), "A"(val)); -} - -static void wrmsr_smp(u32 index, u64 val) -{ - // XXX - should run this on other CPUs also. - wrmsr(index, val); -} +#define MTRR_MEMTYPE_UC 0 +#define MTRR_MEMTYPE_WC 1 +#define MTRR_MEMTYPE_WT 4 +#define MTRR_MEMTYPE_WP 5 +#define MTRR_MEMTYPE_WB 6 void mtrr_setup(void) { - if (! CONFIG_KVM) + if (!CONFIG_MTRR_INIT || CONFIG_COREBOOT || usingXen()) + return; + + u32 eax, ebx, ecx, edx, cpuid_features; + cpuid(1, &eax, &ebx, &ecx, &cpuid_features); + if (!(cpuid_features & CPUID_MTRR)) return; + if (!(cpuid_features & CPUID_MSR)) + return; + dprintf(3, "init mtrr\n"); - int i, vcnt, fix, wc; - u32 ram_size = GET_GLOBAL(RamSize); - u32 mtrr_cap; - union { + u32 mtrr_cap = rdmsr(MSR_MTRRcap); + int vcnt = mtrr_cap & 0xff; + int fix = mtrr_cap & 0x100; + if (!vcnt || !fix) + return; + + // Disable MTRRs + wrmsr_smp(MSR_MTRRdefType, 0); + + // Set fixed MTRRs + union u64b { u8 valb[8]; u64 val; } u; - - mtrr_cap = rdmsr(MSR_MTRRcap); - vcnt = mtrr_cap & 0xff; - fix = mtrr_cap & 0x100; - wc = mtrr_cap & 0x400; - if (!vcnt || !fix) - return; u.val = 0; - for (i = 0; i < 8; ++i) - if (ram_size >= 65536 * (i + 1)) - u.valb[i] = 6; + 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 (ram_size >= 65536 * 8 + 16384 * (i + 1)) - u.valb[i] = 6; + 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); + } + + // 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; + } + u64 phys_mask = ((1ull << phys_bits) - 1); + for (i=0; i