m5a99x-evo: grml, strange romstage ld warning... dunno why :/
[coreboot.git] / src / vendorcode / amd / agesa / f12 / cpcar.inc
1 ;*****************************************************************************
2 ; AMD Generic Encapsulated Software Architecture
3 ;
4 ; $Workfile:: cpcar.inc
5 ;
6 ; Description: CPCAR.INC - AGESA cache-as-RAM setup Include File
7 ;
8 ;*****************************************************************************
9 ;
10 ; Copyright (c) 2011, Advanced Micro Devices, Inc.
11 ; All rights reserved.
12
13 ; Redistribution and use in source and binary forms, with or without
14 ; modification, are permitted provided that the following conditions are met:
15 ;     * Redistributions of source code must retain the above copyright
16 ;       notice, this list of conditions and the following disclaimer.
17 ;     * Redistributions in binary form must reproduce the above copyright
18 ;       notice, this list of conditions and the following disclaimer in the
19 ;       documentation and/or other materials provided with the distribution.
20 ;     * Neither the name of Advanced Micro Devices, Inc. nor the names of 
21 ;       its contributors may be used to endorse or promote products derived 
22 ;       from this software without specific prior written permission.
23
24 ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 ; DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
28 ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 ;*****************************************************************************
35
36 BSP_STACK_BASE_ADDR     EQU 30000h      ; Base address for primary cores stack
37 BSP_STACK_SIZE          EQU 10000h      ; 64KB for BSP core
38 CORE0_STACK_BASE_ADDR   EQU 80000h      ; Base address for primary cores stack
39 CORE0_STACK_SIZE        EQU 4000h       ; 16KB for primary cores
40 CORE1_STACK_BASE_ADDR   EQU 40000h      ; Base address for AP cores
41 CORE1_STACK_SIZE        EQU 1000h       ; 4KB for each AP cores
42
43 L3_CONTROL_REGISTER     EQU 8100C3B8h   ; Bus 0, Device 18h, Function 3, Offset 1B8h
44
45 APIC_BASE_ADDRESS       EQU 0000001Bh
46     APIC_BSC                EQU 8       ; Boot Strap Core
47
48 APIC_MSG_REG            EQU 380h        ; Location of BSC message
49     APIC_MSG            EQU 00DE00ADh   ; Message data
50 APIC_CMD_LO_REG         EQU 300h        ; APIC command low
51 APIC_CMD_HI_REG         EQU 310h        ; APIC command high
52     CMD_REG_TO_READ_DATA EQU 00000338h  ; APIC command for remote read of APIC_MSG_REG
53     REMOTE_READ_STS       EQU 00030000h ; Remote read status mask
54     REMOTE_DELIVERY_PEND  EQU 00010000h ; Remote read is pending
55     REMOTE_DELIVERY_DONE  EQU 00020000h ; Remote read is complete
56     DELIVERY_STS_BIT    EQU 12          ; Delivery status valid bit
57 APIC_ID_REG             EQU 0020h       ; Local APIC ID offset
58     APIC20_APICID       EQU 24
59 APIC_REMOTE_READ_REG    EQU 00C0h       ; Remote read offset
60
61 AMD_CU_NEED_TO_WAIT     EQU 31
62 AMD_CU_SEND_INVD_MSG    EQU 30
63 AMD_CU_RESTORE_ES       EQU 29
64
65 AMD_MTRR_VARIABLE_BASE0 EQU 0200h
66 AMD_MTRR_VARIABLE_BASE6 EQU 020Ch
67 AMD_MTRR_VARIABLE_MASK7 EQU 020Fh
68 AMD_MTRR_FIX64k_00000   EQU 0250h
69 AMD_MTRR_FIX16k_80000   EQU 0258h
70 AMD_MTRR_FIX16k_A0000   EQU 0259h
71 AMD_MTRR_FIX4k_C0000    EQU 0268h
72 AMD_MTRR_FIX4k_C8000    EQU 0269h
73 AMD_MTRR_FIX4k_D0000    EQU 026Ah
74 AMD_MTRR_FIX4k_D8000    EQU 026Bh
75 AMD_MTRR_FIX4k_E0000    EQU 026Ch
76 AMD_MTRR_FIX4k_E8000    EQU 026Dh
77 AMD_MTRR_FIX4k_F0000    EQU 026Eh
78 AMD_MTRR_FIX4k_F8000    EQU 026Fh
79
80 AMD_MTRR_DEFTYPE        EQU 02FFh
81     WB_DRAM_TYPE            EQU 1Eh     ; MemType - memory type
82     MTRR_DEF_TYPE_EN        EQU 11      ; MtrrDefTypeEn - variable and fixed MTRRs default enabled
83     MTRR_DEF_TYPE_FIX_EN    EQU 10      ; MtrrDefTypeEn - fixed MTRRs default enabled
84
85 HWCR                    EQU 0C0010015h  ; Hardware Configuration
86     INVD_WBINVD             EQU 4       ;   INVD to WBINVD conversion
87
88 IORR_BASE               EQU 0C0010016h  ; IO Range Regusters Base/Mask, 2 pairs
89                                         ;   uses 16h - 19h
90 TOP_MEM                 EQU 0C001001Ah  ; Top of Memory
91 TOP_MEM2                EQU 0C001001Dh  ; Top of Memory2
92
93 LS_CFG                  EQU 0C0011020h  ; Load-Store Configuration
94     DIS_SS                  EQU 28      ;   Family 10h,12h,15h:Disable Streaming Store functionality
95     DIS_STREAM_ST           EQU 28      ;   Family 14h:DisStreamSt - Disable Streaming Store functionality
96
97 IC_CFG                  EQU 0C0011021h  ; Instruction Cache Config Register
98     IC_DIS_SPEC_TLB_RLD     EQU 9       ;   Disable speculative TLB reloads
99     DIS_IND                 EQU 14      ;   Family 10-14h:Disable Indirect Branch Predictor
100     DIS_I_CACHE             EQU 14      ;   Family 15h:DisICache - Disable Indirect Branch Predictor
101
102 DC_CFG                  EQU 0C0011022h  ; Data Cache Configuration
103     DC_DIS_SPEC_TLB_RLD     EQU 4       ;   Disable speculative TLB reloads
104     DIS_CLR_WBTOL2_SMC_HIT  EQU 8       ;   self modifying code check buffer bit
105     DIS_HW_PF               EQU 13      ;   Hardware prefetches bit
106
107 CU_CFG                  EQU 0C0011023h  ; Family 15h: Combined Unit Configuration
108     L2_WAY_LOCK_EN          EQU 23      ;   L2WayLock - L2 way lock enable
109     L2_FIRST_LOCKED_WAY     EQU 19      ;   L2FirstLockedWay - first L2 way lockedh
110     L2_FIRST_LOCKED_WAY_OR_MASK  EQU 000780000h
111
112 DE_CFG                  EQU 0C0011029h  ; Decode Configuration
113     CL_FLUSH_SERIALIZE      EQU 23      ;   Family 12h,15h: CL Flush Serialization
114
115 BU_CFG2                 EQU 0C001102Ah  ; Family 10h: Bus Unit Configuration 2
116 CU_CFG2                 EQU 0C001102Ah  ; Family 15h: Combined Unit Configuration 2
117     F10_CL_LINES_TO_NB_DIS  EQU 15      ;   ClLinesToNbDis - allows WP code to be cached in L2
118     IC_DIS_SPEC_TLB_WR      EQU 35      ;   IcDisSpecTlbWr - ITLB speculative writes
119
120 CU_CFG3                 EQU 0C001102Bh  ; Combined Unit Configuration 3
121     COMBINE_CR0_CD          EQU 49      ;   Combine CR0.CD for both cores of a compute unit
122
123
124 CR0_PE                  EQU 0           ; Protection Enable
125 CR0_NW                  EQU 29          ; Not Write-through
126 CR0_CD                  EQU 30          ; Cache Disable
127 CR0_PG                  EQU 31          ; Paging Enable
128
129 ; CPUID Functions
130
131 CPUID_MODEL             EQU 1
132 AMD_CPUID_FMF           EQU 80000001h   ; Family Model Features information
133 AMD_CPUID_APIC          EQU 80000008h   ; Long Mode and APIC info., core count
134     APIC_ID_CORE_ID_SIZE     EQU 12     ; ApicIdCoreIdSize bit position
135
136 NB_CFG                  EQU 0C001001Fh  ; Northbridge Configuration Register
137     INIT_APIC_ID_CPU_ID_LO   EQU 54     ;   InitApicIdCpuIdLo - is core# in high or low half of APIC ID?
138     ENABLE_CF8_EXT_CFG       EQU 46     ;   EnableCf8ExtCfg - enable CF8 extended configuration cycles
139
140 MTRR_SYS_CFG            EQU 0C0010010h  ; System Configuration Register
141   CHX_TO_DIRTY_DIS          EQU 16      ;   ChxToDirtyDis    Change to dirty disable
142   SYS_UC_LOCK_EN            EQU 17      ;   SysUcLockEn      System lock command enable
143   MTRR_FIX_DRAM_EN          EQU 18      ;   MtrrFixDramEn    MTRR fixed RdDram and WrDram attributes enable
144   MTRR_FIX_DRAM_MOD_EN      EQU 19      ;   MtrrFixDramModEn MTRR fixed RdDram and WrDram modification enable
145   MTRR_VAR_DRAM_EN          EQU 20      ;   MtrrVarDramEn    MTRR variable DRAM enable
146   MTRR_TOM2_EN              EQU 21      ;   MtrrTom2En       MTRR top of memory 2 enable
147
148 PERF_CONTROL3           EQU 0C0010003h  ; Performance event control three
149     PERF_CONTROL3_RESERVE_L EQU 00200000h ; Preserve the reserved bits
150     PERF_CONTROL3_RESERVE_H EQU 0FCF0h  ; Preserve the reserved bits
151     CONFIG_EVENT_L          EQU 0F0E2h  ; All cores with level detection
152     CONFIG_EVENT_H          EQU 4       ; Increment count by number of event
153                                         ; occured in clock cycle
154     EVENT_ENABLE            EQU 22      ; Enable the event
155 PERF_COUNTER3           EQU 0C0010007h  ; Performance event counter three
156
157 ; Local use flags, in upper most byte if ESI
158 FLAG_UNKNOWN_FAMILY               EQU 24    ; Signals that the family# of the installed processor is not recognized
159 FLAG_STACK_REENTRY                EQU 25    ; Signals that the environment has made a re-entry (2nd) call to set up the stack
160 FLAG_IS_PRIMARY                   EQU 26    ; Signals that this core is the primary within the compute unit
161 FLAG_CORE_NOT_IDENTIFIED          EQU 27    ; Signals that the cores/compute units of the installed processor is not recognized
162
163 ; Error code returned in EDX by AMD_ENABLE_STACK
164 IFNDEF CPU_EVENT_UNKNOWN_PROCESSOR_FAMILY
165        CPU_EVENT_UNKNOWN_PROCESSOR_FAMILY     EQU   008010500h
166 ENDIF
167 IFNDEF CPU_EVENT_STACK_REENTRY
168        CPU_EVENT_STACK_REENTRY                EQU   008020500h
169 ENDIF
170 IFNDEF CPU_EVENT_CORE_NOT_IDENTIFIED
171        CPU_EVENT_CORE_NOT_IDENTIFIED          EQU   008030500h
172 ENDIF
173
174 ; AGESA_STATUS values
175 IFNDEF AGESA_SUCCESS
176        AGESA_SUCCESS  EQU 0
177 ENDIF
178 IFNDEF AGESA_WARNING
179        AGESA_WARNING  EQU 4
180 ENDIF
181 IFNDEF AGESA_FATAL
182        AGESA_FATAL    EQU 7
183 ENDIF
184 ;;***************************************************************************
185 ;;
186 ;;                      CPU MACROS - PUBLIC
187 ;;
188 ;;***************************************************************************
189 _WRMSR macro
190   db  0Fh, 30h
191   endm
192
193 _RDMSR macro
194   db  0Fh, 32h
195   endm
196
197 AMD_CPUID MACRO arg0
198   IFB <arg0>
199     mov   eax, 1
200     db    0Fh, 0A2h                     ; Execute instruction
201     bswap eax
202     xchg  al, ah                        ; Ext model in al now
203     rol   eax, 8                        ; Ext model in ah, model in al
204     and   ax, 0FFCFh                    ; Keep 23:16, 7:6, 3:0
205   ELSE
206     mov   eax, arg0
207     db    0Fh, 0A2h
208   ENDIF
209 ENDM
210
211
212 ;---------------------------------------------------
213 ;
214 ; AMD_ENABLE_STACK_FAMILY_HOOK Macro - Stackless
215 ;
216 ;   Set any family specific controls needed to enable the use of
217 ;   cache as general storage before main memory is available.
218 ;
219 ; Inputs:
220 ;       none
221 ; Outputs:
222 ;       none
223 ;---------------------------------------------------
224 AMD_ENABLE_STACK_FAMILY_HOOK MACRO
225
226     AMD_ENABLE_STACK_FAMILY_HOOK_F10
227     AMD_ENABLE_STACK_FAMILY_HOOK_F12
228     AMD_ENABLE_STACK_FAMILY_HOOK_F14
229     AMD_ENABLE_STACK_FAMILY_HOOK_F15
230
231 ENDM
232
233 ;----------------------------------------------
234 ;
235 ; AMD_DISABLE_STACK_FAMILY_HOOK Macro - Stackless
236 ;
237 ;   Return any family specific controls to their 'standard'
238 ;   settings for using cache with main memory.
239 ;
240 ; Inputs:
241 ;       none
242 ; Outputs:
243 ;       none
244 ;----------------------------------------------
245 AMD_DISABLE_STACK_FAMILY_HOOK MACRO
246
247     AMD_DISABLE_STACK_FAMILY_HOOK_F10
248     AMD_DISABLE_STACK_FAMILY_HOOK_F12
249     AMD_DISABLE_STACK_FAMILY_HOOK_F14
250     AMD_DISABLE_STACK_FAMILY_HOOK_F15
251
252 ENDM
253
254 ;---------------------------------------------------
255 ;
256 ; GET_NODE_ID_CORE_ID Macro - Stackless
257 ;
258 ;   Read family specific values to determine the node and core
259 ;   numbers for the core executing this code.
260 ;
261 ; Inputs:
262 ;     none
263 ; Outputs:
264 ;     SI[7:0] = Core# (0..N, relative to node)
265 ;     SI[15:8]= Node# (0..N)
266 ;     SI[23:16]= reserved
267 ;     SI[24]=   flag: 1=Family Unrecognized
268 ;     SI[25]=   flag: 1=Interface re-entry call
269 ;     SI[26]=   flag: 1=Core is primary of compute unit
270 ;     SI[31:27]= reserved, =0
271 ;---------------------------------------------------
272 GET_NODE_ID_CORE_ID MACRO
273
274     mov     si, -1
275     GET_NODE_ID_CORE_ID_F10
276     GET_NODE_ID_CORE_ID_F12
277     GET_NODE_ID_CORE_ID_F14
278     GET_NODE_ID_CORE_ID_F15
279       ;
280       ; Check for unrecognized Family
281       ;
282     .if (si == -1)                      ; Has family (node/core) been discovered?
283         mov     esi, ( (1 SHL FLAG_UNKNOWN_FAMILY)+(1 SHL FLAG_IS_PRIMARY) ) ; No, Set error code, Only let BSP continue
284         mov     ecx, APIC_BASE_ADDRESS  ; MSR:0000_001B
285         _RDMSR
286         bt      eax, APIC_BSC           ;   Is this the BSC?
287         .if (!carry?)
288             ; No, this is an AP
289             hlt                         ;       Kill APs
290         .endif
291     .endif
292 ENDM
293
294
295
296
297 ;;***************************************************************************
298 ;;                      Family 10h MACROS
299 ;;***************************************************************************
300 ;---------------------------------------------------
301 ;
302 ; AMD_ENABLE_STACK_FAMILY_HOOK_F10 Macro - Stackless
303 ;
304 ;   Set any family specific controls needed to enable the use of
305 ;   cache as general storage before main memory is available.
306 ;
307 ; Inputs:
308 ;       ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
309 ; Outputs:
310 ;       none
311 ;
312 ; Family 10h requirements (BKDG section 2.3.3):
313 ;   * Paging disabled
314 ;   * MSRC001_0015[INVDWBINVD]=0
315 ;   * MSRC001_1021[DIS_IND]=1
316 ;   * MSRC001_1021[DIS_SPEC_TLB_RLD]=1
317 ;   * MSRC001_1022[DIS_SPEC_TLB_RLD]=1
318 ;   * MSRC001_1022[DIS_CLR_WBTOL2_SMC_HIT]=1
319 ;   * MSRC001_1022[DIS_HW_PF]=1
320 ;   * MSRC001_102A[IcDisSpecTlbWr]=1
321 ;   * MSRC001_102A[ClLinesToNbDis]=1
322 ;   * No INVD or WBINVD, no exceptions, page faults or interrupts
323 ;---------------------------------------------------
324 AMD_ENABLE_STACK_FAMILY_HOOK_F10 MACRO
325     local   fam10_enable_stack_hook_exit
326
327     AMD_CPUID   CPUID_MODEL
328     mov     ebx, eax                    ; Save revision info to EBX
329     shr     eax, 20                     ; AL = cpu extended family
330     cmp     al, 01h                     ; Is this family 10h?
331     jnz     fam10_enable_stack_hook_exit ; Br if no
332
333     ; Errata #385
334     ; F3x1B8[23] = 1 before enabling L3 cache through CR0[30](CD)
335     mov     eax, ebx                    ; Restore revision info to EAX
336     .if (al >= 80h)                     ; Is this Revision D and later?
337         mov     ecx, NB_CFG             ; MSR:C001_001F
338         _RDMSR                          ; EDX has EnableCf8ExtCfg bit
339         bts     edx, (ENABLE_CF8_EXT_CFG - 32)
340         _WRMSR
341
342         mov     eax, esi                ; Get node# from esi[15:8]
343         and     eax, 0000FF00h
344         shl     eax, (11 - 8)           ; Device#
345         add     eax, L3_CONTROL_REGISTER
346         mov     dx, 0CF8h               ; PCI Read
347         out     dx, eax
348         mov     dx, 0CFCh
349         in      eax, dx
350
351         or      eax, (1 shl 23)         ; F3x1B8[23] = 1
352
353         out     dx, eax                 ; PCI Write
354     .endif
355
356     mov     ecx, DC_CFG                 ; MSR:C001_1022
357     _RDMSR
358     bts     eax, DC_DIS_SPEC_TLB_RLD    ; Turn on Disable speculative DTLB reloads bit
359     bts     eax, DIS_CLR_WBTOL2_SMC_HIT ; Turn on Disable the self modifying code check buffer bit
360     bts     eax, DIS_HW_PF              ; Turn on Disable hardware prefetches bit
361     _WRMSR
362
363     dec     cx                          ; MSR:C001_1021
364     _RDMSR
365     bts     eax, IC_DIS_SPEC_TLB_RLD    ; Turn on Disable speculative TLB reloads bit
366     bts     eax, DIS_IND                ; Turn on Disable indirect branch predictor
367     _WRMSR
368
369     mov     ecx, BU_CFG2                ; MSR C001_102A
370     _RDMSR
371     bts     eax, F10_CL_LINES_TO_NB_DIS  ; Allow BIOS ROM to be cached in the IC
372     bts     edx, (IC_DIS_SPEC_TLB_WR-32) ;Disable speculative writes to the ITLB
373     _WRMSR
374
375     mov     ecx, HWCR                   ; MSR C001_0015
376     _RDMSR
377
378     bt      esi, FLAG_STACK_REENTRY     ; Check if stack has already been set
379     .if (!carry?)
380         btr     eax, INVD_WBINVD        ; disable INVD -> WBINVD conversion
381         _WRMSR
382     .endif
383
384     mov eax, esi                        ; load core#
385     .if (al == 0)                       ; If (BSP)
386         mov     ecx, PERF_COUNTER3      ;   Select performance counter three
387                                         ;   to count number of CAR evictions
388         xor     eax, eax                ;   Initialize the lower part of the counter to zero
389         xor     edx, edx                ;   Initializa the upper part of the counter to zero
390         _WRMSR                          ;   Save it
391         mov     ecx, PERF_CONTROL3      ;   Select the event control three
392         _RDMSR                          ;   Get the current setting
393         and     eax, PERF_CONTROL3_RESERVE_L  ; Preserve the reserved bits
394         or      eax, CONFIG_EVENT_L     ;   Set the lower part of event register to
395                                         ;   select CAR Corruption occurred by any cores
396         and     dx, PERF_CONTROL3_RESERVE_H  ; Preserve the reserved bits
397         or      dx, CONFIG_EVENT_H      ;   Set the upper part of event register
398         _WRMSR                          ;   Save it
399         bts     eax, EVENT_ENABLE       ;   Enable it
400         _WRMSR                          ;   Save it
401     .endif                              ; endif
402
403 fam10_enable_stack_hook_exit:
404 ENDM
405
406 ;----------------------------------------------
407 ;
408 ; AMD_DISABLE_STACK_FAMILY_HOOK_F10 Macro - Stackless
409 ;
410 ;   Return any family specific controls to their 'standard'
411 ;   settings for using cache with main memory.
412 ;
413 ; Inputs:
414 ;       ESI - [31:24] flags; [15,8]= Node#; [7,0]= core#
415 ; Outputs:
416 ;       none
417 ;
418 ; Family 10h requirements:
419 ;   * INVD or WBINVD
420 ;   * MSRC001_0015[INVD_WBINVD]=1
421 ;   * MSRC001_1021[DIS_IND]=0
422 ;   * MSRC001_1021[DIS_SPEC_TLB_RLD]=0
423 ;   * MSRC001_1022[DIS_SPEC_TLB_RLD]=0
424 ;   * MSRC001_1022[DIS_CLR_WBTOL2_SMC_HIT]=0
425 ;   * MSRC001_1022[DIS_HW_PF]=0
426 ;   * MSRC001_102A[IcDisSpecTlbWr]=0
427 ;   * MSRC001_102A[ClLinesToNbDis]=0
428 ;----------------------------------------------
429 AMD_DISABLE_STACK_FAMILY_HOOK_F10 MACRO
430     local   fam10_disable_stack_hook_exit
431
432     AMD_CPUID   CPUID_MODEL
433     shr     eax, 20                     ; AL = cpu extended family
434     cmp     al, 01h                     ; Is this family 10h?
435     jnz     fam10_disable_stack_hook_exit ; Br if no
436
437     mov     ecx, DC_CFG                 ; MSR:C001_1022
438     _RDMSR
439     btr     eax, DC_DIS_SPEC_TLB_RLD    ; Enable speculative TLB reloads
440     btr     eax, DIS_CLR_WBTOL2_SMC_HIT ; Allow self modifying code check buffer
441     btr     eax, DIS_HW_PF              ; Allow hardware prefetches
442     _WRMSR
443
444     dec     cx                          ; MSR:C001_1021
445     _RDMSR
446     btr     eax, DIS_IND                ; Turn on indirect branch predictor
447     btr     eax, IC_DIS_SPEC_TLB_RLD    ; Turn on speculative TLB reloads
448     _WRMSR
449
450     mov     ecx, BU_CFG2                ; MSR:C001_102A
451     _RDMSR
452     btr     eax, F10_CL_LINES_TO_NB_DIS  ; Return L3 to normal mode
453     btr     edx, (IC_DIS_SPEC_TLB_WR-32) ;Re-enable speculative writes to the ITLB
454     _WRMSR
455
456     ;--------------------------------------------------------------------------
457     ; Begin critical sequence in which EAX, BX, ECX, and EDX must be preserved.
458     ;--------------------------------------------------------------------------
459     mov     ecx, HWCR                   ; MSR:0000_0015
460     _RDMSR
461     mov     bx, ax                      ; Save INVD -> WBINVD bit
462     btr     eax, INVD_WBINVD            ; Disable INVD -> WBINVD conversion for the invd instruction.
463     _WRMSR
464     invd                                ; Clear the cache tag RAMs
465     mov     ax, bx                      ; Restore INVD -> WBINVD bit
466     _WRMSR
467
468     ;--------------------------------------------------------------------------
469     ; End critical sequence in which EAX, BX, ECX, and EDX must be preserved.
470     ;--------------------------------------------------------------------------
471
472     mov     ecx, PERF_CONTROL3          ; Select the event control three
473     _RDMSR                              ; Retrieve the current value
474     btc     eax, EVENT_ENABLE           ; Is event enable, complement it as well
475     jnc     fam10_disable_stack_hook_exit ; No
476     cmp     ax, CONFIG_EVENT_L          ; Is the lower part of event set to capture the CAR Corruption
477     jne     fam10_disable_stack_hook_exit ; No
478     cmp     dl,  CONFIG_EVENT_H         ; Is the upper part of event set to capture the CAR Corruption
479     jne     fam10_disable_stack_hook_exit ; No
480     _WRMSR                              ; Disable the event
481
482 fam10_disable_stack_hook_exit:
483 ENDM
484
485 ;---------------------------------------------------
486 ;
487 ; GET_NODE_ID_CORE_ID_F10 Macro - Stackless
488 ;
489 ;   Read family specific values to determine the node and core
490 ;   numbers for the core executing this code.
491 ;
492 ; Inputs:
493 ;     none
494 ; Outputs:
495 ;     SI = core#, node# & flags (see GET_NODE_ID_CORE_ID macro above)
496 ;---------------------------------------------------
497 GET_NODE_ID_CORE_ID_F10 MACRO
498
499     local   node_core_f10_exit
500
501     cmp     si, -1                      ; Has node/core already been discovered?
502     jnz     node_core_f10_exit          ; Br if yes
503
504     AMD_CPUID   CPUID_MODEL
505     shr     eax, 20                     ; AL = cpu extended family
506     cmp     al, 01h                     ; Is this family 10h?
507     jnz     node_core_f10_exit          ; Br if no
508
509     xor     esi, esi                    ; Assume BSC, clear flags
510     mov     ecx, APIC_BASE_ADDRESS      ; MSR:0000_001B
511     _RDMSR
512     bt      eax, APIC_BSC               ; Is this the BSC?
513     .if (carry?)
514         ; This is the BSP.
515         ; Enable routing tables on BSP (just in case the HT init code has not yet enabled them)
516         mov     eax, 8000C06Ch          ;   PCI address for D18F0x6C Link Initialization Control Register
517         mov     dx, 0CF8h
518         out     dx, eax
519         add     dx, 4
520         in      eax, dx
521         btr     eax, 0                  ;   Set LinkInitializationControl[RouteTblDis] = 0
522         out     dx, eax
523     .else
524         ; This is an AP. Routing tables have been enabled by the HT Init process.
525         ; Also, the MailBox register was set by the BSP during early init
526         ;   The Mailbox register content is formatted as follows:
527         ;         UINT32 Node:4;        // The node id of Core's node.
528         ;         UINT32 Socket:4;      // The socket of this Core's node.
529         ;         UINT32 Module:2;      // The internal module number for Core's node.
530         ;         UINT32 ModuleType:2;  // Single Module = 0, Multi-module = 1.
531         ;         UINT32 :20;           // Reserved
532         ;
533         mov     ecx, 0C0000408h         ; Read the family 10h mailbox
534         _RDMSR                          ;          MC4_MISC1[63:32]
535         mov     si, dx                  ;   SI = raw mailbox contents (will extract node# from this)
536         shr     ebx, 24                 ;   BL = CPUID Fn0000_0001_EBX[LocalApicId]
537         mov     di, bx                  ;   DI = Initial APIC ID (will extract core# from this)
538
539         AMD_CPUID   AMD_CPUID_APIC      ;
540         shr     ch, 4                   ;   CH = ApicIdSize, #bits in APIC ID that show core#
541         inc     cl                      ;   CL = Number of enabled cores in the socket
542         mov     bx, cx
543
544         mov     ecx, NB_CFG             ;   MSR:C001_001F
545         _RDMSR                          ;   EDX has InitApicIdCpuIdLo bit
546
547         mov     cl, bh                  ;   CL = APIC ID size
548         mov     al, 1                   ;   Convert APIC ID size to an AND mask
549         shl     al, cl                  ;   AL = 2^APIC ID size
550         dec     al                      ;   AL = mask for relative core number
551         xor     ah, ah                  ;   AX = mask for relative core number
552         bt      edx, (INIT_APIC_ID_CPU_ID_LO-32) ; InitApicIdCpuIdLo == 1?
553         .if (!carry?)                   ;   Br if yes
554             mov     ch, 8               ;   Calculate core number shift count
555             sub     ch, cl              ;   CH = core shift count
556             mov     cl, ch
557             shr     di, cl              ;   Right justify core number
558         .endif
559         and     di, ax                  ;   DI = socket-relative core number
560
561         mov     cx, si                  ;   CX = raw mailbox value
562         shr     cx, 10                  ;   CL[1:0] = ModuleType or #nodes per socket (0-SCM, 1-MCM)
563         and     cl, 3                   ;   Isolate ModuleType
564         xor     bh, bh                  ;   BX = Number of enabled cores in the socket
565         shr     bx, cl                  ;   BX = Number of enabled cores per node
566         xor     dx, dx                  ;   Clear upper word for div
567         mov     ax, di                  ;   AX = socket-relative core number
568         div     bx                      ;   DX = node-relative core number
569         movzx   eax, si                 ;   prepare return value (clears flags)
570         and     ax, 000Fh               ;   AX = node number
571         shl     ax, 8                   ;   [15:8]=node#
572         mov     al, dl                  ;   [7:0]=core# (relative to node)
573         mov     esi, eax                ;   ESI = return value
574     .endif                              ; end: Is_AP
575     bts     esi, FLAG_IS_PRIMARY        ; all Family 10h cores are primary
576
577 node_core_f10_exit:
578 ENDM
579
580
581 ;;***************************************************************************
582 ;;                      Family 12h MACROS
583 ;;***************************************************************************
584 ;---------------------------------------------------
585 ;
586 ; AMD_ENABLE_STACK_FAMILY_HOOK_F12 Macro - Stackless
587 ;
588 ;   Set any family specific controls needed to enable the use of
589 ;   cache as general storage before main memory is available.
590 ;
591 ; Inputs:
592 ;       ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
593 ; Outputs:
594 ;       none
595 ;
596 ; Family 12h requirements (BKDG section 2.3.3):
597 ;   The following requirements must be satisfied prior to using the cache as general storage:
598 ;   * Paging must be disabled.
599 ;   * MSRC001_0015[INVD_WBINVD]=0
600 ;   * MSRC001_1020[DIS_SS]=1
601 ;   * MSRC001_1021[DIS_SPEC_TLB_RLD]=1
602 ;   * MSRC001_1022[DIS_SPEC_TLB_RLD]=1
603 ;   * MSRC001_1022[DIS_CLR_WBTOL2_SMC_HIT]=1
604 ;   * MSRC001_1022[DIS_HW_PF]=1
605 ;   * MSRC001_1029[ClflushSerialize]=1
606 ;   * No INVD or WBINVD, no exceptions, page faults or interrupts
607 ;---------------------------------------------------
608 AMD_ENABLE_STACK_FAMILY_HOOK_F12 MACRO
609     local   fam12_enable_stack_hook_exit
610
611     AMD_CPUID   CPUID_MODEL
612     shr     eax, 20                     ; AL = cpu extended family
613     cmp     al, 03h                     ; Is this family 12h?
614     jnz     fam12_enable_stack_hook_exit ; Br if no
615
616     mov     ecx, DC_CFG                 ; MSR:C001_1022
617     _RDMSR
618     bts     eax, DC_DIS_SPEC_TLB_RLD    ; Disable speculative DC-TLB reloads
619     bts     eax, DIS_CLR_WBTOL2_SMC_HIT ; Disable self modifying code check buffer
620     bts     eax, DIS_HW_PF              ; Disable hardware prefetches
621     _WRMSR
622
623     dec     cx   ;IC_CFG                ; MSR:C001_1021
624     _RDMSR
625     bts     eax, IC_DIS_SPEC_TLB_RLD    ; Disable speculative IC-TLB reloads
626     _WRMSR
627
628     dec     cx   ;LS_CFG                ; MSR:C001_1020
629     _RDMSR
630     bts     eax, DIS_SS                 ; Disabled Streaming store functionality
631     _WRMSR
632
633     mov     ecx, HWCR                   ; MSR C001_0015
634     _RDMSR
635     bt      esi, FLAG_STACK_REENTRY     ; Check if stack has already been set
636     .if (!carry?)
637         btr     eax, INVD_WBINVD        ;   disable INVD -> WBINVD conversion
638         _WRMSR
639     .endif
640
641     mov     ecx, DE_CFG                 ; MSR:C001_1029
642     _RDMSR
643     bts     eax, CL_FLUSH_SERIALIZE     ; Serialize all CL Flush actions
644     _WRMSR
645
646 fam12_enable_stack_hook_exit:
647 ENDM
648
649 ;----------------------------------------------
650 ;
651 ; AMD_DISABLE_STACK_FAMILY_HOOK_F12 Macro - Stackless
652 ;
653 ;   Return any family specific controls to their 'standard'
654 ;   settings for using cache with main memory.
655 ;
656 ; Inputs:
657 ;       ESI - [31:24] flags; [15,8]= Node#; [7,0]= core#
658 ; Outputs:
659 ;       none
660 ;
661 ; Family 12h requirements:
662 ;   * INVD or WBINVD
663 ;   * MSRC001_0015[INVD_WBINVD]=1
664 ;   * MSRC001_1020[DIS_SS]=0
665 ;   * MSRC001_1021[DIS_SPEC_TLB_RLD]=0
666 ;   * MSRC001_1022[DIS_SPEC_TLB_RLD]=0
667 ;   * MSRC001_1022[DIS_CLR_WBTOL2_SMC_HIT]=0
668 ;   * MSRC001_1022[DIS_HW_PF]=0
669 ;   * MSRC001_1029[ClflushSerialize]=0
670 ;---------------------------------------------------
671 AMD_DISABLE_STACK_FAMILY_HOOK_F12 MACRO
672     local   fam12_disable_stack_hook_exit
673
674     AMD_CPUID   CPUID_MODEL
675     shr     eax, 20                     ; AL = cpu extended family
676     cmp     al, 03h                     ; Is this family 12h?
677     jnz     fam12_disable_stack_hook_exit ; Br if no
678
679     mov     ecx, DC_CFG                 ; MSR:C001_1022
680     _RDMSR
681     btr     eax, DC_DIS_SPEC_TLB_RLD    ; Turn on speculative DC-TLB reloads
682     btr     eax, DIS_CLR_WBTOL2_SMC_HIT ; Enable self modifying code check buffer
683     btr     eax, DIS_HW_PF              ; Enable Hardware prefetches
684     _WRMSR
685
686     dec     cx   ;IC_CFG                ; MSR:C001_1021
687     _RDMSR
688     btr     eax, IC_DIS_SPEC_TLB_RLD    ; Turn on speculative IC-TLB reloads
689     _WRMSR
690
691     dec     cx   ;LS_CFG                ; MSR:C001_1020
692     _RDMSR
693     btr     eax, DIS_SS                 ; Turn on Streaming store functionality
694     _WRMSR
695
696     mov     ecx, DE_CFG                 ; MSR:C001_1029
697     _RDMSR
698     btr     eax, CL_FLUSH_SERIALIZE
699     _WRMSR
700
701     ;--------------------------------------------------------------------------
702     ; Begin critical sequence in which EAX, BX, ECX, and EDX must be preserved.
703     ;--------------------------------------------------------------------------
704
705     mov     ecx, HWCR                    ; MSR:0000_0015h
706     _RDMSR
707     mov     bx, ax                      ; Save INVD -> WBINVD bit
708     btr     eax, INVD_WBINVD            ; Disable INVD -> WBINVD conversion
709     _WRMSR
710     invd                                ; Clear the cache tag RAMs
711     mov     ax, bx                      ; Restore INVD -> WBINVD bit
712     _WRMSR
713
714     ;--------------------------------------------------------------------------
715     ; End critical sequence in which EAX, BX, ECX, and EDX must be preserved.
716     ;--------------------------------------------------------------------------
717
718 fam12_disable_stack_hook_exit:
719 ENDM
720
721 ;---------------------------------------------------
722 ;
723 ; GET_NODE_ID_CORE_ID_F12 Macro - Stackless
724 ;
725 ;   Read family specific values to determine the node and core
726 ;   numbers for the core executing this code.
727 ;
728 ; Inputs:
729 ;     none
730 ; Outputs:
731 ;     SI = core#, node# & flags (see GET_NODE_ID_CORE_ID macro above)
732 ;---------------------------------------------------
733 GET_NODE_ID_CORE_ID_F12 MACRO
734
735     local   node_core_f12_exit
736
737     cmp     si, -1                      ; Has node/core already been discovered?
738     jnz     node_core_f12_exit          ; Br if yes
739
740     AMD_CPUID   CPUID_MODEL
741     shr     eax, 20                     ; AL = cpu extended family
742     cmp     al, 03h                     ; Is this family 12h?
743     jnz     node_core_f12_exit          ; Br if no
744
745     shr     ebx, 24                     ; CPUID_0000_0001_EBX[31:24]: initial local APIC physical ID
746     bts     ebx, FLAG_IS_PRIMARY        ; all family 12h cores are primary
747     mov     esi, ebx                    ; ESI = Node#=0, core number
748 node_core_f12_exit:
749 ENDM
750
751
752 ;;***************************************************************************
753 ;;                      Family 14h MACROS
754 ;;***************************************************************************
755 ;---------------------------------------------------
756 ;
757 ; AMD_ENABLE_STACK_FAMILY_HOOK_F14 Macro - Stackless
758 ;
759 ;   Set any family specific controls needed to enable the use of
760 ;   cache as general storage before main memory is available.
761 ;
762 ; Inputs:
763 ;       ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
764 ; Outputs:
765 ;       none
766 ;
767 ; Family 14h requirements (BKDG section 2.3.3):
768 ;   * Paging must be disabled.
769 ;   * MSRC001_0015[INVD_WBINVD]=0.
770 ;   * MSRC001_1020[DisStreamSt]=1.
771 ;   * MSRC001_1021[DIS_SPEC_TLB_RLD]=1. Disable speculative ITLB reloads.
772 ;   * MSRC001_1022[DIS_HW_PF]=1.
773 ;   * No INVD or WBINVD, no exceptions, page faults or interrupts
774 ;---------------------------------------------------
775 AMD_ENABLE_STACK_FAMILY_HOOK_F14 MACRO
776     local   fam14_enable_stack_hook_exit
777
778     AMD_CPUID   CPUID_MODEL
779     shr     eax, 20                     ; AL = cpu extended family
780     cmp     al, 05h                     ; Is this family 14h?
781     jnz     fam14_enable_stack_hook_exit ; Br if no
782
783     mov     ecx, DC_CFG                 ; MSR:C001_1022
784     _RDMSR
785     bts     eax, DIS_HW_PF              ; Disable hardware prefetches
786     _WRMSR
787
788     dec     cx  ;IC_CFG                 ; MSR:C001_1021
789     _RDMSR
790     bts     eax, IC_DIS_SPEC_TLB_RLD    ; Disable speculative TLB reloads
791     _WRMSR
792
793     dec     cx  ;LS_CFG                 ; MSR:C001_1020
794     _RDMSR
795     bts     eax, DIS_STREAM_ST          ; Disabled Streaming store functionality
796     _WRMSR
797
798     mov     ecx, HWCR                   ; MSR C001_0015
799     _RDMSR
800     bt      esi, FLAG_STACK_REENTRY     ; Check if stack has already been set
801     .if (!carry?)
802         btr     eax, INVD_WBINVD        ; disable INVD -> WBINVD conversion
803         _WRMSR
804     .endif
805
806 fam14_enable_stack_hook_exit:
807 ENDM
808
809 ;----------------------------------------------
810 ;
811 ; AMD_DISABLE_STACK_FAMILY_HOOK_F14 Macro - Stackless
812 ;
813 ;   Return any family specific controls to their 'standard'
814 ;   settings for using cache with main memory.
815 ;
816 ; Inputs:
817 ;       ESI - [31:24] flags; [15,8]= Node#; [7,0]= core#
818 ; Outputs:
819 ;       none
820 ;
821 ; Family 14h requirements:
822 ;   * INVD or WBINVD
823 ;   * MSRC001_0015[INVD_WBINVD]=1.
824 ;   * MSRC001_1020[DisStreamSt]=0.
825 ;   * MSRC001_1021[DIS_SPEC_TLB_RLD]=0.
826 ;   * MSRC001_1022[DIS_HW_PF]=0.
827 ;---------------------------------------------------
828 AMD_DISABLE_STACK_FAMILY_HOOK_F14 MACRO
829     local   fam14_disable_stack_hook_exit
830
831     AMD_CPUID   CPUID_MODEL
832     shr     eax, 20                     ; AL = cpu extended family
833     cmp     al, 05h                     ; Is this family 14h?
834     jnz     fam14_disable_stack_hook_exit ; Br if no
835
836     mov     ecx, LS_CFG                 ; MSR:C001_1020
837     _RDMSR
838     btr     eax, DIS_STREAM_ST          ; Turn on Streaming store functionality
839     _WRMSR
840
841     inc     cx  ;IC_CFG                 ; MSR:C001_1021
842     _RDMSR
843     btr     eax, IC_DIS_SPEC_TLB_RLD    ; Turn on speculative DC-TLB reloads
844     _WRMSR
845
846     inc     cx  ;DC_CFG                 ; MSR:C001_1022
847     _RDMSR
848     btr     eax, DIS_HW_PF              ; Turn on hardware prefetches
849     _WRMSR
850
851     ;--------------------------------------------------------------------------
852     ; Begin critical sequence in which EAX, BX, ECX, and EDX must be preserved.
853     ;--------------------------------------------------------------------------
854
855     mov     ecx, HWCR                    ; MSR:C001_0015h
856     _RDMSR
857     btr     eax, INVD_WBINVD            ; Disable INVD -> WBINVD conversion
858     _WRMSR
859     invd                                ; Clear the cache tag RAMs
860     bts     eax, INVD_WBINVD            ; Turn on Conversion of INVD to WBINVD
861     _WRMSR
862
863     ;--------------------------------------------------------------------------
864     ; End critical sequence in which EAX, BX, ECX, and EDX must be preserved.
865     ;--------------------------------------------------------------------------
866
867 fam14_disable_stack_hook_exit:
868 ENDM
869
870 ;---------------------------------------------------
871 ;
872 ; GET_NODE_ID_CORE_ID_F14 Macro - Stackless
873 ;
874 ;   Read family specific values to determine the node and core
875 ;   numbers for the core executing this code.
876 ;
877 ; Inputs:
878 ;     none
879 ; Outputs:
880 ;     SI = core#, node# & flags (see GET_NODE_ID_CORE_ID macro above)
881 ;---------------------------------------------------
882 GET_NODE_ID_CORE_ID_F14 MACRO
883
884     local   node_core_f14_exit
885
886     cmp     si, -1                      ; Has node/core already been discovered?
887     jnz     node_core_f14_exit          ; Br if yes
888
889     AMD_CPUID   CPUID_MODEL
890     shr     eax, 20                     ; AL = cpu extended family
891     cmp     al, 05h                     ; Is this family 14h?
892     jnz     node_core_f14_exit          ; Br if no
893
894     shr     ebx, 24                     ; CPUID_0000_0001_EBX[31:24]: initial local APIC physical ID
895     bts     ebx, FLAG_IS_PRIMARY        ; all family 14h cores are primary
896     mov     esi, ebx                    ; ESI = Node#=0, core number
897 node_core_f14_exit:
898 ENDM
899
900
901
902 ;;***************************************************************************
903 ;;                      Family 15h MACROS
904 ;;***************************************************************************
905 ;---------------------------------------------------
906 ;
907 ; AMD_ENABLE_STACK_FAMILY_HOOK_F15 Macro - Stackless
908 ;
909 ;   Set any family specific controls needed to enable the use of
910 ;   cache as general storage before main memory is available.
911 ;
912 ; Inputs:
913 ;       ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
914 ; Outputs:
915 ;       none
916 ;
917 ; Family 15h requirements (BKDG #42301 section 2.3.3):
918 ;   * Paging must be disabled.
919 ;   * MSRC001_0015[INVD_WBINVD]=0
920 ;   * MSRC001_1020[DisSS]=1
921 ;   * MSRC001_1021[DIS_SPEC_TLB_RLD]=1
922 ;   * MSRC001_1022[DIS_SPEC_TLB_RLD]=1
923 ;   * MSRC001_1022[DisHwPf]=1
924 ;   * No INVD or WBINVD, no exceptions, page faults or interrupts
925 ;---------------------------------------------------
926 AMD_ENABLE_STACK_FAMILY_HOOK_F15 MACRO
927     local   fam15_enable_stack_hook_exit
928
929     AMD_CPUID   CPUID_MODEL
930     mov     ebx, eax                    ; Save revision info to EBX
931     shr     eax, 20                     ; AL = cpu extended family
932     cmp     al, 06h                     ; Is this family 15h?
933     jnz     fam15_enable_stack_hook_exit ; Br if no
934
935     bt      esi, FLAG_STACK_REENTRY     ; Check if stack has already been set
936     .if (!carry?)
937         mov     ecx, HWCR               ; MSR C001_0015
938         _RDMSR
939         btr     eax, INVD_WBINVD        ; disable INVD -> WBINVD conversion
940         _WRMSR
941     .endif
942
943     mov     ecx, LS_CFG                 ; MSR:C001_1020
944     _RDMSR
945     bts     eax, DIS_SS                 ; Turn on Streaming store functionality disabled bit
946     _WRMSR
947
948     inc     ecx  ;IC_CFG                ; MSR:C001_1021
949     _RDMSR
950     bts     eax, IC_DIS_SPEC_TLB_RLD    ; Turn on Disable speculative IC-TLB reloads bit
951     _WRMSR
952
953     inc     ecx  ;DC_CFG                ; MSR:C001_1022
954     _RDMSR
955     bts     eax, DC_DIS_SPEC_TLB_RLD    ; Turn on Disable speculative DC-TLB reloads bit
956     bts     eax, DIS_HW_PF              ; Turn on Disable hardware prefetches bit
957     _WRMSR
958
959     mov     ecx, CU_CFG3                ; MSR:C001_102B
960     _RDMSR
961     btr     edx, (COMBINE_CR0_CD - 32)  ; Clear CombineCr0Cd bit
962     _WRMSR
963
964 fam15_enable_stack_hook_exit:
965 ENDM
966
967
968 ;----------------------------------------------
969 ;
970 ; AMD_DISABLE_STACK_FAMILY_HOOK_F15 Macro - Stackless
971 ;
972 ;   Return any family specific controls to their 'standard'
973 ;   settings for using cache with main memory.
974 ;
975 ; Inputs:
976 ;       ESI - [31:24] flags; [15,8]= Node#; [7,0]= core#
977 ; Outputs:
978 ;       none
979 ;
980 ; Family 15h requirements:
981 ;   * INVD or WBINVD
982 ;   * MSRC001_0015[INVD_WBINVD]=1
983 ;   * MSRC001_1020[DisSS]=0
984 ;   * MSRC001_1021[DIS_SPEC_TLB_RLD]=0
985 ;   * MSRC001_1022[DIS_SPEC_TLB_RLD]=0
986 ;   * MSRC001_1022[DIS_HW_PF]=0
987 ;---------------------------------------------------
988 AMD_DISABLE_STACK_FAMILY_HOOK_F15 MACRO
989     local   fam15_disable_stack_hook_exit
990
991     AMD_CPUID   CPUID_MODEL
992     mov     ebx, eax                    ; Save revision info to EBX
993     shr     eax, 20                     ; AL = cpu extended family
994     cmp     al, 06h                     ; Is this family 15h?
995     jnz     fam15_disable_stack_hook_exit ; Br if no
996
997     mov     edi, ebx                    ; Save revision info to EDI
998     AMD_CPUID   AMD_CPUID_APIC
999     mov     al, cl                      ; AL = number of cores - 1
1000     shr     cx, APIC_ID_CORE_ID_SIZE    ; CL = ApicIdCoreIdSize
1001     mov     bx, 1
1002     shl     bl, cl                      ; BL = theoretical number of cores on socket
1003     dec     bx                          ; BL = core number on socket mask
1004     mov     ah, bl                      ; AH = core number on socket mask
1005     mov     ebx, edi                    ; Restore revision info to EBX
1006     mov     di, ax                      ; DI[15:8] = core number mask, DI[7:0] = number of cores - 1
1007
1008     and     ebx, 0F00FFh
1009     mov     eax, ebx
1010     shr     eax, 8
1011     or      bx, ax                      ; Save Extended Model, Model and Stepping to BX
1012                                         ; [11:8] = Extended Model, [7:4] = Model, [3:0] = Stepping
1013
1014     ;; A handshake is required to ensure that all cores on a node invalidate in sync.
1015     mov     ecx, APIC_BASE_ADDRESS
1016     _RDMSR
1017     mov     dx, bx                      ; Save Extended Model, Model and Stepping to DX
1018     shl     edx, 16                     ; EDX[31:16] = Extended Model, Model and Stepping
1019     mov     ebx, eax                    ; EBX = LAPIC base
1020     xor     ecx, ecx                    ; Zero out CU flags
1021     bts     ecx, AMD_CU_NEED_TO_WAIT    ; Default to waiting
1022     bts     ecx, AMD_CU_SEND_INVD_MSG   ; Default to signaling
1023     mov     eax, CR0
1024     bt      ax, CR0_PE                  ; Are we in protected mode?
1025     .if (!carry?)
1026         bts     ecx, AMD_CU_RESTORE_ES  ; Indicate ES restore is required
1027         mov     cx, es                  ; Save ES segment register to CX
1028         xor     ax, ax
1029         mov     es, ax                  ; Set ES to big real mode selector for 4GB access
1030     .endif
1031
1032     and     bx, 0F000h                  ; EBX = LAPIC base, offset 0
1033     or      bl, APIC_ID_REG
1034     mov     eax, es:[ebx]               ; EAX[31:24] = APIC ID
1035     shr     eax, APIC20_APICID          ; AL = APIC ID
1036     mov     ah, al                      ; AH = APIC ID
1037     mov     dx, di                      ; DH = core mask
1038     and     ah, dh                      ; AH = core number
1039     .if (zero?)
1040         ;; Core 0 of a socket
1041         btr     ecx, AMD_CU_SEND_INVD_MSG ; No need to signal after INVD
1042         .if (dl != 0)
1043             ;; This socket has multiple cores
1044             and     bx, 0F000h          ; EBX = LAPIC base, offset 0
1045             or      bx, APIC_MSG_REG
1046             mov     edi, APIC_MSG
1047             mov     es:[ebx], edi       ; Signal for non core 0s to complete CAR breakdown
1048         .else
1049             btr     ecx, AMD_CU_NEED_TO_WAIT ; No need to wait on a single core CPU
1050         .endif
1051     .endif
1052
1053     bt     ecx, AMD_CU_NEED_TO_WAIT
1054     .if (carry?)
1055         .if (ah == dl)
1056             ;; This is the highest numbered core on this socket -- wait on core 0
1057             not     dh                  ; Flip the mask to determine local core 0's APIC ID
1058             and     al, dh              ; AL = target APIC ID
1059         .else
1060             ;; All other cores (including core 0) wait on the next highest core.
1061             ;; In this way, cores will halt in a cascading fashion down to 0.
1062             inc     al
1063         .endif
1064
1065         shl     eax, APIC20_APICID
1066         and     bx, 0F000h
1067         or      bx, APIC_CMD_HI_REG
1068         mov     es:[ebx], eax           ; Set target APIC ID
1069
1070         stc
1071         .while (carry?)
1072             and     bx, 0F000h          ; EBX = LAPIC base, offset 0
1073             or      bx, APIC_CMD_LO_REG
1074             mov     eax, CMD_REG_TO_READ_DATA
1075             mov     es:[ebx], eax       ; Fire remote read IPI
1076             stc
1077             .while (carry?)
1078                 mov     eax, es:[ebx]
1079                 bt      eax, DELIVERY_STS_BIT
1080             .endw
1081             stc
1082             .while (carry?)
1083                 mov     eax, es:[ebx]
1084                 and     eax, REMOTE_READ_STS
1085                 .if (eax == REMOTE_DELIVERY_PEND)
1086                     stc
1087                 .else
1088                     clc
1089                 .endif
1090             .endw
1091             .if (eax == REMOTE_DELIVERY_DONE)
1092                 and     bx, 0F000h      ; EBX = LAPIC base, offset 0
1093                 or      bl, APIC_REMOTE_READ_REG
1094                 mov     eax, es:[ebx]
1095                 .if (eax == APIC_MSG)
1096                     clc
1097                 .else
1098                     stc
1099                 .endif
1100             .else
1101                 stc
1102             .endif
1103         .endw
1104     .endif
1105     bt      ecx, AMD_CU_RESTORE_ES
1106     .if (carry?)
1107         mov     es, cx
1108     .endif
1109     mov     edi, ecx                    ; EDI = CU flags
1110     shr     edx, 16
1111     mov     bx, dx                      ; Restore Extended Model, Model and Stepping
1112
1113     ;; Handshaking complete.  Continue tearing down CAR.
1114     mov     ecx, LS_CFG                 ; MSR:C001_1020
1115     .if (bx != 0)                       ; Is this OR A0?
1116         _RDMSR
1117         btr     eax, DIS_SS             ; Turn on Streaming store functionality
1118         _WRMSR
1119     .endif                              ; End workaround for errata 495 and 496
1120
1121     inc     ecx  ;IC_CFG                ; MSR:C001_1021
1122     _RDMSR
1123     btr     eax, IC_DIS_SPEC_TLB_RLD    ; Turn on speculative TLB reloads
1124     _WRMSR
1125
1126     inc     ecx  ;DC_CFG                ; MSR:C001_1022
1127     _RDMSR
1128     btr     eax, DC_DIS_SPEC_TLB_RLD    ; Turn on speculative TLB reloads
1129     .if (bx != 0)                       ; Is this OR A0?
1130         btr     eax, DIS_HW_PF          ; Turn on hardware prefetches
1131     .endif                              ; End workaround for erratum 498
1132     _WRMSR
1133
1134     mov     ecx, HWCR                   ; MSR:C001_0015h
1135     _RDMSR
1136     btr     eax, INVD_WBINVD            ; Disable INVD -> WBINVD conversion
1137     _WRMSR
1138     invd                                ; Clear the cache tag RAMs
1139
1140     ; Do Standard Family 15 work
1141     mov     ecx, HWCR                   ; MSR:C001_0015h
1142     _RDMSR
1143     bts     eax, INVD_WBINVD            ; Turn on INVD -> WBINVD conversion
1144     _WRMSR
1145
1146     mov     ecx, CU_CFG3                ; MSR:C001_102B
1147     _RDMSR
1148     bts     edx, (COMBINE_CR0_CD - 32)  ; Set CombineCr0Cd bit
1149     _WRMSR
1150
1151     bt      edi, AMD_CU_SEND_INVD_MSG
1152     .if (carry?)
1153         ;; Non core zero needs to signal to core 0 to proceed
1154         mov     ecx, APIC_BASE_ADDRESS
1155         _RDMSR
1156         mov     ebx, eax                ; EBX = LAPIC base
1157         and     bx, 0F000h              ; EBX = LAPIC base, offset 0
1158         or      bx, APIC_MSG_REG
1159         mov     eax, APIC_MSG
1160         mov     es:[ebx], eax           ; Signal for core 0 to complete CAR breakdown
1161     .endif
1162
1163 fam15_disable_stack_hook_exit:
1164 ENDM
1165
1166
1167 ;---------------------------------------------------
1168 ;
1169 ; GET_NODE_ID_CORE_ID_F15 Macro - Stackless
1170 ;
1171 ;   Read family specific values to determine the node and core
1172 ;   numbers for the core executing this code.
1173 ;
1174 ; Inputs:
1175 ;     none
1176 ; Outputs:
1177 ;     SI = core#, node# & flags (see GET_NODE_ID_CORE_ID macro above)
1178 ;---------------------------------------------------
1179 GET_NODE_ID_CORE_ID_F15 MACRO
1180
1181     local   node_core_f15_exit
1182
1183     cmp     si, -1                      ; Has node/core already been discovered?
1184     jnz     node_core_f15_exit          ; Br if yes
1185
1186     AMD_CPUID   CPUID_MODEL
1187     shr     eax, 20                     ; AL = cpu extended family
1188     cmp     al, 06h                     ; Is this family 15h?
1189     jnz     node_core_f15_exit          ; Br if no
1190
1191     xor     esi, esi                    ; Assume BSC, clear local flags
1192     mov     ecx, APIC_BASE_ADDRESS      ; MSR:0000_001B
1193     _RDMSR
1194     bt      eax, APIC_BSC               ; Is this the BSC?
1195     .if (carry?)
1196         ; This is the BSP.
1197         ; Enable routing tables on BSP (just in case the HT init code has not yet enabled them)
1198         mov     eax, 8000C06Ch          ;   PCI address for D18F0x6C Link Initialization Control Register
1199         mov     dx, 0CF8h
1200         out     dx, eax
1201         add     dx, 4
1202         in      eax, dx
1203         btr     eax, 0                  ;   Set LinkInitializationControl[RouteTblDis] = 0
1204         out     dx, eax
1205     .else                               ;
1206         ; This is an AP. Routing tables have been enabled by the HT Init process.
1207         ; Also, the MailBox register was set by the BSP during early init
1208         ;   The Mailbox register content is formatted as follows:
1209         ;         UINT32 Node:4;        // The node id of Core's node.
1210         ;         UINT32 Socket:4;      // The socket of this Core's node.
1211         ;         UINT32 Module:2;      // The internal module number for Core's node.
1212         ;         UINT32 ModuleType:2;  // Single Module = 0, Multi-module = 1.
1213         ;         UINT32 :20;           // Reserved
1214         ;
1215         mov     ecx, 0C0000408h         ;   Read the family 15h mailbox
1216         _RDMSR                          ;      MC4_MISC1[63:32]
1217         mov     si, dx                  ;   SI = raw mailbox contents (will extract node# from this)
1218         shr     ebx, 24                 ;   BL = CPUID Fn0000_0001_EBX[LocalApicId]
1219         mov     di, bx                  ;   DI = Initial APIC ID (will extract core# from this)
1220
1221         AMD_CPUID   AMD_CPUID_APIC      ;
1222         shr     ch, 4                   ;   CH = ApicIdSize, #bits in APIC ID that show core#
1223         inc     cl                      ;   CL = Number of enabled cores in the socket
1224         mov     bx, cx
1225
1226         mov     ecx, NB_CFG
1227         _RDMSR                          ;   EDX has InitApicIdCpuIdLo bit
1228
1229         mov     cl, bh                  ;   CL = APIC ID size
1230         mov     al, 1                   ;   Convert APIC ID size to an AND mask
1231         shl     al, cl                  ;   AL = 2^APIC ID size
1232         dec     al                      ;   AL = mask for relative core number
1233         xor     ah, ah                  ;   AX = mask for relative core number
1234         bt      edx, (INIT_APIC_ID_CPU_ID_LO-32) ; InitApicIdCpuIdLo == 1?
1235         .if (!carry?)                   ;   Br if yes
1236             mov     ch, 8               ;     Calculate core number shift count
1237             sub     ch, cl              ;     CH = core shift count
1238             mov     cl, ch              ;
1239             shr     di, cl              ;     Right justify core number
1240         .endif                          ;
1241         and     di, ax                  ;   DI = socket-relative core number
1242
1243         mov     cx, si                  ;   CX = raw mailbox value
1244         shr     cx, 10                  ;   CL[1:0] = ModuleType or #nodes per socket (0-SCM, 1-MCM)
1245         and     cl, 3                   ;   Isolate ModuleType
1246         xor     bh, bh                  ;   BX = Number of enabled cores in the socket
1247         shr     bx, cl                  ;   BX = Number of enabled cores per node
1248         xor     dx, dx                  ;   Clear upper word for div
1249         mov     ax, di                  ;   AX = socket-relative core number
1250         div     bx                      ;   DX = node-relative core number
1251         movzx   eax, si                 ;   Prepare return value
1252         and     ax, 000Fh               ;   AX = node number
1253         shl     ax, 8                   ;   [15:8]=node#
1254         mov     al, dl                  ;   [7:0]=core# (relative to node)
1255         mov     esi, eax                ;   ESI = node-relative core number
1256     .endif                              ; end
1257
1258     ;
1259     ;   determine if this core shares MTRRs
1260     ;
1261     mov     eax, 8000C580h              ; Compute Unit Status
1262     mov     bx, si                      ; load node#(bh), core#(bl)
1263     shl     bh, 3                       ; Move node# to PCI Dev# field
1264     add     ah, bh                      ; Adjust PCI adress for node number
1265     mov     dx, 0CF8h
1266     out     dx, eax
1267     add     dx, 4
1268     in      eax, dx                     ; [3:0]=Enabled; [19:16]=DualCore
1269
1270                                         ; BL is MyCore#  , BH is primary flag
1271     mov     cx, 06h                     ; Use CH as 'first of pair' core#
1272     .while (cl > 0)
1273         bt      eax, 0                  ;   Is pair enabled?
1274         .if (carry?)                    ;
1275             mov     bh, 01h             ;   flag core as primary
1276             bt      eax, 16             ;   Is there a 2nd in the pair?
1277             .if (carry?)                ;
1278                 .break .if (ch == bl)   ;     Does 1st match MyCore#?
1279                 inc     ch
1280                 xor     bh, bh          ;     flag core as NOT primary
1281                 .break .if (ch == bl)   ;     Does 2nd match MyCore#?
1282             .else                       ;   No 2nd core
1283                 .break .if (ch == bl)   ;     Does 1st match MyCore#?
1284             .endif
1285             inc     ch
1286         .endif
1287         shr     eax, 1
1288         dec     cl
1289     .endw
1290     .if (cl == 0)
1291         ;Error - core# didn't match Compute Unit Status content
1292         bts     esi, FLAG_CORE_NOT_IDENTIFIED
1293         bts     esi, FLAG_IS_PRIMARY    ;   Set Is_Primary for unknowns
1294     .endif
1295     .if (bh != 0)                       ; Check state of primary for the matched core
1296         bts     esi, FLAG_IS_PRIMARY    ;   Set shared flag into return value
1297     .endif
1298 node_core_f15_exit:
1299 ENDM
1300
1301
1302