1
2#include <mainboard.h>
3#include <config.h>
4#include <types.h>
5#include <io.h>
6#include <console.h>
7#include <cpu.h>
8#include <globalvars.h>
9#include <lar.h>
10#include <string.h>
11#include <tables.h>
12#include <lib.h>
13#include <mc146818rtc.h>
14#include <msr.h>
15#include <mtrr.h>
16
17#if 1
18#define BIOS_MTRRS 6
19#define OS_MTRRS 2
20#else
21#define BIOS_MTRRS 8
22#define OS_MTRRS 0
23#endif
24#define MTRRS (BIOS_MTRRS + OS_MTRRS)
25
26
27static inline u32 fms(u32 x)
28{
29 int r;
30
31 __asm__("bsrl %1,%0\n\t"
32 "jnz 1f\n\t"
33 "movl $0,%0\n"
34 "1:" : "=r" (r) : "g" (x));
35 return r;
36}
37
38
39static inline u32 fls(u32 x)
40{
41 int r;
42
43 __asm__("bsfl %1,%0\n\t"
44 "jnz 1f\n\t"
45 "movl $32,%0\n"
46 "1:" : "=r" (r) : "g" (x));
47 return r;
48}
49
50u32 stage1_resk(u64 value)
51{
52 u32 resultk;
53 if (value < (1ULL << 42)) {
54 resultk = value >> 10;
55 }
56 else {
57 resultk = 0xffffffff;
58 }
59 return resultk;
60}
61
62
63void stage1_set_fix_mtrr(u32 reg, u8 type)
64{
65 struct msr msr;
66
67
68 msr = rdmsr(SYSCFG_MSR);
69 msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
70 wrmsr(SYSCFG_MSR, msr);
71
72 msr.lo = (type << 24) | (type << 16) | (type << 8) | type;
73 msr.hi = (type << 24) | (type << 16) | (type << 8) | type;
74 wrmsr(reg, msr);
75
76
77 msr = rdmsr(SYSCFG_MSR);
78 msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
79 wrmsr(SYSCFG_MSR, msr);
80}
81
82
83
84
85static void stage1_set_var_mtrr(u8 reg, u32 basek, u32 sizek,
86 u8 type, u32 address_bits)
87{
88 struct msr base, mask;
89 u32 address_mask_high;
90
91 if (reg >= MTRRS) {
92 printk(BIOS_ERR,"Requested MTRR is out of range!\n");
93 return;
94 }
95
96 if (sizek == 0) {
97 struct msr zero;
98 zero.lo = zero.hi = 0;
99
100 disable_cache();
101
102
103
104 wrmsr (MTRRphysMask_MSR(reg), zero);
105
106 enable_cache();
107 return;
108 }
109
110
111 address_mask_high = ((1u << (address_bits - 32u)) - 1u);
112
113 base.hi = basek >> 22;
114 base.lo = basek << 10;
115
116 printk(BIOS_SPEW, "ADDRESS_MASK_HIGH=%#x\n", address_mask_high);
117
118 if (sizek < 4*1024*1024) {
119 mask.hi = address_mask_high;
120 mask.lo = ~((sizek << 10) -1);
121 }
122 else {
123 mask.hi = address_mask_high & (~((sizek >> 22) -1));
124 mask.lo = 0;
125 }
126
127 disable_cache();
128
129
130 base.lo |= type;
131 mask.lo |= 0x800;
132 wrmsr (MTRRphysBase_MSR(reg), base);
133 wrmsr (MTRRphysMask_MSR(reg), mask);
134
135 enable_cache();
136}
137
138
139
140
141u8 stage1_range_to_mtrr(u8 reg, u32 range_startk, u32 range_sizek,
142 u8 type, u32 address_bits)
143{
144 if (!range_sizek) {
145 printk(BIOS_SPEW, "Zero-sized MTRR range @%dKB\n", range_startk);
146 return reg;
147 }
148
149 if (reg >= BIOS_MTRRS) {
150 printk(BIOS_ERR, "ERROR: Out of MTRRs for base: %4dMB, range: %dMB, type %s\n",
151 range_startk >>10, range_sizek >> 10,
152 (type==MTRR_TYPE_UNCACHEABLE)?"UC":
153 ((type==MTRR_TYPE_WRBACK)?"WB":"Other") );
154 return reg;
155 }
156
157 while(range_sizek) {
158 u32 max_align, align;
159 u32 sizek;
160
161 max_align = fls(range_startk);
162 align = fms(range_sizek);
163 if (align > max_align) {
164 align = max_align;
165 }
166 sizek = 1 << align;
167 printk(BIOS_DEBUG,"Setting variable MTRR %d, base: %dKB, range: %dKB, type %s\n",
168 reg, range_startk, sizek,
169 (type==MTRR_TYPE_UNCACHEABLE)?"UC":
170 ((type==MTRR_TYPE_WRBACK)?"WB":"Other")
171 );
172 stage1_set_var_mtrr(reg++, range_startk, sizek, type, address_bits);
173 range_startk += sizek;
174 range_sizek -= sizek;
175 if (reg >= BIOS_MTRRS) {
176 printk(BIOS_ERR, "Out of variable MTRRs!\n");
177 break;
178 }
179 }
180 return reg;
181}
182
183void cache_cbmem(int type)
184{
185
186 disable_cache();
187 stage1_range_to_mtrr(0, 0, CONFIG_CBMEMK, MTRR_TYPE_WRBACK, CPU_ADDR_BITS);
188 enable_cache();
189}
190
191
192
193
194
195#if 0
196
197
198
199void do_early_mtrr_init(const unsigned long *mtrr_msrs)
200{
201
202
203
204
205 struct msr msr;
206 const unsigned long *msr_addr;
207
208
209 msr.lo = 0;
210 msr.hi = 0;
211 unsigned long msr_nr;
212 for(msr_addr = mtrr_msrs; (msr_nr = *msr_addr); msr_addr++) {
213 wrmsr(msr_nr, msr);
214 }
215
216#warning fix the XIP bits in stage1_mtrr.c that enable write through caching so we can do execute in place on the flash rom.
217#if 0
218#if defined(XIP_ROM_SIZE)
219
220
221
222 stage1_range_to_mtrr(1, 0, XIP_ROM_BASE >> 10, XIP_ROM_SIZE >> 10,
223 MTRR_TYPE_WRBACK, CPU_ADDR_BITS);
224#endif
225#endif
226
227
228
229
230 msr.hi = 0x00000000;
231 msr.lo = 0x00000800;
232 wrmsr(MTRRdefType_MSR, msr);
233
234}
235
236
237
238
239
240void early_mtrr_init(void)
241{
242 static const unsigned long mtrr_msrs[] = {
243
244 0x250, 0x258, 0x259,
245 0x268, 0x269, 0x26A,
246 0x26B, 0x26C, 0x26D,
247 0x26E, 0x26F,
248
249 0x200, 0x201, 0x202, 0x203,
250 0x204, 0x205, 0x206, 0x207,
251 0x208, 0x209, 0x20A, 0x20B,
252 0x20C, 0x20D, 0x20E, 0x20F,
253
254 0
255 };
256 disable_cache();
257 do_early_mtrr_init(mtrr_msrs);
258 enable_cache();
259}
260#endif
261
262int early_mtrr_init_detected(void)
263{
264 struct msr msr;
265
266
267
268
269
270
271 msr = rdmsr(MTRRdefType_MSR);
272 return msr.lo & 0x00000800;
273}
274