1 // Initialize MTRRs - mostly useful on KVM.
3 // Copyright (C) 2006 Fabrice Bellard
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
7 #include "util.h" // dprintf
8 #include "biosvar.h" // GET_EBDA
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
24 #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
25 #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
27 #define MTRR_MEMTYPE_UC 0
28 #define MTRR_MEMTYPE_WC 1
29 #define MTRR_MEMTYPE_WT 4
30 #define MTRR_MEMTYPE_WP 5
31 #define MTRR_MEMTYPE_WB 6
38 u32 eax, ebx, ecx, edx, cpuid_features;
39 cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
40 if (!(cpuid_features & CPUID_MTRR))
42 if (!(cpuid_features & CPUID_MSR))
45 dprintf(3, "init mtrr\n");
54 mtrr_cap = rdmsr(MSR_MTRRcap);
55 vcnt = mtrr_cap & 0xff;
56 fix = mtrr_cap & 0x100;
57 wc = mtrr_cap & 0x400;
63 for (i = 0; i < 8; ++i)
64 if (RamSize >= 65536 * (i + 1))
65 u.valb[i] = MTRR_MEMTYPE_WB;
66 wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
68 for (i = 0; i < 8; ++i)
69 if (RamSize >= 65536 * 8 + 16384 * (i + 1))
70 u.valb[i] = MTRR_MEMTYPE_WB;
71 wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
72 wrmsr_smp(MSR_MTRRfix16K_A0000, 0);
73 wrmsr_smp(MSR_MTRRfix4K_C0000, 0);
74 wrmsr_smp(MSR_MTRRfix4K_C8000, 0);
75 wrmsr_smp(MSR_MTRRfix4K_D0000, 0);
76 wrmsr_smp(MSR_MTRRfix4K_D8000, 0);
77 wrmsr_smp(MSR_MTRRfix4K_E0000, 0);
78 wrmsr_smp(MSR_MTRRfix4K_E8000, 0);
79 wrmsr_smp(MSR_MTRRfix4K_F0000, 0);
80 wrmsr_smp(MSR_MTRRfix4K_F8000, 0);
84 cpuid(0x80000000u, &eax, &ebx, &ecx, &edx);
85 if (eax >= 0x80000008) {
86 /* Get physical bits from leaf 0x80000008 (if available) */
87 cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
88 phys_bits = eax & 0xff;
90 u64 phys_mask = ((1ull << phys_bits) - 1);
91 /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
92 wrmsr_smp(MTRRphysBase_MSR(0), BUILD_MAX_HIGHMEM | MTRR_MEMTYPE_UC);
93 wrmsr_smp(MTRRphysMask_MSR(0)
94 , (-((1ull<<32)-BUILD_MAX_HIGHMEM) & phys_mask) | 0x800);
96 // Enable fixed and variable MTRRs; set default type.
97 wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB);