1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
|
/* SPDX-License-Identifier: GPL-2.0-only */
#include <cpu/intel/post_codes.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/post_code.h>
#include <cpu/x86/lapic_def.h>
/* Macro to access Local APIC registers at default base. */
#define LAPIC(x) $(LAPIC_DEFAULT_BASE | LAPIC_ ## x)
.section .init
.global bootblock_pre_c_entry
#include <cpu/intel/car/cache_as_ram_symbols.inc>
#include <cpu/x86/64bit/entry64.inc>
.code32
_cache_as_ram_setup:
bootblock_pre_c_entry:
cache_as_ram:
post_code(POSTCODE_BOOTBLOCK_CAR)
movl $LAPIC_BASE_MSR, %ecx
rdmsr
andl $LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR, %eax
jz ap_init
/* Clear/disable fixed MTRRs */
mov $fixed_mtrr_list, %ebx
xor %eax, %eax
xor %edx, %edx
clear_fixed_mtrr:
movzwl (%ebx), %ecx
wrmsr
add $2, %ebx
cmp $fixed_mtrr_list_end, %ebx
jl clear_fixed_mtrr
/* Figure out how many MTRRs we have, and clear them out */
mov $MTRR_CAP_MSR, %ecx
rdmsr
movzb %al, %ebx /* Number of variable MTRRs */
mov $MTRR_PHYS_BASE(0), %ecx
xor %eax, %eax
xor %edx, %edx
clear_var_mtrr:
wrmsr
inc %ecx
wrmsr
inc %ecx
dec %ebx
jnz clear_var_mtrr
post_code(POSTCODE_SOC_SET_DEF_MTRR_TYPE)
/* Configure the default memory type to uncacheable. */
movl $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
andl $(~0x00000cff), %eax
wrmsr
post_code(POSTCODE_SOC_DETERMINE_CPU_ADDR_BITS)
/* Determine CPU_ADDR_BITS and load PHYSMASK high
* word to %edx.
*/
movl $0x80000000, %eax
cpuid
cmpl $0x80000008, %eax
jc addrsize_no_MSR
movl $0x80000008, %eax
cpuid
movb %al, %cl
sub $32, %cl
movl $1, %edx
shl %cl, %edx
subl $1, %edx
jmp addrsize_set_high
addrsize_no_MSR:
movl $1, %eax
cpuid
andl $(1 << 6 | 1 << 17), %edx /* PAE or PSE36 */
jz addrsize_set_high
movl $0x0f, %edx
/* Preload high word of address mask (in %edx) for Variable
* MTRRs 0 and 1 and enable local APIC at default base.
*/
addrsize_set_high:
xorl %eax, %eax
movl $MTRR_PHYS_MASK(0), %ecx
wrmsr
movl $MTRR_PHYS_MASK(1), %ecx
wrmsr
movl $LAPIC_BASE_MSR, %ecx
not %edx
movl %edx, %ebx
rdmsr
andl %ebx, %edx
andl $(~LAPIC_BASE_MSR_ADDR_MASK), %eax
orl $(LAPIC_DEFAULT_BASE | LAPIC_BASE_MSR_ENABLE), %eax
wrmsr
bsp_init:
post_code(POSTCODE_SOC_BSP_INIT)
/* Send INIT IPI to all excluding ourself. */
movl LAPIC(ICR), %edi
movl $(LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | LAPIC_MT_INIT), %eax
1: movl %eax, (%edi)
movl $0x30, %ecx
2: pause
dec %ecx
jnz 2b
movl (%edi), %ecx
andl $LAPIC_ICR_BUSY, %ecx
jnz 1b
post_code(POSTCODE_SOC_COUNT_CORES)
movl $1, %eax
cpuid
btl $28, %edx
jnc sipi_complete
bswapl %ebx
movzx %bh, %edi
cmpb $1, %bh
jbe sipi_complete /* only one LAPIC ID in package */
movl $0, %eax
cpuid
movb $1, %bl
cmpl $4, %eax
jb cores_counted
movl $4, %eax
movl $0, %ecx
cpuid
shr $26, %eax
movb %al, %bl
inc %bl
cores_counted:
movl %edi, %eax
divb %bl
cmpb $1, %al
jbe sipi_complete /* only LAPIC ID of a core */
/* For a hyper-threading processor, cache must not be disabled
* on an AP on the same physical package with the BSP.
*/
hyper_threading_cpu:
post_code(POSTCODE_SOC_CPU_HYPER_THREADING)
/* Send Start IPI to all excluding ourself. */
movl LAPIC(ICR), %edi
movl $(LAPIC_DEST_ALLBUT | LAPIC_MT_STARTUP), %eax
orl $ap_sipi_vector_in_rom, %eax
1: movl %eax, (%edi)
movl $0x30, %ecx
2: pause
dec %ecx
jnz 2b
movl (%edi), %ecx
andl $LAPIC_ICR_BUSY, %ecx
jnz 1b
post_code(POSTCODE_SOC_CPU_SIBLING_DELAY)
/* Wait for sibling CPU to start. */
1: movl $(MTRR_PHYS_BASE(0)), %ecx
rdmsr
andl %eax, %eax
jnz sipi_complete
movl $0x30, %ecx
2: pause
dec %ecx
jnz 2b
jmp 1b
ap_init:
post_code(POSTCODE_SOC_CPU_AP_INIT)
/* Do not disable cache (so BSP can enable it). */
movl %cr0, %eax
andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
movl %eax, %cr0
post_code(POSTCODE_SOC_SET_MTRR_BASE)
/* MTRR registers are shared between HT siblings. */
movl $(MTRR_PHYS_BASE(0)), %ecx
movl $(1 << 12), %eax
xorl %edx, %edx
wrmsr
post_code(POSTCODE_SOC_AP_HALT)
ap_halt:
cli
1: hlt
jmp 1b
sipi_complete:
post_code(POSTCODE_SOC_SET_CAR_BASE)
/* Set Cache-as-RAM base address. */
movl $(MTRR_PHYS_BASE(0)), %ecx
movl car_mtrr_start, %eax
orl $MTRR_TYPE_WRBACK, %eax
xorl %edx, %edx
wrmsr
/* Set Cache-as-RAM mask. */
movl $(MTRR_PHYS_MASK(0)), %ecx
rdmsr
movl car_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr
post_code(POSTCODE_SOC_ENABLE_MTRRS)
/* Enable MTRR. */
movl $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
orl $MTRR_DEF_TYPE_EN, %eax
wrmsr
/* Enable L2 cache Write-Back (WBINVD and FLUSH#).
*
* MSR is set when DisplayFamily_DisplayModel is one of:
* 06_0x, 06_17, 06_1C
*
* Description says this bit enables use of WBINVD and FLUSH#.
* Should this be set only after the system bus and/or memory
* controller can successfully handle write cycles?
*/
#define EAX_FAMILY(a) (a << 8) /* for family <= 0fH */
#define EAX_MODEL(a) (((a & 0xf0) << 12) | ((a & 0xf) << 4))
movl $1, %eax
cpuid
movl %eax, %ebx
andl $EAX_FAMILY(0x0f), %eax
cmpl $EAX_FAMILY(0x06), %eax
jne no_msr_11e
movl %ebx, %eax
andl $EAX_MODEL(0xff), %eax
cmpl $EAX_MODEL(0x17), %eax
je has_msr_11e
cmpl $EAX_MODEL(0x1c), %eax
je has_msr_11e
andl $EAX_MODEL(0xf0), %eax
cmpl $EAX_MODEL(0x00), %eax
jne no_msr_11e
has_msr_11e:
movl $0x11e, %ecx
rdmsr
orl $(1 << 8), %eax
wrmsr
no_msr_11e:
post_code(POSTCODE_SOC_ENABLE_CACHE)
/* Cache the whole rom to fetch microcode updates */
movl $MTRR_PHYS_BASE(1), %ecx
xorl %edx, %edx
movl rom_mtrr_base, %eax
orl $MTRR_TYPE_WRPROT, %eax
wrmsr
movl $MTRR_PHYS_MASK(1), %ecx
rdmsr
movl rom_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr
/* Enable cache (CR0.CD = 0, CR0.NW = 0). */
movl %cr0, %eax
andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
invd
movl %eax, %cr0
#if CONFIG(MICROCODE_UPDATE_PRE_RAM)
update_microcode:
/* put the return address in %esp */
movl $end_microcode_update, %esp
jmp update_bsp_microcode
end_microcode_update:
#endif
post_code(POSTCODE_SOC_DISABLE_CACHE)
/* Disable caching to change MTRR's. */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
movl %eax, %cr0
/*
* An unidentified combination of speculative reads and branch
* predictions inside WRPROT-cacheable memory can cause invalidation
* of cachelines and loss of stack on models based on NetBurst
* microarchitecture. Therefore disable WRPROT region entirely for
* all family F models.
*/
movl $1, %eax
cpuid
cmp $0xf, %ah
jne cache_rom
disable_cache_rom:
movl $MTRR_PHYS_MASK(1), %ecx
rdmsr
andl $(~MTRR_PHYS_MASK_VALID), %eax
wrmsr
jmp fill_cache
cache_rom:
/* Enable cache for our code in Flash because we do XIP here */
movl $MTRR_PHYS_BASE(1), %ecx
xorl %edx, %edx
movl $_program, %eax
andl xip_mtrr_mask, %eax
orl $MTRR_TYPE_WRPROT, %eax
wrmsr
movl $MTRR_PHYS_MASK(1), %ecx
rdmsr
movl xip_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr
fill_cache:
post_code(POSTCODE_SOC_FILL_CACHE)
/* Enable cache. */
movl %cr0, %eax
andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
invd
movl %eax, %cr0
/* Clear the cache memory region. This will also fill up the cache. */
cld
xorl %eax, %eax
movl $_car_mtrr_start, %edi
movl $_car_mtrr_size, %ecx
shr $2, %ecx
rep stosl
/* Setup the stack. */
mov $_ecar_stack, %esp
/* Need to align stack to 16 bytes at call instruction. Account for
the pushes below. */
andl $0xfffffff0, %esp
subl $4, %esp
#if ENV_X86_64
setup_longmode $PML4E
movd %mm2, %rdi
shlq $32, %rdi /* BIST */
movd %mm1, %rsi
or %rsi, %rdi /* tsc[63:32] */
movd %mm0, %rsi /* tsc[31:0] */
#else
/* push TSC and BIST to stack */
movd %mm0, %eax
pushl %eax /* BIST */
movd %mm2, %eax
pushl %eax /* tsc[63:32] */
movd %mm1, %eax
pushl %eax /* tsc[31:0] */
#endif
/* Copy .data section content to Cache-As-Ram */
#include <cpu/x86/copy_data_section.inc>
before_c_entry:
post_code(POSTCODE_BOOTBLOCK_BEFORE_C_ENTRY)
call bootblock_c_entry_bist
/* Should never see this postcode */
post_code(POSTCODE_DEAD_CODE)
.Lhlt:
hlt
jmp .Lhlt
fixed_mtrr_list:
.word MTRR_FIX_64K_00000
.word MTRR_FIX_16K_80000
.word MTRR_FIX_16K_A0000
.word MTRR_FIX_4K_C0000
.word MTRR_FIX_4K_C8000
.word MTRR_FIX_4K_D0000
.word MTRR_FIX_4K_D8000
.word MTRR_FIX_4K_E0000
.word MTRR_FIX_4K_E8000
.word MTRR_FIX_4K_F0000
.word MTRR_FIX_4K_F8000
fixed_mtrr_list_end:
_cache_as_ram_setup_end:
|