]>
Commit | Line | Data |
---|---|---|
9a717b55 AL |
1 | add mtrr support (Avi Kivity) |
2 | ||
3 | program mtrrs for cpu 0. Doesn't support >=4G at the moment. | |
4 | ||
5 | Signed-off-by: Avi Kivity <avi@qumranet.com> | |
6 | Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> | |
7 | ||
8 | Index: bochs/bios/rombios32.c | |
9 | =================================================================== | |
10 | --- bochs.orig/bios/rombios32.c | |
11 | +++ bochs/bios/rombios32.c | |
12 | @@ -64,6 +64,23 @@ typedef unsigned long long uint64_t; | |
13 | ||
14 | #define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */ | |
15 | ||
16 | +#define MSR_MTRRcap 0x000000fe | |
17 | +#define MSR_MTRRfix64K_00000 0x00000250 | |
18 | +#define MSR_MTRRfix16K_80000 0x00000258 | |
19 | +#define MSR_MTRRfix16K_A0000 0x00000259 | |
20 | +#define MSR_MTRRfix4K_C0000 0x00000268 | |
21 | +#define MSR_MTRRfix4K_C8000 0x00000269 | |
22 | +#define MSR_MTRRfix4K_D0000 0x0000026a | |
23 | +#define MSR_MTRRfix4K_D8000 0x0000026b | |
24 | +#define MSR_MTRRfix4K_E0000 0x0000026c | |
25 | +#define MSR_MTRRfix4K_E8000 0x0000026d | |
26 | +#define MSR_MTRRfix4K_F0000 0x0000026e | |
27 | +#define MSR_MTRRfix4K_F8000 0x0000026f | |
28 | +#define MSR_MTRRdefType 0x000002ff | |
29 | + | |
30 | +#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) | |
31 | +#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) | |
32 | + | |
33 | static inline void outl(int addr, int val) | |
34 | { | |
35 | asm volatile ("outl %1, %w0" : : "d" (addr), "a" (val)); | |
36 | @@ -135,6 +152,19 @@ static inline void putc(int c) | |
37 | outb(INFO_PORT, c); | |
38 | } | |
39 | ||
40 | +static uint64_t rdmsr(unsigned index) | |
41 | +{ | |
42 | + unsigned long long ret; | |
43 | + | |
44 | + asm ("rdmsr" : "=A"(ret) : "c"(index)); | |
45 | + return ret; | |
46 | +} | |
47 | + | |
48 | +static void wrmsr(unsigned index, uint64_t val) | |
49 | +{ | |
50 | + asm volatile ("wrmsr" : : "c"(index), "A"(val)); | |
51 | +} | |
52 | + | |
53 | static inline int isdigit(int c) | |
54 | { | |
55 | return c >= '0' && c <= '9'; | |
56 | @@ -469,6 +499,54 @@ static int cmos_readb(int addr) | |
57 | return inb(0x71); | |
58 | } | |
59 | ||
60 | +void setup_mtrr(void) | |
61 | +{ | |
62 | + int i, vcnt, fix, wc; | |
63 | + uint32_t mtrr_cap; | |
64 | + union { | |
65 | + uint8_t valb[8]; | |
66 | + uint64_t val; | |
67 | + } u; | |
68 | + uint64_t vbase, vmask; | |
69 | + | |
70 | + mtrr_cap = rdmsr(MSR_MTRRcap); | |
71 | + vcnt = mtrr_cap & 0xff; | |
72 | + fix = mtrr_cap & 0x100; | |
73 | + wc = mtrr_cap & 0x400; | |
74 | + if (!vcnt || !fix) | |
75 | + return; | |
76 | + u.val = 0; | |
77 | + for (i = 0; i < 8; ++i) | |
78 | + if (ram_size >= 65536 * (i + 1)) | |
79 | + u.valb[i] = 6; | |
80 | + wrmsr(MSR_MTRRfix64K_00000, u.val); | |
81 | + u.val = 0; | |
82 | + for (i = 0; i < 8; ++i) | |
83 | + if (ram_size >= 65536 * 8 + 16384 * (i + 1)) | |
84 | + u.valb[i] = 6; | |
85 | + wrmsr(MSR_MTRRfix16K_80000, u.val); | |
86 | + wrmsr(MSR_MTRRfix16K_A0000, 0); | |
87 | + wrmsr(MSR_MTRRfix4K_C0000, 0); | |
88 | + wrmsr(MSR_MTRRfix4K_C8000, 0); | |
89 | + wrmsr(MSR_MTRRfix4K_D0000, 0); | |
90 | + wrmsr(MSR_MTRRfix4K_D8000, 0); | |
91 | + wrmsr(MSR_MTRRfix4K_E0000, 0); | |
92 | + wrmsr(MSR_MTRRfix4K_E8000, 0); | |
93 | + wrmsr(MSR_MTRRfix4K_F0000, 0); | |
94 | + wrmsr(MSR_MTRRfix4K_F8000, 0); | |
95 | + vbase = 0; | |
96 | + --vcnt; /* leave one mtrr for VRAM */ | |
97 | + for (i = 0; i < vcnt && vbase < ram_size; ++i) { | |
98 | + vmask = (1ull << 40) - 1; | |
99 | + while (vbase + vmask + 1 > ram_size) | |
100 | + vmask >>= 1; | |
101 | + wrmsr(MTRRphysBase_MSR(i), vbase | 6); | |
102 | + wrmsr(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800); | |
103 | + vbase += vmask + 1; | |
104 | + } | |
105 | + wrmsr(MSR_MTRRdefType, 0xc00); | |
106 | +} | |
107 | + | |
108 | void ram_probe(void) | |
109 | { | |
110 | if (cmos_readb(0x34) | cmos_readb(0x35)) | |
111 | @@ -482,6 +560,7 @@ void ram_probe(void) | |
112 | ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380; | |
113 | BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr); | |
114 | #endif | |
115 | + setup_mtrr(); | |
116 | } | |
117 | ||
118 | /****************************************************/ | |
119 | ||
120 |