mb/google/rauru: Implement regulator interface
[coreboot2.git] / src / vendorcode / amd / pi / 00670F00 / binaryPI / gcccar.inc
blob4f5bdc56a33322af00ac5428f057bcfe40c2b10c
1 /* SPDX-License-Identifier: BSD-3-Clause */
3 /*
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  */
31 /******************************************************************************
32 * AMD Generic Encapsulated Software Architecture
34 * $Workfile:: GccCar.inc    $Revision:: 32932   $
36 * Description: GccCar.inc - AGESA cache-as-RAM setup Include File for GCC complier
38 ******************************************************************************/
40 .altmacro
42 BSP_STACK_BASE_ADDR     =       0x30000         /* Base address for primary cores stack   */
43 BSP_STACK_SIZE          =       0x10000         /* 64KB for BSP core                      */
44 BSP_STACK_SIZE_64K      =       0x10000        /*64KB for BSP core */
45 BSP_STACK_SIZE_32K      =       0x8000         /*32KB for BSP core*/
47 CORE0_STACK_BASE_ADDR   =       0x80000         /* Base address for primary cores stack   */
48 CORE0_STACK_SIZE        =       0x4000          /* 16KB for primary cores                 */
49 CORE1_STACK_BASE_ADDR   =       0x40000         /* Base address for AP cores              */
50 CORE1_STACK_SIZE        =       0x1000          /* 4KB for each AP cores                  */
52 APIC_BASE_ADDRESS       =       0x0000001B
53   APIC_BSC              =       8               /* Boot Strap Core  */
55 APIC_MSG_REG            = 0x380        # Location of BSC message
56     APIC_MSG            = 0x00DE00AD   # Message data
57 APIC_CMD_LO_REG         = 0x300        # APIC command low
58 APIC_CMD_HI_REG         = 0x310        # APIC command high
59     CMD_REG_TO_READ_DATA = 0x00000338  # APIC command for remote read of APIC_MSG_REG
60     REMOTE_READ_STS       = 0x00030000 # Remote read status mask
61     REMOTE_DELIVERY_PEND  = 0x00010000 # Remote read is pending
62     REMOTE_DELIVERY_DONE  = 0x00020000 # Remote read is complete
63     DELIVERY_STS_BIT    = 12          #Delivery status valid bit
64 APIC_ID_REG             = 0x0020       # Local APIC ID offset
65     APIC20_APICID       = 24
66 APIC_REMOTE_READ_REG    = 0x00C0       # Remote read offset
68 # Flags can only run from bits 31 to 24.  Bits 23:0 are in use.
69 AMD_CU_NEED_TO_WAIT     = 31
70 AMD_CU_SEND_INVD_MSG    = 30
71 AMD_CU_RESTORE_ES       = 29
73 AMD_MTRR_VARIABLE_BASE0  =      0x0200
74 AMD_MTRR_VARIABLE_BASE6  =      0x020C
75 AMD_MTRR_VARIABLE_BASE7 = 0x020E
76     VMTRR_VALID             =     11
77     MTRR_TYPE_WB            =     0x06
78     MTRR_TYPE_WP            =     0x05
79     MTRR_TYPE_WT            =     0x04
80     MTRR_TYPE_UC            =     0x00
81 AMD_MTRR_VARIABLE_MASK7 = 0x020F
82 AMD_MTRR_FIX64k_00000    =      0x0250
83 AMD_MTRR_FIX16k_80000    =      0x0258
84 AMD_MTRR_FIX16k_A0000    =      0x0259
85 AMD_MTRR_FIX4k_C0000     =      0x0268
86 AMD_MTRR_FIX4k_C8000     =      0x0269
87 AMD_MTRR_FIX4k_D0000     =      0x026A
88 AMD_MTRR_FIX4k_D8000     =      0x026B
89 AMD_MTRR_FIX4k_E0000     =      0x026C
90 AMD_MTRR_FIX4k_E8000     =      0x026D
91 AMD_MTRR_FIX4k_F0000     =      0x026E
92 AMD_MTRR_FIX4k_F8000     =      0x026F
94 /* Reproduced from AGESA.h */
95 AMD_AP_MTRR_FIX64k_00000  =  0x00000250
96 AMD_AP_MTRR_FIX16k_80000  =  0x00000258
97 AMD_AP_MTRR_FIX16k_A0000  =  0x00000259
98 AMD_AP_MTRR_FIX4k_C0000   =  0x00000268
99 AMD_AP_MTRR_FIX4k_C8000   =  0x00000269
100 AMD_AP_MTRR_FIX4k_D0000   =  0x0000026A
101 AMD_AP_MTRR_FIX4k_D8000   =  0x0000026B
102 AMD_AP_MTRR_FIX4k_E0000   =  0x0000026C
103 AMD_AP_MTRR_FIX4k_E8000   =  0x0000026D
104 AMD_AP_MTRR_FIX4k_F0000   =  0x0000026E
105 AMD_AP_MTRR_FIX4k_F8000   =  0x0000026F
106 CPU_LIST_TERMINAL         =  0xFFFFFFFF
108 AMD_MTRR_DEFTYPE         =      0x02FF
109     WB_DRAM_TYPE         =      0x1E             /* MemType - memory type */
110     MTRR_DEF_TYPE_EN     =      11               /* MtrrDefTypeEn - variable and fixed MTRRs default enabled */
111     MTRR_DEF_TYPE_FIX_EN =      10               /* MtrrDefTypeEn - fixed MTRRs default enabled */
113 HWCR                     =      0x0C0010015      /* Hardware Configuration                                                                                                                                       */
114     INVD_WBINVD          =      0x04             /* INVD to WBINVD conversion */
116 IORR_BASE                =      0x0C0010016      /* IO Range Regusters Base/Mask, 2 pairs */
117                                                  /*  uses 16h - 19h                                                                                                                                                             */
118 TOP_MEM                  =      0x0C001001A      /* Top of Memory                                                                                                                                                                                */
119 TOP_MEM2                 =      0x0C001001D      /* Top of Memory2                                                                                                                                                                       */
121 LS_CFG3                  =      0x0C001101C  /* Load-Store Configuration 3 */
122     DIS_SS_F15CZ            = 7         /* Disable Streaming Store functionality*/
123     DC_DIS_SPEC_TLB_RLD_F15CZ   = 20    /* Disable speculative TLB reloads*/
124     DC_DIS_HW_PF_F15CZ      = 23        /* Hardware prefetches bit*/
127 LS_CFG                   =      0x0C0011020      /* Load-Store Configuration                                                                                                                             */
128     DIS_SS               =     28                /* Family 10h,12h,15h:Disable Streng Store functionality */
129     DIS_STREAM_ST        =     28                /* Family 14h:DisStreamSt - Disable Streaming Store functionality */
131 IC_CFG                   =      0x0C0011021      /* Instruction Cache Config Register  */
132     IC_DIS_SPEC_TLB_RLD  =      9                /*   Disable speculative TLB reloads  */
133     DIS_IND              =      14               /*   Family 10-14h:Disable Indirect Branch Predictor */
134     DIS_I_CACHE          =      14               /*   Family 15h:DisICache - Disable Indirect Branch Predictor */
136 DC_CFG                   =      0x0C0011022      /* Data Cache Configuration                                                                                                                                   */
137     DC_DIS_SPEC_TLB_RLD      =  4                /*   Disable speculative TLB reloads */
138     DIS_CLR_WBTOL2_SMC_HIT   =  8                /*   self modifying code check buffer bit */
139     DIS_HW_PF                =  13               /*   Hardware prefetches bit                                                                                                                                    */
141 CU_CFG                  = 0x0C0011023  /* Family 15h: Combined Unit Configuration */
142     L2_WAY_LOCK_EN          = 23      /*   L2WayLock - L2 way lock enable */
143     L2_FIRST_LOCKED_WAY     = 19      /*   L2FirstLockedWay - first L2 way lockedh */
144     L2_FIRST_LOCKED_WAY_OR_MASK  = 0x000780000
146 DE_CFG                   =      0x0C0011029      /* Decode Configuration */
147     CL_FLUSH_SERIALIZE   =      23               /*   Family 12h,15h: CL Flush Serialization */
149 BU_CFG2                  =      0x0C001102A      /* Family 10h: Bus Unit Configuration 2 */
150 CU_CFG2                  =      0x0C001102A      /* Family 15h: Combined Unit Configuration 2 */
151     F10_CL_LINES_TO_NB_DIS  =   15               /*   ClLinesToNbDis - allows WP code to be cached in L2 */
152     IC_DIS_SPEC_TLB_WR      =   35               /*   IcDisSpecTlbWr - ITLB speculative writes */
154 CU_CFG3                  =      0x0C001102B      /* Combined Unit Configuration 3 */
155     COMBINE_CR0_CD       =      49               /*   Combine CR0.CD for both cores of a compute unit */
157 CR0_PE                  = 0           # Protection Enable
158 CR0_NW                  = 29          # Not Write-through
159 CR0_CD                  = 30          # Cache Disable
160 CR0_PG                  = 31          # Paging Enable
162 /* CPUID Functions */
164 CPUID_MODEL              =      1
165 AMD_CPUID_FMF            =      0x80000001       /* Family Model Features information */
166 AMD_CPUID_L2Cache        =      0x80000006       /* L2/L3 cache info */
167 AMD_CPUID_APIC           =      0x80000008       /* Long Mode and APIC info., core count */
168     APIC_ID_CORE_ID_SIZE      = 12               /* ApicIdCoreIdSize bit position */
170 NB_CFG                   =      0x0C001001F      /* Northbridge Configuration Register */
171     INIT_APIC_ID_CPU_ID_LO    = 54               /*  InitApicIdCpuIdLo - is core# in high or low half of APIC ID? */
172     ENABLE_CF8_EXT_CFG        = 46               /*  EnableCf8ExtCfg - enable CF8 extended configuration cycles */
174 MTRR_SYS_CFG             =      0x0C0010010      /* System Configuration Register */
175   CHX_TO_DIRTY_DIS       =      16               /*   ChxToDirtyDis    Change to dirty disable  */
176   SYS_UC_LOCK_EN         =      17               /*   SysUcLockEn      System lock command enable */
177   MTRR_FIX_DRAM_EN       =      18               /*   MtrrFixDramEn    MTRR fixed RdDram and WrDram attributes enable */
178   MTRR_FIX_DRAM_MOD_EN   =      19               /*   MtrrFixDramModEn MTRR fixed RdDram and WrDram modification enable */
179   MTRR_VAR_DRAM_EN       =      20               /*   MtrrVarDramEn    MTRR variable DRAM enable */
180   MTRR_TOM2_EN           =      21               /*   MtrrTom2En       MTRR top of memory 2 enable */
182 PERF_CONTROL3            =      0x0C0010003      /* Performance event control three */
183     PERF_CONTROL3_RESERVE_L  =  0x00200000       /* Preserve the reserved bits */
184     PERF_CONTROL3_RESERVE_H  =  0x0FCF0          /* Preserve the reserved bits */
185     CONFIG_EVENT_L           =  0x0F0E2          /* All cores with level detection */
186     CONFIG_EVENT_H           =  4                /* Increment count by number of event */
187                                                  /* occured in clock cycle */
188     EVENT_ENABLE             =  22               /* Enable the event */
189 PERF_COUNTER3            =      0x0C0010007      /* Performance event counter three */
191 FUNC_3                  =       3
192 MCA_NB_CFG              =       0x44             /* MCA NB Configuration */
193 CPU_ERR_DIS             =       6                /* CPU error response disable */
194 PRODUCT_INFO_REG1       =       0x1FC                   /* Product Information Register 1 */
196 # Local use flags, in upper most byte if ESI
197 FLAG_UNKNOWN_FAMILY     = 24          # Signals that the family# of the installed processor is not recognized
198 FLAG_STACK_REENTRY      = 25          # Signals that the environment has made a re-entry (2nd) call to set up the stack
199 FLAG_IS_PRIMARY         = 26          # Signals that this core is the primary within the comoute unit
200 FLAG_CORE_NOT_IDENTIFIED     = 27          # Signals that the cores/compute units of the installed processor is not recognized
201 FLAG_FORCE_32K_STACK     = 28         # Signals that to force 32KB stack size for BSP core
202 CR0_MASK    = ((1 << CR0_CD) | (1 << CR0_NW))
203 MSR_MASK    = ((1 << MTRR_DEF_TYPE_EN)+(1 << MTRR_DEF_TYPE_FIX_EN))
205 /****************************************************************************
207  *                      CPU MACROS - PUBLIC
209  ****************************************************************************/
210 .macro   _WRMSR
211         .byte 0x0f, 0x30
212 .endm
214 .macro  _RDMSR
215         .byte   0x0F, 0x32
216 .endm
218 .macro AMD_CPUID arg0
219   .ifb \arg0
220     mov   $0x1, %eax
221     .byte 0x0F, 0x0A2                     /* Execute instruction */
222     bswap %eax
223     xchg  %ah, %al                        /* Ext model in al now */
224     rol   $0x08, %eax                     /* Ext model in ah, model in al */
225     and   $0x0FFCF, ax                    /* Keep 23:16, 7:6, 3:0 */
226   .else
227     mov   \arg0, %eax
228     .byte 0x0F, 0x0A2
229   .endif
230 .endm
232 .macro MAKE_EXT_PCI_ADDR  Seg, Bus, Dev, Func, Offset
233         mov $(1 << 31 | (Seg) << 28 | (((Offset) & (0x0F00)) >> 8) << 24 | (Bus) << 16 | (Dev) << 11 | (Func) << 8) | ((Offset) & (0xFC)), %eax
234 .endm
235 /****************************************************************************
237 * AMD_ENABLE_STACK_FAMILY_HOOK Macro - Stackless
239 *   Set any family specific controls needed to enable the use of
240 *   cache as general storage before main memory is available.
242 * Inputs:
243 *       none
244 * Outputs:
245 *       none
246  ****************************************************************************/
247 .macro  AMD_ENABLE_STACK_FAMILY_HOOK
249 //    AMD_ENABLE_STACK_FAMILY_HOOK_F10
250 //    AMD_ENABLE_STACK_FAMILY_HOOK_F12
251 //    AMD_ENABLE_STACK_FAMILY_HOOK_F14
252     AMD_ENABLE_STACK_FAMILY_HOOK_F15
253 .endm
255 /****************************************************************************
257 * AMD_DISABLE_STACK_FAMILY_HOOK Macro - Stackless
259 *   Return any family specific controls to their 'standard'
260 *   settings for using cache with main memory.
262 * Inputs:
263 *       none
264 * Outputs:
265 *       none
266  ****************************************************************************/
267 .macro  AMD_DISABLE_STACK_FAMILY_HOOK
269     //AMD_DISABLE_STACK_FAMILY_HOOK_F10
270     //AMD_DISABLE_STACK_FAMILY_HOOK_F12
271     //AMD_DISABLE_STACK_FAMILY_HOOK_F14
272     AMD_DISABLE_STACK_FAMILY_HOOK_F15
274 .endm
276 /****************************************************************************
278 * GET_NODE_ID_CORE_ID Macro - Stackless
280 *   Read family specific values to determine the node and core
281 *   numbers for the core executing this code.
283 * Inputs:
284 *     none
285 * Outputs:
286 *     SI[7:0] = Core# (0..N, relative to node)
287 *     SI[15:8]= Node# (0..N)
288 *     SI[23:16]= reserved
289 *     SI[24]=   flag: 1=Family Unrecognized
290 *     SI[25]=   flag: 1=Interface re-entry call
291 *     SI[26]=   flag: 1=Core is primary of compute unit
292 *     SI[31:27]= reserved, =0
293 ****************************************************************************/
294 .macro  GET_NODE_ID_CORE_ID
296     mov     $-1, %si
297     //GET_NODE_ID_CORE_ID_F10
298     //GET_NODE_ID_CORE_ID_F12
299     //GET_NODE_ID_CORE_ID_F14
300     GET_NODE_ID_CORE_ID_F15
301     /*
302      * Check for unrecognized Family
303      */
304     cmp     $-1, %si                      # Has family (node/core) already been discovered?
305     jnz     node_core_exit\@              # Br if yes
307    mov     $((1 << FLAG_UNKNOWN_FAMILY)+(1 << FLAG_IS_PRIMARY)), %esi # No, Set error code, Only let BSP continue
309     mov     $APIC_BASE_ADDRESS, %ecx      # MSR:0000_001B
310     _RDMSR
311     bt      $APIC_BSC, %eax               # Is this the BSC?
312     jc      node_core_exit\@              # Br if yes
313     hlt                                 # Kill APs
314 node_core_exit\@:
316 .endm
319 /*****************************************************************************
320 **                      Family 15h MACROS
321 *****************************************************************************/
322 /*****************************************************************************
324 * AMD_ENABLE_STACK_FAMILY_HOOK_F15 Macro - Stackless
326 *   Set any family specific controls needed to enable the use of
327 *   cache as general storage before main memory is available.
329 * Inputs:
330 *       ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
331 * Outputs:
332 *       none
334 * Family 15h requirements (BKDG #42301 section 2.3.3):
335 *   * Paging must be disabled.
336 *   * MSRC001_0015[INVD_WBINVD]=0
337 *   * MSRC001_1020[DisSS]=1
338 *   * MSRC001_1021[DIS_SPEC_TLB_RLD]=1
339 *   * MSRC001_1022[DIS_SPEC_TLB_RLD]=1
340 *   * MSRC001_1022[DisHwPf]=1
341 *   * No INVD or WBINVD, no exceptions, page faults or interrupts
342 *****************************************************************************/
343 .macro  AMD_ENABLE_STACK_FAMILY_HOOK_F15
345     AMD_CPUID   $CPUID_MODEL
346     mov     %eax, %ebx                # Save revision info to EBX
347     shr     $20, %eax                 # AL = cpu extended family
348     cmp     $0x06, %al                     # Is this family 15h?
349     jnz     fam15_enable_stack_hook_exit\@ # Br if no
351     bt      $FLAG_STACK_REENTRY , %esi                 # Check if stack has already been set
352     jc      fam15_skipClearingBit4
353     mov     $HWCR, %ecx                   # MSR C001_0015
354     _RDMSR
355     btr     $INVD_WBINVD, %eax            # disable INVD -> WBINVD conversion
356     _WRMSR
358 fam15_skipClearingBit4:
359         #cz
360       mov     $LS_CFG3, %ecx             # MSR:C001_101C
361       _RDMSR
362       bts     $DIS_SS_F15CZ, %eax        # Turn on Streaming store functionality disabled bit
363       _WRMSR
365       mov     $IC_CFG, %ecx             # MSR:C001_1021
366       _RDMSR
367       bts     $IC_DIS_SPEC_TLB_RLD, %eax  # Turn on Disable speculative IC-TLB reloads bit
368       _WRMSR
370       mov     $LS_CFG3, %ecx            # MSR:C001_101C
371       _RDMSR
372       bts     $DC_DIS_SPEC_TLB_RLD_F15CZ, %eax  # Turn on Disable speculative DC-TLB reloads bit
373       bts     $DC_DIS_HW_PF_F15CZ, %eax
374       _WRMSR
375     # Do CZ enable stack special
377     mov     $CU_CFG, %ecx   #MSR:C001_1023
378     _RDMSR
379     bt      $L2_WAY_LOCK_EN, %eax
380     #.if (!carry?)
381     jc      dofamily15w
382     bts     $L2_WAY_LOCK_EN, %eax
383     or     $L2_FIRST_LOCKED_WAY_OR_MASK, %eax
384     _WRMSR
385     #.endif
387 dofamily15w:  # Do Standard Family 15 work
389     mov     $CU_CFG3, %ecx                # MSR:C001_102B
390     _RDMSR
391     btr     $(COMBINE_CR0_CD - 32), %edx         # Clear CombineCr0Cd bit
392     _WRMSR
394 fam15_enable_stack_hook_exit\@:
395 .endm
397 /*****************************************************************************
399 * AMD_DISABLE_STACK_FAMILY_HOOK_F15 Macro - Stackless
401 *   Return any family specific controls to their 'standard'
402 *   settings for using cache with main memory.
404 * Inputs:
405 *       ESI - [31:24] flags; [15,8]= Node#; [7,0]= core#
406 * Outputs:
407 *       none
409 * Family 15h requirements:
410 *   * INVD or WBINVD
411 *   * MSRC001_0015[INVD_WBINVD]=1
412 *   * MSRC001_1020[DisSS]=0
413 *   * MSRC001_1021[DIS_SPEC_TLB_RLD]=0
414 *   * MSRC001_1022[DIS_SPEC_TLB_RLD]=0
415 *   * MSRC001_1022[DIS_HW_PF]=0
416 *****************************************************************************/
417 .macro  AMD_DISABLE_STACK_FAMILY_HOOK_F15
419     AMD_CPUID   $CPUID_MODEL
420     mov     %eax, %ebx                    # Save revision info to EBX
421     shr     $20, %eax                     # AL = cpu extended family
422     cmp     $0x06, %al                     # Is this family 15h?
423     jnz     fam15_disable_stack_hook_exit\@ # Br if no
425     mov     %ebx, %edi                    # Save revision info to EDI
426     AMD_CPUID  $AMD_CPUID_APIC
427     mov     %cl,  %al                     # AL = number of cores - 1
428     shr     $APIC_ID_CORE_ID_SIZE, %cx    # CL = ApicIdCoreIdSize
429     mov     $1,   %bx
430     shl     %cl,  %bl                     # BL = theoretical number of cores on socket
431     dec     %bx                           # BL = core number on socket mask
432     mov     %bl,  %ah                     # AH = core number on socket mask
433     mov     %edi, %ebx                    # Restore revision info to EBX
434     mov     %ax,  %di                     # DI[15:8] = core number mask, DI[7:0] = number of cores - 1
436     and     $0x0F00FF, %ebx
437     mov     %ebx,  %eax
438     shr     $8,    %eax
439     or      %ax,   %bx                    # Save Extended Model, Model and Stepping to BX
440                                           # [11:8] = Extended Model, [7:4] = Model, [3:0] = Stepping (bx=0000000000010100, ok)
442     mov     $APIC_BASE_ADDRESS, %ecx
443     _RDMSR                                # dx=0 ax=fee00800
444     mov     %bx,  %dx                     # Save Extended Model, Model and Stepping to DX
445     shl     $16,  %edx                    #EDX[31:16] = Extended Model, Model and Stepping
446     mov     %eax ,%ebx                    # EBX = LAPIC base
447     xor     %ecx ,%ecx                    # Zero out CU flags
448     bts     $AMD_CU_NEED_TO_WAIT,  %ecx  # Default to waiting
449     bts     $AMD_CU_SEND_INVD_MSG, %ecx  # Default to signaling
450     mov     %cr0, %eax
451     bt      $CR0_PE, %ax                  # Are we in protected mode?
452     # .if (!carry?)
453     jc      1f
454     bts     $AMD_CU_RESTORE_ES, %ecx  # Indicate ES restore is required
455     mov     %es,   %cx    # Save ES segment register to CX
456     xor     %ax,   %ax
457     mov     %ax,   %es    # Set ES to big real mode selector for 4GB access
458     # .endif
461     and     $0x0F000, %bx                  # EBX = LAPIC base, offset 0
462     or      $APIC_ID_REG, %bl           #
463     mov     %es:(%ebx), %eax               # EAX[31:24] = APIC ID
464     shr     $APIC20_APICID, %eax          # AL = APIC ID
465     mov     %al, %ah                      # AH = APIC ID
466     mov     %di, %dx                      # DH = core mask
467     and     %dh, %ah                      # AH = core number #  ax=111 dx=01000F03
469 //1:    jmp 1b
470     # .if (zero?)
471     jnz      1f
472     #  Core 0 of a socket
473         btr     $AMD_CU_SEND_INVD_MSG, %ecx  # No need to signal after INVD
474         #.if (dl != 0)
475         cmp     $0,  %dl
476         jz      2f
477         # This socket has multiple cores
478         and     $0xf000, %bx            # EBX = LAPIC base, offset 0
479         or      $APIC_MSG_REG, %bx
480         mov     $APIC_MSG,  %edi
481         mov     %edi,  %es:(%ebx)      # Signal for non core 0s to complete CAR breakdown
482         jmp     1f
483         #.else
484 2:      btr     $AMD_CU_NEED_TO_WAIT, %ecx   # No need to wait on a single core CPU
485         #.endif
486     # .endif
489     bt      $AMD_CU_NEED_TO_WAIT, %ecx  #cx = c0000000
490     #.if (carry?)
491     jnc    1f
492         #.if (ah == dl)
493         cmp  %dl,  %ah
494         jnz  2f
495         # This is the highest numbered core on this socket -- wait on core 0
496             not  %dh                       # Flip the mask to determine local core 0's APID ID
497             and   %dh, %al                 # AL = target APIC ID  # ax=310
498         jmp   3f
499 2:      #.else
500         # All other cores (including core 0) wait on the next highest core.
501         # In this way, cores will halt in a cascading fashion down to 0.
502             inc    %al
503         #.endif
505         shl     $APIC20_APICID, %eax
506         and     $0x0F000, %bx
507         or      $APIC_CMD_HI_REG, %bx
508         mov     %eax, %es:(%ebx)          # Set target APIC ID
510         # Use bits 23:16 as a timeout for unresponsive cores
511         ror     $8,  %ecx
512         mov     $0xFF, %ch
513         stc
515         #.while (carry?)
516 5:      jnc     4f
517             and     $0xF000, %bx         #EBX = LAPIC base, offset 0
518             or      $APIC_CMD_LO_REG, %bx # bx = 00000000FEE00300
519             mov     $CMD_REG_TO_READ_DATA, %eax
520             mov     %eax, %es:(%ebx)     #Fire remove read IPI
521             inc     %ch                  #Pre increment the timeout
522             stc
523             #.while (carry?)
524 7:          jnc     6f
525                 dec     %ch                   #Check the timeout
526                 jz      fam15_disable_stack_remote_read_exit\@
527                 mov     %es:(%ebx), %eax      # ax = 0000000000020338
528                 bt      $DELIVERY_STS_BIT, %eax
529             jmp     7b
530 6:          #.endw
531             stc
532             #.while (carry?)
533 7:          jnc     6f
534                 mov     %es:(%ebx), %eax
535                 and     $REMOTE_READ_STS, %eax
536                 #.if (eax == REMOTE_DELIVERY_PEND)
537                     cmp     $REMOTE_DELIVERY_PEND, %eax
538                     jnz      8f
539                     dec     %ch               # Check the timeout
540                     jz      fam15_disable_stack_hook_exit\@ # Branch if there is an unreponsive core
541                     stc
542                 jmp     9f
543 8:              #.else
544                     clc
545 9:              #.endif
546             jmp     7b
547 6:          #.endw
548             #.if (eax == REMOTE_DELIVERY_DONE)
549             cmp     $REMOTE_DELIVERY_DONE, %eax
550             jnz     6f
551                 and     $0x0F000, %bx        #EBX = LAPIC base, offset 0
552                 or      $APIC_REMOTE_READ_REG, %bl
553                 mov     %es:(%ebx), %eax
554                 #.if (eax == APIC_MSG)
555                 cmp     $APIC_MSG, %eax     # ax=00000000FFC5BBB2
556                 jnz     8f
557                     clc
558                 jmp     9f
559                 #.else
560 8:                  stc
561 9:              #.endif
562             jmp     7f
563 6:          #.else
564                 dec     %ch
565                 jz      fam15_disable_stack_remote_read_exit\@
566                 stc
567 7:          #.endif
568         jmp     5b
569 4:      #.endw
571 fam15_disable_stack_remote_read_exit\@:
572         rol   $8, %ecx                 # Restore ECX
574 1:  #.endif
575 #    jmp 1b
576     bt     $AMD_CU_RESTORE_ES,  %ecx
577     #.if (carry?)
578     jnc    1f
579         mov    %cx, %es
581     mov    %ecx,   %edi
582     shr    $16, %edx
583     //mov    %dx,  %bx
585     #Handshaking complete.  Continue tearing down CAR.
588     mov     $LS_CFG3, %ecx                # MSR:C001_101C
589     _RDMSR
590     btr     $DIS_SS_F15CZ, %eax           # Turn on Streaming store functionality
591     _WRMSR
593     mov     $IC_CFG, %ecx                 # MSR:C001_1021
594     _RDMSR
595     btr     $IC_DIS_SPEC_TLB_RLD, %eax    # Turn on speculative TLB reloads
596     _WRMSR
598     mov     $LS_CFG3, %ecx                # MSR:C001_101C
599     _RDMSR
600     btr     $DC_DIS_SPEC_TLB_RLD_F15CZ, %eax  # Turn on speculative TLB reloads
601     btr     $DC_DIS_HW_PF_F15CZ, %eax         # Turn on hardware prefetches
602     _WRMSR
604 #not cz
605 //    mov     $LS_CFG, %ecx                 # MSR:C001_1020
606 //    #.if (bx != 0)              ; Is this OR A0?
607 //    cmp          $0x0, %bx
608 //    jz    0f
609 //    _RDMSR
610 //    btr     $DIS_SS, %eax                 # Turn on Streaming store functionality
611 //    _WRMSR
612 //    #.endif
613 //0:                              # End workaround for errata 495 and 496
615 //    inc     %ecx  #IC_CFG                # MSR:C001_1021
616 //    _RDMSR
617 //    btr     $IC_DIS_SPEC_TLB_RLD, %eax    # Turn on speculative TLB reloads
618 //    _WRMSR
620 //    inc     %ecx  #DC_CFG                # MSR:C001_1022
621 //    _RDMSR
622 //    btr     $DC_DIS_SPEC_TLB_RLD, %eax    # Turn on speculative TLB reloads
623 //    #.if (bx != 0)              # Is this rev A0?
624 //    cmp       $0, %bx
625 //    jz        0f
626 //    btr     $DIS_HW_PF, %eax              # Turn on hardware prefetches
627 //    #.endif                              # End workaround for erratum 498
628 //    0:
629 //    _WRMSR
630 # end of not cz
631     #--------------------------------------------------------------------------
632     # Begin critical sequence in which EAX, BX, ECX, and EDX must be preserved.
633     #--------------------------------------------------------------------------
635     invd
637 #    #.if (bh == 01h) || (bh == 03h)      ; Is this TN or KM?
638 #    cmp   $01, %bh
639 #    jz    4f
640 #    cmp   $03, %bh
641 #    jnz   1f
643     mov   $CU_CFG, %ecx                 # MSR:C001_1023
644     _RDMSR
645     shr   $L2_FIRST_LOCKED_WAY, %eax
646     and   $0x1F,  %eax
647     #.if (eax == 01Fh)
648     cmp   $0x1F,  %eax                  #Check if way 15 of the L2 needs to be reserved
649     jnz   3f
650     _RDMSR
651     btr   $L2_WAY_LOCK_EN, %eax
652     _WRMSR
653 3:  #.endif
655 1:  #.endif
656     #Do Standard Family 15 work
657     mov     $HWCR, %ecx                    # MSR:C001_0015h
658     _RDMSR
659     bts     $INVD_WBINVD, %eax            # Turn on Conversion of INVD to WBINVD
660     _WRMSR
661     #.endif                              # end
662     0:
664 //    #--------------------------------------------------------------------------
665 //    # End critical sequence in which EAX, BX, ECX, and EDX must be preserved.
666 //    #--------------------------------------------------------------------------
668     mov     $CU_CFG3, %ecx                # MSR:C001_102B
669     _RDMSR
670     bts     $(COMBINE_CR0_CD - 32), %edx         # Set CombineCr0Cd bit
671     _WRMSR
673     bt      $AMD_CU_SEND_INVD_MSG, %edi
674     #.if (carry?)
675     jnc     1f
676     # Non core zero needs to signal to core 0 to proceed
677     mov     $APIC_BASE_ADDRESS, %ecx
678     _RDMSR
679     mov     %eax, %ebx                # EBX = LAPIC base
680     and     $0x0F000, %bx              # EBX = LAPIC base, offset 0
681     or      $APIC_MSG_REG, %bx
682     mov     $APIC_MSG, %eax
683     mov     %eax, %es:(%ebx)           # Signal for core 0 to complete CAR breakdown
685 1:  #.endif
687 fam15_disable_stack_hook_exit\@:
688 .endm
690 /*****************************************************************************
692 * GET_NODE_ID_CORE_ID_F15 Macro - Stackless
694 *   Read family specific values to determine the node and core
695 *   numbers for the core executing this code.
697 * Inputs:
698 *     none
699 * Outputs:
700 *     SI = core#, node# & flags (see GET_NODE_ID_CORE_ID macro above)
701 *****************************************************************************/
702 .macro  GET_NODE_ID_CORE_ID_F15
705 #define F15_L2Size      512
706 #define F15_ShareCores  2
707 #define F15_AllocMem    0
708 #define F15_AllocExe    0
709 #define F15_SzAddrBus   48
710 #define F15_pad         0
711     cmp     $-1, %si                      # Has node/core already been discovered?
712     jnz     node_core_f15_exit\@          # Br if yes
714     AMD_CPUID   $CPUID_MODEL
715     shr     $12, %eax                     # AL = cpu extended family
716     cmp     $06, %ah                     # Is this family 15h?
717     jnz     node_core_f15_exit\@          # Br if no
718     shr     $4,  %al                     # AL = cpu extended model
719     shr     $16, %ebx                    # BH = LocalApicId
720     mov     %al, %bl                     # BL = cpu extended model
722     # LoadTableAddress(FAM15H_INFO_STRUCT)
723     # movd    mm5, eax                    # load pointer to Family Info Struc
725     xor     %esi, %esi                    # Assume BSC, clear local flags
726     mov     $APIC_BASE_ADDRESS, %ecx      # MSR:0000_001B
727     _RDMSR
728     bt      $APIC_BSC, %eax               # Is this the BSC?
729     jnc      node_core_f15_AP\@            # Br if no
731     # This is the BSP.
732     # Enable routing tables on BSP (just in case the HT init code has not yet enabled them)
733     mov     $0x8000C06C, %eax              # PCI address for D18F0x6C Link Initialization Control Register
734     mov     $0x0CF8, %dx
735     out     %eax, %dx
736     add     $4, %dx
737     in      %dx, %eax
738     btr     $0, %eax                      # Set LinkInitializationControl[RouteTblDis] = 0
739     out     %eax, %dx
740     jmp     node_core_f15_shared\@        #
742 node_core_f15_AP\@:
743 //1:    jmp 1b   # not crash
744     mov     %bl, %al                        # AL = cpu extended model
745     shr     $8,  %bx                        # BL = CPUID Fn0000_0001_EBX[LocalApicId]
746 //    cmp    $1,  %al                        # Is This TN?
747 //    jz     4f
748 //    cmp    $3,  %al
749 //    jnz    node_core_f15_AP_not_TN\@
750     mov     %bx, %si
751     jmp     node_core_f15_shared\@
752     #
753     # This is an AP. Routing tables have been enabled by the HT Init process.
754     # Also, the MailBox register was set by the BSP during early init
755     #   The Mailbox register content is formatted as follows:
756     #         UINT32 Node:4;          // The node id of Core's node.
757     #         UINT32 Socket:4;        // The socket of this Core's node.
758     #         UINT32 Module:2;        // The internal module number for Core's node.
759     #         UINT32 ModuleType:2;    // Single Module = 0, Multi-module = 1.
760     #         UINT32 :20;             // Reserved
761     #
762 #node_core_f15_AP_not_TN\@:
763 #    mov     $0x0C0000408, %ecx             # Read the family 15h mailbox
764 #    _RDMSR                              #      MC4_MISC1[63:32]
765 #    mov     %dx, %si                      # SI = raw mailbox contents (will extract node# from this)
766 #    shr     $24, %ebx                     # BL = CPUID Fn0000_0001_EBX[LocalApicId]
767 #    mov     %bx, %di                      # DI = Initial APIC ID (will extract core# from this)
769 #    AMD_CPUID   $AMD_CPUID_APIC          #
770 #    shr     $4, %ch                       # CH = ApicIdSize, #bits in APIC ID that show core#
771 #    inc     %cl                          # CL = Number of enabled cores in the socket
772 #    mov     %cx, %bx
774 #    mov     $NB_CFG, %ecx
775 #    _RDMSR                              # EDX has InitApicIdCpuIdLo bit
777 #    mov     %bh, %cl                      # CL = APIC ID size
778 #    mov     $1, %al                       # Convert APIC ID size to an AND mask
779 #    shl     %cl, %al                      # AL = 2^APIC ID size
780 #    dec     %al                          # AL = mask for relative core number
781 #    xor     %ah, %ah                      # AX = mask for relative core number
782 #    bt      $(INIT_APIC_ID_CPU_ID_LO-32), %edx # InitApicIdCpuIdLo == 1?
783 #    #.if (!carry?)                       # Br if yes
784 #    jc      0f
785 #        mov     $8, %ch                   # Calculate core number shift count
786 #        sub     %cl, %ch                  # CH = core shift count
787 #        mov     %ch, %cl
788 #        shr     %cl, %di                  # Right justify core number
789 #    #.endif
790 #    0:
791 #    and     %ax, %di                      # DI = socket-relative core number
793 #    mov     %si, %cx                      # CX = raw mailbox value
794 #    shr     $10, %cx                      # CL[1:0] = ModuleType or #nodes per socket (0-SCM, 1-MCM)
795 #    and     $3, %cl                       # Isolate ModuleType
796 #    xor     %bh, %bh                      # BX = Number of enabled cores in the socket
797 #    shr     %cl, %bx                      # BX = Number of enabled cores per node
798 #    xor     %dx, %dx                      # Clear upper word for div
799 #    mov     %di, %ax                      # AX = socket-relative core number
800 #    div     %bx                          # DX = node-relative core number
801 #    movzx   %si, %eax                     # Prepare return value
802 #    and     $0x000F, %ax                   # AX = node number
803 #    shl     $8,%ax                       # [15:8]=node#
804 #    mov     %dl, %al                      # [7:0]=core# (relative to node)
805 #    mov     %eax, %esi                    # ESI = node-relative core number
807       #
808       #   determine if this core shares MTRRs
809       #
810 node_core_f15_shared\@:
811     mov     $0x8000C580, %eax              # Compute Unit Status
812     mov     %si, %bx
813     shl     $3, %bh                       # Move node# to PCI Dev# field
814     add     %bh, %ah                      # Adjust for node number
815     mov     $0x0CF8, %dx
816     out     %eax, %dx
817     add     $4, %dx
818     in      %dx, %eax                     # [3:0]=Enabled# [19:16]=DualCore
820                                         # BL is MyCore#
821     mov     $0x08, %cx                     # Use CH as 'first of pair' core#
822     #.while (cl > 0)
823     jmp  0f
824     8:
825         bt      $0, %eax                  # Is pair enabled?
826         #.if (carry?)                    #
827         jnc     1f
828             mov     $0x01, %bh             #   flag core as primary
829             bt      $16, %eax             # Is there a 2nd in the pair?
830             #.if (carry?)                #
831             jnc 4f
832                 #.break .if (ch == bl)   # Does 1st match MyCore#?
833                 cmp     %bl, %ch
834                 je      9f
835                 inc     %ch
836                 xor     %bh, %bh          #     flag core as NOT primary
837                 #.break .if (ch == bl)   # Does 2nd match MyCore#?
838                 cmp     %bl, %ch
839                 je      9f
840                 jmp     2f
841             #.else                       # No 2nd core
842             4:
843                 #.break .if (ch == bl)   # Does 1st match MyCore#?
844                 cmp     %bl, %ch
845                 je      9f
846             #.endif
847             2:
848             inc     %ch
849         #.endif
850         1:
851         shr     $1, %eax
852         dec     %cl
853     #.endw
854     0:
855     #.if (cl == 0)
856     cmp $0x0, %cl
857     ja  8b
858     9:
859     or  %cl, %cl
860     jne 1f
861         #Error - core# didn't match Compute Unit Status content
862         bts     $FLAG_CORE_NOT_IDENTIFIED, %esi
863         bts     $FLAG_IS_PRIMARY, %esi    #   Set Is_Primary for unknowns
864     #.endif
865     1:
866     #.if (bh != 0)                       # Check state of primary for the matched core
867     or %bh, %bh
868     je 2f
869         bts     $FLAG_IS_PRIMARY, %esi    #   Set shared flag into return value
870     #.endif
871     2:
873 node_core_f15_exit\@:
875 .endm
877 /*****************************************************************************
878 * AMD_ENABLE_STACK:  Setup a stack
880 *   In:
881 *       No inputs
883 *   Out:
884 *       SS:ESP - Our new private stack location
886 *       EAX = AGESA_STATUS
888 *       ECX = Stack size in bytes
890 *   Requirements:
891 *       * This routine presently is limited to a max of 64 processor cores
892 *   Destroyed:
893 *       EBX, EDX, EDI, ESI, EBP, DS, ES
895 *   Description:
896 * Fixed MTRR address allocation to cores:
897 * The BSP gets 64K of stack, Core0 of each node gets 16K of stack, all other cores get 4K.
898 * There is a max of 1 BSP, 7 core0s and 56 other cores.
899 * Although each core has it's own cache storage, they share the address space. Each core must
900 * be assigned a private and unique address space for its stack. To support legacy systems,
901 * the stack needs to be within the legacy address space (1st 1Meg). Room must also be reserved
902 * for the other legacy elements (Interrupt vectors, BIOS ROM, video buffer, etc.)
904 * 80000h                                        40000h                                      00000h
905 *     +----------+----------+----------+----------+----------+----------+----------+----------+
906 * 64K |          |          |          |          |          |          |          |          |  64K  ea
907 *  ea +----------+----------+----------+----------+----------+----------+----------+----------+
908 *     |                             MTRR 0000_0250 MTRRfix64K_00000                           |
909 *     +----------+----------+----------+----------+----------+----------+----------+----------+
910 *     |  7 ,  6  |  5 ,  4  |  3 ,  2  |  1 ,  0  |     0    |          |          |          | <-node
911 *     |7..1,7..1 |7..1,7..1 |7..1,7..1 |7..1,7..1 |     0    |          |          |          | <-core
912 *     +----------+----------+----------+----------+----------+----------+----------+----------+
914 * C0000h                       B0000h                      A0000h                      90000h                      80000h
915 *     +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
916 *16K  |      |      |      |      |      |      |      |      |      |      |      |      |      |      |      |      |
917 * ea  +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
918 *     |              MTRR 0259 MTRRfix16K_A0000               |             MTRR 0258 MTRRfix16K_80000                |
919 *     +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
920 *     | > Dis|play B|uffer |   <  |      |      |      |      |   7  |  6   |  5   |  4   |  3   |  2   |  1   |      | <-node
921 *     | >   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
922 *     +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
924 * E0000h                                            D0000h                                         C0000h
925 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
926 * 4K  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  4K  ea
927 *  ea +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
928 *     |  026B MTRRfix4K_D8000 | 026A MTRRfix4K_D0000  | 0269 MTRRfix4K_C8000  | 0268 MTRRfix4K_C0000  |
929 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
930 *     |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | >| V| I| D| E| O|  |B |I |O |S |  |A |r |e |a<|
931 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
933 * 100000h                                           F0000h                                          E0000h
934 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
935 *     |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  4K  ea
936 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
937 *     |  026F MTRRfix4K_F8000 | 026E MTRRfix4K_F0000  | 026D MTRRfix4K_E8000  | 026C MTRRfix4K_E0000  |
938 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
939 *     | >|MA|IN| B|IO|S |RA|NG|E |  |  |  |  |  |  |< | >|EX|TE|ND|ED| B|IO|S |ZO|NE|  |  |  |  |  |< |
940 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
941 *****************************************************************************/
942 .macro  AMD_ENABLE_STACK
944 # These are local labels. Declared so linker doesn't cause 'redefined label' errors
946 #   Note that SS:ESP will be default stack.  Note that this stack
947 #   routine will not be used after memory has been initialized.  Because
948 #   of its limited lifetime, it will not conflict with typical PCI devices.
950     # get node id and core id of current executing core
951     GET_NODE_ID_CORE_ID                 # Sets ESI[23:16]=Shared core## SI[15,8]= Node## SI[7,0]= core# (relative to node)
952     # Note: ESI[31:24] are used for flags:  Unrecognized Family,  Is_Primary core,  Stack already established
954     # determine if stack is already enabled. We are using the DefType MSR for this determination.
955     # It is =0 after reset; CAR setup sets it to enable the MTRRs
956     mov     %cr0, %eax
957     test    $CR0_MASK, %eax              # Is cache disabled? (CD & NW bits)
958     jnz     SetupStack\@                  # Jump if yes
959     mov     $AMD_MTRR_DEFTYPE, %ecx       # MSR:0000_02FF
960     _RDMSR
961     test    $MSR_MASK, %eax                     # Are the default types enabled? (MTRR_DEF_TYPE_EN + MTRR_DEF_TYPE_FIX_EN)
962     jz      SetupStack\@                  # Jump if no
963     or      $FLAG_STACK_REENTRY, %esi             # Bit25, indicate stack has already been initialized
965 SetupStack\@:
966     # Set node to map the first 16MB to node 0# 0000_0000 to 00FF_FFFF as DRAM
967     mov     %esi, %ebx                    # Get my Node/Core info
968     xor     %bl, %bl
969     shl     $3, %bh                       # Isolate my node#, match alignment for PCI Dev#
970     mov     $0x8000C144, %eax              # D18F1x44:DRAM Base/Limit# N is Base, N+4 is Limit
971     add     %bh, %ah
972     mov     %eax, %ebx                    # Save PCI address for Base/Limit pair
974     mov     $0x0CF8, %dx
975     out     %eax, %dx
976     add     $4, %dx
977     xor     %eax, %eax                    # Least Significant bit is AD24 so 0 sets mask of 00FF_FFFF (16MB)
978     out     %eax, %dx                     # DRAM Limit = node0, no interleave
980     mov     %ebx, %eax
981     sub     $4, %eax                      # Now point to the Base register
982     mov     $0x0CF8, %dx
983     out     %eax, %dx
984     add     $4, %dx
985     mov     $0x00000003, %eax              # Set the read and write enable bits
986     out     %eax, %dx                     # DRAM Base = 0x0000, R/W
988     AMD_ENABLE_STACK_FAMILY_HOOK
990     # Init CPU MSRs for our init routines
991     mov     $MTRR_SYS_CFG, %ecx           # SYS_CFG
992     _RDMSR
993     bts     $MTRR_FIX_DRAM_MOD_EN, %eax   # Turn on modification enable bit
994     _WRMSR
996     mov     %esi, %eax
997     bt      $FLAG_STACK_REENTRY, %eax     # Is this a 2nd entry?
998     #.if (!carry?)                       #   On a re-entry, do not clear MTRRs or reset TOM; just reset the stack SS:ESP
999     jc 0f
1000         bt      $FLAG_IS_PRIMARY, %eax    #   Is this core the primary in a compute unit?
1001         #.if (carry?)                    #     Families using shared groups do not need to clear the MTRRs since that is done at power-on reset
1002             #  Note: Relying on MSRs to be cleared to 0's at reset for families w/shared cores
1003             # Clear all variable and Fixed MTRRs for non-shared cores
1004         jnc 0f
1005         mov     $AMD_MTRR_VARIABLE_BASE0, %ecx
1006         xor     %eax, %eax
1007         xor     %edx, %edx
1008         #.while (cl != 10h)                  # Variable MTRRphysBase[n] and MTRRphysMask[n]
1009         jmp     1f
1010         2:
1011             _WRMSR
1012             inc     %cl
1013         #.endw
1014         1:
1015         cmp     $0x10, %cl
1016         jne     2b
1017         mov     $AMD_MTRR_FIX64k_00000, %cx   # MSR:0000_0250
1018         _WRMSR
1019         mov     $AMD_MTRR_FIX16k_80000, %cx   # MSR:0000_0258
1020         _WRMSR
1021         mov     $AMD_MTRR_FIX16k_A0000, %cx   # MSR:0000_0259
1022         _WRMSR
1023         mov     $AMD_MTRR_FIX4k_C0000, %cx    # Fixed 4Ks: MTRRfix4K_C0000 to MTRRfix4K_F8000
1024         #.while (cl != 70h)
1025         jmp 3f
1026         4:
1027             _WRMSR
1028             inc     %cl
1029         #.endw
1030         3:
1031         cmp $0x70, %cl
1032         jne  4b
1033         # Set TOP_MEM (C001_001A) for non-shared cores to 16M. This will be increased at heap init.
1034         #  - not strictly needed since the FixedMTRRs take presedence.
1035         mov     $(16 * 1024 * 1024), %eax
1036         mov     $TOP_MEM, %ecx            # MSR:C001_001A
1037         _WRMSR
1038         #.endif                          #   End Is_Primary
1039     #.endif                              # End Stack_ReEntry
1040     0:
1041     # Clear IORRs (C001_0016-19) and TOM2(C001_001D) for all cores
1042     xor     %eax, %eax
1043     xor     %edx, %edx
1044     mov     $IORR_BASE, %ecx              # MSR:C001_0016 - 0019
1045     #.while (cl != 1Ah)
1046     jmp  1f
1047     2:
1048         _WRMSR
1049         inc     %cl
1050     #.endw
1051     1:
1052     cmp $0x1A, %cl
1053     jne  2b
1054     mov     $TOP_MEM2, %ecx               # MSR:C001_001D
1055     _WRMSR
1057     # setup MTRRs for stacks
1058     #   A speculative read can be generated by a speculative fetch mis-aligned in a code zone
1059     #    or due to a data zone being interpreted as code. When a speculative read occurs outside a
1060     #    controlled region (intentionally used by software), it could cause an unwanted cache eviction.
1061     #   To prevent speculative reads from causing an eviction, the unused cache ranges are set
1062     #    to UC type. Only the actively used regions (stack, heap) are reflected in the MTRRs.
1063     #    Note: some core stack regions will share an MTRR since the control granularity is much
1064     #    larger than the allocated stack zone. The allocation algorithm must account for this 'extra'
1065     #    space covered by the MTRR when parseling out cache space for the various uses. In some cases
1066     #    this could reduce the amount of EXE cache available to a core. see cpuCacheInit.c
1067     #
1068     # Outcome of this block is that:   (Note the MTRR map at the top of the file)
1069     #   ebp - start address of stack block
1070     #   ebx - [31:16] - MTRR MSR address
1071     #       - [15:8]  - slot# in MTRR register
1072     #       - [7:0]   - block size in #4K blocks
1073     # review: ESI[31:24]=Flags; SI[15,8]= Node#; SI[7,0]= core# (relative to node)
1074     #
1076     mov     %esi, %eax                      # Load Flags,node, core
1077     #.if (al == 0)                       # Is a core 0?
1078     or %al, %al
1079     jne 1f
1080         #.if (ah == 0)                   # Is Node 0? (BSP)
1081         or %ah, %ah
1082         jne 2f
1083             # Is BSP, assign a 64K stack
1084             mov     $((AMD_MTRR_FIX64k_00000 << 16) + (3 << 8) + (BSP_STACK_SIZE  >> 12)), %ebx
1085             bt      $FLAG_FORCE_32K_STACK, %eax
1086             jnc w64k_here            # Br if no
1087             mov     $((AMD_MTRR_FIX64k_00000 << 16) + (3 << 8) + (BSP_STACK_SIZE_32K  >> 12)), %ebx
1088 w64k_here:
1089             mov     $BSP_STACK_BASE_ADDR, %ebp
1090             jmp     0f
1091         #.else   # node 1 to 7, core0
1092         2:
1093             # Is a Core0 of secondary node, assign 16K stacks
1094             mov     $AMD_MTRR_FIX16k_80000, %bx
1095             shl     $16, %ebx             #
1096             dec     %ah                  #index from 0
1097             mov     %ah, %bh              # Node# is used as slot#
1098             mov     $(CORE0_STACK_SIZE >> 12), %bl
1099             mov     %ah, %al              # Base = (Node# * Size)#
1100             mul     %bl                  #
1101             movzx   %ax, %eax             #
1102             shl     $12, %eax             # Expand back to full byte count (* 4K)
1103             add     $CORE0_STACK_BASE_ADDR, %eax
1104             mov     %eax, %ebp
1105         #.endif
1106         jmp 0f
1107     #.else    #core 1 thru core 7
1108     1:
1109         # Is core 1-7 of any node, assign 4K stacks
1110         mov     $8, %al                   # CoreIndex = ( (Node# * 8) ...
1111         mul     %ah                      #
1112         mov     %si, %bx                  #
1113         add     %bl, %al                  #         ...  + Core#)#
1115         mov     $AMD_MTRR_FIX64k_00000, %bx
1116         shl     $16, %ebx                 #
1117         mov     %al, %bh                  # Slot# = (CoreIndex / 16) + 4#
1118         shr     $4, %bh                   #
1119         add     $4, %bh                   #
1120         mov     $(CORE1_STACK_SIZE >> 12), %bl
1122         mul     %bl                      # Base = ( (CoreIndex * Size) ...
1123         movzx   %ax, %eax                 #
1124         shl     $12, %eax                 # Expand back to full byte count (* 4K)
1125         add     $CORE1_STACK_BASE_ADDR, %eax #     ...   + Base_Addr)#
1126         mov     %eax, %ebp
1127     #.endif
1128     0:
1130     # Now set the MTRR. Add this to already existing settings (don't clear any MTRR)
1131     mov     $WB_DRAM_TYPE, %edi           # Load Cache type in 1st slot
1132     mov     %bh, %cl                      # ShiftCount =  ((slot#   ...
1133     and     $0x03, %cl                     #   ...  % 4)             ...
1134     shl     $0x03, %cl                       #   ...  * 8)#
1135     shl     %cl, %edi                     # Cache type is now in correct position
1136     ror     $16, %ebx                     # Get the MTRR address
1137     movzx   %bx, %ecx                     #
1138     rol     $16, %ebx                     # Put slot# & size back in BX
1139     _RDMSR                              # Read-modify-write the MSR
1140     #.if (bh < 4)                        # Is value in lower or upper half of MSR?
1141     cmp $4, %bh
1142     jae 1f
1143         or      %edi, %eax                #
1144         jmp     0f
1145     #.else
1146     1:                               #
1147         or      %edi, %edx                #
1148     #.endif                              #
1149     0:
1150     _WRMSR                              #
1152     # All cores must see BSP stack region that is also used to
1153     # communicate global variables before DRAM is up.
1154     mov     $AMD_MTRR_FIX64k_00000, %ecx  # MSR:0000_0250
1155     _RDMSR
1156     or      $0x1e000000, %eax
1157     _WRMSR
1159     # Enable MTRR defaults as UC type
1160     mov     $AMD_MTRR_DEFTYPE, %ecx       # MSR:0000_02FF
1161     _RDMSR                              # Read-modify-write the MSR
1162     bts     $MTRR_DEF_TYPE_EN, %eax       # MtrrDefTypeEn
1163     bts     $MTRR_DEF_TYPE_FIX_EN, %eax   # MtrrDefTypeFixEn
1164     _WRMSR
1166     # Close the modification window on the Fixed MTRRs
1167     mov     $MTRR_SYS_CFG, %ecx           # MSR:0C001_0010
1168     _RDMSR
1169     bts     $MTRR_FIX_DRAM_EN, %eax       # MtrrFixDramEn
1170     bts     $MTRR_VAR_DRAM_EN, %eax       # variable MTRR enable bit
1171     btr     $MTRR_FIX_DRAM_MOD_EN, %eax   # Turn off modification enable bit
1172     _WRMSR
1174     # Enable caching in CR0
1175     mov     %cr0, %eax                    # Enable WT/WB cache
1176     btr     $CR0_PG, %eax                     # Make sure paging is disabled
1177     btr     $CR0_CD, %eax                     # Clear CR0 NW and CD
1178     btr     $CR0_NW, %eax
1179     mov     %eax, %cr0
1181     # Use the Stack Base & size to calculate SS and ESP values
1182     # review:
1183     #       esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
1184     #       ebp - start address of stack block
1185     #       ebx - [31:16] - MTRR MSR address
1186     #           - [15:8]  - slot# in MTRR register
1187     #           - [7:0]   - block size in #4K blocks
1188     #
1189     mov     %ebp, %esp                    # Initialize the stack pointer
1190     mov     %esp, %edi                    # Copy the stack start to edi
1191     movzx   %bl, %bx
1192     movzx   %bx, %ebx                     # Clear upper ebx, don't need MSR addr anymore
1193     shl     $12, %ebx                     # Make size full byte count (* 4K)
1194     add     %ebx, %esp                    # Set the Stack Pointer as full linear address
1195     sub     $4, %esp
1196     #
1197     # review:
1198     #       esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
1199     #       edi - 32b start address of stack block
1200     #       ebx - size of stack block
1201     #       esp - 32b linear stack pointer
1202     #
1204     # Determine mode for SS base;
1205     mov     %cr0, %ecx                    # Check for 32-bit protect mode
1206     bt      $CR0_PE, %ecx                 #
1207     #.if (!carry?)                       # PE=0 means real mode
1208     jc      Protected32Mode\@
1209     mov     %cs, %cx                      # PE=1
1210     cmp     $0x0D000, %cx                  # Check for CS
1211     jb      Protected32Mode\@             # If CS < D000, it is a selector instead of a segment
1212             # alter SS:ESP for 16b Real Mode:
1213 Real16bMode\@:
1214     mov     %edi, %eax
1215     shr     $4, %eax                      # Create a Real Mode segment for ss, ds, es
1216     mov     %ax, %ss
1217     mov     %ax, %ds
1218     mov     %ax, %es
1219     shl     $4, %eax
1220     sub     %eax, %edi                    # Adjust the clearing pointer for Seg:Offset mode
1221     mov     %ebx, %esp                    # Make SP an offset from SS
1222     sub     $4, %esp              #
1223     #    .endif                          # endif
1224     # #else
1225     #   Default is to use Protected 32b Mode
1226     #.endif
1227     ;
1228 Protected32Mode\@:
1229     #
1230     # Clear The Stack
1231     #   Now that we have set the location and the MTRRs, initialize the cache by
1232     #   reading then writing to zero all of the stack area.
1233     # review:
1234     #       ss  - Stack base
1235     #       esp - stack pointer
1236     #       ebx - size of stack block
1237     #       esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
1238     #       edi -  address of start of stack block
1239     #
1241 ClearTheStack\@:                          # Stack base is in SS, stack pointer is in ESP
1242     shr     $2, %ebx                      # ebx = stack block size in dwords
1243     mov     %bx, %cx                      #
1244     # Check our flags - Don't clear an existing stack
1245     #.if ( !(esi & 0FF000000h))          # Check our flags
1246     test    $(1 << FLAG_STACK_REENTRY), %esi
1247     jne 1f
1248         cld
1249         mov     %edi, %esi
1250         rep     lodsl (%esi)    # Pre-load the range
1251         xor     %eax, %eax
1252         mov     %bx, %cx
1253         mov     %edi, %esi                # Preserve base for push on stack
1254         rep     stosl (%edi)    # Clear the range
1255         movl     $0x0ABCDDCBA, (%esp) # Put marker in top stack dword
1256         shl     $2, %ebx                  # Put stack size and base
1257         push    %ebx                     #  in top of stack
1258         push    %esi
1260         mov     %ebx, %ecx                # Return size of stack in bytes
1261         xor     %eax, %eax                # eax = 0 : no error return code
1262         jmp     0f
1263     #.else
1264     1:
1265         movzx   %cx, %ecx
1266         shl     $2, %ecx                  # Return size of stack in bytes
1267         mov     %esi, %eax
1268         shr     $24, %eax                 # Keep the flags as part of the error report
1269         or      $0x40000000, %eax          # eax = AGESA_WARNING (Stack has already been set up)
1270     #.endif
1271     0:
1272 .endm
1274 /*****************************************************************************
1275 * AMD_DISABLE_STACK:
1277 *   In:
1278 *       none
1280 *   Out:
1281 *       none
1283 *   Preserved:
1284 *       ESP
1285 *   Destroyed:
1286 *       EAX, EBX, ECX, EDX, EDI, ESI
1287 *****************************************************************************/
1288 .macro  AMD_DISABLE_STACK
1290     # get node/core/flags of current executing core
1291     GET_NODE_ID_CORE_ID                 # Sets ESI[15,8]= Node#; ESI[7,0]= core# (relative to node)
1292 #1:      jmp 1b
1293     # Turn on modification enable bit
1294     mov     $MTRR_SYS_CFG, %ecx           # MSR:C001_0010
1295     _RDMSR
1296     bts     $MTRR_FIX_DRAM_MOD_EN, %eax   # Enable modifications
1297     _WRMSR
1299     # Set lower 640K MTRRs for Write-Back memory caching
1300     mov     $AMD_MTRR_FIX64k_00000, %ecx
1301     mov     $0x1E1E1E1E, %eax
1302     mov     %eax, %edx
1303     _WRMSR                              # 0 - 512K = WB Mem
1304     mov     $AMD_MTRR_FIX16k_80000, %ecx
1305     _WRMSR                              # 512K - 640K = WB Mem
1307     # Turn off modification enable bit
1308     mov     $MTRR_SYS_CFG, %ecx           # MSR:C001_0010
1309     _RDMSR
1310     btr     $MTRR_FIX_DRAM_MOD_EN, %eax   # Disable modification
1311     _WRMSR
1313     AMD_DISABLE_STACK_FAMILY_HOOK       # Re-Enable 'normal' cache operations
1315 .endm