blob: 1798de5117c9f19fdcf5898f091020869b68590c [file] [log] [blame]
Subrata Banik03e971c2017-03-07 14:02:23 +05301/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2015-2016 Intel Corp.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <commonlib/helpers.h>
18#include <cpu/x86/cache.h>
19#include <cpu/x86/cr.h>
20#include <cpu/x86/mtrr.h>
21#include <cpu/x86/post_code.h>
22#include <rules.h>
23#include <intelblocks/msr.h>
24
25.global bootblock_pre_c_entry
26bootblock_pre_c_entry:
27
28 post_code(0x20)
29
30 /*
31 * Use the MTRR default type MSR as a proxy for detecting INIT#.
32 * Reset the system if any known bits are set in that MSR. That is
33 * an indication of the CPU not being properly reset.
34 */
35check_for_clean_reset:
36 mov $MTRR_DEF_TYPE_MSR, %ecx
37 rdmsr
38 and $(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN), %eax
39 cmp $0, %eax
40 jz no_reset
41 /* perform warm reset */
42 movw $0xcf9, %dx
43 movb $0x06, %al
44 outb %al, %dx
45
46no_reset:
47 post_code(0x21)
48
49 /* Clear/disable fixed MTRRs */
50 mov $fixed_mtrr_list_size, %ebx
51 xor %eax, %eax
52 xor %edx, %edx
53
54clear_fixed_mtrr:
55 add $-2, %ebx
56 movzwl fixed_mtrr_list(%ebx), %ecx
57 wrmsr
58 jnz clear_fixed_mtrr
59
60 post_code(0x22)
61
62 /* Figure put how many MTRRs we have, and clear them out */
63 mov $MTRR_CAP_MSR, %ecx
64 rdmsr
65 movzb %al, %ebx /* Number of variable MTRRs */
66 mov $MTRR_PHYS_BASE(0), %ecx
67 xor %eax, %eax
68 xor %edx, %edx
69
70clear_var_mtrr:
71 wrmsr
72 inc %ecx
73 wrmsr
74 inc %ecx
75 dec %ebx
76 jnz clear_var_mtrr
77
78 post_code(0x23)
79
80 /* Configure default memory type to uncacheable (UC) */
81 mov $MTRR_DEF_TYPE_MSR, %ecx
82 rdmsr
83 /* Clear enable bits and set default type to UC. */
84 and $~(MTRR_DEF_TYPE_MASK | MTRR_DEF_TYPE_EN | \
85 MTRR_DEF_TYPE_FIX_EN), %eax
86 wrmsr
87
88 /* Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB
89 * based on the physical address size supported for this processor
90 * This is based on read from CPUID EAX = 080000008h, EAX bits [7:0]
91 *
92 * Examples:
93 * MTRR_PHYS_MASK_HIGH = 00000000Fh For 36 bit addressing
94 * MTRR_PHYS_MASK_HIGH = 0000000FFh For 40 bit addressing
95 */
96
97 movl $0x80000008, %eax /* Address sizes leaf */
98 cpuid
99 sub $32, %al
100 movzx %al, %eax
101 xorl %esi, %esi
102 bts %eax, %esi
103 dec %esi /* esi <- MTRR_PHYS_MASK_HIGH */
104
105 post_code(0x24)
106
107#if ((CONFIG_DCACHE_RAM_SIZE & (CONFIG_DCACHE_RAM_SIZE - 1)) == 0)
108 /* Configure CAR region as write-back (WB) */
109 mov $MTRR_PHYS_BASE(0), %ecx
110 mov $CONFIG_DCACHE_RAM_BASE, %eax
111 or $MTRR_TYPE_WRBACK, %eax
112 xor %edx,%edx
113 wrmsr
114
115 /* Configure the MTRR mask for the size region */
116 mov $MTRR_PHYS_MASK(0), %ecx
117 mov $CONFIG_DCACHE_RAM_SIZE, %eax /* size mask */
118 dec %eax
119 not %eax
120 or $MTRR_PHYS_MASK_VALID, %eax
121 movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
122 wrmsr
123#elif (CONFIG_DCACHE_RAM_SIZE == 768 * KiB) /* 768 KiB */
124 /* Configure CAR region as write-back (WB) */
125 mov $MTRR_PHYS_BASE(0), %ecx
126 mov $CONFIG_DCACHE_RAM_BASE, %eax
127 or $MTRR_TYPE_WRBACK, %eax
128 xor %edx,%edx
129 wrmsr
130
131 mov $MTRR_PHYS_MASK(0), %ecx
132 mov $(512 * KiB), %eax /* size mask */
133 dec %eax
134 not %eax
135 or $MTRR_PHYS_MASK_VALID, %eax
136 movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
137 wrmsr
138
139 mov $MTRR_PHYS_BASE(1), %ecx
140 mov $(CONFIG_DCACHE_RAM_BASE + 512 * KiB), %eax
141 or $MTRR_TYPE_WRBACK, %eax
142 xor %edx,%edx
143 wrmsr
144
145 mov $MTRR_PHYS_MASK(1), %ecx
146 mov $(256 * KiB), %eax /* size mask */
147 dec %eax
148 not %eax
149 or $MTRR_PHYS_MASK_VALID, %eax
150 movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
151 wrmsr
152#else
153#error "DCACHE_RAM_SIZE is not a power of 2 and setup code is missing"
154#endif
155 post_code(0x25)
156
157 /* Enable variable MTRRs */
158 mov $MTRR_DEF_TYPE_MSR, %ecx
159 rdmsr
160 or $MTRR_DEF_TYPE_EN, %eax
161 wrmsr
162
163 /* Enable caching */
164 mov %cr0, %eax
165 and $~(CR0_CD | CR0_NW), %eax
166 invd
167 mov %eax, %cr0
168
169#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
170 jmp car_nem
171#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
172 jmp car_cqos
173#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
174 jmp car_nem_enhanced
175#else
176 jmp .halt_forever /* In case nothing has selected */
177#endif
178
179.global car_init_done
180car_init_done:
181
182 post_code(0x29)
183
184 /* Setup bootblock stack */
185 mov $_car_stack_end, %esp
186
Aaron Durbin028e18f2017-06-23 11:14:58 -0500187 /* Need to align stack to 16 bytes at call instruction. Account for
188 the two pushes below. */
189 andl $0xfffffff0, %esp
190 sub $8, %esp
191
Subrata Banik03e971c2017-03-07 14:02:23 +0530192 /*push TSC value to stack*/
193 movd %mm2, %eax
194 pushl %eax /* tsc[63:32] */
195 movd %mm1, %eax
196 pushl %eax /* tsc[31:0] */
197
198before_carstage:
199 post_code(0x2A)
200
201 call bootblock_c_entry
202 /* Never reached */
203
204.halt_forever:
205 post_code(POST_DEAD_CODE)
206 hlt
207 jmp .halt_forever
208
209fixed_mtrr_list:
210 .word MTRR_FIX_64K_00000
211 .word MTRR_FIX_16K_80000
212 .word MTRR_FIX_16K_A0000
213 .word MTRR_FIX_4K_C0000
214 .word MTRR_FIX_4K_C8000
215 .word MTRR_FIX_4K_D0000
216 .word MTRR_FIX_4K_D8000
217 .word MTRR_FIX_4K_E0000
218 .word MTRR_FIX_4K_E8000
219 .word MTRR_FIX_4K_F0000
220 .word MTRR_FIX_4K_F8000
221fixed_mtrr_list_size = . - fixed_mtrr_list
222
223#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
224.global car_nem
225car_nem:
226 /* Disable cache eviction (setup stage) */
227 mov $MSR_EVICT_CTL, %ecx
228 rdmsr
229 or $0x1, %eax
230 wrmsr
231
232 post_code(0x26)
233
234 /* Clear the cache memory region. This will also fill up the cache */
235 movl $CONFIG_DCACHE_RAM_BASE, %edi
236 movl $CONFIG_DCACHE_RAM_SIZE, %ecx
237 shr $0x02, %ecx
238 xor %eax, %eax
239 cld
240 rep stosl
241
242 post_code(0x27)
243
244 /* Disable cache eviction (run stage) */
245 mov $MSR_EVICT_CTL, %ecx
246 rdmsr
247 or $0x2, %eax
248 wrmsr
249
250 post_code(0x28)
251
252 jmp car_init_done
253
254#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
255.global car_cqos
256car_cqos:
257 /*
Naresh G Solankif329f0c2017-09-27 14:21:18 +0530258 * Create CBM_LEN_MASK based on CBM_LEN
259 * Get CPUID.(EAX=10H, ECX=2H):EAX.CBM_LEN[bits 4:0]
260 */
261 mov $0x10, %eax
262 mov $0x2, %ecx
263 cpuid
264 and $0x1F, %eax
265 add $1, %al
266
267 mov $1, %ebx
268 mov %al, %cl
269 shl %cl, %ebx
270 sub $1, %ebx
271
272 /* Store the CBM_LEN_MASK in mm3 for later use. */
273 movd %ebx, %mm3
274
275 /*
Subrata Banik03e971c2017-03-07 14:02:23 +0530276 * Disable both L1 and L2 prefetcher. For yet-to-understood reason,
277 * prefetchers slow down filling cache with rep stos in CQOS mode.
278 */
279 mov $MSR_PREFETCH_CTL, %ecx
280 rdmsr
281 or $(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
282 wrmsr
283
284#if (CONFIG_DCACHE_RAM_SIZE == CONFIG_L2_CACHE_SIZE)
285/*
286 * If CAR size is set to full L2 size, mask is calculated as all-zeros.
287 * This is not supported by the CPU/uCode.
288 */
289#error "CQOS CAR may not use whole L2 cache area"
290#endif
291
292 /* Calculate how many bits to be used for CAR */
293 xor %edx, %edx
294 mov $CONFIG_DCACHE_RAM_SIZE, %eax /* dividend */
295 mov $CONFIG_CACHE_QOS_SIZE_PER_BIT, %ecx /* divisor */
296 div %ecx /* result is in eax */
297 mov %eax, %ecx /* save to ecx */
298 mov $1, %ebx
299 shl %cl, %ebx
300 sub $1, %ebx /* resulting mask is is in ebx */
301
302 /* Set this mask for initial cache fill */
303 mov $MSR_L2_QOS_MASK(0), %ecx
304 rdmsr
Naresh G Solankif329f0c2017-09-27 14:21:18 +0530305 mov %ebx, %eax
Subrata Banik03e971c2017-03-07 14:02:23 +0530306 wrmsr
307
308 /* Set CLOS selector to 0 */
309 mov $MSR_IA32_PQR_ASSOC, %ecx
310 rdmsr
311 and $~IA32_PQR_ASSOC_MASK, %edx /* select mask 0 */
312 wrmsr
313
314 /* We will need to block CAR region from evicts */
315 mov $MSR_L2_QOS_MASK(1), %ecx
316 rdmsr
317 /* Invert bits that are to be used for cache */
Naresh G Solankif329f0c2017-09-27 14:21:18 +0530318 mov %ebx, %eax
319 xor $~0, %eax /* invert 32 bits */
320
321 /*
322 * Use CBM_LEN_MASK stored in mm3 to set bits based on Capacity Bit
323 * Mask Length.
324 */
325 movd %mm3, %ebx
326 and %ebx, %eax
Subrata Banik03e971c2017-03-07 14:02:23 +0530327 wrmsr
328
329 post_code(0x26)
330
331 /* Clear the cache memory region. This will also fill up the cache */
332 movl $CONFIG_DCACHE_RAM_BASE, %edi
333 movl $CONFIG_DCACHE_RAM_SIZE, %ecx
334 shr $0x02, %ecx
335 xor %eax, %eax
336 cld
337 rep stosl
338
339 post_code(0x27)
340
341 /* Cache is populated. Use mask 1 that will block evicts */
342 mov $MSR_IA32_PQR_ASSOC, %ecx
343 rdmsr
344 and $~IA32_PQR_ASSOC_MASK, %edx /* clear index bits first */
345 or $1, %edx /* select mask 1 */
346 wrmsr
347
348 /* Enable prefetchers */
349 mov $MSR_PREFETCH_CTL, %ecx
350 rdmsr
351 and $~(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
352 wrmsr
353
354 post_code(0x28)
355
356 jmp car_init_done
357
358#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
359.global car_nem_enhanced
360car_nem_enhanced:
361 /* Disable cache eviction (setup stage) */
362 mov $MSR_EVICT_CTL, %ecx
363 rdmsr
364 or $0x1, %eax
365 wrmsr
366 post_code(0x26)
367
368 /* Create n-way set associativity of cache */
369 xorl %edi, %edi
370find_llc_subleaf:
371 movl %edi, %ecx
372 movl $0x04, %eax
373 cpuid
374 inc %edi
375 and $0xe0, %al /* EAX[7:5] = Cache Level */
376 cmp $0x60, %al /* Check to see if it is LLC */
377 jnz find_llc_subleaf
378
379 /*
380 * Set MSR 0xC91 IA32_L3_MASK_! = 0xE/0xFE/0xFFE/0xFFFE
381 * for 4/8/16 way of LLC
382 */
383 shr $22, %ebx
384 inc %ebx
385 /* Calculate n-way associativity of LLC */
386 mov %bl, %cl
387
388 /*
389 * Maximizing RO cacheability while locking in the CAR to a
390 * single way since that particular way won't be victim candidate
391 * for evictions.
392 * This has been done after programing LLC_WAY_MASK_1 MSR
393 * with desired LLC way as mentioned below.
394 *
395 * Hence create Code and Data Size as per request
396 * Code Size (RO) : Up to 16M
397 * Data Size (RW) : Up to 256K
398 */
399 movl $0x01, %eax
400 /*
401 * LLC Ways -> LLC_WAY_MASK_1:
402 * 4: 0x000E
403 * 8: 0x00FE
404 * 12: 0x0FFE
405 * 16: 0xFFFE
406 *
407 * These MSRs contain one bit per each way of LLC
408 * - If this bit is '0' - the way is protected from eviction
409 * - If this bit is '1' - the way is not protected from eviction
410 */
411 shl %cl, %eax
412 subl $0x02, %eax
413 movl $MSR_IA32_L3_MASK_1, %ecx
414 xorl %edx, %edx
415 wrmsr
416 /*
417 * Set MSR 0xC92 IA32_L3_MASK_2 = 0x1
418 *
419 * For SKL SOC, data size remains 256K consistently.
420 * Hence, creating 1-way associative cache for Data
421 */
422 mov $MSR_IA32_L3_MASK_2, %ecx
423 mov $0x01, %eax
424 xorl %edx, %edx
425 wrmsr
426 /*
427 * Set MSR_IA32_PQR_ASSOC = 0x02
428 *
429 * Possible values:
430 * 0: Default value, no way mask should be applied
431 * 1: Apply way mask 1 to LLC
432 * 2: Apply way mask 2 to LLC
433 * 3: Shouldn't be use in NEM Mode
434 */
435 movl $MSR_IA32_PQR_ASSOC, %ecx
436 movl $0x02, %eax
437 xorl %edx, %edx
438 wrmsr
439
440 movl $CONFIG_DCACHE_RAM_BASE, %edi
441 movl $CONFIG_DCACHE_RAM_SIZE, %ecx
442 shr $0x02, %ecx
443 xor %eax, %eax
444 cld
445 rep stosl
446 /*
447 * Set MSR_IA32_PQR_ASSOC = 0x01
448 * At this stage we apply LLC_WAY_MASK_1 to the cache.
449 * i.e. way 0 is protected from eviction.
450 */
451 movl $MSR_IA32_PQR_ASSOC, %ecx
452 movl $0x01, %eax
453 xorl %edx, %edx
454 wrmsr
455
456 post_code(0x27)
457 /*
458 * Enable No-Eviction Mode Run State by setting
459 * NO_EVICT_MODE MSR 2E0h bit [1] = '1'.
460 */
461
462 movl $MSR_EVICT_CTL, %ecx
463 rdmsr
464 orl $0x02, %eax
465 wrmsr
466
467 post_code(0x28)
468
469 jmp car_init_done
470#endif