|
|
1.1 ! root 1: // Initialize MTRRs - mostly useful on KVM. ! 2: // ! 3: // Copyright (C) 2006 Fabrice Bellard ! 4: // ! 5: // This file may be distributed under the terms of the GNU LGPLv3 license. ! 6: ! 7: #include "util.h" // dprintf ! 8: #include "biosvar.h" // GET_EBDA ! 9: ! 10: #define MSR_MTRRcap 0x000000fe ! 11: #define MSR_MTRRfix64K_00000 0x00000250 ! 12: #define MSR_MTRRfix16K_80000 0x00000258 ! 13: #define MSR_MTRRfix16K_A0000 0x00000259 ! 14: #define MSR_MTRRfix4K_C0000 0x00000268 ! 15: #define MSR_MTRRfix4K_C8000 0x00000269 ! 16: #define MSR_MTRRfix4K_D0000 0x0000026a ! 17: #define MSR_MTRRfix4K_D8000 0x0000026b ! 18: #define MSR_MTRRfix4K_E0000 0x0000026c ! 19: #define MSR_MTRRfix4K_E8000 0x0000026d ! 20: #define MSR_MTRRfix4K_F0000 0x0000026e ! 21: #define MSR_MTRRfix4K_F8000 0x0000026f ! 22: #define MSR_MTRRdefType 0x000002ff ! 23: ! 24: #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) ! 25: #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) ! 26: ! 27: void mtrr_setup(void) ! 28: { ! 29: if (CONFIG_COREBOOT) ! 30: return; ! 31: ! 32: u32 eax, ebx, ecx, edx, cpuid_features; ! 33: cpuid(1, &eax, &ebx, &ecx, &cpuid_features); ! 34: if (!(cpuid_features & CPUID_MTRR)) ! 35: return; ! 36: if (!(cpuid_features & CPUID_MSR)) ! 37: return; ! 38: ! 39: dprintf(3, "init mtrr\n"); ! 40: ! 41: int i, vcnt, fix, wc; ! 42: u32 ram_size = GET_GLOBAL(RamSize); ! 43: u32 mtrr_cap; ! 44: union { ! 45: u8 valb[8]; ! 46: u64 val; ! 47: } u; ! 48: ! 49: mtrr_cap = rdmsr(MSR_MTRRcap); ! 50: vcnt = mtrr_cap & 0xff; ! 51: fix = mtrr_cap & 0x100; ! 52: wc = mtrr_cap & 0x400; ! 53: if (!vcnt || !fix) ! 54: return; ! 55: u.val = 0; ! 56: for (i = 0; i < 8; ++i) ! 57: if (ram_size >= 65536 * (i + 1)) ! 58: u.valb[i] = 6; ! 59: wrmsr_smp(MSR_MTRRfix64K_00000, u.val); ! 60: u.val = 0; ! 61: for (i = 0; i < 8; ++i) ! 62: if (ram_size >= 65536 * 8 + 16384 * (i + 1)) ! 63: u.valb[i] = 6; ! 64: wrmsr_smp(MSR_MTRRfix16K_80000, u.val); ! 65: wrmsr_smp(MSR_MTRRfix16K_A0000, 0); ! 66: wrmsr_smp(MSR_MTRRfix4K_C0000, 0); ! 67: wrmsr_smp(MSR_MTRRfix4K_C8000, 0); ! 68: wrmsr_smp(MSR_MTRRfix4K_D0000, 0); ! 69: wrmsr_smp(MSR_MTRRfix4K_D8000, 0); ! 70: wrmsr_smp(MSR_MTRRfix4K_E0000, 0); ! 71: wrmsr_smp(MSR_MTRRfix4K_E8000, 0); ! 72: wrmsr_smp(MSR_MTRRfix4K_F0000, 0); ! 73: wrmsr_smp(MSR_MTRRfix4K_F8000, 0); ! 74: /* Mark 3.5-4GB as UC, anything not specified defaults to WB */ ! 75: wrmsr_smp(MTRRphysBase_MSR(0), 0xe0000000ull | 0); ! 76: ! 77: int phys_bits = 36; ! 78: cpuid(0x80000000u, &eax, &ebx, &ecx, &edx); ! 79: if (eax >= 0x80000008) { ! 80: /* Get physical bits from leaf 0x80000008 (if available) */ ! 81: cpuid(0x80000008u, &eax, &ebx, &ecx, &edx); ! 82: phys_bits = eax & 0xff; ! 83: } ! 84: u64 phys_mask = ((1ull << phys_bits) - 1); ! 85: wrmsr_smp(MTRRphysMask_MSR(0), (~(0x20000000ull - 1) & phys_mask) | 0x800); ! 86: ! 87: wrmsr_smp(MSR_MTRRdefType, 0xc06); ! 88: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.