blob: fdeb0af8ec2a0a05b0d0254a7406519f57dc2d82 [file] [log] [blame]
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +03001/*
2 * This file is part of the coreboot project.
3 *
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +03004 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <cpu/x86/mtrr.h>
15#include <cpu/x86/cache.h>
16#include <cpu/x86/post_code.h>
17#include <cpu/x86/lapic_def.h>
18
19/* Macro to access Local APIC registers at default base. */
20#define LAPIC(x) $(LAPIC_DEFAULT_BASE | LAPIC_ ## x)
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +030021
22#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE
23#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE
24
Arthur Heymans942ad6a2019-10-12 18:06:46 +020025#if ((CONFIG_C_ENV_BOOTBLOCK_SIZE & (CONFIG_C_ENV_BOOTBLOCK_SIZE - 1)) != 0)
26#error "CONFIG_C_ENV_BOOTBLOCK_SIZE must be a power of 2!"
27#endif
28#define XIP_ROM_SIZE CONFIG_C_ENV_BOOTBLOCK_SIZE
Arthur Heymans942ad6a2019-10-12 18:06:46 +020029
Kyösti Mälkkic641f7e2018-12-28 16:54:54 +020030.global bootblock_pre_c_entry
31
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +030032.code32
33_cache_as_ram_setup:
34
Kyösti Mälkkic641f7e2018-12-28 16:54:54 +020035bootblock_pre_c_entry:
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +030036
37cache_as_ram:
38 post_code(0x20)
39
40 movl $LAPIC_BASE_MSR, %ecx
41 rdmsr
42 andl $LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR, %eax
43 jz ap_init
44
45 /* Clear/disable fixed MTRRs */
46 mov $fixed_mtrr_list_size, %ebx
47 xor %eax, %eax
48 xor %edx, %edx
49
50clear_fixed_mtrr:
51 add $-2, %ebx
52 movzwl fixed_mtrr_list(%ebx), %ecx
53 wrmsr
54 jnz clear_fixed_mtrr
55
Elyes HAOUAS02820ca2018-09-30 07:44:39 +020056 /* Figure out how many MTRRs we have, and clear them out */
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +030057 mov $MTRR_CAP_MSR, %ecx
58 rdmsr
59 movzb %al, %ebx /* Number of variable MTRRs */
60 mov $MTRR_PHYS_BASE(0), %ecx
61 xor %eax, %eax
62 xor %edx, %edx
63
64clear_var_mtrr:
65 wrmsr
66 inc %ecx
67 wrmsr
68 inc %ecx
69 dec %ebx
70 jnz clear_var_mtrr
71 post_code(0x21)
72
73 /* Configure the default memory type to uncacheable. */
74 movl $MTRR_DEF_TYPE_MSR, %ecx
75 rdmsr
76 andl $(~0x00000cff), %eax
77 wrmsr
78
79 post_code(0x22)
80
81 /* Determine CPU_ADDR_BITS and load PHYSMASK high
82 * word to %edx.
83 */
84 movl $0x80000000, %eax
85 cpuid
86 cmpl $0x80000008, %eax
87 jc addrsize_no_MSR
88 movl $0x80000008, %eax
89 cpuid
90 movb %al, %cl
91 sub $32, %cl
92 movl $1, %edx
93 shl %cl, %edx
94 subl $1, %edx
95 jmp addrsize_set_high
96addrsize_no_MSR:
97 movl $1, %eax
98 cpuid
99 andl $(1 << 6 | 1 << 17), %edx /* PAE or PSE36 */
100 jz addrsize_set_high
101 movl $0x0f, %edx
102
103 /* Preload high word of address mask (in %edx) for Variable
104 * MTRRs 0 and 1 and enable local APIC at default base.
105 */
106addrsize_set_high:
107 xorl %eax, %eax
108 movl $MTRR_PHYS_MASK(0), %ecx
109 wrmsr
110 movl $MTRR_PHYS_MASK(1), %ecx
111 wrmsr
112 movl $LAPIC_BASE_MSR, %ecx
113 not %edx
114 movl %edx, %ebx
115 rdmsr
116 andl %ebx, %edx
117 andl $(~LAPIC_BASE_MSR_ADDR_MASK), %eax
118 orl $(LAPIC_DEFAULT_BASE | LAPIC_BASE_MSR_ENABLE), %eax
119 wrmsr
120
121bsp_init:
122
123 post_code(0x23)
124
125 /* Send INIT IPI to all excluding ourself. */
126 movl LAPIC(ICR), %edi
127 movl $(LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | LAPIC_DM_INIT), %eax
1281: movl %eax, (%edi)
129 movl $0x30, %ecx
1302: pause
131 dec %ecx
132 jnz 2b
133 movl (%edi), %ecx
134 andl $LAPIC_ICR_BUSY, %ecx
135 jnz 1b
136
137 post_code(0x24)
138
139 movl $1, %eax
140 cpuid
141 btl $28, %edx
142 jnc sipi_complete
143 bswapl %ebx
144 movzx %bh, %edi
145 cmpb $1, %bh
146 jbe sipi_complete /* only one LAPIC ID in package */
147
148 movl $0, %eax
149 cpuid
150 movb $1, %bl
151 cmpl $4, %eax
152 jb cores_counted
153 movl $4, %eax
154 movl $0, %ecx
155 cpuid
156 shr $26, %eax
157 movb %al, %bl
158 inc %bl
159
160cores_counted:
161 movl %edi, %eax
162 divb %bl
163 cmpb $1, %al
164 jbe sipi_complete /* only LAPIC ID of a core */
165
166 /* For a hyper-threading processor, cache must not be disabled
167 * on an AP on the same physical package with the BSP.
168 */
169
170hyper_threading_cpu:
171
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300172 post_code(0x25)
173
174 /* Send Start IPI to all excluding ourself. */
175 movl LAPIC(ICR), %edi
Kyösti Mälkki34856572019-01-09 20:30:52 +0200176 movl $(LAPIC_DEST_ALLBUT | LAPIC_DM_STARTUP), %eax
177 orl $ap_sipi_vector_in_rom, %eax
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +03001781: movl %eax, (%edi)
179 movl $0x30, %ecx
1802: pause
181 dec %ecx
182 jnz 2b
183 movl (%edi), %ecx
184 andl $LAPIC_ICR_BUSY, %ecx
185 jnz 1b
186
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300187 post_code(0x26)
188
189 /* Wait for sibling CPU to start. */
1901: movl $(MTRR_PHYS_BASE(0)), %ecx
191 rdmsr
192 andl %eax, %eax
193 jnz sipi_complete
194
195 movl $0x30, %ecx
1962: pause
197 dec %ecx
198 jnz 2b
199 jmp 1b
200
201
202ap_init:
203 post_code(0x27)
204
205 /* Do not disable cache (so BSP can enable it). */
206 movl %cr0, %eax
207 andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
208 movl %eax, %cr0
209
210 post_code(0x28)
211
212 /* MTRR registers are shared between HT siblings. */
213 movl $(MTRR_PHYS_BASE(0)), %ecx
214 movl $(1 << 12), %eax
215 xorl %edx, %edx
216 wrmsr
217
218 post_code(0x29)
219
220ap_halt:
221 cli
2221: hlt
223 jmp 1b
224
225
226
227sipi_complete:
228
229 post_code(0x2a)
230
231 /* Set Cache-as-RAM base address. */
232 movl $(MTRR_PHYS_BASE(0)), %ecx
233 movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
234 xorl %edx, %edx
235 wrmsr
236
237 /* Set Cache-as-RAM mask. */
238 movl $(MTRR_PHYS_MASK(0)), %ecx
239 rdmsr
240 movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
241 wrmsr
242
243 post_code(0x2b)
244
245 /* Enable MTRR. */
246 movl $MTRR_DEF_TYPE_MSR, %ecx
247 rdmsr
248 orl $MTRR_DEF_TYPE_EN, %eax
249 wrmsr
250
251 /* Enable L2 cache Write-Back (WBINVD and FLUSH#).
252 *
253 * MSR is set when DisplayFamily_DisplayModel is one of:
254 * 06_0x, 06_17, 06_1C
255 *
256 * Description says this bit enables use of WBINVD and FLUSH#.
257 * Should this be set only after the system bus and/or memory
258 * controller can successfully handle write cycles?
259 */
260
261#define EAX_FAMILY(a) (a << 8) /* for family <= 0fH */
262#define EAX_MODEL(a) (((a & 0xf0) << 12) | ((a & 0xf) << 4))
263
264 movl $1, %eax
265 cpuid
266 movl %eax, %ebx
267 andl $EAX_FAMILY(0x0f), %eax
268 cmpl $EAX_FAMILY(0x06), %eax
269 jne no_msr_11e
270 movl %ebx, %eax
271 andl $EAX_MODEL(0xff), %eax
272 cmpl $EAX_MODEL(0x17), %eax
273 je has_msr_11e
274 cmpl $EAX_MODEL(0x1c), %eax
275 je has_msr_11e
276 andl $EAX_MODEL(0xf0), %eax
277 cmpl $EAX_MODEL(0x00), %eax
278 jne no_msr_11e
279has_msr_11e:
280 movl $0x11e, %ecx
281 rdmsr
282 orl $(1 << 8), %eax
283 wrmsr
284no_msr_11e:
285
286 post_code(0x2c)
287
Arthur Heymans95b3ba52019-01-09 12:24:58 +0100288 /* Cache the whole rom to fetch microcode updates */
289 movl $MTRR_PHYS_BASE(1), %ecx
290 xorl %edx, %edx
Arthur Heymanseeedf832019-02-08 16:27:35 +0100291 movl $(CACHE_ROM_BASE | MTRR_TYPE_WRPROT), %eax
Arthur Heymans95b3ba52019-01-09 12:24:58 +0100292 wrmsr
293
294 movl $MTRR_PHYS_MASK(1), %ecx
295 rdmsr
296 movl $(~(CACHE_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
297 wrmsr
298
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300299 /* Enable cache (CR0.CD = 0, CR0.NW = 0). */
300 movl %cr0, %eax
301 andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
302 invd
303 movl %eax, %cr0
304
Julius Wernercd49cce2019-03-05 16:53:33 -0800305#if CONFIG(MICROCODE_UPDATE_PRE_RAM)
Arthur Heymans95b3ba52019-01-09 12:24:58 +0100306 update_microcode:
307 /* put the return address in %esp */
308 movl $end_microcode_update, %esp
309 jmp update_bsp_microcode
310 end_microcode_update:
311#endif
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300312 post_code(0x2d)
Arthur Heymans95b3ba52019-01-09 12:24:58 +0100313 /* Disable caching to change MTRR's. */
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300314 movl %cr0, %eax
315 orl $CR0_CacheDisable, %eax
316 movl %eax, %cr0
317
Arthur Heymans7875dbd2018-06-16 20:01:47 +0200318 /*
319 * An unidentified combination of speculative reads and branch
320 * predictions inside WRPROT-cacheable memory can cause invalidation
321 * of cachelines and loss of stack on models based on NetBurst
322 * microarchitecture. Therefore disable WRPROT region entirely for
323 * all family F models.
324 */
325 movl $1, %eax
326 cpuid
327 cmp $0xf, %ah
Arthur Heymans95b3ba52019-01-09 12:24:58 +0100328 jne cache_rom
Arthur Heymans7875dbd2018-06-16 20:01:47 +0200329
Arthur Heymans95b3ba52019-01-09 12:24:58 +0100330disable_cache_rom:
331 movl $MTRR_PHYS_MASK(1), %ecx
332 rdmsr
333 andl $(~MTRR_PHYS_MASK_VALID), %eax
334 wrmsr
335 jmp fill_cache
336
337cache_rom:
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300338 /* Enable cache for our code in Flash because we do XIP here */
339 movl $MTRR_PHYS_BASE(1), %ecx
340 xorl %edx, %edx
341 /*
342 * IMPORTANT: The following calculation _must_ be done at runtime. See
Stefan Taunerde028782018-08-19 20:02:05 +0200343 * https://mail.coreboot.org/pipermail/coreboot/2010-October/060922.html
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300344 */
Kyösti Mälkkice9f4222018-06-25 18:53:36 +0300345 movl $_program, %eax
Arthur Heymans942ad6a2019-10-12 18:06:46 +0200346 andl $(~(XIP_ROM_SIZE - 1)), %eax
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300347 orl $MTRR_TYPE_WRPROT, %eax
348 wrmsr
349
350 movl $MTRR_PHYS_MASK(1), %ecx
351 rdmsr
Arthur Heymans942ad6a2019-10-12 18:06:46 +0200352 movl $(~(XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300353 wrmsr
354
Arthur Heymans95b3ba52019-01-09 12:24:58 +0100355fill_cache:
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300356 post_code(0x2e)
357 /* Enable cache. */
358 movl %cr0, %eax
359 andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
Arthur Heymans95b3ba52019-01-09 12:24:58 +0100360 invd
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300361 movl %eax, %cr0
362
Arthur Heymans95b3ba52019-01-09 12:24:58 +0100363 /* Clear the cache memory region. This will also fill up the cache. */
364 cld
365 xorl %eax, %eax
366 movl $CACHE_AS_RAM_BASE, %edi
367 movl $(CACHE_AS_RAM_SIZE >> 2), %ecx
368 rep stosl
369
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300370 /* Setup the stack. */
Arthur Heymansdf9cdcf2019-11-09 06:50:20 +0100371 mov $_ecar_stack, %esp
Kyösti Mälkkic641f7e2018-12-28 16:54:54 +0200372
373 /* Need to align stack to 16 bytes at call instruction. Account for
374 the pushes below. */
Arthur Heymans348b79f2018-06-03 17:14:19 +0200375 andl $0xfffffff0, %esp
Kyösti Mälkkic641f7e2018-12-28 16:54:54 +0200376 subl $4, %esp
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300377
Kyösti Mälkkic641f7e2018-12-28 16:54:54 +0200378 /* push TSC and BIST to stack */
379 movd %mm0, %eax
Elyes HAOUAS87930b32019-01-16 12:41:57 +0100380 pushl %eax /* BIST */
Kyösti Mälkkic641f7e2018-12-28 16:54:54 +0200381 movd %mm2, %eax
382 pushl %eax /* tsc[63:32] */
383 movd %mm1, %eax
Elyes HAOUAS87930b32019-01-16 12:41:57 +0100384 pushl %eax /* tsc[31:0] */
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300385
Kyösti Mälkkic641f7e2018-12-28 16:54:54 +0200386before_c_entry:
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300387 post_code(0x2f)
Kyösti Mälkkic641f7e2018-12-28 16:54:54 +0200388 call bootblock_c_entry_bist
Kyösti Mälkki6a8ce0d2018-05-17 17:22:51 +0300389
390 /* Should never see this postcode */
391 post_code(POST_DEAD_CODE)
392
393.Lhlt:
394 hlt
395 jmp .Lhlt
396
397fixed_mtrr_list:
398 .word MTRR_FIX_64K_00000
399 .word MTRR_FIX_16K_80000
400 .word MTRR_FIX_16K_A0000
401 .word MTRR_FIX_4K_C0000
402 .word MTRR_FIX_4K_C8000
403 .word MTRR_FIX_4K_D0000
404 .word MTRR_FIX_4K_D8000
405 .word MTRR_FIX_4K_E0000
406 .word MTRR_FIX_4K_E8000
407 .word MTRR_FIX_4K_F0000
408 .word MTRR_FIX_4K_F8000
409fixed_mtrr_list_size = . - fixed_mtrr_list
410
411_cache_as_ram_setup_end: