|
|
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.