|
|
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
1.1.1.4 root 9: #include "xen.h" // usingXen
1.1 root 10:
11: #define MSR_MTRRcap 0x000000fe
12: #define MSR_MTRRfix64K_00000 0x00000250
13: #define MSR_MTRRfix16K_80000 0x00000258
14: #define MSR_MTRRfix16K_A0000 0x00000259
15: #define MSR_MTRRfix4K_C0000 0x00000268
16: #define MSR_MTRRfix4K_C8000 0x00000269
17: #define MSR_MTRRfix4K_D0000 0x0000026a
18: #define MSR_MTRRfix4K_D8000 0x0000026b
19: #define MSR_MTRRfix4K_E0000 0x0000026c
20: #define MSR_MTRRfix4K_E8000 0x0000026d
21: #define MSR_MTRRfix4K_F0000 0x0000026e
22: #define MSR_MTRRfix4K_F8000 0x0000026f
23: #define MSR_MTRRdefType 0x000002ff
24:
25: #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
26: #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
27:
1.1.1.2 root 28: #define MTRR_MEMTYPE_UC 0
29: #define MTRR_MEMTYPE_WC 1
30: #define MTRR_MEMTYPE_WT 4
31: #define MTRR_MEMTYPE_WP 5
32: #define MTRR_MEMTYPE_WB 6
33:
1.1 root 34: void mtrr_setup(void)
35: {
1.1.1.4 root 36: if (!CONFIG_MTRR_INIT || CONFIG_COREBOOT || usingXen())
1.1 root 37: return;
38:
39: u32 eax, ebx, ecx, edx, cpuid_features;
40: cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
41: if (!(cpuid_features & CPUID_MTRR))
42: return;
43: if (!(cpuid_features & CPUID_MSR))
44: return;
45:
46: dprintf(3, "init mtrr\n");
47:
1.1.1.2 root 48: u32 mtrr_cap = rdmsr(MSR_MTRRcap);
49: int vcnt = mtrr_cap & 0xff;
50: int fix = mtrr_cap & 0x100;
51: if (!vcnt || !fix)
52: return;
53:
54: // Disable MTRRs
55: wrmsr_smp(MSR_MTRRdefType, 0);
56:
57: // Set fixed MTRRs
58: union u64b {
1.1 root 59: u8 valb[8];
60: u64 val;
61: } u;
62: u.val = 0;
1.1.1.2 root 63: int i;
64: for (i = 0; i < 8; i++)
65: if (RamSize >= 65536 * (i + 1))
66: u.valb[i] = MTRR_MEMTYPE_WB;
1.1 root 67: wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
68: u.val = 0;
1.1.1.2 root 69: for (i = 0; i < 8; i++)
70: if (RamSize >= 0x80000 + 16384 * (i + 1))
71: u.valb[i] = MTRR_MEMTYPE_WB;
1.1 root 72: wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
1.1.1.2 root 73: wrmsr_smp(MSR_MTRRfix16K_A0000, 0); // 0xA0000-0xC0000 is uncached
74: int j;
75: for (j = 0; j < 8; j++) {
76: u.val = 0;
77: for (i = 0; i < 8; i++)
78: if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1))
79: u.valb[i] = MTRR_MEMTYPE_WP;
80: wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val);
81: }
1.1 root 82:
1.1.1.2 root 83: // Set variable MTRRs
1.1 root 84: int phys_bits = 36;
85: cpuid(0x80000000u, &eax, &ebx, &ecx, &edx);
86: if (eax >= 0x80000008) {
1.1.1.5 ! root 87: /* Get physical bits from leaf 0x80000008 (if available) */
! 88: cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
! 89: phys_bits = eax & 0xff;
1.1 root 90: }
91: u64 phys_mask = ((1ull << phys_bits) - 1);
1.1.1.2 root 92: for (i=0; i<vcnt; i++) {
93: wrmsr_smp(MTRRphysBase_MSR(i), 0);
94: wrmsr_smp(MTRRphysMask_MSR(i), 0);
95: }
96: /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
97: wrmsr_smp(MTRRphysBase_MSR(0), BUILD_MAX_HIGHMEM | MTRR_MEMTYPE_UC);
98: wrmsr_smp(MTRRphysMask_MSR(0)
99: , (-((1ull<<32)-BUILD_MAX_HIGHMEM) & phys_mask) | 0x800);
1.1 root 100:
1.1.1.2 root 101: // Enable fixed and variable MTRRs; set default type.
102: wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB);
1.1 root 103: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.