AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / cpcarmac.inc
1 ;*****************************************************************************
2 ; AMD Generic Encapsulated Software Architecture
3 ;
4 ;  Workfile: cpcarmac.inc    $Revision:: 50472   $    $Date:: 2011-04-11 01:57:56 -0600 (Mon, 11 Apr 2011) $
5 ;
6 ; Description: Code to setup and break down cache-as-stack
7 ;
8 ;*****************************************************************************
9 ;
10 ; Copyright (C) 2012 Advanced Micro Devices, Inc.
11 ; All rights reserved.
12 ;
13 ; Redistribution and use in source and binary forms, with or without
14 ; modification, are permitted provided that the following conditions are met:
15 ;     * Redistributions of source code must retain the above copyright
16 ;       notice, this list of conditions and the following disclaimer.
17 ;     * Redistributions in binary form must reproduce the above copyright
18 ;       notice, this list of conditions and the following disclaimer in the
19 ;       documentation and/or other materials provided with the distribution.
20 ;     * Neither the name of Advanced Micro Devices, Inc. nor the names of
21 ;       its contributors may be used to endorse or promote products derived
22 ;       from this software without specific prior written permission.
23 ;
24 ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 ; DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
28 ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 ;
35 ;*****************************************************************************
36
37     .XLIST
38     INCLUDE cpcar.inc
39     .LIST
40     .586P
41     .mmx
42
43 ;======================================================================
44 ; AMD_ENABLE_STACK:  Setup a stack
45 ;
46 ;   In:
47 ;       EBX  = Return address (preserved)
48 ;
49 ;   Out:
50 ;       SS:ESP - Our new private stack location
51 ;
52 ;       EAX = AGESA_STATUS
53 ;       EDX = Return status code if EAX contains a return code of higher
54 ;             severity than AGESA_SUCCESS
55 ;       ECX = Stack size in bytes
56 ;
57 ;   Requirements:
58 ;       * This routine presently is limited to a max of 64 processor cores
59 ;   Preserved:
60 ;       ebx ebp
61 ;   Destroyed:
62 ;       eax, ecx, edx, edi, esi, ds, es, ss, esp
63 ;       mmx0, mmx1, mmx5
64 ;
65 ;   Description:
66 ; Fixed MTRR address allocation to cores:
67 ; The BSP gets 64K of stack, Core0 of each node gets 16K of stack, all other cores get 4K.
68 ; There is a max of 1 BSP, 7 core0s and 56 other cores.
69 ; Although each core has it's own cache storage, they share the address space. Each core must
70 ; be assigned a private and unique address space for its stack. To support legacy systems,
71 ; the stack needs to be within the legacy address space (1st 1Meg). Room must also be reserved
72 ; for the other legacy elements (Interrupt vectors, BIOS ROM, video buffer, etc.)
73 ;
74 ; 80000h                                        40000h                                      00000h
75 ;     +----------+----------+----------+----------+----------+----------+----------+----------+
76 ; 64K |          |          |          |          |          |          |          |          |  64K  ea
77 ;  ea +----------+----------+----------+----------+----------+----------+----------+----------+
78 ;     |                             MTRR 0000_0250 MTRRfix64K_00000                           |
79 ;     +----------+----------+----------+----------+----------+----------+----------+----------+
80 ;     |  7 ,  6  |  5 ,  4  |  3 ,  2  |  1 ,  0  |     0    |          |          |          | <-node
81 ;     |7..1,7..1 |7..1,7..1 |7..1,7..1 |7..1,7..1 |     0    |          |          |          | <-core
82 ;     +----------+----------+----------+----------+----------+----------+----------+----------+
83 ;
84 ; C0000h                       B0000h                      A0000h                      90000h                      80000h
85 ;     +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
86 ;16K  |      |      |      |      |      |      |      |      |      |      |      |      |      |      |      |      |
87 ; ea  +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
88 ;     |              MTRR 0259 MTRRfix16K_A0000               |             MTRR 0258 MTRRfix16K_80000                |
89 ;     +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
90 ;     | > Dis|play B|uffer |   <  |      |      |      |      |   7  |  6   |  5   |  4   |  3   |  2   |  1   |      | <-node
91 ;     | >   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
92 ;     +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
93 ;
94 ; E0000h                                            D0000h                                         C0000h
95 ;     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
96 ; 4K  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  4K  ea
97 ;  ea +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
98 ;     |  026B MTRRfix4K_D8000 | 026A MTRRfix4K_D0000  | 0269 MTRRfix4K_C8000  | 0268 MTRRfix4K_C0000  |
99 ;     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
100 ;     |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | >| V| I| D| E| O|  |B |I |O |S |  |A |r |e |a<|
101 ;     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
102 ;
103 ; 100000h                                           F0000h                                          E0000h
104 ;     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
105 ;     |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  4K  ea
106 ;     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
107 ;     |  026F MTRRfix4K_F8000 | 026E MTRRfix4K_F0000  | 026D MTRRfix4K_E8000  | 026C MTRRfix4K_E0000  |
108 ;     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
109 ;     | >|MA|IN| B|IO|S |RA|NG|E |  |  |  |  |  |  |< | >|EX|TE|ND|ED| B|IO|S |ZO|NE|  |  |  |  |  |< |
110 ;     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
111 ;======================================================================
112 AMD_ENABLE_STACK MACRO
113   local AmdEnableStackExit
114
115 ;   Note that SS:ESP will be default stack.  Note that this stack
116 ;   routine will not be used after memory has been initialized.  Because
117 ;   of its limited lifetime, it will not conflict with typical PCI devices.
118     movd    mm0, ebx                    ; Put return address in a safe place
119     movd    mm1, ebp                    ; Save some other user registers
120
121     ; get node id and core id of current executing core
122     GET_NODE_ID_CORE_ID                 ; Sets ESI[15,8]= Node#; ESI[7,0]= core# (relative to node)
123     ; Note: ESI[31:24] are used for flags:  Unrecognized Family,  Is_Primary core,  Stack already established
124
125     ; If we detected an unknown processor family or core combination, return AGESA_FATAL.
126     .if (esi & (1 SHL FLAG_UNKNOWN_FAMILY))
127       mov edx, CPU_EVENT_UNKNOWN_PROCESSOR_FAMILY
128       mov eax, AGESA_FATAL
129       jmp AmdEnableStackExit
130     .elseif (esi & (1 SHL FLAG_CORE_NOT_IDENTIFIED))
131       mov edx, CPU_EVENT_CORE_NOT_IDENTIFIED
132       mov eax, AGESA_FATAL
133       jmp AmdEnableStackExit
134     .endif
135
136     ; determine if stack is already enabled. We are using the DefType MSR for this determination.
137     ; It is =0 after reset; CAR setup sets it to enable the MTRRs
138     mov     eax, cr0                    ; Is cache enabled? (CD or NW bit set)
139     CR0_MASK    TEXTEQU %((1 SHL CR0_CD) OR (1 SHL CR0_NW))
140     .if (!(eax & CR0_MASK))
141         mov     ecx, AMD_MTRR_DEFTYPE   ; MSR:0000_02FF
142         _RDMSR                          ; Are either of the default types enabled? (MTRR_DEF_TYPE_EN + MTRR_DEF_TYPE_FIX_EN)
143         MSR_MASK    TEXTEQU %((1 SHL MTRR_DEF_TYPE_EN)+(1 SHL MTRR_DEF_TYPE_FIX_EN))
144         .if (eax & MSR_MASK)
145             bts     esi, FLAG_STACK_REENTRY     ; indicate stack has already been initialized
146         .endif
147     .endif
148
149     ; Set node to map the first 16MB to node 0; 0000_0000 to 00FF_FFFF as DRAM
150     mov     ebx, esi                    ; Get my Node/Core info
151     xor     bl, bl
152     shl     bh, 3                       ; Isolate my node#, match alignment for PCI Dev#
153     mov     eax, 8000C144h              ; D18F1x44:DRAM Base/Limit; N is Base, N+4 is Limit
154     add     ah, bh
155     mov     ebx, eax                    ; Save PCI address for Base/Limit pair
156
157     mov     dx, 0CF8h
158     out     dx, eax
159     add     dx, 4
160     xor     eax, eax                    ; Least Significant bit is AD24 so 0 sets mask of 00FF_FFFF (16MB)
161     out     dx, eax                     ; DRAM Limit = node0, no interleave
162
163     mov     eax, ebx
164     sub     eax, 4                      ; Now point to the Base register
165     mov     dx, 0CF8h
166     out     dx, eax
167     add     dx, 4
168     mov     eax, 00000003h              ; Set the read and write enable bits
169     out     dx, eax                     ; DRAM Base = 0x0000, R/W
170
171     AMD_ENABLE_STACK_FAMILY_HOOK
172
173     ; Init CPU MSRs for our init routines
174     mov     ecx, MTRR_SYS_CFG           ; SYS_CFG
175     _RDMSR
176     bts     eax, MTRR_FIX_DRAM_MOD_EN   ; Turn on modification enable bit
177     _WRMSR
178
179     mov     eax, esi
180     bt      eax, FLAG_STACK_REENTRY     ; Is this a 2nd entry?
181     .if (!carry?)                       ;   On a re-entry, do not clear MTRRs or reset TOM; just reset the stack SS:ESP
182         bt      eax, FLAG_IS_PRIMARY    ;   Is this core the primary in a compute unit?
183         .if (carry?)                    ;     Families using shared groups do not need to clear the MTRRs since that is done at power-on reset
184             ;  Note: Relying on MSRs to be cleared to 0's at reset for families w/shared cores
185             ; Clear all variable and Fixed MTRRs for non-shared cores
186             mov     ecx, AMD_MTRR_VARIABLE_BASE0
187             xor     eax, eax
188             xor     edx, edx
189             .while (cl != 10h)                  ; Variable MTRRphysBase[n] and MTRRphysMask[n]
190                 _WRMSR
191                 inc     cl
192             .endw
193             mov     cx, AMD_MTRR_FIX64k_00000   ; MSR:0000_0250
194             _WRMSR
195             mov     cx, AMD_MTRR_FIX16k_80000   ; MSR:0000_0258
196             _WRMSR
197             mov     cx, AMD_MTRR_FIX16k_A0000   ; MSR:0000_0259
198             _WRMSR
199             mov     cx, AMD_MTRR_FIX4k_C0000    ; Fixed 4Ks: MTRRfix4K_C0000 to MTRRfix4K_F8000
200             .while (cl != 70h)
201                 _WRMSR
202                 inc     cl
203             .endw
204
205             ; Set TOP_MEM (C001_001A) for non-shared cores to 16M. This will be increased at heap init.
206             ;  - not strictly needed since the FixedMTRRs take presedence.
207             mov     eax, (16 * 1024 * 1024)
208             mov     ecx, TOP_MEM                ; MSR:C001_001A
209             _WRMSR
210         .endif                          ;   End Is_Primary
211     .endif                              ; End Stack_ReEntry
212
213     ; Clear IORRs (C001_0016-19) and TOM2(C001_001D) for all cores
214     xor     eax, eax
215     xor     edx, edx
216     mov     ecx, IORR_BASE              ; MSR:C001_0016 - 0019
217     .while (cl != 1Ah)
218         _WRMSR
219         inc     cl
220     .endw
221     mov     ecx, TOP_MEM2               ; MSR:C001_001D
222     _WRMSR
223
224     ; setup MTTRs for stacks
225     ;   A speculative read can be generated by a speculative fetch mis-aligned in a code zone
226     ;    or due to a data zone being interpreted as code. When a speculative read occurs outside a
227     ;    controlled region (intentionally used by software), it could cause an unwanted cache eviction.
228     ;   To prevent speculative reads from causing an eviction, the unused cache ranges are set
229     ;    to UC type. Only the actively used regions (stack, heap) are reflected in the MTRRs.
230     ;    Note: some core stack regions will share an MTRR since the control granularity is much
231     ;    larger than the allocated stack zone. The allocation algorithm must account for this 'extra'
232     ;    space covered by the MTRR when parseling out cache space for the various uses. In some cases
233     ;    this could reduce the amount of EXE cache available to a core. see cpuCacheInit.c
234     ;
235     ; Outcome of this block is that:   (Note the MTRR map at the top of the file)
236     ;   ebp - start address of stack block
237     ;   ebx - [31:16] - MTRR MSR address
238     ;       - [15:8]  - slot# in MTRR register
239     ;       - [7:0]   - block size in #4K blocks
240     ; review: ESI[31:24]=Flags; SI[15,8]= Node#; SI[7,0]= core# (relative to node)
241     ;
242
243     mov     eax, esi                    ; Load Flags, node, core
244     .if (al == 0)                       ; Is a core 0?
245         .if (ah == 0)                   ; Is Node 0? (BSP)
246             ; Is BSP, assign a 64K stack; for F10/F12, foce to a 32K stack
247             mov     ebx, ((AMD_MTRR_FIX64k_00000 SHL 16) + (3 SHL 8) + (BSP_STACK_SIZE_64K  / 1000h))
248             bt      eax, FLAG_FORCE_32K_STACK
249             .if (carry?)
250                 mov     ebx, ((AMD_MTRR_FIX64k_00000 SHL 16) + (3 SHL 8) + (BSP_STACK_SIZE_32K  / 1000h))
251             .endif
252             mov     ebp, BSP_STACK_BASE_ADDR
253         .else   ; node 1 to 7, core0
254             ; Is a Core0 of secondary node, assign 16K stacks
255             mov     bx, AMD_MTRR_FIX16k_80000
256             shl     ebx, 16             ;
257             mov     bh, ah              ; Node# is used as slot#
258             mov     bl, (CORE0_STACK_SIZE / 1000h)
259             mov     al, ah              ; Base = (Node# * Size);
260             mul     bl                  ;
261             movzx   eax, ax             ;
262             shl     eax, 12             ; Expand back to full byte count (* 4K)
263             add     eax, CORE0_STACK_BASE_ADDR
264             mov     ebp, eax
265         .endif
266     .else    ;core 1 thru core 7
267         ; Is core 1-7 of any node, assign 4K stacks
268         mov     al, 8                   ; CoreIndex = ( (Node# * 8) ...
269         mul     ah                      ;
270         mov     bx, si                  ;
271         add     al, bl                  ;         ...  + Core#);
272
273         mov     bx, AMD_MTRR_FIX64k_00000
274         shl     ebx, 16                 ;
275         mov     bh, al                  ; Slot# = (CoreIndex / 16) + 4;
276         shr     bh, 4                   ;
277         add     bh, 4                   ;
278         mov     bl, (CORE1_STACK_SIZE / 1000h)
279
280         mul     bl                      ; Base = ( (CoreIndex * Size) ...
281         movzx   eax, ax                 ;
282         shl     eax, 12                 ; Expand back to full byte count (* 4K)
283         add     eax, CORE1_STACK_BASE_ADDR ;     ...   + Base_Addr);
284         mov     ebp, eax
285     .endif
286
287     ; Now set the MTRR. Add this to already existing settings (don't clear any MTRR)
288     mov     edi, WB_DRAM_TYPE           ; Load Cache type in 1st slot
289     mov     cl, bh                      ; ShiftCount =  ((slot#   ...
290     and     cl, 03h                     ;   ...  % 4)             ...
291     shl     cl, 3                       ;   ...  * 8);
292     shl     edi, cl                     ; Cache type is now in correct position
293     ror     ebx, 16                     ; Get the MTRR address
294     movzx   ecx, bx                     ;
295     rol     ebx, 16                     ; Put slot# & size back in BX
296     _RDMSR                              ; Read-modify-write the MSR
297     .if (bh < 4)                        ; Is value in lower or upper half of MSR?
298         or      eax, edi                ;
299     .else                               ;
300         or      edx, edi                ;
301     .endif                              ;
302     _WRMSR                              ;
303
304     ; Enable MTRR defaults as UC type
305     mov     ecx, AMD_MTRR_DEFTYPE       ; MSR:0000_02FF
306     _RDMSR                              ; Read-modify-write the MSR
307     bts     eax, MTRR_DEF_TYPE_EN       ; MtrrDefTypeEn
308     bts     eax, MTRR_DEF_TYPE_FIX_EN   ; MtrrDefTypeFixEn
309     _WRMSR
310
311     ; Close the modification window on the Fixed MTRRs
312     mov     ecx, MTRR_SYS_CFG           ; MSR:0C001_0010
313     _RDMSR
314     bts     eax, MTRR_FIX_DRAM_EN       ; MtrrFixDramEn
315     bts     eax, MTRR_VAR_DRAM_EN       ; variable MTRR enable bit
316     btr     eax, MTRR_FIX_DRAM_MOD_EN   ; Turn off modification enable bit
317     _WRMSR
318
319     ; Enable caching in CR0
320     mov     eax, CR0                    ; Enable WT/WB cache
321     btr     eax, CR0_PG                 ; Make sure paging is disabled
322     btr     eax, CR0_CD                 ; Clear CR0 NW and CD
323     btr     eax, CR0_NW
324     mov     CR0, eax
325
326     ; Use the Stack Base & size to calculate SS and ESP values
327     ; review:
328     ;       esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
329     ;       ebp - start address of stack block
330     ;       ebx - [31:16] - MTRR MSR address
331     ;           - [15:8]  - slot# in MTRR register
332     ;           - [7:0]   - block size in #4K blocks
333     ;
334     mov     esp, ebp                    ; Initialize the stack pointer
335     mov     edi, esp                    ; Copy the stack start to edi
336     movzx   bx, bl
337     movzx   ebx, bx                     ; Clear upper ebx, don't need MSR addr anymore
338     shl     ebx, 12                     ; Make size full byte count (* 4K)
339     add     esp, ebx                    ; Set the Stack Pointer as full linear address
340     sub     esp, 4
341     ;
342     ; review:
343     ;       esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
344     ;       edi - 32b start address of stack block
345     ;       ebx - size of stack block
346     ;       esp - 32b linear stack pointer
347     ;
348
349     ; Determine mode for SS base;
350     mov     ecx, CR0                    ; Check for 32-bit protect mode
351     bt      ecx, CR0_PE                 ;
352     .if (!carry?)                       ; PE=0 means real mode
353         mov     cx, cs                  ;
354         .if (cx >= 0D000h)              ; If CS >= D000, it's a real mode segment. PM selector would be 08-> 1000
355             ; alter SS:ESP for 16b Real Mode:
356             mov     eax, edi            ;
357             shr     eax, 4              ;   Create a Real Mode segment for ss, ds, es
358             mov     ss, ax              ;
359             mov     ds, ax              ;
360             mov     es, ax              ;
361             shl     eax, 4              ;
362             sub     edi, eax            ;   Adjust the clearing pointer for Seg:Offset mode
363             mov     esp, ebx            ;   Make SP an offset from SS
364             sub     esp, 4              ;
365         .endif                          ; endif
366     ; else
367     ;   Default is to use Protected 32b Mode
368     .endif
369     ;
370     ; Clear The Stack
371     ;   Now that we have set the location and the MTRRs, initialize the cache by
372     ;   reading then writing to zero all of the stack area.
373     ; review:
374     ;       ss  - Stack base
375     ;       esp - stack pointer
376     ;       ebx - size of stack block
377     ;       esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node)
378     ;       edi -  address of start of stack block
379     ;
380     shr     ebx, 2                      ;
381     mov     cx, bx                      ; set cx for size count of DWORDS
382     ; Check our flags - Don't clear an existing stack
383     .if ( !(esi & (1 SHL FLAG_STACK_REENTRY)) )
384         cld
385         mov     esi, edi
386         rep     lods DWORD PTR [esi]    ; Pre-load the range
387         xor     eax, eax
388         mov     cx, bx
389         mov     esi, edi                ; Preserve base for push on stack
390         rep     stos DWORD PTR [edi]    ; Clear the range
391         mov     DWORD PTR [esp], 0ABCDDCBAh ; Put marker in top stack dword
392         shl     ebx, 2                  ; Put stack size and base
393         push    ebx                     ;  in top of stack
394         push    esi
395
396         mov     ecx, ebx                ; Return size of stack in bytes
397         mov     eax, AGESA_SUCCESS      ; eax = AGESA_SUCCESS : no error return code
398     .else
399         movzx   ecx, cx
400         shl     ecx, 2                  ; Return size of stack, in bytes
401         mov     edx, CPU_EVENT_STACK_REENTRY
402         mov     eax, AGESA_WARNING      ; eax = AGESA_WARNING (Stack has already been set up)
403     .endif
404
405 AmdEnableStackExit:
406     movd        ebx, mm0                ; Restore return address
407     movd        ebp, mm1
408 ENDM
409
410 ;======================================================================
411 ; AMD_DISABLE_STACK:  Destroy the stack inside the cache. This routine
412 ;                     should only be executed on the BSP
413 ;
414 ;   In:
415 ;       none
416 ;
417 ;   Out:
418 ;       EAX = AGESA_SUCCESS
419 ;
420 ;   Preserved:
421 ;       ebx
422 ;   Destroyed:
423 ;       eax, ecx, edx, esp, mmx5
424 ;======================================================================
425 AMD_DISABLE_STACK MACRO
426
427     mov     esp, ebx                    ; Save return address
428
429     ; get node/core/flags of current executing core
430     GET_NODE_ID_CORE_ID                 ; Sets ESI[15,8]= Node#; ESI[7,0]= core# (relative to node)
431
432     ; Turn on modification enable bit
433     mov     ecx, MTRR_SYS_CFG           ; MSR:C001_0010
434     _RDMSR
435     bts     eax, MTRR_FIX_DRAM_MOD_EN   ; Enable modifications
436     _WRMSR
437
438     ; Set lower 640K MTRRs for Write-Back memory caching
439     mov     ecx, AMD_MTRR_FIX64k_00000
440     mov     eax, 1E1E1E1Eh
441     mov     edx, eax
442     _WRMSR                              ; 0 - 512K = WB Mem
443     mov     ecx, AMD_MTRR_FIX16k_80000
444     _WRMSR                              ; 512K - 640K = WB Mem
445
446     ; Turn off modification enable bit
447     mov     ecx, MTRR_SYS_CFG           ; MSR:C001_0010
448     _RDMSR
449     btr     eax, MTRR_FIX_DRAM_MOD_EN   ; Disable modification
450     _WRMSR
451
452     AMD_DISABLE_STACK_FAMILY_HOOK       ; Re-Enable 'normal' cache operations
453
454     mov     ebx, esp                    ; restore return address (ebx)
455     xor     eax, eax
456
457 ENDM