blob: 2d654a09603374c597a27d4f5a6d93a19b53887e [file] [log] [blame]
Martin Roth7687e772023-08-22 16:32:20 -06001/* SPDX-License-Identifier: BSD-3-Clause */
2
Marc Jones0b11bd02015-07-19 15:20:17 -06003/*
4 * Copyright (c) 2012, Advanced Micro Devices, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31/******************************************************************************
32* AMD Generic Encapsulated Software Architecture
33*
34* $Workfile:: GccCar.inc $Revision:: 32932 $
35*
36* Description: GccCar.inc - AGESA cache-as-RAM setup Include File for GCC complier
37*
38******************************************************************************/
39
40.altmacro
41
42BSP_STACK_BASE_ADDR = 0x30000 /* Base address for primary cores stack */
43BSP_STACK_SIZE = 0x10000 /* 64KB for BSP core */
44CORE0_STACK_BASE_ADDR = 0x80000 /* Base address for primary cores stack */
45CORE0_STACK_SIZE = 0x4000 /* 16KB for primary cores */
46CORE1_STACK_BASE_ADDR = 0x40000 /* Base address for AP cores */
47CORE1_STACK_SIZE = 0x1000 /* 4KB for each AP cores */
48
49APIC_BASE_ADDRESS = 0x0000001B
50 APIC_BSC = 8 /* Boot Strap Core */
51
52APIC_MSG_REG = 0x380 # Location of BSC message
53 APIC_MSG = 0x00DE00AD # Message data
54 APIC_INVD_ALL_DONE_MSG = 0x00AD00DE /* Indicate all cores have invalidated */
55APIC_CMD_LO_REG = 0x300 # APIC command low
56APIC_CMD_HI_REG = 0x310 # APIC command high
57// del CMD_REG_TO_READ_DATA = 0x00000338 # APIC command for remote read of APIC_MSG_REG
58 REMOTE_READ_STS = 0x00030000 # Remote read status mask
59 REMOTE_DELIVERY_PEND = 0x00010000 # Remote read is pending
60 REMOTE_DELIVERY_DONE = 0x00020000 # Remote read is complete
61 DELIVERY_STS_BIT = 12 #Delivery status valid bit
62APIC_ID_REG = 0x0020 # Local APIC ID offset
63 APIC20_APICID = 24
64APIC_REMOTE_READ_REG = 0x00C0 # Remote read offset
65
66# Flags can only run from bits 31 to 24. Bits 23:0 are in use.
67AMD_CU_NEED_TO_WAIT = 31
68AMD_CU_SEND_INVD_MSG = 30
69AMD_CU_RESTORE_ES = 29
70
71AMD_MTRR_VARIABLE_BASE0 = 0x0200
72AMD_MTRR_VARIABLE_BASE6 = 0x020C
73AMD_MTRR_VARIABLE_BASE7 = 0x020E
74 VMTRR_VALID = 11
75 MTRR_TYPE_WB = 0x06
76 MTRR_TYPE_WP = 0x05
77 MTRR_TYPE_WT = 0x04
78 MTRR_TYPE_UC = 0x00
79AMD_MTRR_VARIABLE_MASK7 = 0x020F
80AMD_MTRR_FIX64k_00000 = 0x0250
81AMD_MTRR_FIX16k_80000 = 0x0258
82AMD_MTRR_FIX16k_A0000 = 0x0259
83AMD_MTRR_FIX4k_C0000 = 0x0268
84AMD_MTRR_FIX4k_C8000 = 0x0269
85AMD_MTRR_FIX4k_D0000 = 0x026A
86AMD_MTRR_FIX4k_D8000 = 0x026B
87AMD_MTRR_FIX4k_E0000 = 0x026C
88AMD_MTRR_FIX4k_E8000 = 0x026D
89AMD_MTRR_FIX4k_F0000 = 0x026E
90AMD_MTRR_FIX4k_F8000 = 0x026F
91
92/* Reproduced from AGESA.h */
93AMD_AP_MTRR_FIX64k_00000 = 0x00000250
94AMD_AP_MTRR_FIX16k_80000 = 0x00000258
95AMD_AP_MTRR_FIX16k_A0000 = 0x00000259
96AMD_AP_MTRR_FIX4k_C0000 = 0x00000268
97AMD_AP_MTRR_FIX4k_C8000 = 0x00000269
98AMD_AP_MTRR_FIX4k_D0000 = 0x0000026A
99AMD_AP_MTRR_FIX4k_D8000 = 0x0000026B
100AMD_AP_MTRR_FIX4k_E0000 = 0x0000026C
101AMD_AP_MTRR_FIX4k_E8000 = 0x0000026D
102AMD_AP_MTRR_FIX4k_F0000 = 0x0000026E
103AMD_AP_MTRR_FIX4k_F8000 = 0x0000026F
104CPU_LIST_TERMINAL = 0xFFFFFFFF
105
106AMD_MTRR_DEFTYPE = 0x02FF
107 WB_DRAM_TYPE = 0x1E /* MemType - memory type */
108 MTRR_DEF_TYPE_EN = 11 /* MtrrDefTypeEn - variable and fixed MTRRs default enabled */
109 MTRR_DEF_TYPE_FIX_EN = 10 /* MtrrDefTypeEn - fixed MTRRs default enabled */
110
111HWCR = 0x0C0010015 /* Hardware Configuration */
112 INVD_WBINVD = 0x04 /* INVD to WBINVD conversion */
113
114IORR_BASE = 0x0C0010016 /* IO Range Regusters Base/Mask, 2 pairs */
115 /* uses 16h - 19h */
116TOP_MEM = 0x0C001001A /* Top of Memory */
117TOP_MEM2 = 0x0C001001D /* Top of Memory2 */
118
119LS_CFG = 0x0C0011020 /* Load-Store Configuration */
120 DIS_SS = 28 /* Family 10h,12h,15h:Disable Streng Store functionality */
121 DIS_STREAM_ST = 28 /* Family 14h:DisStreamSt - Disable Streaming Store functionality */
122
123IC_CFG = 0x0C0011021 /* Instruction Cache Config Register */
124 IC_DIS_SPEC_TLB_RLD = 9 /* Disable speculative TLB reloads */
125 DIS_IND = 14 /* Family 10-14h:Disable Indirect Branch Predictor */
126 DIS_I_CACHE = 14 /* Family 15h:DisICache - Disable Indirect Branch Predictor */
127
128DC_CFG = 0x0C0011022 /* Data Cache Configuration */
129 DC_DIS_SPEC_TLB_WALK = 4 /* Disable speculative table-walks */
130 DIS_HW_PF = 13 /* Hardware prefetches bit */
131DE_CFG = 0x0C0011029 /* Decode Configuration */
132 CL_FLUSH_SERIALIZE = 23 /* Family 12h,15h: CL Flush Serialization */
133
134BU_CFG2 = 0x0C001102A /* Family 10h: Bus Unit Configuration 2 */
135CU_CFG2 = 0x0C001102A /* Family 15h: Combined Unit Configuration 2 */
136 F10_CL_LINES_TO_NB_DIS = 15 /* ClLinesToNbDis - allows WP code to be cached in L2 */
137 IC_DIS_SPEC_TLB_WR = 35 /* IcDisSpecTlbWr - ITLB speculative writes */
138 F16_CL_LINES_TO_L2_DIS = 15 /* ClLinesToL2Dis */
139
140//del CU_CFG3 = 0x0C001102B /* Combined Unit Configuration 3 */
141//del COMBINE_CR0_CD = 49 /* Combine CR0.CD for both cores of a compute unit */
142//del L2I_CFG = 0x0C00110A0 /* L2I Configuration */
143 L2_RINSER_DIS = 20 /* L2 rinser disable */
144 PREFETCHER_DIS = 7 /* L2 prefetcher disable*/
145 CACHE_IC_ATTR_DIS = 3 /* Inserting IC attributes into the L2 disable */
146
147CR0_PE = 0 # Protection Enable
148CR0_NW = 29 # Not Write-through
149CR0_CD = 30 # Cache Disable
150CR0_PG = 31 # Paging Enable
151
152/* CPUID Functions */
153
154CPUID_MODEL = 1
155AMD_CPUID_FMF = 0x80000001 /* Family Model Features information */
Subrata Banik8e6d5f22020-08-30 13:51:44 +0530156AMD_CPUID_L2Cache = 0x80000006 /* L2/L3 cache info */
Marc Jones0b11bd02015-07-19 15:20:17 -0600157AMD_CPUID_APIC = 0x80000008 /* Long Mode and APIC info., core count */
158 APIC_ID_CORE_ID_SIZE = 12 /* ApicIdCoreIdSize bit position */
159
160NB_CFG = 0x0C001001F /* Northbridge Configuration Register */
161 INIT_APIC_ID_CPU_ID_LO = 54 /* InitApicIdCpuIdLo - is core# in high or low half of APIC ID? */
162 ENABLE_CF8_EXT_CFG = 46 /* EnableCf8ExtCfg - enable CF8 extended configuration cycles */
163
164MTRR_SYS_CFG = 0x0C0010010 /* System Configuration Register */
165 CHX_TO_DIRTY_DIS = 16 /* ChxToDirtyDis Change to dirty disable */
166 SYS_UC_LOCK_EN = 17 /* SysUcLockEn System lock command enable */
167 MTRR_FIX_DRAM_EN = 18 /* MtrrFixDramEn MTRR fixed RdDram and WrDram attributes enable */
168 MTRR_FIX_DRAM_MOD_EN = 19 /* MtrrFixDramModEn MTRR fixed RdDram and WrDram modification enable */
169 MTRR_VAR_DRAM_EN = 20 /* MtrrVarDramEn MTRR variable DRAM enable */
170 MTRR_TOM2_EN = 21 /* MtrrTom2En MTRR top of memory 2 enable */
171
172PERF_CONTROL3 = 0x0C0010003 /* Performance event control three */
173 PERF_CONTROL3_RESERVE_L = 0x00200000 /* Preserve the reserved bits */
174 PERF_CONTROL3_RESERVE_H = 0x0FCF0 /* Preserve the reserved bits */
175 CONFIG_EVENT_L = 0x0F0E2 /* All cores with level detection */
176 CONFIG_EVENT_H = 4 /* Increment count by number of event */
177 /* occured in clock cycle */
178 EVENT_ENABLE = 22 /* Enable the event */
179PERF_COUNTER3 = 0x0C0010007 /* Performance event counter three */
180
181COMPUTE_UNIT_STATUS = 0x08000C580 /* Compute Unit Status Register */
182 QUAD_CORE = 24 /* QuadCore four cores of a compute unit are enabled */
183 DUAL_CORE = 16 /* DualCore two cores of a compute unit are enabled */
184 TRIPLE_CORE = 8 /* TripleCore three cores of a compute unit are enabled */
185 CU_ENABLED = 0 /* Enabled at least one core of a compute unit is enabled */
186
187FUNC_3 = 3
188MCA_NB_CFG = 0x44 /* MCA NB Configuration */
189CPU_ERR_DIS = 6 /* CPU error response disable */
190PRODUCT_INFO_REG1 = 0x1FC /* Product Information Register 1 */
191
192# Local use flags, in upper most byte if ESI
193FLAG_UNKNOWN_FAMILY = 24 # Signals that the family# of the installed processor is not recognized
194FLAG_STACK_REENTRY = 25 # Signals that the environment has made a re-entry (2nd) call to set up the stack
195FLAG_IS_PRIMARY = 26 # Signals that this core is the primary within the comoute unit
196FLAG_CORE_NOT_IDENTIFIED = 27 # Signals that the cores/compute units of the installed processor is not recognized
197FLAG_FORCE_32K_STACK = 28 # Signals that to force 32KB stack size for BSP core
198CR0_MASK = ((1 << CR0_CD) | (1 << CR0_NW))
199MSR_MASK = ((1 << MTRR_DEF_TYPE_EN)+(1 << MTRR_DEF_TYPE_FIX_EN))
200
201/****************************************************************************
202 *
203 * CPU MACROS - PUBLIC
204 *
205 ****************************************************************************/
206.macro _WRMSR
207 .byte 0x0f, 0x30
208.endm
209
210.macro _RDMSR
211 .byte 0x0F, 0x32
212.endm
213
214.macro AMD_CPUID arg0
215 .ifb \arg0
216 mov $0x1, %eax
217 .byte 0x0F, 0x0A2 /* Execute instruction */
218 bswap %eax
219 xchg %ah, %al /* Ext model in al now */
220 rol $0x08, %eax /* Ext model in ah, model in al */
221 and $0x0FFCF, ax /* Keep 23:16, 7:6, 3:0 */
222 .else
223 mov \arg0, %eax
224 .byte 0x0F, 0x0A2
225 .endif
226.endm
227
228.macro MAKE_EXT_PCI_ADDR Seg, Bus, Dev, Func, Offset
229 mov $(1 << 31 | (Seg) << 28 | (((Offset) & (0x0F00)) >> 8) << 24 | (Bus) << 16 | (Dev) << 11 | (Func) << 8) | ((Offset) & (0xFC)), %eax
230.endm
231/****************************************************************************
232*
233* AMD_ENABLE_STACK_FAMILY_HOOK Macro - Stackless
234*
235* Set any family specific controls needed to enable the use of
236* cache as general storage before main memory is available.
237*
238* Inputs:
239* none
240* Outputs:
241* none
242 ****************************************************************************/
243.macro AMD_ENABLE_STACK_FAMILY_HOOK
244
245 AMD_ENABLE_STACK_FAMILY_HOOK_F16
246
247.endm
248
249/****************************************************************************
250*
251* AMD_DISABLE_STACK_FAMILY_HOOK Macro - Stackless
252*
253* Return any family specific controls to their 'standard'
254* settings for using cache with main memory.
255*
256* Inputs:
257* none
258* Outputs:
259* none
260 ****************************************************************************/
261.macro AMD_DISABLE_STACK_FAMILY_HOOK
262
263 AMD_DISABLE_STACK_FAMILY_HOOK_F16
264
265.endm
266
267/****************************************************************************
268*
269* GET_NODE_ID_CORE_ID Macro - Stackless
270*
271* Read family specific values to determine the node and core
272* numbers for the core executing this code.
273*
274* Inputs:
275* none
276* Outputs:
277* SI[7:0] = Core# (0..N, relative to node)
278* SI[15:8]= Node# (0..N)
279* SI[23:16]= reserved
280* SI[24]= flag: 1=Family Unrecognized
281* SI[25]= flag: 1=Interface re-entry call
282* SI[26]= flag: 1=Core is primary of compute unit
283* SI[31:27]= reserved, =0
284****************************************************************************/
285.macro GET_NODE_ID_CORE_ID
Marc Jones0b11bd02015-07-19 15:20:17 -0600286
287 mov $-1, %si
288 GET_NODE_ID_CORE_ID_F16
289
290 /*
291 * Check for unrecognized Family
292 */
293 cmp $-1, %si # Has family (node/core) already been discovered?
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100294 jnz node_core_exit\@ # Br if yes
Marc Jones0b11bd02015-07-19 15:20:17 -0600295
296 mov $((1 << FLAG_UNKNOWN_FAMILY)+(1 << FLAG_IS_PRIMARY)), %esi # No, Set error code, Only let BSP continue
297
298 mov $APIC_BASE_ADDRESS, %ecx # MSR:0000_001B
299 _RDMSR
300 bt $APIC_BSC, %eax # Is this the BSC?
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100301 jc node_core_exit\@ # Br if yes
Marc Jones0b11bd02015-07-19 15:20:17 -0600302 hlt # Kill APs
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100303node_core_exit\@:
Marc Jones0b11bd02015-07-19 15:20:17 -0600304
305.endm
306
307/*
308***************************************************************************
309 Family 16h MACROS
310***************************************************************************/
311/*--------------------------------------------------
312
313AMD_ENABLE_STACK_FAMILY_HOOK_F16 Macro - Stackless
314
315 Set any family specific controls needed to enable the use of
316 cache as general storage before main memory is available.
317
318Inputs:
319 ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
320Outputs:
321 none
322Destroyed:
323 eax, ebx, ecx, edx
324
325Family 16h requirements (BKDG #48751 section 2.3.3):
326 * Paging must be disabled.
327 * MSRC001_0015[INVD_WBINVD]=0
328 * MSRC001_1020[DisSS]=1
329 * MSRC001_1021[DIS_SPEC_TLB_RLD]=1
330 * MSRC001_1022[DIS_SPEC_TLB_RLD]=1
331 * MSRC001_1022[DisHwPf]=1
332 * If MSRC001_102B[CombineCr0Cd] == 1 then MSRC001_102B[CombineCroCd] = 0
333 * No INVD or WBINVD, no exceptions, page faults or interrupts
334--------------------------------------------------
335
336 */
337
338.macro AMD_ENABLE_STACK_FAMILY_HOOK_F16
Marc Jones0b11bd02015-07-19 15:20:17 -0600339
340 AMD_CPUID $CPUID_MODEL
341 mov %eax, %ebx # Save revision info to EBX
342 shr $20, %eax # AL = cpu extended family
343 cmp $0x07, %al # Is this family 16h?
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100344 jnz fam16_enable_stack_hook_exit\@ # Br if no
Marc Jones0b11bd02015-07-19 15:20:17 -0600345
346 bt $FLAG_STACK_REENTRY , %esi # Check if stack has already been set
347 jc fam16_skipClearingBit4
348 mov $HWCR, %ecx # MSR C001_0015
349 _RDMSR
350 btr $INVD_WBINVD, %eax # disable INVD -> WBINVD conversion
351 _WRMSR
352
353fam16_skipClearingBit4:
354 mov $IC_CFG, %ecx # MSR:C001_1021
355 _RDMSR
356 bts $IC_DIS_SPEC_TLB_RLD, %eax # Turn on Disable speculative IC-TLB reloads bit
357 _WRMSR
358
359# mov %ebx, %eax # Restore revision info to EAX
360# shr $16, %eax
361# and $0x0F, %al # AL = cpu extended model
362
363 mov $DC_CFG, %ecx # MSR:C001_1022
364 _RDMSR
365 bts $DC_DIS_SPEC_TLB_WALK, %eax # Turn on Disable speculative DC-TLB reloads bit
366 bts $DIS_HW_PF, %eax # Turn on Disable hardware prefetches bit
367 _WRMSR # Remove KM in PI 1.1.0.0
368
369 mov $0x0C00110A0, %ecx # MSR:C001_10A0
370 _RDMSR
371 bts $L2_RINSER_DIS, %eax #Do not search for the repair single bit errors in the background
372 bts $PREFETCHER_DIS, %eax
373 bts $CACHE_IC_ATTR_DIS, %eax
374 _WRMSR
375
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100376fam16_enable_stack_hook_exit\@:
Marc Jones0b11bd02015-07-19 15:20:17 -0600377.endm
378
379/*
380;
381; AMD_DISABLE_STACK_FAMILY_HOOK_F16 Macro - Stackless
382;
383; Return any family specific controls to their 'standard'
384; settings for using cache with main memory.
385;
386; Inputs:
387; ESI - [31:24] flags; [15:8]= Node#; [7:0]= core#
388; Outputs:
389; none
390; Destroyed:
391; eax, ebx, ecx, edx
392;
393; Family 16h requirements:
394; * INVD or WBINVD
395; * MSRC001_0015[INVD_WBINVD]=1
396; * MSRC001_1020[DisSS]=0
397; * MSRC001_1021[DIS_SPEC_TLB_RLD]=0
398; * MSRC001_1022[DIS_SPEC_TLB_RLD]=0
399; * MSRC001_1022[DIS_HW_PF]=0
400;---------------------------------------------------
401*/
402.macro AMD_DISABLE_STACK_FAMILY_HOOK_F16
Marc Jones0b11bd02015-07-19 15:20:17 -0600403
404 AMD_CPUID $CPUID_MODEL
405 mov %eax, %ebx # Save revision info to EBX
406 shr $20, %eax # AL = cpu extended family
407 cmp $0x07, %al # Is this family 16h?
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100408 jnz fam16_disable_stack_hook_exit\@ # Br if no
Marc Jones0b11bd02015-07-19 15:20:17 -0600409
410 mov %ebx, %edi # Save revision info to EDI
411 AMD_CPUID $AMD_CPUID_APIC
412 mov %cl, %al # AL = number of cores - 1
413 shr $APIC_ID_CORE_ID_SIZE, %cx # CL = ApicIdCoreIdSize
414 mov $1, %bx
415 shl %cl, %bl # BL = theoretical number of cores on socket
416 dec %bx # BL = core number on socket mask
417 mov %bl, %ah # AH = core number on socket mask
418 mov %edi, %ebx # Restore revision info to EBX
419 mov %ax, %di # DI[15:8] = core number mask, DI[7:0] = number of cores - 1
420
421 and $0x0F00FF, %ebx
422 mov %ebx, %eax
423 shr $8, %eax
424 or %ax, %bx # Save Extended Model, Model and Stepping to BX
425 # [11:8] = Extended Model, [7:4] = Model, [3:0] = Stepping (bx=0000000000010100, ok)
426
427 mov $APIC_BASE_ADDRESS, %ecx
428 _RDMSR # dx=0 ax=fee00800
429 mov %bx, %dx # Save Extended Model, Model and Stepping to DX
430 shl $16, %edx #EDX[31:16] = Extended Model, Model and Stepping
431 mov %eax ,%ebx # EBX = LAPIC base
432 xor %ecx ,%ecx # Zero out CU flags
433 bts $AMD_CU_NEED_TO_WAIT, %ecx # Default to waiting
434 bts $AMD_CU_SEND_INVD_MSG, %ecx # Default to signaling
435 mov %cr0, %eax
436 bt $CR0_PE, %ax # Are we in protected mode?
437 # .if (!carry?)
438 jc 1f
439 bts $AMD_CU_RESTORE_ES, %ecx # Indicate ES restore is required
440 mov %es, %cx # Save ES segment register to CX
441 xor %ax, %ax
442 mov %ax, %es # Set ES to big real mode selector for 4GB access
443 # .endif
444
4451:
446 and $0x0F000, %bx # EBX = LAPIC base, offset 0
447 or $APIC_ID_REG, %bl #
448 mov %es:(%ebx), %eax # EAX[31:24] = APIC ID
449 shr $APIC20_APICID, %eax # AL = APIC ID
450 mov %al, %ah # AH = APIC ID
451 mov %di, %dx # DH = core mask
452 and %dh, %ah # AH = core number # ax=111 dx=01000F03
453
454 # .if (zero?)
455 jnz 1f
456 # Core 0 of a socket
457 btr $AMD_CU_SEND_INVD_MSG, %ecx # No need to signal after INVD
458 #.if (dl != 0)
459 cmp $0, %dl
460 jz 2f
461 # This socket has multiple cores
462 and $0xf000, %bx # EBX = LAPIC base, offset 0
463 or $APIC_MSG_REG, %bx
464 mov $APIC_MSG, %edi
465 mov %edi, %es:(%ebx) # Signal for non core 0s to complete CAR breakdown
466 jmp 1f
467 #.else
4682: btr $AMD_CU_NEED_TO_WAIT, %ecx # No need to wait on a single core CPU
469 #.endif
470 # .endif
4711:
472
473 bt $AMD_CU_NEED_TO_WAIT, %ecx #cx = c0000000
474 #.if (carry?)
475 jnc 1f
476 #.if (ah == dl)
477 cmp %dl, %ah
478 jnz 2f
479 # This is the highest numbered core on this socket -- wait on core 0
480 not %dh # Flip the mask to determine local core 0's APID ID
481 and %dh, %al # AL = target APIC ID # ax=310
482 jmp 3f
4832: #.else
484 # All other cores (including core 0) wait on the next highest core.
485 # In this way, cores will halt in a cascading fashion down to 0.
486 inc %al
487 #.endif
4883:
489 shl $APIC20_APICID, %eax
490 and $0x0F000, %bx
491 or $APIC_CMD_HI_REG, %bx
492 mov %eax, %es:(%ebx) # Set target APIC ID
493
494 # Use bits 23:16 as a timeout for unresponsive cores
495 ror $8, %ecx
496 mov $0xFF, %ch
497 stc
498
499 #.while (carry?)
5005: jnc 4f
501 and $0xF000, %bx #EBX = LAPIC base, offset 0
502 or $APIC_CMD_LO_REG, %bx # bx = 00000000FEE00300
503 mov $0x338, %eax
504 mov %eax, %es:(%ebx) #Fire remove read IPI
505 inc %ch #Pre increment the timeout
506 stc
507 #.while (carry?)
5087: jnc 6f
509 dec %ch #Check the timeout
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100510 jz fam16_disable_stack_remote_read_exit\@
Marc Jones0b11bd02015-07-19 15:20:17 -0600511 mov %es:(%ebx), %eax # ax = 0000000000020338
512 bt $DELIVERY_STS_BIT, %eax
513 jmp 7b
5146: #.endw
515 stc
516 #.while (carry?)
5177: jnc 6f
518 mov %es:(%ebx), %eax
519 and $REMOTE_READ_STS, %eax
520 #.if (eax == REMOTE_DELIVERY_PEND)
521 cmp $REMOTE_DELIVERY_PEND, %eax
522 jnz 8f
523 dec %ch # Check the timeout
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100524 jz fam16_disable_stack_hook_exit\@ # Branch if there is an unreponsive core
Marc Jones0b11bd02015-07-19 15:20:17 -0600525 stc
526 jmp 9f
5278: #.else
528 clc
5299: #.endif
530 jmp 7b
5316: #.endw
532 #.if (eax == REMOTE_DELIVERY_DONE)
533 cmp $REMOTE_DELIVERY_DONE, %eax
534 jnz 6f
535 and $0x0F000, %bx #EBX = LAPIC base, offset 0
536 or $APIC_REMOTE_READ_REG, %bl
537 mov %es:(%ebx), %eax
538 #.if (eax == APIC_MSG)
539 cmp $APIC_MSG, %eax # ax=00000000FFC5BBB2
540 jnz 8f
541 clc
542 jmp 9f
543 #.else
5448: stc
5459: #.endif
546 jmp 7f
5476: #.else
548 dec %ch
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100549 jz fam16_disable_stack_remote_read_exit\@
Marc Jones0b11bd02015-07-19 15:20:17 -0600550 stc
5517: #.endif
552 jmp 5b
5534: #.endw
554
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100555fam16_disable_stack_remote_read_exit\@:
Marc Jones0b11bd02015-07-19 15:20:17 -0600556 rol $8, %ecx # Restore ECX
557
5581: #.endif
559
560 bt $AMD_CU_RESTORE_ES, %ecx
561 #.if (carry?)
562 jnc 1f
563 mov %cx, %es
5641:
565 mov %ecx, %edi
566 shr $16, %edx
567 mov %dx, %bx
568
569 #Handshaking complete. Continue tearing down CAR.
570
571 mov $IC_CFG, %ecx # MSR:C001_1021
572 _RDMSR
573 btr $IC_DIS_SPEC_TLB_RLD, %eax # Turn on speculative TLB reloads
574 _WRMSR
575
576 mov $DC_CFG, %ecx # MSR:C001_1022
577 _RDMSR
578 btr $DC_DIS_SPEC_TLB_WALK, %eax # Turn on speculative table-walks
579 #.if (bx != 0) # Is this rev A0?
580 #cmp $0, %bx
581 #jz 0f
582 btr $DIS_HW_PF, %eax # Turn on hardware prefetches
583 #.endif # End workaround for erratum 498
584 #0:
585 _WRMSR
586
587 mov $0x0C00110A0, %ecx #MSR:C001_10A0
588 _RDMSR
589 btr $PREFETCHER_DIS, %eax
590 btr $CACHE_IC_ATTR_DIS, %eax
591 _WRMSR
592
593 mov $BU_CFG2, %ecx
594 _RDMSR
595 btr $F16_CL_LINES_TO_L2_DIS, %eax
596 _WRMSR
597
598 mov $HWCR, %ecx # MSR:C001_0015h
599 _RDMSR
600 btr $INVD_WBINVD, %eax # Disable INVD -> WBINVD conversion
601 _WRMSR
Marc Jones7f5d0f32017-02-24 16:40:41 -0700602
Kyösti Mälkkic08fdf32019-12-03 08:04:31 +0200603 # An invd here sometimes breaks AP CPU startup
604 wbinvd
Marc Jones0b11bd02015-07-19 15:20:17 -0600605
606 #Do Standard Family 16 work
607 mov $HWCR, %ecx # MSR:C001_0015h
608 _RDMSR
609 bts $INVD_WBINVD, %eax # Turn on Conversion of INVD to WBINVD
610 _WRMSR
611 #.endif # end
612
613 bt $AMD_CU_SEND_INVD_MSG, %edi
614 #.if (carry?)
615 jnc 1f
616 AMD_CPUID $AMD_CPUID_APIC
617 shr $APIC_ID_CORE_ID_SIZE, %cx # CL = ApicIdCoreIdSize
618 mov $1, %di
619 shl %cl, %di #DI = theoretical number of cores on socket
620 dec %di # DI = core number on socket mask
621 # Non core zero needs to signal to core 0 to proceed
622 mov $APIC_BASE_ADDRESS, %ecx
623 _RDMSR
624 mov %eax, %ebx # EBX = LAPIC base
625 and $0x0F000, %bx # EBX = LAPIC base, offset 0
626 or $APIC_MSG_REG, %bx
627 mov $APIC_MSG, %eax
628 mov %eax, %es:(%ebx) # Signal for core 0 to complete CAR breakdown
629
630 #TODO: Non core zero needs to wait for core zero to do INVD
631 #A handshake is required to ensure that all cores on a node invalidate in sync.
632 and $0x0F000, %bx
633 or $APIC_ID_REG, %bl
634 mov %es:(%ebx), %eax # EAX[31:24] = APIC ID
635 shr $APIC20_APICID, %eax # AL = APIC ID
636 mov %di, %dx # Use DL as core mask
637 not %dl
638 and %dl, %al # Remote read message from core zero
639 shl $APIC20_APICID, %eax
640
641 and $0x0F000, %bx
642 or $APIC_CMD_HI_REG, %bx
643 mov %eax, %es:(%ebx) #
644 # Use bits 23:16 as a timeout for unresponsive cores
645 ror $8, %ecx
646 mov $0xFF, %ch
647 stc
648
649 #.while (carry?)
6505: jnc 4f
651 and $0xF000, %bx #EBX = LAPIC base, offset 0
652 or $APIC_CMD_LO_REG, %bx # bx = 00000000FEE00300
653 mov $0x338, %eax
654 mov %eax, %es:(%ebx) #Fire remove read IPI
655 inc %ch #Pre increment the timeout
656 stc
657 #.while (carry?)
6587: jnc 6f
659 dec %ch #Check the timeout
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100660 jz fam16_invd_done_remote_read_exit\@
Marc Jones0b11bd02015-07-19 15:20:17 -0600661 mov %es:(%ebx), %eax # ax = 0000000000020338
662 bt $DELIVERY_STS_BIT, %eax
663 jmp 7b
6646: #.endw
665 stc
666 #.while (carry?)
6677: jnc 6f
668 mov %es:(%ebx), %eax
669 and $REMOTE_READ_STS, %eax
670 #.if (eax == REMOTE_DELIVERY_PEND)
671 cmp $REMOTE_DELIVERY_PEND, %eax
672 jnz 8f
673 dec %ch # Check the timeout
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100674 jz fam16_invd_done_remote_read_exit\@ # Branch if there is an unreponsive core
Marc Jones0b11bd02015-07-19 15:20:17 -0600675 stc
676 jmp 9f
6778: #.else
678 clc
6799: #.endif
680 jmp 7b
6816: #.endw
682 #.if (eax == REMOTE_DELIVERY_DONE)
683 cmp $REMOTE_DELIVERY_DONE, %eax
684 jnz 6f
685 and $0x0F000, %bx #EBX = LAPIC base, offset 0
686 or $APIC_REMOTE_READ_REG, %bl
687 mov %es:(%ebx), %eax
688 #.if (eax == APIC_MSG)
689 cmp $APIC_MSG, %eax # ax=00000000FFC5BBB2
690 jnz 8f
691 clc
692 jmp 9f
693 #.else
6948: stc
6959: #.endif
696 jmp 7f
6976: #.else
698 dec %ch
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100699 jz fam16_invd_done_remote_read_exit\@
Marc Jones0b11bd02015-07-19 15:20:17 -0600700 stc
7017: #.endif
702 jmp 5b
7034: #.endw
704
705 jmp 2f
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100706fam16_invd_done_remote_read_exit\@:
Marc Jones0b11bd02015-07-19 15:20:17 -06007071: #.else
708 mov $APIC_BASE_ADDRESS, %ecx
709 _RDMSR
710 mov %eax, %ebx
711 and $0x0F000, %bx
712 or $APIC_MSG_REG, %bx
713 mov $APIC_INVD_ALL_DONE_MSG, %edi
714 mov %edi, %es:(%ebx)
7152: #.endif
716
717 mov $0xc0011004, %ecx
718 _RDMSR
719 btr $30, %edx
720 _WRMSR
721
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100722fam16_disable_stack_hook_exit\@:
Marc Jones0b11bd02015-07-19 15:20:17 -0600723.endm
724
725/*
726*/
727.macro GET_NODE_ID_CORE_ID_F16
728
Marc Jones0b11bd02015-07-19 15:20:17 -0600729
730#define F16_L2Size 1024
731#define F16_ShareCores 4
732#define F16_AllocMem 0
733#define F16_AllocExe 0
734#define F16_SzAddrBus 40
735#define F16_pad 0
736 cmp $-1, %si # Has node/core already been discovered?
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100737 jnz node_core_f16_exit\@ # Br if yes
Marc Jones0b11bd02015-07-19 15:20:17 -0600738
739 AMD_CPUID $CPUID_MODEL
740 shr $12, %eax # AL = cpu extended family
741 cmp $07, %ah # Is this family 16h?
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100742 jnz node_core_f16_exit\@ # Br if no
Marc Jones0b11bd02015-07-19 15:20:17 -0600743 shr $4, %al # AL = cpu extended model
744 shr $16, %ebx # BH = LocalApicId
745 mov %al, %bl # BL = cpu extended model
746
747 # LoadTableAddress(FAM16H_INFO_STRUCT)
748 # movd mm5, eax # load pointer to Family Info Struc
749
750 xor %esi, %esi # Assume BSC, clear local flags
751 mov $APIC_BASE_ADDRESS, %ecx # MSR:0000_001B
752 _RDMSR
753 bt $APIC_BSC, %eax # Is this the BSC?
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100754 jnc node_core_f16_AP\@ # Br if no
Marc Jones0b11bd02015-07-19 15:20:17 -0600755
756 # This is the BSP.
757 # Enable routing tables on BSP (just in case the HT init code has not yet enabled them)
758 mov $0x8000C06C, %eax # PCI address for D18F0x6C Link Initialization Control Register
759 mov $0x0CF8, %dx
760 out %eax, %dx
761 add $4, %dx
762 in %dx, %eax
763 btr $0, %eax # Set LinkInitializationControl[RouteTblDis] = 0
764 out %eax, %dx
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100765 jmp 6f #node_core_f16_shared\@ #
Marc Jones0b11bd02015-07-19 15:20:17 -0600766
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100767node_core_f16_AP\@:
Marc Jones0b11bd02015-07-19 15:20:17 -0600768 mov %bl, %al # AL = cpu extended model
769 shr $8, %bx # BL = CPUID Fn0000_0001_EBX[LocalApicId]
770 #.if (al == 0)
771 cmp $3, %al # Is This ML?
772 jnz 5f
773 #.else
7744: mov %bx, %si
775 jmp 6f
Arthur Heymans4bf582f2022-03-23 21:36:24 +01007765: #node_core_f16_AP_not_KB\@
Marc Jones0b11bd02015-07-19 15:20:17 -0600777 bts $FLAG_CORE_NOT_IDENTIFIED, %esi
778 #.endif
779 #.endif
780 #
781 # determine if this core shares MTRRs
782 #
Arthur Heymans4bf582f2022-03-23 21:36:24 +01007836: #node_core_f16_shared\@
Marc Jones0b11bd02015-07-19 15:20:17 -0600784 mov $COMPUTE_UNIT_STATUS, %eax # Compute Unit Status
785 mov %si, %bx
786 shl $3, %bh # Move node# to PCI Dev# field
787 add %bh, %ah # Adjust for node number
788 mov $0x0CF8, %dx
789 out %eax, %dx
790 add $4, %dx
791 in %dx, %eax # [3:0]=Enabled# [19:16]=DualCore
792
793 # BL is MyCore#
794 mov $0x04, %cx # Use CH as 'first of pair' core#
795 #.while (cl > 0)
796 jmp 0f
797 8:
798 bt $CU_ENABLED, %eax # Is pair enabled?
799 #.if (carry?) #
800 jnc 1f
801 mov $0x01, %bh # flag core as primary
802 #.break .if (ch == bl) # Does 1st match MyCore#?
803 cmp %bl, %ch
804 je 9f
805 #inc %ch
806 xor %bh, %bh # flag core as NOT primary
807 #
808 bt $DUAL_CORE, %eax
809 #.if (carry?)
810 jnc 5f
811 add $1, %eax
812 #.endif
813 5:
814 bt $TRIPLE_CORE, %eax
815 jnc 5f
816 #.if (carry?)
817 add $2, %eax
818 #.endif
819 5:
820 bt $QUAD_CORE, %eax
821 jnc 5f
822 #.if (carry?)
823 add $3, %eax
824 #.endif
825 5:
826 #.break .if (ch >= bl) #TODO:
827 cmp %bl, %ch
828 jae 9f
829 inc %ch
830 #.endif
831 1:
832 shr $1, %eax
833 dec %cl
834 0:
835 cmp $0x0, %cl
836 ja 8b
837
838 #.endw
839 9:
840
841 #.if (cl == 0)
842 or %cl, %cl
843 jne 1f
844 #Error - core# didn't match Compute Unit Status content
845 bts $FLAG_CORE_NOT_IDENTIFIED, %esi
846 bts $FLAG_IS_PRIMARY, %esi # Set Is_Primary for unknowns
847 #.endif
848 1:
849 #.if (bh != 0) # Check state of primary for the matched core
850 or %bh, %bh
851 je 2f
852 bts $FLAG_IS_PRIMARY, %esi # Set shared flag into return value
853 #.endif
854 2:
855
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100856node_core_f16_exit\@:
Marc Jones0b11bd02015-07-19 15:20:17 -0600857
858.endm
859
860/*****************************************************************************
861* AMD_ENABLE_STACK: Setup a stack
862*
863* In:
Kyösti Mälkkibfe6bca2017-07-12 16:30:47 +0300864* No inputs
Marc Jones0b11bd02015-07-19 15:20:17 -0600865*
866* Out:
867* SS:ESP - Our new private stack location
868*
869* EAX = AGESA_STATUS
870*
871* ECX = Stack size in bytes
872*
873* Requirements:
874* * This routine presently is limited to a max of 64 processor cores
Marc Jones0b11bd02015-07-19 15:20:17 -0600875* Destroyed:
Kyösti Mälkkibfe6bca2017-07-12 16:30:47 +0300876* EBX, EDX, EDI, ESI, EBP, DS, ES
Marc Jones0b11bd02015-07-19 15:20:17 -0600877*
878* Description:
879* Fixed MTRR address allocation to cores:
880* The BSP gets 64K of stack, Core0 of each node gets 16K of stack, all other cores get 4K.
881* There is a max of 1 BSP, 7 core0s and 56 other cores.
882* Although each core has it's own cache storage, they share the address space. Each core must
883* be assigned a private and unique address space for its stack. To support legacy systems,
884* the stack needs to be within the legacy address space (1st 1Meg). Room must also be reserved
885* for the other legacy elements (Interrupt vectors, BIOS ROM, video buffer, etc.)
886*
887* 80000h 40000h 00000h
888* +----------+----------+----------+----------+----------+----------+----------+----------+
889* 64K | | | | | | | | | 64K ea
890* ea +----------+----------+----------+----------+----------+----------+----------+----------+
891* | MTRR 0000_0250 MTRRfix64K_00000 |
892* +----------+----------+----------+----------+----------+----------+----------+----------+
893* | 7 , 6 | 5 , 4 | 3 , 2 | 1 , 0 | 0 | | | | <-node
894* |7..1,7..1 |7..1,7..1 |7..1,7..1 |7..1,7..1 | 0 | | | | <-core
895* +----------+----------+----------+----------+----------+----------+----------+----------+
896*
897* C0000h B0000h A0000h 90000h 80000h
898* +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
899*16K | | | | | | | | | | | | | | | | |
900* ea +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
901* | MTRR 0259 MTRRfix16K_A0000 | MTRR 0258 MTRRfix16K_80000 |
902* +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
903* | > Dis|play B|uffer | < | | | | | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | <-node
904* | > T| e m |p o r |a r y | B u |f f e |r A |r e a<| 0 | 0 | 0 | 0 | 0 | 0 | 0 | | <-core
905* +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
906*
907* E0000h D0000h C0000h
908* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
909* 4K | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 4K ea
910* ea +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
911* | 026B MTRRfix4K_D8000 | 026A MTRRfix4K_D0000 | 0269 MTRRfix4K_C8000 | 0268 MTRRfix4K_C0000 |
912* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
913* | | | | | | | | | | | | | | | | | >| V| I| D| E| O| |B |I |O |S | |A |r |e |a<|
914* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
915*
916* 100000h F0000h E0000h
917* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
918* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 4K ea
919* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
920* | 026F MTRRfix4K_F8000 | 026E MTRRfix4K_F0000 | 026D MTRRfix4K_E8000 | 026C MTRRfix4K_E0000 |
921* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
922* | >|MA|IN| B|IO|S |RA|NG|E | | | | | | |< | >|EX|TE|ND|ED| B|IO|S |ZO|NE| | | | | |< |
923* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
924*****************************************************************************/
925.macro AMD_ENABLE_STACK
926
927# These are local labels. Declared so linker doesn't cause 'redefined label' errors
Marc Jones0b11bd02015-07-19 15:20:17 -0600928
929# Note that SS:ESP will be default stack. Note that this stack
930# routine will not be used after memory has been initialized. Because
931# of its limited lifetime, it will not conflict with typical PCI devices.
Marc Jones0b11bd02015-07-19 15:20:17 -0600932
933 # get node id and core id of current executing core
934 GET_NODE_ID_CORE_ID # Sets ESI[23:16]=Shared core## SI[15,8]= Node## SI[7,0]= core# (relative to node)
935 # Note: ESI[31:24] are used for flags: Unrecognized Family, Is_Primary core, Stack already established
936
937 # determine if stack is already enabled. We are using the DefType MSR for this determination.
938 # It is =0 after reset; CAR setup sets it to enable the MTRRs
939 mov %cr0, %eax
940 test $CR0_MASK, %eax # Is cache disabled? (CD & NW bits)
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100941 jnz SetupStack\@ # Jump if yes
Marc Jones0b11bd02015-07-19 15:20:17 -0600942 mov $AMD_MTRR_DEFTYPE, %ecx # MSR:0000_02FF
943 _RDMSR
944 test $MSR_MASK, %eax # Are the default types enabled? (MTRR_DEF_TYPE_EN + MTRR_DEF_TYPE_FIX_EN)
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100945 jz SetupStack\@ # Jump if no
Marc Jones0b11bd02015-07-19 15:20:17 -0600946 or $FLAG_STACK_REENTRY, %esi # Bit25, indicate stack has already been initialized
947
Arthur Heymans4bf582f2022-03-23 21:36:24 +0100948SetupStack\@:
Marc Jones0b11bd02015-07-19 15:20:17 -0600949 # Set node to map the first 16MB to node 0# 0000_0000 to 00FF_FFFF as DRAM
950 mov %esi, %ebx # Get my Node/Core info
951 xor %bl, %bl
952 shl $3, %bh # Isolate my node#, match alignment for PCI Dev#
953 mov $0x8000C144, %eax # D18F1x44:DRAM Base/Limit# N is Base, N+4 is Limit
954 add %bh, %ah
955 mov %eax, %ebx # Save PCI address for Base/Limit pair
956
957 mov $0x0CF8, %dx
958 out %eax, %dx
959 add $4, %dx
960 xor %eax, %eax # Least Significant bit is AD24 so 0 sets mask of 00FF_FFFF (16MB)
961 out %eax, %dx # DRAM Limit = node0, no interleave
962
963 mov %ebx, %eax
964 sub $4, %eax # Now point to the Base register
965 mov $0x0CF8, %dx
966 out %eax, %dx
967 add $4, %dx
968 mov $0x00000003, %eax # Set the read and write enable bits
969 out %eax, %dx # DRAM Base = 0x0000, R/W
970
971 AMD_ENABLE_STACK_FAMILY_HOOK
972
973 # Init CPU MSRs for our init routines
974 mov $MTRR_SYS_CFG, %ecx # SYS_CFG
975 _RDMSR
976 bts $MTRR_FIX_DRAM_MOD_EN, %eax # Turn on modification enable bit
977 _WRMSR
978
979 mov %esi, %eax
980 bt $FLAG_STACK_REENTRY, %eax # Is this a 2nd entry?
981 #.if (!carry?) # On a re-entry, do not clear MTRRs or reset TOM; just reset the stack SS:ESP
982 jc 0f
983 bt $FLAG_IS_PRIMARY, %eax # Is this core the primary in a compute unit?
984 #.if (carry?) # Families using shared groups do not need to clear the MTRRs since that is done at power-on reset
985 # Note: Relying on MSRs to be cleared to 0's at reset for families w/shared cores
986 # Clear all variable and Fixed MTRRs for non-shared cores
987 jnc 0f
988 mov $AMD_MTRR_VARIABLE_BASE0, %ecx
989 xor %eax, %eax
990 xor %edx, %edx
991 #.while (cl != 10h) # Variable MTRRphysBase[n] and MTRRphysMask[n]
992 jmp 1f
993 2:
994 _WRMSR
995 inc %cl
996 #.endw
997 1:
998 cmp $0x10, %cl
999 jne 2b
1000 mov $AMD_MTRR_FIX64k_00000, %cx # MSR:0000_0250
1001 _WRMSR
1002 mov $AMD_MTRR_FIX16k_80000, %cx # MSR:0000_0258
1003 _WRMSR
1004 mov $AMD_MTRR_FIX16k_A0000, %cx # MSR:0000_0259
1005 _WRMSR
1006 mov $AMD_MTRR_FIX4k_C0000, %cx # Fixed 4Ks: MTRRfix4K_C0000 to MTRRfix4K_F8000
1007 #.while (cl != 70h)
1008 jmp 3f
1009 4:
1010 _WRMSR
1011 inc %cl
1012 #.endw
1013 3:
1014 cmp $0x70, %cl
1015 jne 4b
1016 # Set TOP_MEM (C001_001A) for non-shared cores to 16M. This will be increased at heap init.
1017 # - not strictly needed since the FixedMTRRs take presedence.
1018 mov $(16 * 1024 * 1024), %eax
1019 mov $TOP_MEM, %ecx # MSR:C001_001A
1020 _WRMSR
1021 #.endif # End Is_Primary
1022 #.endif # End Stack_ReEntry
1023 0:
1024 # Clear IORRs (C001_0016-19) and TOM2(C001_001D) for all cores
1025 xor %eax, %eax
1026 xor %edx, %edx
1027 mov $IORR_BASE, %ecx # MSR:C001_0016 - 0019
1028 #.while (cl != 1Ah)
1029 jmp 1f
1030 2:
1031 _WRMSR
1032 inc %cl
1033 #.endw
1034 1:
1035 cmp $0x1A, %cl
1036 jne 2b
1037 mov $TOP_MEM2, %ecx # MSR:C001_001D
1038 _WRMSR
1039
Jonathan Neuschäferbb3a5ef2018-04-09 20:14:19 +02001040 # setup MTRRs for stacks
Marc Jones0b11bd02015-07-19 15:20:17 -06001041 # A speculative read can be generated by a speculative fetch mis-aligned in a code zone
1042 # or due to a data zone being interpreted as code. When a speculative read occurs outside a
1043 # controlled region (intentionally used by software), it could cause an unwanted cache eviction.
1044 # To prevent speculative reads from causing an eviction, the unused cache ranges are set
1045 # to UC type. Only the actively used regions (stack, heap) are reflected in the MTRRs.
1046 # Note: some core stack regions will share an MTRR since the control granularity is much
1047 # larger than the allocated stack zone. The allocation algorithm must account for this 'extra'
1048 # space covered by the MTRR when parseling out cache space for the various uses. In some cases
1049 # this could reduce the amount of EXE cache available to a core. see cpuCacheInit.c
1050 #
1051 # Outcome of this block is that: (Note the MTRR map at the top of the file)
1052 # ebp - start address of stack block
1053 # ebx - [31:16] - MTRR MSR address
1054 # - [15:8] - slot# in MTRR register
1055 # - [7:0] - block size in #4K blocks
1056 # review: ESI[31:24]=Flags; SI[15,8]= Node#; SI[7,0]= core# (relative to node)
1057 #
1058
1059 mov %si, %ax # Load node, core
1060 #.if (al == 0) # Is a core 0?
1061 or %al, %al
1062 jne 1f
1063 #.if (ah == 0) # Is Node 0? (BSP)
1064 or %ah, %ah
1065 jne 2f
1066 # Is BSP, assign a 64K stack
1067 mov $((AMD_MTRR_FIX64k_00000 << 16) + (3 << 8) + (BSP_STACK_SIZE >> 12)), %ebx
1068 mov $BSP_STACK_BASE_ADDR, %ebp
1069 jmp 0f
1070 #.else # node 1 to 7, core0
1071 2:
1072 # Is a Core0 of secondary node, assign 16K stacks
1073 mov $AMD_MTRR_FIX16k_80000, %bx
1074 shl $16, %ebx #
1075 mov %ah, %bh # Node# is used as slot#
1076 mov $(CORE0_STACK_SIZE >> 12), %bl
1077 mov %ah, %al # Base = (Node# * Size)#
1078 mul %bl #
1079 movzx %ax, %eax #
1080 shl $12, %eax # Expand back to full byte count (* 4K)
1081 add $CORE0_STACK_BASE_ADDR, %eax
1082 mov %eax, %ebp
1083 #.endif
1084 jmp 0f
1085 #.else #core 1 thru core 7
1086 1:
1087 # Is core 1-7 of any node, assign 4K stacks
1088 mov $8, %al # CoreIndex = ( (Node# * 8) ...
1089 mul %ah #
1090 mov %si, %bx #
1091 add %bl, %al # ... + Core#)#
1092
1093 mov $AMD_MTRR_FIX64k_00000, %bx
1094 shl $16, %ebx #
1095 mov %al, %bh # Slot# = (CoreIndex / 16) + 4#
1096 shr $4, %bh #
1097 add $4, %bh #
1098 mov $(CORE1_STACK_SIZE >> 12), %bl
1099
1100 mul %bl # Base = ( (CoreIndex * Size) ...
1101 movzx %ax, %eax #
1102 shl $12, %eax # Expand back to full byte count (* 4K)
1103 add $CORE1_STACK_BASE_ADDR, %eax # ... + Base_Addr)#
1104 mov %eax, %ebp
1105 #.endif
1106 0:
1107
1108 # Now set the MTRR. Add this to already existing settings (don't clear any MTRR)
1109 mov $WB_DRAM_TYPE, %edi # Load Cache type in 1st slot
1110 mov %bh, %cl # ShiftCount = ((slot# ...
1111 and $0x03, %cl # ... % 4) ...
1112 shl $0x03, %cl # ... * 8)#
1113 shl %cl, %edi # Cache type is now in correct position
1114 ror $16, %ebx # Get the MTRR address
1115 movzx %bx, %ecx #
1116 rol $16, %ebx # Put slot# & size back in BX
1117 _RDMSR # Read-modify-write the MSR
1118 #.if (bh < 4) # Is value in lower or upper half of MSR?
1119 cmp $4, %bh
1120 jae 1f
1121 or %edi, %eax #
1122 jmp 0f
1123 #.else
1124 1: #
1125 or %edi, %edx #
1126 #.endif #
1127 0:
1128 _WRMSR #
1129
Kyösti Mälkkiccb53e12018-05-05 15:56:18 +03001130 # All cores must see BSP stack region that is also used to
1131 # communicate global variables before DRAM is up.
1132 mov $AMD_MTRR_FIX64k_00000, %ecx # MSR:0000_0250
1133 _RDMSR
1134 or $0x1e000000, %eax
1135 _WRMSR #
1136
Marc Jones0b11bd02015-07-19 15:20:17 -06001137 # Enable MTRR defaults as UC type
1138 mov $AMD_MTRR_DEFTYPE, %ecx # MSR:0000_02FF
1139 _RDMSR # Read-modify-write the MSR
1140 bts $MTRR_DEF_TYPE_EN, %eax # MtrrDefTypeEn
1141 bts $MTRR_DEF_TYPE_FIX_EN, %eax # MtrrDefTypeFixEn
1142 _WRMSR
1143
1144 # Close the modification window on the Fixed MTRRs
1145 mov $MTRR_SYS_CFG, %ecx # MSR:0C001_0010
1146 _RDMSR
1147 bts $MTRR_FIX_DRAM_EN, %eax # MtrrFixDramEn
1148 bts $MTRR_VAR_DRAM_EN, %eax # variable MTRR enable bit
1149 btr $MTRR_FIX_DRAM_MOD_EN, %eax # Turn off modification enable bit
1150 _WRMSR
1151
1152 # Enable caching in CR0
1153 mov %cr0, %eax # Enable WT/WB cache
1154 btr $CR0_PG, %eax # Make sure paging is disabled
1155 btr $CR0_CD, %eax # Clear CR0 NW and CD
1156 btr $CR0_NW, %eax
1157 mov %eax, %cr0
1158
1159 # Use the Stack Base & size to calculate SS and ESP values
1160 # review:
1161 # esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
1162 # ebp - start address of stack block
1163 # ebx - [31:16] - MTRR MSR address
1164 # - [15:8] - slot# in MTRR register
1165 # - [7:0] - block size in #4K blocks
1166 #
1167 mov %ebp, %esp # Initialize the stack pointer
1168 mov %esp, %edi # Copy the stack start to edi
1169 movzx %bl, %bx
1170 movzx %bx, %ebx # Clear upper ebx, don't need MSR addr anymore
1171 shl $12, %ebx # Make size full byte count (* 4K)
1172 add %ebx, %esp # Set the Stack Pointer as full linear address
1173 sub $4, %esp
1174 #
1175 # review:
1176 # esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
1177 # edi - 32b start address of stack block
1178 # ebx - size of stack block
1179 # esp - 32b linear stack pointer
1180 #
1181
1182 # Determine mode for SS base;
1183 mov %cr0, %ecx # Check for 32-bit protect mode
1184 bt $CR0_PE, %ecx #
1185 #.if (!carry?) # PE=0 means real mode
Arthur Heymans4bf582f2022-03-23 21:36:24 +01001186 jc Protected32Mode\@
Marc Jones0b11bd02015-07-19 15:20:17 -06001187 mov %cs, %cx # PE=1
1188 cmp $0x0D000, %cx # Check for CS
Arthur Heymans4bf582f2022-03-23 21:36:24 +01001189 jb Protected32Mode\@ # If CS < D000, it is a selector instead of a segment
Marc Jones0b11bd02015-07-19 15:20:17 -06001190 # alter SS:ESP for 16b Real Mode:
Arthur Heymans4bf582f2022-03-23 21:36:24 +01001191Real16bMode\@:
Marc Jones0b11bd02015-07-19 15:20:17 -06001192 mov %edi, %eax
1193 shr $4, %eax # Create a Real Mode segment for ss, ds, es
1194 mov %ax, %ss
1195 mov %ax, %ds
1196 mov %ax, %es
1197 shl $4, %eax
1198 sub %eax, %edi # Adjust the clearing pointer for Seg:Offset mode
1199 mov %ebx, %esp # Make SP an offset from SS
1200 sub $4, %esp #
1201 # .endif # endif
1202 # #else
1203 # Default is to use Protected 32b Mode
1204 #.endif
1205 ;
Arthur Heymans4bf582f2022-03-23 21:36:24 +01001206Protected32Mode\@:
Marc Jones0b11bd02015-07-19 15:20:17 -06001207 #
1208 # Clear The Stack
1209 # Now that we have set the location and the MTRRs, initialize the cache by
1210 # reading then writing to zero all of the stack area.
1211 # review:
1212 # ss - Stack base
1213 # esp - stack pointer
1214 # ebx - size of stack block
1215 # esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
1216 # edi - address of start of stack block
1217 #
1218
Arthur Heymans4bf582f2022-03-23 21:36:24 +01001219ClearTheStack\@: # Stack base is in SS, stack pointer is in ESP
Marc Jones0b11bd02015-07-19 15:20:17 -06001220 shr $2, %ebx # ebx = stack block size in dwords
1221 mov %bx, %cx #
1222 # Check our flags - Don't clear an existing stack
1223 #.if ( !(esi & 0FF000000h)) # Check our flags
1224 test $(1 << FLAG_STACK_REENTRY), %esi
1225 jne 1f
1226 cld
1227 mov %edi, %esi
1228 rep lodsl (%esi) # Pre-load the range
1229 xor %eax, %eax
1230 mov %bx, %cx
1231 mov %edi, %esi # Preserve base for push on stack
1232 rep stosl (%edi) # Clear the range
1233 movl $0x0ABCDDCBA, (%esp) # Put marker in top stack dword
1234 shl $2, %ebx # Put stack size and base
1235 push %ebx # in top of stack
1236 push %esi
1237
1238 mov %ebx, %ecx # Return size of stack in bytes
1239 xor %eax, %eax # eax = 0 : no error return code
1240 jmp 0f
1241 #.else
1242 1:
1243 movzx %cx, %ecx
1244 shl $2, %ecx # Return size of stack in bytes
1245 mov %esi, %eax
1246 shr $24, %eax # Keep the flags as part of the error report
1247 or $0x40000000, %eax # eax = AGESA_WARNING (Stack has already been set up)
1248 #.endif
1249 0:
Marc Jones0b11bd02015-07-19 15:20:17 -06001250.endm
1251
1252/*****************************************************************************
Kyösti Mälkki56397362017-09-07 22:13:10 +03001253* AMD_DISABLE_STACK: Destroy the stack inside the cache. This routine
1254* should only be executed on the BSP
Marc Jones0b11bd02015-07-19 15:20:17 -06001255*
1256* In:
1257* none
1258*
1259* Out:
Kyösti Mälkkibfe6bca2017-07-12 16:30:47 +03001260* none
Marc Jones0b11bd02015-07-19 15:20:17 -06001261*
1262* Preserved:
Kyösti Mälkkibfe6bca2017-07-12 16:30:47 +03001263* ESP
Marc Jones0b11bd02015-07-19 15:20:17 -06001264* Destroyed:
Kyösti Mälkkibfe6bca2017-07-12 16:30:47 +03001265* EAX, EBX, ECX, EDX, EDI, ESI
Marc Jones0b11bd02015-07-19 15:20:17 -06001266*****************************************************************************/
1267.macro AMD_DISABLE_STACK
1268
Marc Jones0b11bd02015-07-19 15:20:17 -06001269 # get node/core/flags of current executing core
1270 GET_NODE_ID_CORE_ID # Sets ESI[15,8]= Node#; ESI[7,0]= core# (relative to node)
1271
1272 # Turn on modification enable bit
1273 mov $MTRR_SYS_CFG, %ecx # MSR:C001_0010
1274 _RDMSR
1275 bts $MTRR_FIX_DRAM_MOD_EN, %eax # Enable modifications
1276 _WRMSR
1277
1278 # Set lower 640K MTRRs for Write-Back memory caching
1279 mov $AMD_MTRR_FIX64k_00000, %ecx
1280 mov $0x1E1E1E1E, %eax
1281 mov %eax, %edx
1282 _WRMSR # 0 - 512K = WB Mem
1283 mov $AMD_MTRR_FIX16k_80000, %ecx
1284 _WRMSR # 512K - 640K = WB Mem
1285
1286 # Turn off modification enable bit
1287 mov $MTRR_SYS_CFG, %ecx # MSR:C001_0010
1288 _RDMSR
1289 btr $MTRR_FIX_DRAM_MOD_EN, %eax # Disable modification
1290 _WRMSR
1291
1292 AMD_DISABLE_STACK_FAMILY_HOOK # Re-Enable 'normal' cache operations
1293
Marc Jones0b11bd02015-07-19 15:20:17 -06001294.endm