S3 code whitespaces changes.
[coreboot.git] / src / vendorcode / amd / agesa / f14 / gcccar.inc
1 /*
2  * Copyright (c) 2011, Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
13  *       its contributors may be used to endorse or promote products derived
14  *       from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28
29 /******************************************************************************
30 * AMD Generic Encapsulated Software Architecture
31 *
32 * $Workfile:: GccCar.inc    $Revision:: 32932   $
33 *
34 * Description: GccCar.inc - AGESA cache-as-RAM setup Include File for GCC complier
35 *
36 ******************************************************************************/
37
38 .altmacro
39
40 BSP_STACK_BASE_ADDR     =       0x30000         /* Base address for primary cores stack   */                             
41 BSP_STACK_SIZE          =       0x10000         /* 64KB for BSP core                      */                                               
42 CORE0_STACK_BASE_ADDR   =       0x80000         /* Base address for primary cores stack   */                             
43 CORE0_STACK_SIZE        =       0x4000          /* 16KB for primary cores                 */                                          
44 CORE1_STACK_BASE_ADDR   =       0x40000         /* Base address for AP cores              */                                           
45 CORE1_STACK_SIZE        =       0x1000          /* 4KB for each AP cores                  */                                               
46                                                                                                              
47 APIC_BASE_ADDRESS       =       0x0000001B                                                                       
48   APIC_BSC              =       8               /* Boot Strap Core  */                                                  
49                                                                                                              
50 AMD_MTRR_VARIABLE_BASE0  =      0x0200                                                                          
51 AMD_MTRR_VARIABLE_BASE6  =      0x020C                                                                          
52 AMD_MTRR_FIX64k_00000    =      0x0250                                                                          
53 AMD_MTRR_FIX16k_80000    =      0x0258                                                                          
54 AMD_MTRR_FIX16k_A0000    =      0x0259                                                                          
55 AMD_MTRR_FIX4k_C0000     =      0x0268                                                                          
56 AMD_MTRR_FIX4k_C8000     =      0x0269                                                                          
57 AMD_MTRR_FIX4k_D0000     =      0x026A                                                                          
58 AMD_MTRR_FIX4k_D8000     =      0x026B                                                                          
59 AMD_MTRR_FIX4k_E0000     =      0x026C                                                                          
60 AMD_MTRR_FIX4k_E8000     =      0x026D                                                                          
61 AMD_MTRR_FIX4k_F0000     =      0x026E                                                                          
62 AMD_MTRR_FIX4k_F8000     =      0x026F                                                                          
63                                                                                                              
64 AMD_MTRR_DEFTYPE         =      0x02FF                                                                            
65     WB_DRAM_TYPE         =      0x1E             /* MemType - memory type */                                           
66     MTRR_DEF_TYPE_EN     =      11               /* MtrrDefTypeEn - variable and fixed MTRRs default enabled */          
67     MTRR_DEF_TYPE_FIX_EN =      10               /* MtrrDefTypeEn - fixed MTRRs default enabled */                        
68                                                                                                              
69 HWCR                     =      0x0C0010015      /* Hardware Configuration                                                                                                                                       */                                             
70     INVD_WBINVD          =      0x04             /* INVD to WBINVD conversion */                                         
71                                                                                                              
72 IORR_BASE                =      0x0C0010016      /* IO Range Regusters Base/Mask, 2 pairs */                              
73                                                  /*  uses 16h - 19h                                                                                                                                                             */                                                   
74 TOP_MEM                  =      0x0C001001A      /* Top of Memory                                                                                                                                                                                */                                                      
75 TOP_MEM2                 =      0x0C001001D      /* Top of Memory2                                                                                                                                                                       */                                                    
76                                                                                                              
77 LS_CFG                   =      0x0C0011020      /* Load-Store Configuration                                                                                                                             */                                           
78     DIS_SS               =     28                /* Family 10h,12h,15h:Disable Streng Store functionality */         
79     DIS_STREAM_ST        =     28                /* Family 14h:DisStreamSt - Disable Streaming Store functionality */   
80                                                                                                              
81 IC_CFG                   =      0x0C0011021      /* Instruction Cache Config Register  */                                 
82     IC_DIS_SPEC_TLB_RLD  =      9                /*   Disable speculative TLB reloads  */                                 
83     DIS_IND              =      14               /*   Family 10-14h:Disable Indirect Branch Predictor */                  
84     DIS_I_CACHE          =      14               /*   Family 15h:DisICache - Disable Indirect Branch Predictor */         
85                                                                                                              
86 DC_CFG                   =      0x0C0011022      /* Data Cache Configuration                                                                                                                                   */                                           
87     DC_DIS_SPEC_TLB_RLD      =  4                /*   Disable speculative TLB reloads */                                  
88     DIS_CLR_WBTOL2_SMC_HIT   =  8                /*   self modifying code check buffer bit */                              
89     DIS_HW_PF                =  13               /*   Hardware prefetches bit                                                                                                                                    */                                          
90                                                                                                              
91 DE_CFG                   =      0x0C0011029      /* Decode Configuration */                                               
92     CL_FLUSH_SERIALIZE   =      23               /*   Family 12h,15h: CL Flush Serialization */                           
93                                                                                                              
94 BU_CFG2                  =      0x0C001102A      /* Family 10h: Bus Unit Configuration 2 */                           
95 CU_CFG2                  =      0x0C001102A      /* Family 15h: Combined Unit Configuration 2 */                           
96     F10_CL_LINES_TO_NB_DIS  =   15               /*   ClLinesToNbDis - allows WP code to be cached in L2 */               
97     IC_DIS_SPEC_TLB_WR      =   35               /*   IcDisSpecTlbWr - ITLB speculative writes */                        
98                                                                                                              
99 CU_CFG3                  =      0x0C001102B      /* Combined Unit Configuration 3 */                                      
100     COMBINE_CR0_CD       =      49               /*   Combine CR0.CD for both cores of a compute unit */                  
101                                                                                                              
102                                                                                                              
103 CR0_PE                  = 1           # Protection Enable
104 CR0_NW                  = 29          # Not Write-through
105 CR0_CD                  = 30          # Cache Disable
106 CR0_PG                  = 31          # Paging Enable
107                                                                                                              
108 /* CPUID Functions */                                                                                            
109                                                                                                              
110 CPUID_MODEL              =      1                                                                                
111 AMD_CPUID_FMF            =      0x80000001       /* Family Model Features information */                                  
112 AMD_CPUID_APIC           =      0x80000008       /* Long Mode and APIC info., core count */                         
113                                                                                                            
114 NB_CFG                   =      0x0C001001F      /* Northbridge Configuration Register */                            
115     INIT_APIC_ID_CPU_ID_LO    = 54               /*  InitApicIdCpuIdLo - is core# in high or low half of APIC ID? */    
116                                                                                                              
117 MTRR_SYS_CFG             =      0x0C0010010      /* System Configuration Register */                                      
118   CHX_TO_DIRTY_DIS       =      16               /*   ChxToDirtyDis    Change to dirty disable  */                        
119   SYS_UC_LOCK_EN         =      17               /*   SysUcLockEn      System lock command enable */                    
120   MTRR_FIX_DRAM_EN       =      18               /*   MtrrFixDramEn    MTRR fixed RdDram and WrDram attributes enable */ 
121   MTRR_FIX_DRAM_MOD_EN   =      19               /*   MtrrFixDramModEn MTRR fixed RdDram and WrDram modification enable */ 
122   MTRR_VAR_DRAM_EN       =      20               /*   MtrrVarDramEn    MTRR variable DRAM enable */                     
123   MTRR_TOM2_EN           =      21               /*   MtrrTom2En       MTRR top of memory 2 enable */                    
124                                                                                                              
125 PERF_CONTROL3            =      0x0C0010003      /* Performance event control three */                                    
126     PERF_CONTROL3_RESERVE_L  =  0x00200000       /* Preserve the reserved bits */                                   
127     PERF_CONTROL3_RESERVE_H  =  0x0FCF0          /* Preserve the reserved bits */                                    
128     CONFIG_EVENT_L           =  0x0F0E2          /* All cores with level detection */                                    
129     CONFIG_EVENT_H           =  4                /* Increment count by number of event */                                 
130                                                  /* occured in clock cycle */                                 
131     EVENT_ENABLE             =  22               /* Enable the event */ 
132 PERF_COUNTER3            =      0x0C0010007      /* Performance event counter three */                                 
133
134 # Local use flags, in upper most byte if ESI
135 FLAG_UNKNOWN_FAMILY     = 24          # Signals that the family# of the installed processor is not recognized
136 FLAG_STACK_REENTRY      = 25          # Signals that the environment has made a re-entry (2nd) call to set up the stack
137 FLAG_IS_PRIMARY         = 26          # Signals that this core is the primary within the comoute unit
138
139 CR0_MASK    = ((1 << CR0_CD) | (1 << CR0_NW))
140 MSR_MASK    = ((1 << MTRR_DEF_TYPE_EN)+(1 << MTRR_DEF_TYPE_FIX_EN))
141
142 /****************************************************************************
143  *
144  *                      CPU MACROS - PUBLIC
145  *
146  ****************************************************************************/
147 .macro   _WRMSR
148         .byte 0x0f, 0x30
149 .endm
150
151 .macro  _RDMSR
152         .byte   0x0F, 0x32
153 .endm
154
155 .macro AMD_CPUID arg0
156   .ifb \arg0
157     mov   $0x1, %eax
158     .byte 0x0F, 0x0A2                     /* Execute instruction */
159     bswap %eax
160     xchg  %ah, %al                        /* Ext model in al now */
161     rol   $0x08, %eax                     /* Ext model in ah, model in al */
162     and   $0x0FFCF, ax                    /* Keep 23:16, 7:6, 3:0 */
163   .else
164     mov   \arg0, %eax
165     .byte 0x0F, 0x0A2
166   .endif
167 .endm
168
169 /****************************************************************************
170 *
171 * AMD_ENABLE_STACK_FAMILY_HOOK Macro - Stackless
172 *
173 *   Set any family specific controls needed to enable the use of
174 *   cache as general storage before main memory is available.
175 *
176 * Inputs:
177 *       none
178 * Outputs:
179 *       none
180  ****************************************************************************/
181 .macro  AMD_ENABLE_STACK_FAMILY_HOOK
182
183     AMD_ENABLE_STACK_FAMILY_HOOK_F10
184     AMD_ENABLE_STACK_FAMILY_HOOK_F12
185     AMD_ENABLE_STACK_FAMILY_HOOK_F14
186     AMD_ENABLE_STACK_FAMILY_HOOK_F15
187 .endm
188
189 /****************************************************************************
190 *
191 * AMD_DISABLE_STACK_FAMILY_HOOK Macro - Stackless
192 *
193 *   Return any family specific controls to their 'standard'
194 *   settings for using cache with main memory.
195 *
196 * Inputs:
197 *       none
198 * Outputs:
199 *       none
200  ****************************************************************************/
201 .macro  AMD_DISABLE_STACK_FAMILY_HOOK
202
203     AMD_DISABLE_STACK_FAMILY_HOOK_F10
204     AMD_DISABLE_STACK_FAMILY_HOOK_F12
205     AMD_DISABLE_STACK_FAMILY_HOOK_F14
206     AMD_DISABLE_STACK_FAMILY_HOOK_F15
207
208 .endm
209
210 /****************************************************************************
211 *
212 * GET_NODE_ID_CORE_ID Macro - Stackless
213 *
214 *   Read family specific values to determine the node and core
215 *   numbers for the core executing this code.
216 *
217 * Inputs:
218 *     none
219 * Outputs:
220 *     SI[7:0] = Core# (0..N, relative to node)
221 *     SI[15:8]= Node# (0..N)
222 *     SI[23:16]= reserved
223 *     SI[24]=   flag: 1=Family Unrecognized
224 *     SI[25]=   flag: 1=Interface re-entry call
225 *     SI[26]=   flag: 1=Core is primary of compute unit
226 *     SI[31:27]= reserved, =0
227 ****************************************************************************/
228 .macro  GET_NODE_ID_CORE_ID
229     LOCAL  node_core_exit
230
231     mov     $-1, %si
232     GET_NODE_ID_CORE_ID_F10
233     GET_NODE_ID_CORE_ID_F12
234     GET_NODE_ID_CORE_ID_F14
235     GET_NODE_ID_CORE_ID_F15
236     /*
237      * Check for unrecognized Family
238      */
239     cmp     $-1, %si                      # Has family (node/core) already been discovered?
240     jnz     node_core_exit              # Br if yes
241
242    mov     $((1 << FLAG_UNKNOWN_FAMILY)+(1 << FLAG_IS_PRIMARY)), %esi # No, Set error code, Only let BSP continue
243
244     mov     $APIC_BASE_ADDRESS, %ecx      # MSR:0000_001B
245     _RDMSR
246     bt      $APIC_BSC, %eax               # Is this the BSC?
247     jc      node_core_exit              # Br if yes
248     hlt                                 # Kill APs
249 node_core_exit:
250
251 .endm
252
253 /****************************************************************************
254 ##                      Family 10h MACROS
255 ##***************************************************************************
256 #---------------------------------------------------
257 #
258 # AMD_ENABLE_STACK_FAMILY_HOOK_F10 Macro - Stackless
259 #
260 #   Set any family specific controls needed to enable the use of
261 #   cache as general storage before main memory is available.
262 #
263 # Inputs:
264 #       ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
265 # Outputs:
266 #       none
267 #
268 # Family 10h requirements (BKDG section 2.3.3):
269 #   * Paging disabled
270 #   * MSRC001_0015[INVDWBINVD]=0
271 #   * MSRC001_1021[DIS_IND]=1
272 #   * MSRC001_1021[DIS_SPEC_TLB_RLD]=1
273 #   * MSRC001_1022[DIS_SPEC_TLB_RLD]=1
274 #   * MSRC001_1022[DIS_CLR_WBTOL2_SMC_HIT]=1
275 #   * MSRC001_1022[DIS_HW_PF]=1
276 #   * MSRC001_102A[IcDisSpecTlbWr]=1
277 #   * MSRC001_102A[ClLinesToNbDis]=1
278 #   * No INVD or WBINVD, no exceptions, page faults or interrupts
279 ****************************************************************************/
280 .macro AMD_ENABLE_STACK_FAMILY_HOOK_F10
281     LOCAL   fam10_enable_stack_hook_exit
282
283     AMD_CPUID   $CPUID_MODEL
284     shr     $20, %eax                     # AL = cpu extended family
285     cmp     $0x01, %al                      # Is this family 10h?
286     jnz     fam10_enable_stack_hook_exit # Br if no
287
288     mov     $DC_CFG, %ecx                 # MSR:C001_1022
289     _RDMSR
290     bts     $DC_DIS_SPEC_TLB_RLD, %eax     # Turn on Disable speculative DTLB reloads bit
291     bts     $DIS_CLR_WBTOL2_SMC_HIT, %eax  # Turn on Disable the self modifying code check buffer bit
292     bts     $DIS_HW_PF, %eax               # Turn on Disable hardware prefetches bit
293     _WRMSR
294
295     dec     %cx                          # MSR:C001_1021
296     _RDMSR
297     bts     $IC_DIS_SPEC_TLB_RLD, %eax     # Turn on Disable speculative TLB reloads bit
298     bts     $DIS_IND, %eax                 # Turn on Disable indirect branch predictor
299     _WRMSR
300
301     mov     $BU_CFG2, %ecx                # MSR C001_102A
302     _RDMSR
303     bts     $F10_CL_LINES_TO_NB_DIS, %eax   # Allow BIOS ROM to be cached in the IC
304     bts     $(IC_DIS_SPEC_TLB_WR-32), %edx  #Disable speculative writes to the ITLB
305     _WRMSR
306
307     mov     $HWCR, %ecx                    # MSR C001_0015
308     _RDMSR
309     bt      $FLAG_STACK_REENTRY, %esi                 # Check if stack has already been set
310     jc      fam10_skipClearingBit4
311     btr     $INVD_WBINVD, %eax             # disable INVD -> WBINVD conversion
312     _WRMSR
313
314 fam10_skipClearingBit4:
315     mov %esi, %eax                         # load core#
316     or %al, %al                       # If (BSP)
317     jne  fam10_enable_stack_hook_exit
318     mov     $PERF_COUNTER3, %ecx       #   Select performance counter three
319                                         #   to count number of CAR evictions
320     xor     %eax, %eax                #   Initialize the lower part of the counter to zero
321     xor     %edx, %edx                #   Initializa the upper part of the counter to zero
322     _WRMSR                          #   Save it
323     mov     $PERF_CONTROL3, %ecx      #   Select the event control three
324     _RDMSR                          #   Get the current setting
325     and     $PERF_CONTROL3_RESERVE_L, %eax   # Preserve the reserved bits
326     or      $CONFIG_EVENT_L, %eax      #   Set the lower part of event register to
327                                         #   select CAR Corruption occurred by any cores
328     and     $PERF_CONTROL3_RESERVE_H, %dx   # Preserve the reserved bits
329     or      $CONFIG_EVENT_H, %dx       #   Set the upper part of event register
330     _WRMSR                          #   Save it
331     bts     $EVENT_ENABLE, %eax        #   Enable it
332     _WRMSR                          #   Save it
333
334 fam10_enable_stack_hook_exit:
335 .endm
336
337 /****************************************************************************
338 *
339 * AMD_DISABLE_STACK_FAMILY_HOOK_F10 Macro - Stackless
340 *
341 *   Return any family specific controls to their 'standard'
342 *   settings for using cache with main memory.
343 *
344 * Inputs:
345 *       ESI - [31:24] flags; [15,8]= Node#; [7,0]= core#
346 * Outputs:
347 *       none
348 *
349 * Family 10h requirements:
350 *   * INVD or WBINVD
351 *   * MSRC001_0015[INVD_WBINVD]=1
352 *   * MSRC001_1021[DIS_IND]=0
353 *   * MSRC001_1021[DIS_SPEC_TLB_RLD]=0
354 *   * MSRC001_1022[DIS_SPEC_TLB_RLD]=0
355 *   * MSRC001_1022[DIS_CLR_WBTOL2_SMC_HIT]=0
356 *   * MSRC001_1022[DIS_HW_PF]=0
357 *   * MSRC001_102A[IcDisSpecTlbWr]=0
358 *   * MSRC001_102A[ClLinesToNbDis]=0
359 *****************************************************************************/
360
361 .macro  AMD_DISABLE_STACK_FAMILY_HOOK_F10
362     LOCAL   fam10_disable_stack_hook_exit
363
364     AMD_CPUID   CPUID_MODEL
365     shr     $20, %eax                     # AL = cpu extended family
366     cmp     $0x01, %al                     # Is this family 10h?
367     jnz     fam10_disable_stack_hook_exit # Br if no
368
369     mov     $DC_CFG, %ecx                 # MSR:C001_1022
370     _RDMSR
371     btr     $DC_DIS_SPEC_TLB_RLD, %eax    # Enable speculative TLB reloads
372     btr     $DIS_CLR_WBTOL2_SMC_HIT, %eax # Allow self modifying code check buffer
373     btr     $DIS_HW_PF, %eax              # Allow hardware prefetches
374     _WRMSR
375
376     dec     %cx                          # MSR:C001_1021
377     _RDMSR
378     btr     $DIS_IND, %eax                # Turn on indirect branch predictor
379     btr     $IC_DIS_SPEC_TLB_RLD, %eax    # Turn on speculative TLB reloads
380     _WRMSR
381
382     mov     $BU_CFG2, %ecx                # MSR:C001_102A
383     _RDMSR
384     btr     $F10_CL_LINES_TO_NB_DIS, %eax  # Return L3 to normal mode
385     btr     $(IC_DIS_SPEC_TLB_WR-32), %edx #Re-enable speculative writes to the ITLB
386     _WRMSR
387
388     #--------------------------------------------------------------------------
389     # Begin critical sequence in which EAX, BX, ECX, and EDX must be preserved.
390     #--------------------------------------------------------------------------
391
392     mov     $HWCR, %ecx                    # MSR:0000_0015
393     _RDMSR
394     mov     %ax, %bx                      # Save INVD -> WBINVD bit
395     btr    $INVD_WBINVD, %eax            # Disable INVD -> WBINVD conversion for the invd instruction.
396     _WRMSR
397     invd                                # Clear the cache tag RAMs
398     mov    %bx, %ax                      # Restore INVD -> WBINVD bit
399     _WRMSR
400
401     #--------------------------------------------------------------------------
402     # End critical sequence in which EAX, BX, ECX, and EDX must be preserved.
403     #--------------------------------------------------------------------------
404
405     mov     $PERF_CONTROL3, %ecx          # Select the event control three
406     _RDMSR                              # Retrieve the current value
407     btc     $EVENT_ENABLE, %eax           # Is event enable, complement it as well
408     jnc     fam10_disable_stack_hook_exit # No
409     cmp     $CONFIG_EVENT_L, %ax          # Is the lower part of event set to capture the CAR Corruption
410     jne     fam10_disable_stack_hook_exit # No
411     cmp     $CONFIG_EVENT_H, %dl        # Is the upper part of event set to capture the CAR Corruption
412     jne     fam10_disable_stack_hook_exit # No
413     _WRMSR                              # Disable the event
414
415 fam10_disable_stack_hook_exit:
416 .endm
417
418 /****************************************************************************
419 *
420 * GET_NODE_ID_CORE_ID_F10 Macro - Stackless
421 *
422 *   Read family specific values to determine the node and core
423 *   numbers for the core executing this code.
424 *
425 * Inputs:
426 *     none
427 * Outputs:
428 *     SI = core#, node# & flags (see GET_NODE_ID_CORE_ID macro above)
429 *****************************************************************************/
430 .macro  GET_NODE_ID_CORE_ID_F10
431
432     LOCAL   node_core_f10_exit
433     LOCAL   node_core_f10_AP
434
435     cmp     $-1, %si                      # Has node/core already been discovered?
436     jnz     node_core_f10_exit          # Br if yes
437
438     AMD_CPUID   $CPUID_MODEL
439     shr     $20, %eax                     # AL = cpu extended family
440     cmp     $0x01, %al                     # Is this family 10h?
441     jnz     node_core_f10_exit          # Br if no
442
443     xor     %esi, %esi                    # Assume BSC, clear flags
444     mov     $APIC_BASE_ADDRESS, %ecx      # MSR:0000_001B
445     _RDMSR
446     bt      $APIC_BSC, %eax             # Is this the BSC?
447     jnc      node_core_f10_AP            # Br if no
448
449         # This is the BSP.
450     # Enable routing tables on BSP (just in case the HT init code has not yet enabled them)
451     mov     $0x8000C06C, %eax             # PCI address for D18F0x6C Link Initialization Control Register
452     mov     $0x0CF8, %dx
453     out     %eax, %dx
454     add     $4, %dx
455     in      %dx, %eax
456     btr     $0, %eax                      # Set LinkInitializationControl[RouteTblDis] = 0
457     out     %eax, %dx
458     jmp     1f          #
459
460 node_core_f10_AP:
461     #
462     # This is an AP. Routing tables have been enabled by the HT Init process.
463     # Also, the MailBox register was set by the BSP during early init
464     #   The Mailbox register content is formatted as follows:
465     #         UINT32 Node:4#          // The node id of Core's node.
466     #         UINT32 Socket:4#        // The socket of this Core's node.
467     #         UINT32 Module:2#        // The internal module number for Core's node.
468     #         UINT32 ModuleType:2#    // Single Module = 0, Multi-module = 1.
469     #         UINT32 :20#             // Reserved
470     #
471     mov     $0x0C0000408, %ecx             # Read the family 10h mailbox
472     _RDMSR                              #        MC4_MISC1[63:32]
473     mov     %dx, %si                      # SI = raw mailbox contents (will extract node# from this)
474     shr     $24, %ebx                     # BL = CPUID Fn0000_0001_EBX[LocalApicId]
475     mov     %bx, %di                      # DI = Initial APIC ID (will extract core# from this)
476
477     AMD_CPUID   $AMD_CPUID_APIC          #
478     shr     $4, %ch                       # CH = ApicIdSize, #bits in APIC ID that show core#
479     inc     %cl                          # CL = Number of enabled cores in the socket
480     mov     %cx, %bx
481
482     mov     $NB_CFG, %ecx                 # MSR:C001_001F
483     _RDMSR                              # EDX has InitApicIdCpuIdLo bit
484
485     mov     %bh, %cl                      # CL = APIC ID size
486     mov     $1, %al                       # Convert APIC ID size to an AND mask
487     shl     %cl, %al                      # AL = 2^APIC ID size
488     dec     %al                          # AL = mask for relative core number
489     xor     %ah, %ah                      # AX = mask for relative core number
490     bt      $(INIT_APIC_ID_CPU_ID_LO-32), %edx # InitApicIdCpuIdLo == 1?
491     #.if (!carry?)                       # Br if yes
492     jc      0f
493         mov     $8, %ch                   # Calculate core number shift count
494         sub     %cl, %ch                  # CH = core shift count
495         mov     %ch, %cl
496         shr     %cl, %di                  # Right justify core number
497     #.endif
498    0:
499     and     %ax, %di                      # DI = socket-relative core number
500
501     mov     %si, %cx                      # CX = raw mailbox value
502     shr     $10, %cx                      # CL[1:0] = ModuleType or #nodes per socket (0-SCM, 1-MCM)
503     and     $3, %cl                       # Isolate ModuleType
504     xor     %bh, %bh                      # BX = Number of enabled cores in the socket
505     shr     %cl, %bx                      # BX = Number of enabled cores per node
506     xor     %dx, %dx                      # Clear upper word for div
507     mov     %di, %ax                      # AX = socket-relative core number
508     div     %bx                          # DX = node-relative core number
509     movzx   %si, %eax                     # prepare return value, [23:16]=shared Core# (=0, not shared)
510     and     $0x000F, %ax                   # AX = node number
511     shl     $8, %ax                       # [15:8]=node#
512     mov     %dl, %al                      # [7:0]=core# (relative to node)
513     mov     %eax, %esi                    # ESI = return value
514 1:
515  bts     $FLAG_IS_PRIMARY, %esi        # all Family 10h cores are primary
516 node_core_f10_exit:
517 .endm
518
519
520 /*****************************************************************************
521 **                      Family 12h MACROS
522 *****************************************************************************/
523 /*****************************************************************************
524 *
525 * AMD_ENABLE_STACK_FAMILY_HOOK_F12 Macro - Stackless
526 *
527 *   Set any family specific controls needed to enable the use of
528 *   cache as general storage before main memory is available.
529 *
530 * Inputs:
531 *       ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
532 * Outputs:
533 *       none
534 *
535 * Family 12h requirements (BKDG section 2.3.3):
536 *   The following requirements must be satisfied prior to using the cache as general storage:
537 *   * Paging must be disabled.
538 *   * MSRC001_0015[INVD_WBINVD]=0
539 *   * MSRC001_1020[DIS_SS]=1
540 *   * MSRC001_1021[DIS_SPEC_TLB_RLD]=1
541 *   * MSRC001_1022[DIS_SPEC_TLB_RLD]=1
542 *   * MSRC001_1022[DIS_CLR_WBTOL2_SMC_HIT]=1
543 *   * MSRC001_1022[DIS_HW_PF]=1
544 *   * MSRC001_1029[ClflushSerialize]=1
545 *   * No INVD or WBINVD, no exceptions, page faults or interrupts
546 *****************************************************************************/
547 .macro  AMD_ENABLE_STACK_FAMILY_HOOK_F12
548     LOCAL   fam12_enable_stack_hook_exit
549
550     AMD_CPUID   $CPUID_MODEL
551     shr     $20, %eax                     # AL = cpu extended family
552     cmp     $0x03, %al                     # Is this family 12h?
553     jnz     fam12_enable_stack_hook_exit # Br if no
554
555     mov     $DC_CFG, %ecx                 # MSR:C001_1022
556     _RDMSR
557     bts     $DC_DIS_SPEC_TLB_RLD, %eax    # Disable speculative DC-TLB reloads
558     bts     $DIS_CLR_WBTOL2_SMC_HIT, %eax # Disable self modifying code check buffer
559     bts     $DIS_HW_PF, %eax              # Disable hardware prefetches
560     _WRMSR
561
562     dec     %cx   #IC_CFG                # MSR:C001_1021
563     _RDMSR
564     bts     $IC_DIS_SPEC_TLB_RLD, %eax    # Disable speculative IC-TLB reloads
565     _WRMSR
566
567     dec     %cx   #LS_CFG                # MSR:C001_1020
568     _RDMSR
569     bts     $DIS_SS, %eax                 # Disabled Streaming store functionality
570     _WRMSR
571
572     mov     $HWCR, %ecx                   # MSR C001_0015
573     _RDMSR
574     bt      $FLAG_STACK_REENTRY , %esi                 # Check if stack has already been set
575     jc      fam12_skipClearingBit4
576     btr     $INVD_WBINVD, %eax            # disable INVD -> WBINVD conversion
577     _WRMSR
578
579 fam12_skipClearingBit4:
580     mov     $DE_CFG, %ecx                 # MSR:C001_1029
581     _RDMSR
582     bts     $CL_FLUSH_SERIALIZE, %eax     # Serialize all CL Flush actions
583     _WRMSR
584
585 fam12_enable_stack_hook_exit:
586 .endm
587
588 /*****************************************************************************
589 *
590 * AMD_DISABLE_STACK_FAMILY_HOOK_F12 Macro - Stackless
591 *
592 *   Return any family specific controls to their 'standard'
593 *   settings for using cache with main memory.
594 *
595 * Inputs:
596 *       ESI - [31:24] flags; [15,8]= Node#; [7,0]= core#
597 * Outputs:
598 *       none
599 *
600 * Family 12h requirements:
601 *   * INVD or WBINVD
602 *   * MSRC001_0015[INVD_WBINVD]=1
603 *   * MSRC001_1020[DIS_SS]=0
604 *   * MSRC001_1021[IC_DIS_SPEC_TLB_RLD]=0
605 *   * MSRC001_1022[DC_DIS_SPEC_TLB_RLD]=0
606 *   * MSRC001_1022[DIS_CLR_WBTOL2_SMC_HIT]=0
607 *   * MSRC001_1022[DIS_HW_PF]=0
608 *   * MSRC001_1029[ClflushSerialize]=0
609 *****************************************************************************/
610 .macro  AMD_DISABLE_STACK_FAMILY_HOOK_F12
611     LOCAL   fam12_disable_stack_hook_exit
612
613     AMD_CPUID   $CPUID_MODEL
614     shr     $20, %eax                     # AL = cpu extended family
615     cmp     $0x03, %al                     # Is this family 12h?
616     jnz     fam12_disable_stack_hook_exit # Br if no
617
618     mov     $DC_CFG, %ecx                 # MSR:C001_1022
619     _RDMSR
620     btr     $DC_DIS_SPEC_TLB_RLD, %eax    # Turn on speculative DC-TLB reloads
621     btr     $DIS_CLR_WBTOL2_SMC_HIT, %eax # Enable self modifying code check buffer
622     btr     $DIS_HW_PF, %eax              # Enable Hardware prefetches
623     _WRMSR
624
625     dec     %cx   #IC_CFG                # MSR:C001_1021
626     _RDMSR
627     btr     $IC_DIS_SPEC_TLB_RLD, %eax    # Turn on speculative IC-TLB reloads
628     _WRMSR
629
630     dec     %cx   #LS_CFG                # MSR:C001_1020
631     _RDMSR
632     btr     $DIS_SS, %eax                 # Turn on Streaming store functionality
633     _WRMSR
634
635     mov     $DE_CFG, %ecx                 # MSR:C001_1029
636     _RDMSR
637     btr     $CL_FLUSH_SERIALIZE, %eax
638     _WRMSR
639
640     #--------------------------------------------------------------------------
641     # Begin critical sequence in which EAX, BX, ECX, and EDX must be preserved.
642     #--------------------------------------------------------------------------
643
644     mov     $HWCR, %ecx                    # MSR:0000_0015h
645     _RDMSR
646     mov     %ax, %bx                      # Save INVD -> WBINVD bit
647     btr     $INVD_WBINVD, %eax            # Disable INVD -> WBINVD conversion
648     _WRMSR
649     invd                                # Clear the cache tag RAMs
650     mov     %bx, %ax                      # Restore INVD -> WBINVD bit
651     _WRMSR
652
653     #--------------------------------------------------------------------------
654     # End critical sequence in which EAX, BX, ECX, and EDX must be preserved.
655     #--------------------------------------------------------------------------
656
657 fam12_disable_stack_hook_exit:
658 .endm
659
660 /*****************************************************************************
661 *
662 * GET_NODE_ID_CORE_ID_F12 Macro - Stackless
663 *
664 *   Read family specific values to determine the node and core
665 *   numbers for the core executing this code.
666 *
667 * Inputs:
668 *     none
669 * Outputs:
670 *     SI = core#, node# & flags (see GET_NODE_ID_CORE_ID macro above)
671 *****************************************************************************/
672 .macro  GET_NODE_ID_CORE_ID_F12
673
674     LOCAL   node_core_f12_exit
675
676     cmp     $-1, %si                      # Has node/core already been discovered?
677     jnz     node_core_f12_exit          # Br if yes
678
679     AMD_CPUID   $CPUID_MODEL
680     shr     $20, %eax                     # AL = cpu extended family
681     cmp     $0x03, %al                     # Is this family 12h?
682     jnz     node_core_f12_exit          # Br if no
683
684     shr     $24, %ebx                     # CPUID_0000_0001_EBX[31:24]: initial local APIC physical ID
685     bts     $FLAG_IS_PRIMARY, %ebx        # all family 12h cores are primary
686     mov     %ebx, %esi                    # ESI = Node#=0, core number
687 node_core_f12_exit:
688 .endm
689
690 /*****************************************************************************
691 **                      Family 14h MACROS
692 *****************************************************************************/
693 /*****************************************************************************
694 *
695 * AMD_ENABLE_STACK_FAMILY_HOOK_F14 Macro - Stackless
696 *
697 *   Set any family specific controls needed to enable the use of
698 *   cache as general storage before main memory is available.
699 *
700 * Inputs:
701 *       ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
702 * Outputs:
703 *       none
704 *
705 * Family 14h requirements (BKDG section 2.3.3):
706 *   * Paging must be disabled.
707 *   * MSRC001_0015[INVD_WBINVD]=0.
708 *   * MSRC001_1020[DisStreamSt]=1.
709 *   * MSRC001_1021[DIS_SPEC_TLB_RLD]=1. Disable speculative ITLB reloads.
710 *   * MSRC001_1022[DIS_HW_PF]=1.
711 *   * No INVD or WBINVD, no exceptions, page faults or interrupts
712 *****************************************************************************/
713 .macro  AMD_ENABLE_STACK_FAMILY_HOOK_F14
714     LOCAL   fam14_enable_stack_hook_exit
715
716     AMD_CPUID   $CPUID_MODEL
717     shr     $20, %eax                     # AL = cpu extended family
718     cmp     $0x05, %al                     # Is this family 14h?
719     jnz     fam14_enable_stack_hook_exit # Br if no
720
721     mov     $DC_CFG, %ecx                 # MSR:C001_1022
722     _RDMSR
723     bts     $DIS_HW_PF, %eax              # Disable hardware prefetches
724     _WRMSR
725
726     dec     %cx  #IC_CFG                 # MSR:C001_1021
727     _RDMSR
728     bts     $IC_DIS_SPEC_TLB_RLD, %eax    # Disable speculative TLB reloads
729     _WRMSR
730
731     dec     %cx  #LS_CFG                 # MSR:C001_1020
732     _RDMSR
733     bts     $DIS_STREAM_ST, %eax          # Disabled Streaming store functionality
734     _WRMSR
735
736     mov     $HWCR, %ecx                   # MSR C001_0015
737     _RDMSR
738     bt      $FLAG_STACK_REENTRY, %esi     # Check if stack has already been set
739     jc      fam14_skipClearingBit4
740     btr     $INVD_WBINVD, %eax            # Disable INVD -> WBINVD conversion
741     _WRMSR
742 fam14_skipClearingBit4:                 # Keeping this label
743
744 fam14_enable_stack_hook_exit:
745 .endm
746
747 /*****************************************************************************
748 *
749 * AMD_DISABLE_STACK_FAMILY_HOOK_F14 Macro - Stackless
750 *
751 *   Return any family specific controls to their 'standard'
752 *   settings for using cache with main memory.
753 *
754 * Inputs:
755 *       ESI - [31:24] flags; [15,8]= Node#; [7,0]= core#
756 * Outputs:
757 *       none
758 *
759 * Family 14h requirements:
760 *   * INVD or WBINVD
761 *   * MSRC001_0015[INVD_WBINVD]=1.
762 *   * MSRC001_1020[DisStreamSt]=0.
763 *   * MSRC001_1021[DIS_SPEC_TLB_RLD]=0.
764 *   * MSRC001_1022[DIS_HW_PF]=0.
765 *****************************************************************************/
766 .macro  AMD_DISABLE_STACK_FAMILY_HOOK_F14
767     LOCAL   fam14_disable_stack_hook_exit
768
769     AMD_CPUID   $CPUID_MODEL
770     shr     $20, %eax                     # AL = cpu extended family
771     cmp     $0x05, %al                     # Is this family 14h?
772     jnz     fam14_disable_stack_hook_exit # Br if no
773
774     mov     $LS_CFG, %ecx                 # MSR:C001_1020
775     _RDMSR
776     btr     $DIS_STREAM_ST, %eax          # Turn on Streaming store functionality
777     _WRMSR
778
779     inc     %cx  #IC_CFG                 # MSR:C001_1021
780     _RDMSR
781     btr     $IC_DIS_SPEC_TLB_RLD, %eax    # Turn on speculative DC-TLB reloads
782     _WRMSR
783
784     inc     %cx  #DC_CFG                 # MSR:C001_1022
785     _RDMSR
786     btr     $DIS_HW_PF, %eax              # Turn on hardware prefetches
787     _WRMSR
788
789     #--------------------------------------------------------------------------
790     # Begin critical sequence in which EAX, BX, ECX, and EDX must be preserved.
791     #--------------------------------------------------------------------------
792
793     mov     $HWCR, %ecx                    # MSR:C001_0015h
794     _RDMSR
795     btr     $INVD_WBINVD, %eax            # Disable INVD -> WBINVD conversion
796     _WRMSR
797     invd                                # Clear the cache tag RAMs
798     bts     $INVD_WBINVD, %eax            # Turn on Conversion of INVD to WBINVD
799     _WRMSR
800
801     #--------------------------------------------------------------------------
802     # End critical sequence in which EAX, BX, ECX, and EDX must be preserved.
803     #--------------------------------------------------------------------------
804
805 fam14_disable_stack_hook_exit:
806 .endm
807
808 /*****************************************************************************
809 *
810 * GET_NODE_ID_CORE_ID_F14 Macro - Stackless
811 *
812 *   Read family specific values to determine the node and core
813 *   numbers for the core executing this code.
814 *
815 * Inputs:
816 *     none
817 * Outputs:
818 *     SI = core#, node# & flags (see GET_NODE_ID_CORE_ID macro above)
819 *****************************************************************************/
820 .macro  GET_NODE_ID_CORE_ID_F14
821
822     LOCAL   node_core_f14_exit
823
824     cmp     $0x-1, %si                      # Has node/core already been discovered?
825     jnz     node_core_f14_exit          # Br if yes
826
827     AMD_CPUID   $CPUID_MODEL
828     shr     $20, %eax                     # AL = cpu extended family
829     cmp     $0x05, %al                     # Is this family 14h?
830     jnz     node_core_f14_exit          # Br if no
831
832     xor     %esi, %esi                    # Node must be 0
833     bts     $FLAG_IS_PRIMARY, %esi        # all family 14h cores are primary
834     mov     $APIC_BASE_ADDRESS, %ecx      # MSR:0000_001B
835     _RDMSR
836     bt      $APIC_BSC, %eax               # Is this the BSC?
837     jc      node_core_f14_exit          # Br if yes
838     inc     %si                          # Set core to 1
839 node_core_f14_exit:
840 .endm
841
842
843
844 /*****************************************************************************
845 **                      Family 15h MACROS
846 *****************************************************************************/
847 /*****************************************************************************
848 *
849 * AMD_ENABLE_STACK_FAMILY_HOOK_F15 Macro - Stackless
850 *
851 *   Set any family specific controls needed to enable the use of
852 *   cache as general storage before main memory is available.
853 *
854 * Inputs:
855 *       ESI - node#, core#, flags from GET_NODE_ID_CORE_ID
856 * Outputs:
857 *       none
858 *
859 * Family 15h requirements (BKDG #42301 section 2.3.3):
860 *   * Paging must be disabled.
861 *   * MSRC001_0015[INVD_WBINVD]=0
862 *   * MSRC001_1020[DisSS]=1
863 *   * MSRC001_1021[DIS_SPEC_TLB_RLD]=1
864 *   * MSRC001_1022[DIS_SPEC_TLB_RLD]=1
865 *   * MSRC001_1022[DisHwPf]=1
866 *   * No INVD or WBINVD, no exceptions, page faults or interrupts
867 *****************************************************************************/
868 .macro  AMD_ENABLE_STACK_FAMILY_HOOK_F15
869     LOCAL   fam15_enable_stack_hook_exit
870
871     AMD_CPUID   $CPUID_MODEL
872     shr     $20, %eax                     # AL = cpu extended family
873     cmp     $0x06, %al                     # Is this family 15h?
874     jnz     fam15_enable_stack_hook_exit # Br if no
875
876     bt      $FLAG_STACK_REENTRY , %esi                 # Check if stack has already been set
877     jc      fam15_skipClearingBit4
878     mov     $HWCR, %ecx                   # MSR C001_0015
879     _RDMSR
880     btr     $INVD_WBINVD, %eax            # disable INVD -> WBINVD conversion
881     _WRMSR
882
883 fam15_skipClearingBit4:
884     mov     $LS_CFG, %ecx                 # MSR:C001_1020
885     _RDMSR
886     bts     $DIS_SS, %eax                 # Turn on Streaming store functionality disabled bit
887     _WRMSR
888
889     inc     %ecx  #IC_CFG                # MSR:C001_1021
890     _RDMSR
891     bts     $IC_DIS_SPEC_TLB_RLD, %eax    # Turn on Disable speculative IC-TLB reloads bit
892     _WRMSR
893
894     inc     %ecx  #DC_CFG                # MSR:C001_1022
895     _RDMSR
896     bts     $DC_DIS_SPEC_TLB_RLD, %eax    # Turn on Disable speculative DC-TLB reloads bit
897     bts     $DIS_HW_PF, %eax              # Turn on Disable hardware prefetches bit
898     _WRMSR
899
900     mov     $CU_CFG3, %ecx                # MSR:C001_102B
901     _RDMSR
902     btr     $(COMBINE_CR0_CD - 32), %edx         # Clear CombineCr0Cd bit
903     _WRMSR
904
905 fam15_enable_stack_hook_exit:
906 .endm
907
908
909 /*****************************************************************************
910 *
911 * AMD_DISABLE_STACK_FAMILY_HOOK_F15 Macro - Stackless
912 *
913 *   Return any family specific controls to their 'standard'
914 *   settings for using cache with main memory.
915 *
916 * Inputs:
917 *       ESI - [31:24] flags; [15,8]= Node#; [7,0]= core#
918 * Outputs:
919 *       none
920 *
921 * Family 15h requirements:
922 *   * INVD or WBINVD
923 *   * MSRC001_0015[INVD_WBINVD]=1
924 *   * MSRC001_1020[DisSS]=0
925 *   * MSRC001_1021[DIS_SPEC_TLB_RLD]=0
926 *   * MSRC001_1022[DIS_SPEC_TLB_RLD]=0
927 *   * MSRC001_1022[DIS_HW_PF]=0
928 *****************************************************************************/
929 .macro  AMD_DISABLE_STACK_FAMILY_HOOK_F15
930     LOCAL   fam15_disable_stack_hook_exit
931
932     AMD_CPUID   $CPUID_MODEL
933     mov     %eax, %ebx                    # Save revision info to EBX
934     shr     $20, %eax                     # AL = cpu extended family
935     cmp     $0x06, %al                     # Is this family 15h?
936     jnz     fam15_disable_stack_hook_exit # Br if no
937
938     mov     $LS_CFG, %ecx                 # MSR:C001_1020
939     #.if (ebx != 00600F00h)              ; Is this rev A0?
940     cmp $0x00600F00, %ebx
941     jz  0f
942     _RDMSR
943     btr     $DIS_SS, %eax                 # Turn on Streaming store functionality
944     _WRMSR
945     #.endif
946     0:                              # End workaround for errata 495 and 496
947
948     inc     %ecx  #IC_CFG                # MSR:C001_1021
949     _RDMSR
950     btr     $IC_DIS_SPEC_TLB_RLD, %eax    # Turn on speculative TLB reloads
951     _WRMSR
952
953     inc     %ecx  #DC_CFG                # MSR:C001_1022
954     _RDMSR
955     btr     $DC_DIS_SPEC_TLB_RLD, %eax    # Turn on speculative TLB reloads
956     #.if (ebx != 00600F00h)              # Is this rev A0?
957     cmp $0x00600F00, %ebx
958     jz  0f
959     btr     $DIS_HW_PF, %eax              # Turn on hardware prefetches
960     #.endif                              # End workaround for erratum 498
961     0:
962     _WRMSR
963     #--------------------------------------------------------------------------
964     # Begin critical sequence in which EAX, BX, ECX, and EDX must be preserved.
965     #--------------------------------------------------------------------------
966
967     bt      $FLAG_IS_PRIMARY, %esi
968     #.if (carry?)                        # Only clear cache from primary core
969     jnc 0f
970     mov     $HWCR, %ecx                    # MSR:C001_0015h
971     _RDMSR
972     btr     $INVD_WBINVD, %eax            # Disable INVD -> WBINVD conversion
973     _WRMSR
974     invd                                # Clear the cache tag RAMs
975     bts     $INVD_WBINVD, %eax            # Turn on Conversion of INVD to WBINVD
976     _WRMSR
977     #.endif                              # end
978     0:
979
980     #--------------------------------------------------------------------------
981     # End critical sequence in which EAX, BX, ECX, and EDX must be preserved.
982     #--------------------------------------------------------------------------
983
984     mov     $CU_CFG3, %ecx                # MSR:C001_102B
985     _RDMSR
986     bts     $(COMBINE_CR0_CD - 32), %eax         # Set CombineCr0Cd bit
987     _WRMSR
988
989 fam15_disable_stack_hook_exit:
990 .endm
991
992
993 /*****************************************************************************
994 *
995 * GET_NODE_ID_CORE_ID_F15 Macro - Stackless
996 *
997 *   Read family specific values to determine the node and core
998 *   numbers for the core executing this code.
999 *
1000 * Inputs:
1001 *     none
1002 * Outputs:
1003 *     SI = core#, node# & flags (see GET_NODE_ID_CORE_ID macro above)
1004 *****************************************************************************/
1005 .macro  GET_NODE_ID_CORE_ID_F15
1006
1007     LOCAL   node_core_f15_exit
1008     LOCAL   node_core_f15_AP
1009     LOCAL   node_core_f15_shared
1010
1011     cmp     $-1, %si                      # Has node/core already been discovered?
1012     jnz     node_core_f15_exit          # Br if yes
1013
1014     AMD_CPUID   $CPUID_MODEL
1015     shr     $20, %eax                     # AL = cpu extended family
1016     cmp     $06, %al                     # Is this family 15h?
1017     jnz     node_core_f15_exit          # Br if no
1018
1019     xor     %esi, %esi                    # Assume BSC, clear local flags
1020     mov     $APIC_BASE_ADDRESS, %ecx      # MSR:0000_001B
1021     _RDMSR
1022     bt      $APIC_BSC, %eax               # Is this the BSC?
1023     jnc      node_core_f15_AP            # Br if no
1024
1025     # This is the BSP.
1026     # Enable routing tables on BSP (just in case the HT init code has not yet enabled them)
1027     mov     $0x8000C06C, %eax              # PCI address for D18F0x6C Link Initialization Control Register
1028     mov     $0x0CF8, %dx
1029     out     %eax, %dx
1030     add     $4, %dx
1031     in      %dx, %eax
1032     btr     $0, %eax                      # Set LinkInitializationControl[RouteTblDis] = 0
1033     out     %eax, %dx
1034     jmp     node_core_f15_shared        #
1035
1036 node_core_f15_AP:
1037     #
1038     # This is an AP. Routing tables have been enabled by the HT Init process.
1039     # Also, the MailBox register was set by the BSP during early init
1040     #   The Mailbox register content is formatted as follows:
1041     #         UINT32 Node:4;          // The node id of Core's node.
1042     #         UINT32 Socket:4;        // The socket of this Core's node.
1043     #         UINT32 Module:2;        // The internal module number for Core's node.
1044     #         UINT32 ModuleType:2;    // Single Module = 0, Multi-module = 1.
1045     #         UINT32 :20;             // Reserved
1046     #
1047     mov     $0x0C0000408, %ecx             # Read the family 15h mailbox
1048     _RDMSR                              #      MC4_MISC1[63:32]
1049     mov     %dx, %si                      # SI = raw mailbox contents (will extract node# from this)
1050     shr     $24, %ebx                     # BL = CPUID Fn0000_0001_EBX[LocalApicId]
1051     mov     %bx, %di                      # DI = Initial APIC ID (will extract core# from this)
1052
1053     AMD_CPUID   $AMD_CPUID_APIC          #
1054     shr     $4, %ch                       # CH = ApicIdSize, #bits in APIC ID that show core#
1055     inc     %cl                          # CL = Number of enabled cores in the socket
1056     mov     %cx, %bx
1057
1058     mov     $NB_CFG, %ecx
1059     _RDMSR                              # EDX has InitApicIdCpuIdLo bit
1060
1061     mov     %bh, %cl                      # CL = APIC ID size
1062     mov     $1, %al                       # Convert APIC ID size to an AND mask
1063     shl     %cl, %al                      # AL = 2^APIC ID size
1064     dec     %al                          # AL = mask for relative core number
1065     xor     %ah, %ah                      # AX = mask for relative core number
1066     bt      $(INIT_APIC_ID_CPU_ID_LO-32), %edx # InitApicIdCpuIdLo == 1?
1067     #.if (!carry?)                       # Br if yes
1068     jc      0f
1069         mov     $8, %ch                   # Calculate core number shift count
1070         sub     %cl, %ch                  # CH = core shift count
1071         mov     %ch, %cl
1072         shr     %cl, %di                  # Right justify core number
1073     #.endif
1074     0:
1075     and     %ax, %di                      # DI = socket-relative core number
1076
1077     mov     %si, %cx                      # CX = raw mailbox value
1078     shr     $10, %cx                      # CL[1:0] = ModuleType or #nodes per socket (0-SCM, 1-MCM)
1079     and     $3, %cl                       # Isolate ModuleType
1080     xor     %bh, %bh                      # BX = Number of enabled cores in the socket
1081     shr     %cl, %bx                      # BX = Number of enabled cores per node
1082     xor     %dx, %dx                      # Clear upper word for div
1083     mov     %di, %ax                      # AX = socket-relative core number
1084     div     %bx                          # DX = node-relative core number
1085     movzx   %si, %eax                     # Prepare return value
1086     and     $0x000F, %ax                   # AX = node number
1087     shl     $8,%ax                       # [15:8]=node#
1088     mov     %dl, %al                      # [7:0]=core# (relative to node)
1089     mov     %eax, %esi                    # ESI = node-relative core number
1090
1091       #
1092       #   determine if this core shares MTRRs
1093       #
1094 node_core_f15_shared:
1095     mov     $0x8000C580, %eax              # Compute Unit Status
1096     mov     %si, %bx
1097     shl     $3, %bh                       # Move node# to PCI Dev# field
1098     add     %bh, %ah                      # Adjust for node number
1099     mov     $0x0CF8, %dx
1100     out     %eax, %dx
1101     add     $4, %dx
1102     in      %dx, %eax                     # [3:0]=Enabled# [19:16]=DualCore
1103
1104                                         # BL is MyCore#
1105     mov     $0x06, %cx                     # Use CH as 'first of pair' core#
1106     #.while (cl > 0)
1107     jmp  0f
1108     8:
1109         bt      $0, %eax                  # Is pair enabled?
1110         #.if (carry?)                    #
1111         jnc     1f
1112             mov     $0x01, %bh             #   flag core as primary
1113             bt      $16, %eax             # Is there a 2nd in the pair?
1114             #.if (carry?)                #
1115             jnc 4f
1116                 #.break .if (ch == bl)   # Does 1st match MyCore#?
1117                 cmp     %bl, %ch
1118                 je      9f
1119                 inc     %ch
1120                 xor     %bh, %bh          #     flag core as NOT primary
1121                 #.break .if (ch == bl)   # Does 2nd match MyCore#?
1122                 cmp     %bl, %ch
1123                 je      9f
1124                 jmp     2f
1125             #.else                       # No 2nd core
1126             4:
1127                 #.break .if (ch == bl)   # Does 1st match MyCore#?
1128                 cmp     %bl, %ch
1129                 je      9f
1130             #.endif
1131             2:
1132             inc     %ch
1133         #.endif
1134         1:
1135         shr     $1, %eax
1136         dec     %cl
1137     #.endw
1138     0:
1139     #.if (cl == 0)
1140     cmp $0x0, %cl
1141     ja  8b
1142     9:
1143     or  %cl, %cl
1144     jne 1f
1145         #Error - core# didn't match Compute Unit Status content
1146         bts     $FLAG_UNKNOWN_FAMILY, %esi
1147         bts     $FLAG_IS_PRIMARY, %esi    #   Set Is_Primary for unknowns
1148     #.endif
1149     1:
1150     #.if (bh != 0)                       # Check state of primary for the matched core
1151     or %bh, %bh
1152     je 2f
1153         bts     $FLAG_IS_PRIMARY, %esi    #   Set shared flag into return value
1154     #.endif
1155     2:
1156
1157 node_core_f15_exit:
1158
1159 .endm
1160
1161 /*****************************************************************************
1162 * AMD_ENABLE_STACK:  Setup a stack
1163 *
1164 *   In:
1165 *       EBX  = Return address (preserved)
1166 *
1167 *   Out:
1168 *       SS:ESP - Our new private stack location
1169 *
1170 *       EAX = AGESA_STATUS
1171 *
1172 *       ECX = Stack size in bytes
1173 *
1174 *   Requirements:
1175 *       * This routine presently is limited to a max of 64 processor cores
1176 *   Preserved:
1177 *       ebx ebp
1178 *   Destroyed:
1179 *       eax, ecx, edx, edi, esi, ds, es, ss, esp
1180 *       mmx0, mmx1
1181 *
1182 *   Description:
1183 * Fixed MTRR address allocation to cores:
1184 * The BSP gets 64K of stack, Core0 of each node gets 16K of stack, all other cores get 4K.
1185 * There is a max of 1 BSP, 7 core0s and 56 other cores.
1186 * Although each core has it's own cache storage, they share the address space. Each core must
1187 * be assigned a private and unique address space for its stack. To support legacy systems,
1188 * the stack needs to be within the legacy address space (1st 1Meg). Room must also be reserved
1189 * for the other legacy elements (Interrupt vectors, BIOS ROM, video buffer, etc.)
1190 *
1191 * 80000h                                        40000h                                      00000h
1192 *     +----------+----------+----------+----------+----------+----------+----------+----------+
1193 * 64K |          |          |          |          |          |          |          |          |  64K  ea
1194 *  ea +----------+----------+----------+----------+----------+----------+----------+----------+
1195 *     |                             MTRR 0000_0250 MTRRfix64K_00000                           |
1196 *     +----------+----------+----------+----------+----------+----------+----------+----------+
1197 *     |  7 ,  6  |  5 ,  4  |  3 ,  2  |  1 ,  0  |     0    |          |          |          | <-node
1198 *     |7..1,7..1 |7..1,7..1 |7..1,7..1 |7..1,7..1 |     0    |          |          |          | <-core
1199 *     +----------+----------+----------+----------+----------+----------+----------+----------+
1200 *
1201 * C0000h                       B0000h                      A0000h                      90000h                      80000h
1202 *     +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1203 *16K  |      |      |      |      |      |      |      |      |      |      |      |      |      |      |      |      |
1204 * ea  +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1205 *     |              MTRR 0259 MTRRfix16K_A0000               |             MTRR 0258 MTRRfix16K_80000                |
1206 *     +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1207 *     | > Dis|play B|uffer |   <  |      |      |      |      |   7  |  6   |  5   |  4   |  3   |  2   |  1   |      | <-node
1208 *     | >   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
1209 *     +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1210 *
1211 * E0000h                                            D0000h                                         C0000h
1212 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1213 * 4K  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  4K  ea
1214 *  ea +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1215 *     |  026B MTRRfix4K_D8000 | 026A MTRRfix4K_D0000  | 0269 MTRRfix4K_C8000  | 0268 MTRRfix4K_C0000  |
1216 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1217 *     |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | >| V| I| D| E| O|  |B |I |O |S |  |A |r |e |a<|
1218 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1219 *
1220 * 100000h                                           F0000h                                          E0000h
1221 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1222 *     |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  4K  ea
1223 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1224 *     |  026F MTRRfix4K_F8000 | 026E MTRRfix4K_F0000  | 026D MTRRfix4K_E8000  | 026C MTRRfix4K_E0000  |
1225 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1226 *     | >|MA|IN| B|IO|S |RA|NG|E |  |  |  |  |  |  |< | >|EX|TE|ND|ED| B|IO|S |ZO|NE|  |  |  |  |  |< |
1227 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1228 *****************************************************************************/
1229 .macro  AMD_ENABLE_STACK
1230
1231 # These are local labels. Declared so linker doesn't cause 'redefined label' errors
1232     LOCAL   SetupStack
1233     LOCAL   Real16bMode
1234     LOCAL   Protected32Mode
1235     LOCAL   ClearTheStack
1236
1237 #   Note that SS:ESP will be default stack.  Note that this stack
1238 #   routine will not be used after memory has been initialized.  Because
1239 #   of its limited lifetime, it will not conflict with typical PCI devices.
1240     movd    %ebx, %mm0                    # Put return address in a safe place
1241     movd    %ebp, %mm1                    # Save some other user registers
1242
1243     # get node id and core id of current executing core
1244     GET_NODE_ID_CORE_ID                 # Sets ESI[23:16]=Shared core## SI[15,8]= Node## SI[7,0]= core# (relative to node)
1245     # Note: ESI[31:24] are used for flags:  Unrecognized Family,  Is_Primary core,  Stack already established
1246
1247     # determine if stack is already enabled. We are using the DefType MSR for this determination.
1248     # It is =0 after reset; CAR setup sets it to enable the MTRRs
1249     mov     %cr0, %eax
1250     test    $CR0_MASK, %eax              # Is cache disabled? (CD & NW bits)
1251     jnz     SetupStack                  # Jump if yes
1252     mov     $AMD_MTRR_DEFTYPE, %ecx       # MSR:0000_02FF
1253     _RDMSR
1254     test    $MSR_MASK, %eax                     # Are the default types enabled? (MTRR_DEF_TYPE_EN + MTRR_DEF_TYPE_FIX_EN)
1255     jz      SetupStack                  # Jump if no
1256     or      $FLAG_STACK_REENTRY, %esi             # Bit25, indicate stack has already been initialized
1257
1258 SetupStack:
1259     # Set node to map the first 16MB to node 0# 0000_0000 to 00FF_FFFF as DRAM
1260     mov     %esi, %ebx                    # Get my Node/Core info
1261     xor     %bl, %bl
1262     shl     $3, %bh                       # Isolate my node#, match alignment for PCI Dev#
1263     mov     $0x8000C144, %eax              # D18F1x44:DRAM Base/Limit# N is Base, N+4 is Limit
1264     add     %bh, %ah
1265     mov     %eax, %ebx                    # Save PCI address for Base/Limit pair
1266
1267     mov     $0x0CF8, %dx
1268     out     %eax, %dx
1269     add     $4, %dx
1270     xor     %eax, %eax                    # Least Significant bit is AD24 so 0 sets mask of 00FF_FFFF (16MB)
1271     out     %eax, %dx                     # DRAM Limit = node0, no interleave
1272
1273     mov     %ebx, %eax
1274     sub     $4, %eax                      # Now point to the Base register
1275     mov     $0x0CF8, %dx
1276     out     %eax, %dx
1277     add     $4, %dx
1278     mov     $0x00000003, %eax              # Set the read and write enable bits
1279     out     %eax, %dx                     # DRAM Base = 0x0000, R/W
1280
1281     AMD_ENABLE_STACK_FAMILY_HOOK
1282
1283     # Init CPU MSRs for our init routines
1284     mov     $MTRR_SYS_CFG, %ecx           # SYS_CFG
1285     _RDMSR
1286     bts     $MTRR_FIX_DRAM_MOD_EN, %eax   # Turn on modification enable bit
1287     _WRMSR
1288
1289     mov     %esi, %eax
1290     bt      $FLAG_STACK_REENTRY, %eax     # Is this a 2nd entry?
1291     #.if (!carry?)                       #   On a re-entry, do not clear MTRRs or reset TOM; just reset the stack SS:ESP
1292     jc 0f
1293         bt      $FLAG_IS_PRIMARY, %eax    #   Is this core the primary in a compute unit?
1294         #.if (carry?)                    #     Families using shared groups do not need to clear the MTRRs since that is done at power-on reset
1295             #  Note: Relying on MSRs to be cleared to 0's at reset for families w/shared cores
1296             # Clear all variable and Fixed MTRRs for non-shared cores
1297         jnc 0f
1298         mov     $AMD_MTRR_VARIABLE_BASE0, %ecx
1299         xor     %eax, %eax
1300         xor     %edx, %edx
1301         #.while (cl != 10h)                  # Variable MTRRphysBase[n] and MTRRphysMask[n]
1302         jmp     1f
1303         2:
1304             _WRMSR
1305             inc     %cl
1306         #.endw
1307         1:
1308         cmp     $0x10, %cl
1309         jne     2b
1310         mov     $AMD_MTRR_FIX64k_00000, %cx   # MSR:0000_0250
1311         _WRMSR
1312         mov     $AMD_MTRR_FIX16k_80000, %cx   # MSR:0000_0258
1313         _WRMSR
1314         mov     $AMD_MTRR_FIX16k_A0000, %cx   # MSR:0000_0259
1315         _WRMSR
1316         mov     $AMD_MTRR_FIX4k_C0000, %cx    # Fixed 4Ks: MTRRfix4K_C0000 to MTRRfix4K_F8000
1317         #.while (cl != 70h)
1318         jmp 3f
1319         4:
1320             _WRMSR
1321             inc     %cl
1322         #.endw
1323         3:
1324         cmp $0x70, %cl
1325         jne  4b
1326         # Set TOP_MEM (C001_001A) for non-shared cores to 16M. This will be increased at heap init.
1327         #  - not strictly needed since the FixedMTRRs take presedence.
1328         mov     $(16 * 1024 * 1024), %eax
1329         mov     $TOP_MEM, %ecx            # MSR:C001_001A
1330         _WRMSR
1331         #.endif                          #   End Is_Primary
1332     #.endif                              # End Stack_ReEntry
1333     0:
1334     # Clear IORRs (C001_0016-19) and TOM2(C001_001D) for all cores
1335     xor     %eax, %eax
1336     xor     %edx, %edx
1337     mov     $IORR_BASE, %ecx              # MSR:C001_0016 - 0019
1338     #.while (cl != 1Ah)
1339     jmp  1f
1340     2:
1341         _WRMSR
1342         inc     %cl
1343     #.endw
1344     1:
1345     cmp $0x1A, %cl
1346     jne  2b
1347     mov     $TOP_MEM2, %ecx               # MSR:C001_001D
1348     _WRMSR
1349
1350     # setup MTTRs for stacks
1351     #   A speculative read can be generated by a speculative fetch mis-aligned in a code zone
1352     #    or due to a data zone being interpreted as code. When a speculative read occurs outside a
1353     #    controlled region (intentionally used by software), it could cause an unwanted cache eviction.
1354     #   To prevent speculative reads from causing an eviction, the unused cache ranges are set
1355     #    to UC type. Only the actively used regions (stack, heap) are reflected in the MTRRs.
1356     #    Note: some core stack regions will share an MTRR since the control granularity is much
1357     #    larger than the allocated stack zone. The allocation algorithm must account for this 'extra'
1358     #    space covered by the MTRR when parseling out cache space for the various uses. In some cases
1359     #    this could reduce the amount of EXE cache available to a core. see cpuCacheInit.c
1360     #
1361     # Outcome of this block is that:   (Note the MTRR map at the top of the file)
1362     #   ebp - start address of stack block
1363     #   ebx - [31:16] - MTRR MSR address
1364     #       - [15:8]  - slot# in MTRR register
1365     #       - [7:0]   - block size in #4K blocks
1366     # review: ESI[31:24]=Flags; SI[15,8]= Node#; SI[7,0]= core# (relative to node)
1367     #
1368
1369     mov     %si, %ax                      # Load node, core
1370     #.if (al == 0)                       # Is a core 0?
1371     or %al, %al
1372     jne 1f
1373         #.if (ah == 0)                   # Is Node 0? (BSP)
1374         or %ah, %ah
1375         jne 2f
1376             # Is BSP, assign a 64K stack
1377             mov     $((AMD_MTRR_FIX64k_00000 << 16) + (3 << 8) + (BSP_STACK_SIZE  / 0x1000)), %ebx
1378             mov     $BSP_STACK_BASE_ADDR, %ebp
1379             jmp     0f
1380         #.else   # node 1 to 7, core0
1381         2:
1382             # Is a Core0 of secondary node, assign 16K stacks
1383             mov     $AMD_MTRR_FIX16k_80000, %bx
1384             shl     $16, %ebx             #
1385             mov     %ah, %bh              # Node# is used as slot#
1386             mov     $(CORE0_STACK_SIZE / 0x1000), %bl
1387             mov     %ah, %al              # Base = (Node# * Size)#
1388             mul     %bl                  #
1389             movzx   %ax, %eax             #
1390             shl     $12, %eax             # Expand back to full byte count (* 4K)
1391             add     $CORE0_STACK_BASE_ADDR, %eax
1392             mov     %eax, %ebp
1393         #.endif
1394         jmp 0f
1395     #.else    #core 1 thru core 7
1396     1:
1397         # Is core 1-7 of any node, assign 4K stacks
1398         mov     $8, %al                   # CoreIndex = ( (Node# * 8) ...
1399         mul     %ah                      #
1400         mov     %si, %bx                  #
1401         add     %bl, %al                  #         ...  + Core#)#
1402
1403         mov     $AMD_MTRR_FIX64k_00000, %bx
1404         shl     $16, %ebx                 #
1405         mov     %al, %bh                  # Slot# = (CoreIndex / 16) + 4#
1406         shr     $4, %bh                   #
1407         add     $4, %bh                   #
1408         mov     $(CORE1_STACK_SIZE / 0x1000), %bl
1409
1410         mul     %bl                      # Base = ( (CoreIndex * Size) ...
1411         movzx   %ax, %eax                 #
1412         shl     $12, %eax                 # Expand back to full byte count (* 4K)
1413         add     $CORE1_STACK_BASE_ADDR, %eax #     ...   + Base_Addr)#
1414         mov     %eax, %ebp
1415     #.endif
1416     0:
1417
1418     # Now set the MTRR. Add this to already existing settings (don't clear any MTRR)
1419     mov     $WB_DRAM_TYPE, %edi           # Load Cache type in 1st slot
1420     mov     %bh, %cl                      # ShiftCount =  ((slot#   ...
1421     and     $0x03, %cl                     #   ...  % 4)             ...
1422     shl     $0x03, %cl                       #   ...  * 8)#
1423     shl     %cl, %edi                     # Cache type is now in correct position
1424     ror     $16, %ebx                     # Get the MTRR address
1425     movzx   %bx, %ecx                     #
1426     rol     $16, %ebx                     # Put slot# & size back in BX
1427     _RDMSR                              # Read-modify-write the MSR
1428     #.if (bh < 4)                        # Is value in lower or upper half of MSR?
1429     cmp $4, %bh
1430     jae 1f
1431         or      %edi, %eax                #
1432         jmp     0f
1433     #.else
1434     1:                               #
1435         or      %edi, %edx                #
1436     #.endif                              #
1437     0:
1438     _WRMSR                              #
1439
1440     # Enable MTRR defaults as UC type
1441     mov     $AMD_MTRR_DEFTYPE, %ecx       # MSR:0000_02FF
1442     _RDMSR                              # Read-modify-write the MSR
1443     bts     $MTRR_DEF_TYPE_EN, %eax       # MtrrDefTypeEn
1444     bts     $MTRR_DEF_TYPE_FIX_EN, %eax   # MtrrDefTypeFixEn
1445     _WRMSR
1446
1447     # Close the modification window on the Fixed MTRRs
1448     mov     $MTRR_SYS_CFG, %ecx           # MSR:0C001_0010
1449     _RDMSR
1450     bts     $MTRR_FIX_DRAM_EN, %eax       # MtrrFixDramEn
1451     bts     $MTRR_VAR_DRAM_EN, %eax       # variable MTRR enable bit
1452     btr     $MTRR_FIX_DRAM_MOD_EN, %eax   # Turn off modification enable bit
1453     _WRMSR
1454
1455     # Enable caching in CR0
1456     mov     %cr0, %eax                    # Enable WT/WB cache
1457     btr     $CR0_PG, %eax                     # Make sure paging is disabled
1458     btr     $CR0_CD, %eax                     # Clear CR0 NW and CD
1459     btr     $CR0_NW, %eax
1460     mov     %eax, %cr0
1461
1462     # Use the Stack Base & size to calculate SS and ESP values
1463     # review:
1464     #       esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
1465     #       ebp - start address of stack block
1466     #       ebx - [31:16] - MTRR MSR address
1467     #           - [15:8]  - slot# in MTRR register
1468     #           - [7:0]   - block size in #4K blocks
1469     #
1470     mov     %ebp, %esp                    # Initialize the stack pointer
1471     mov     %esp, %edi                    # Copy the stack start to edi
1472     movzx   %bl, %bx
1473     movzx   %bx, %ebx                     # Clear upper ebx, don't need MSR addr anymore
1474     shl     $12, %ebx                     # Make size full byte count (* 4K)
1475     add     %ebx, %esp                    # Set the Stack Pointer as full linear address
1476     sub     $4, %esp
1477     #
1478     # review:
1479     #       esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
1480     #       edi - 32b start address of stack block
1481     #       ebx - size of stack block
1482     #       esp - 32b linear stack pointer
1483     #
1484
1485     # Determine mode for SS base;
1486     mov     %cr0, %ecx                    # Check for 32-bit protect mode
1487     bt      $CR0_PE, %ecx                 #
1488     #.if (!carry?)                       # PE=0 means real mode
1489     jc      Protected32Mode
1490     mov     %cs, %cx                      # PE=1
1491     cmp     $0x0D000, %cx                  # Check for CS
1492     jb      Protected32Mode             # If CS < D000, it is a selector instead of a segment
1493             # alter SS:ESP for 16b Real Mode:
1494 Real16bMode:
1495     mov     %edi, %eax
1496     shr     $4, %eax                      # Create a Real Mode segment for ss, ds, es
1497     mov     %ax, %ss
1498     mov     %ax, %ds
1499     mov     %ax, %es
1500     shl     $4, %eax
1501     sub     %eax, %edi                    # Adjust the clearing pointer for Seg:Offset mode
1502     mov     %ebx, %esp                    # Make SP an offset from SS
1503     sub     $4, %esp              #
1504     #    .endif                          # endif
1505     # #else
1506     #   Default is to use Protected 32b Mode
1507     #.endif
1508     ;
1509 Protected32Mode:
1510     #
1511     # Clear The Stack
1512     #   Now that we have set the location and the MTRRs, initialize the cache by
1513     #   reading then writing to zero all of the stack area.
1514     # review:
1515     #       ss  - Stack base
1516     #       esp - stack pointer
1517     #       ebx - size of stack block
1518     #       esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
1519     #       edi -  address of start of stack block
1520     #
1521
1522 ClearTheStack:                          # Stack base is in SS, stack pointer is in ESP
1523     shr     $2, %ebx                      # ebx = stack block size in dwords
1524     mov     %bx, %cx                      #
1525     # Check our flags - Don't clear an existing stack
1526     #.if ( !(esi & 0FF000000h))          # Check our flags
1527     test    $(1 << FLAG_STACK_REENTRY), %esi
1528     jne 1f
1529         cld
1530         mov     %edi, %esi
1531         rep     lodsl (%esi)    # Pre-load the range
1532         xor     %eax, %eax
1533         mov     %bx, %cx
1534         mov     %edi, %esi                # Preserve base for push on stack
1535         rep     stosl (%edi)    # Clear the range
1536         movl     $0x0ABCDDCBA, (%esp) # Put marker in top stack dword
1537         shl     $2, %ebx                  # Put stack size and base
1538         push    %ebx                     #  in top of stack
1539         push    %esi
1540
1541         mov     %ebx, %ecx                # Return size of stack in bytes
1542         xor     %eax, %eax                # eax = 0 : no error return code
1543         jmp     0f
1544     #.else
1545     1:
1546         movzx   %cx, %ecx
1547         shl     $2, %ecx                  # Return size of stack in bytes
1548         mov     %esi, %eax
1549         shr     $24, %eax                 # Keep the flags as part of the error report
1550         or      $0x40000000, %eax          # eax = AGESA_WARNING (Stack has already been set up)
1551     #.endif
1552     0:
1553
1554     movd        %mm0, %ebx                # Restore return address
1555     movd        %mm1, %ebp
1556 .endm
1557
1558 /*****************************************************************************
1559 * AMD_DISABLE_STACK:  Destroy the stack inside the cache. This routine
1560 *                     should only be executed on the BSP
1561 *
1562 *   In:
1563 *       none
1564 *
1565 *   Out:
1566 *       EAX = AGESA_SUCCESS
1567 *
1568 *   Preserved:
1569 *       ebx
1570 *   Destroyed:
1571 *       eax, ecx, edx, esp
1572 *****************************************************************************/
1573 .macro  AMD_DISABLE_STACK
1574
1575     mov     %ebx, %esp                    # Save return address
1576
1577     # get node/core/flags of current executing core
1578     GET_NODE_ID_CORE_ID                 # Sets ESI[15,8]= Node#; ESI[7,0]= core# (relative to node)
1579
1580     # Turn on modification enable bit
1581     mov     $MTRR_SYS_CFG, %ecx           # MSR:C001_0010
1582     _RDMSR
1583     bts     $MTRR_FIX_DRAM_MOD_EN, %eax   # Enable modifications
1584     _WRMSR
1585
1586     # Set lower 640K MTRRs for Write-Back memory caching
1587     mov     $AMD_MTRR_FIX64k_00000, %ecx
1588     mov     $0x1E1E1E1E, %eax
1589     mov     %eax, %edx
1590     _WRMSR                              # 0 - 512K = WB Mem
1591     mov     $AMD_MTRR_FIX16k_80000, %ecx
1592     _WRMSR                              # 512K - 640K = WB Mem
1593
1594     # Turn off modification enable bit
1595     mov     $MTRR_SYS_CFG, %ecx           # MSR:C001_0010
1596     _RDMSR
1597     btr     $MTRR_FIX_DRAM_MOD_EN, %eax   # Disable modification
1598     _WRMSR
1599
1600     AMD_DISABLE_STACK_FAMILY_HOOK       # Re-Enable 'normal' cache operations
1601
1602     mov     %esp, %ebx
1603     xor     %eax, %eax
1604
1605 .endm
1606