diff options
Diffstat (limited to 'src/vendorcode/amd/agesa/f15/cpcarmac.inc')
-rw-r--r-- | src/vendorcode/amd/agesa/f15/cpcarmac.inc | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f15/cpcarmac.inc b/src/vendorcode/amd/agesa/f15/cpcarmac.inc new file mode 100644 index 0000000000..24a607377c --- /dev/null +++ b/src/vendorcode/amd/agesa/f15/cpcarmac.inc @@ -0,0 +1,457 @@ +;***************************************************************************** +; AMD Generic Encapsulated Software Architecture +; +; Workfile: cpcarmac.inc $Revision:: 50472 $ $Date:: 2011-04-11 01:57:56 -0600 (Mon, 11 Apr 2011) $ +; +; Description: Code to setup and break down cache-as-stack +; +;***************************************************************************** +; +; Copyright (C) 2012 Advanced Micro Devices, Inc. +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of Advanced Micro Devices, Inc. nor the names of +; its contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; +;***************************************************************************** + + .XLIST + INCLUDE cpcar.inc + .LIST + .586P + .mmx + +;====================================================================== +; AMD_ENABLE_STACK: Setup a stack +; +; In: +; EBX = Return address (preserved) +; +; Out: +; SS:ESP - Our new private stack location +; +; EAX = AGESA_STATUS +; EDX = Return status code if EAX contains a return code of higher +; severity than AGESA_SUCCESS +; ECX = Stack size in bytes +; +; Requirements: +; * This routine presently is limited to a max of 64 processor cores +; Preserved: +; ebx ebp +; Destroyed: +; eax, ecx, edx, edi, esi, ds, es, ss, esp +; mmx0, mmx1, mmx5 +; +; Description: +; Fixed MTRR address allocation to cores: +; The BSP gets 64K of stack, Core0 of each node gets 16K of stack, all other cores get 4K. +; There is a max of 1 BSP, 7 core0s and 56 other cores. +; Although each core has it's own cache storage, they share the address space. Each core must +; be assigned a private and unique address space for its stack. To support legacy systems, +; the stack needs to be within the legacy address space (1st 1Meg). Room must also be reserved +; for the other legacy elements (Interrupt vectors, BIOS ROM, video buffer, etc.) +; +; 80000h 40000h 00000h +; +----------+----------+----------+----------+----------+----------+----------+----------+ +; 64K | | | | | | | | | 64K ea +; ea +----------+----------+----------+----------+----------+----------+----------+----------+ +; | MTRR 0000_0250 MTRRfix64K_00000 | +; +----------+----------+----------+----------+----------+----------+----------+----------+ +; | 7 , 6 | 5 , 4 | 3 , 2 | 1 , 0 | 0 | | | | <-node +; |7..1,7..1 |7..1,7..1 |7..1,7..1 |7..1,7..1 | 0 | | | | <-core +; +----------+----------+----------+----------+----------+----------+----------+----------+ +; +; C0000h B0000h A0000h 90000h 80000h +; +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+ +;16K | | | | | | | | | | | | | | | | | +; ea +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+ +; | MTRR 0259 MTRRfix16K_A0000 | MTRR 0258 MTRRfix16K_80000 | +; +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+ +; | > Dis|play B|uffer | < | | | | | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | <-node +; | > 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 +; +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+ +; +; E0000h D0000h C0000h +; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +; 4K | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 4K ea +; ea +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +; | 026B MTRRfix4K_D8000 | 026A MTRRfix4K_D0000 | 0269 MTRRfix4K_C8000 | 0268 MTRRfix4K_C0000 | +; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +; | | | | | | | | | | | | | | | | | >| V| I| D| E| O| |B |I |O |S | |A |r |e |a<| +; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +; +; 100000h F0000h E0000h +; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 4K ea +; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +; | 026F MTRRfix4K_F8000 | 026E MTRRfix4K_F0000 | 026D MTRRfix4K_E8000 | 026C MTRRfix4K_E0000 | +; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +; | >|MA|IN| B|IO|S |RA|NG|E | | | | | | |< | >|EX|TE|ND|ED| B|IO|S |ZO|NE| | | | | |< | +; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +;====================================================================== +AMD_ENABLE_STACK MACRO + local AmdEnableStackExit + +; Note that SS:ESP will be default stack. Note that this stack +; routine will not be used after memory has been initialized. Because +; of its limited lifetime, it will not conflict with typical PCI devices. + movd mm0, ebx ; Put return address in a safe place + movd mm1, ebp ; Save some other user registers + + ; get node id and core id of current executing core + GET_NODE_ID_CORE_ID ; Sets ESI[15,8]= Node#; ESI[7,0]= core# (relative to node) + ; Note: ESI[31:24] are used for flags: Unrecognized Family, Is_Primary core, Stack already established + + ; If we detected an unknown processor family or core combination, return AGESA_FATAL. + .if (esi & (1 SHL FLAG_UNKNOWN_FAMILY)) + mov edx, CPU_EVENT_UNKNOWN_PROCESSOR_FAMILY + mov eax, AGESA_FATAL + jmp AmdEnableStackExit + .elseif (esi & (1 SHL FLAG_CORE_NOT_IDENTIFIED)) + mov edx, CPU_EVENT_CORE_NOT_IDENTIFIED + mov eax, AGESA_FATAL + jmp AmdEnableStackExit + .endif + + ; determine if stack is already enabled. We are using the DefType MSR for this determination. + ; It is =0 after reset; CAR setup sets it to enable the MTRRs + mov eax, cr0 ; Is cache enabled? (CD or NW bit set) + CR0_MASK TEXTEQU %((1 SHL CR0_CD) OR (1 SHL CR0_NW)) + .if (!(eax & CR0_MASK)) + mov ecx, AMD_MTRR_DEFTYPE ; MSR:0000_02FF + _RDMSR ; Are either of the default types enabled? (MTRR_DEF_TYPE_EN + MTRR_DEF_TYPE_FIX_EN) + MSR_MASK TEXTEQU %((1 SHL MTRR_DEF_TYPE_EN)+(1 SHL MTRR_DEF_TYPE_FIX_EN)) + .if (eax & MSR_MASK) + bts esi, FLAG_STACK_REENTRY ; indicate stack has already been initialized + .endif + .endif + + ; Set node to map the first 16MB to node 0; 0000_0000 to 00FF_FFFF as DRAM + mov ebx, esi ; Get my Node/Core info + xor bl, bl + shl bh, 3 ; Isolate my node#, match alignment for PCI Dev# + mov eax, 8000C144h ; D18F1x44:DRAM Base/Limit; N is Base, N+4 is Limit + add ah, bh + mov ebx, eax ; Save PCI address for Base/Limit pair + + mov dx, 0CF8h + out dx, eax + add dx, 4 + xor eax, eax ; Least Significant bit is AD24 so 0 sets mask of 00FF_FFFF (16MB) + out dx, eax ; DRAM Limit = node0, no interleave + + mov eax, ebx + sub eax, 4 ; Now point to the Base register + mov dx, 0CF8h + out dx, eax + add dx, 4 + mov eax, 00000003h ; Set the read and write enable bits + out dx, eax ; DRAM Base = 0x0000, R/W + + AMD_ENABLE_STACK_FAMILY_HOOK + + ; Init CPU MSRs for our init routines + mov ecx, MTRR_SYS_CFG ; SYS_CFG + _RDMSR + bts eax, MTRR_FIX_DRAM_MOD_EN ; Turn on modification enable bit + _WRMSR + + mov eax, esi + bt eax, FLAG_STACK_REENTRY ; Is this a 2nd entry? + .if (!carry?) ; On a re-entry, do not clear MTRRs or reset TOM; just reset the stack SS:ESP + bt eax, FLAG_IS_PRIMARY ; Is this core the primary in a compute unit? + .if (carry?) ; Families using shared groups do not need to clear the MTRRs since that is done at power-on reset + ; Note: Relying on MSRs to be cleared to 0's at reset for families w/shared cores + ; Clear all variable and Fixed MTRRs for non-shared cores + mov ecx, AMD_MTRR_VARIABLE_BASE0 + xor eax, eax + xor edx, edx + .while (cl != 10h) ; Variable MTRRphysBase[n] and MTRRphysMask[n] + _WRMSR + inc cl + .endw + mov cx, AMD_MTRR_FIX64k_00000 ; MSR:0000_0250 + _WRMSR + mov cx, AMD_MTRR_FIX16k_80000 ; MSR:0000_0258 + _WRMSR + mov cx, AMD_MTRR_FIX16k_A0000 ; MSR:0000_0259 + _WRMSR + mov cx, AMD_MTRR_FIX4k_C0000 ; Fixed 4Ks: MTRRfix4K_C0000 to MTRRfix4K_F8000 + .while (cl != 70h) + _WRMSR + inc cl + .endw + + ; Set TOP_MEM (C001_001A) for non-shared cores to 16M. This will be increased at heap init. + ; - not strictly needed since the FixedMTRRs take presedence. + mov eax, (16 * 1024 * 1024) + mov ecx, TOP_MEM ; MSR:C001_001A + _WRMSR + .endif ; End Is_Primary + .endif ; End Stack_ReEntry + + ; Clear IORRs (C001_0016-19) and TOM2(C001_001D) for all cores + xor eax, eax + xor edx, edx + mov ecx, IORR_BASE ; MSR:C001_0016 - 0019 + .while (cl != 1Ah) + _WRMSR + inc cl + .endw + mov ecx, TOP_MEM2 ; MSR:C001_001D + _WRMSR + + ; setup MTTRs for stacks + ; A speculative read can be generated by a speculative fetch mis-aligned in a code zone + ; or due to a data zone being interpreted as code. When a speculative read occurs outside a + ; controlled region (intentionally used by software), it could cause an unwanted cache eviction. + ; To prevent speculative reads from causing an eviction, the unused cache ranges are set + ; to UC type. Only the actively used regions (stack, heap) are reflected in the MTRRs. + ; Note: some core stack regions will share an MTRR since the control granularity is much + ; larger than the allocated stack zone. The allocation algorithm must account for this 'extra' + ; space covered by the MTRR when parseling out cache space for the various uses. In some cases + ; this could reduce the amount of EXE cache available to a core. see cpuCacheInit.c + ; + ; Outcome of this block is that: (Note the MTRR map at the top of the file) + ; ebp - start address of stack block + ; ebx - [31:16] - MTRR MSR address + ; - [15:8] - slot# in MTRR register + ; - [7:0] - block size in #4K blocks + ; review: ESI[31:24]=Flags; SI[15,8]= Node#; SI[7,0]= core# (relative to node) + ; + + mov eax, esi ; Load Flags, node, core + .if (al == 0) ; Is a core 0? + .if (ah == 0) ; Is Node 0? (BSP) + ; Is BSP, assign a 64K stack; for F10/F12, foce to a 32K stack + mov ebx, ((AMD_MTRR_FIX64k_00000 SHL 16) + (3 SHL 8) + (BSP_STACK_SIZE_64K / 1000h)) + bt eax, FLAG_FORCE_32K_STACK + .if (carry?) + mov ebx, ((AMD_MTRR_FIX64k_00000 SHL 16) + (3 SHL 8) + (BSP_STACK_SIZE_32K / 1000h)) + .endif + mov ebp, BSP_STACK_BASE_ADDR + .else ; node 1 to 7, core0 + ; Is a Core0 of secondary node, assign 16K stacks + mov bx, AMD_MTRR_FIX16k_80000 + shl ebx, 16 ; + mov bh, ah ; Node# is used as slot# + mov bl, (CORE0_STACK_SIZE / 1000h) + mov al, ah ; Base = (Node# * Size); + mul bl ; + movzx eax, ax ; + shl eax, 12 ; Expand back to full byte count (* 4K) + add eax, CORE0_STACK_BASE_ADDR + mov ebp, eax + .endif + .else ;core 1 thru core 7 + ; Is core 1-7 of any node, assign 4K stacks + mov al, 8 ; CoreIndex = ( (Node# * 8) ... + mul ah ; + mov bx, si ; + add al, bl ; ... + Core#); + + mov bx, AMD_MTRR_FIX64k_00000 + shl ebx, 16 ; + mov bh, al ; Slot# = (CoreIndex / 16) + 4; + shr bh, 4 ; + add bh, 4 ; + mov bl, (CORE1_STACK_SIZE / 1000h) + + mul bl ; Base = ( (CoreIndex * Size) ... + movzx eax, ax ; + shl eax, 12 ; Expand back to full byte count (* 4K) + add eax, CORE1_STACK_BASE_ADDR ; ... + Base_Addr); + mov ebp, eax + .endif + + ; Now set the MTRR. Add this to already existing settings (don't clear any MTRR) + mov edi, WB_DRAM_TYPE ; Load Cache type in 1st slot + mov cl, bh ; ShiftCount = ((slot# ... + and cl, 03h ; ... % 4) ... + shl cl, 3 ; ... * 8); + shl edi, cl ; Cache type is now in correct position + ror ebx, 16 ; Get the MTRR address + movzx ecx, bx ; + rol ebx, 16 ; Put slot# & size back in BX + _RDMSR ; Read-modify-write the MSR + .if (bh < 4) ; Is value in lower or upper half of MSR? + or eax, edi ; + .else ; + or edx, edi ; + .endif ; + _WRMSR ; + + ; Enable MTRR defaults as UC type + mov ecx, AMD_MTRR_DEFTYPE ; MSR:0000_02FF + _RDMSR ; Read-modify-write the MSR + bts eax, MTRR_DEF_TYPE_EN ; MtrrDefTypeEn + bts eax, MTRR_DEF_TYPE_FIX_EN ; MtrrDefTypeFixEn + _WRMSR + + ; Close the modification window on the Fixed MTRRs + mov ecx, MTRR_SYS_CFG ; MSR:0C001_0010 + _RDMSR + bts eax, MTRR_FIX_DRAM_EN ; MtrrFixDramEn + bts eax, MTRR_VAR_DRAM_EN ; variable MTRR enable bit + btr eax, MTRR_FIX_DRAM_MOD_EN ; Turn off modification enable bit + _WRMSR + + ; Enable caching in CR0 + mov eax, CR0 ; Enable WT/WB cache + btr eax, CR0_PG ; Make sure paging is disabled + btr eax, CR0_CD ; Clear CR0 NW and CD + btr eax, CR0_NW + mov CR0, eax + + ; Use the Stack Base & size to calculate SS and ESP values + ; review: + ; esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node) + ; ebp - start address of stack block + ; ebx - [31:16] - MTRR MSR address + ; - [15:8] - slot# in MTRR register + ; - [7:0] - block size in #4K blocks + ; + mov esp, ebp ; Initialize the stack pointer + mov edi, esp ; Copy the stack start to edi + movzx bx, bl + movzx ebx, bx ; Clear upper ebx, don't need MSR addr anymore + shl ebx, 12 ; Make size full byte count (* 4K) + add esp, ebx ; Set the Stack Pointer as full linear address + sub esp, 4 + ; + ; review: + ; esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node) + ; edi - 32b start address of stack block + ; ebx - size of stack block + ; esp - 32b linear stack pointer + ; + + ; Determine mode for SS base; + mov ecx, CR0 ; Check for 32-bit protect mode + bt ecx, CR0_PE ; + .if (!carry?) ; PE=0 means real mode + mov cx, cs ; + .if (cx >= 0D000h) ; If CS >= D000, it's a real mode segment. PM selector would be 08-> 1000 + ; alter SS:ESP for 16b Real Mode: + mov eax, edi ; + shr eax, 4 ; Create a Real Mode segment for ss, ds, es + mov ss, ax ; + mov ds, ax ; + mov es, ax ; + shl eax, 4 ; + sub edi, eax ; Adjust the clearing pointer for Seg:Offset mode + mov esp, ebx ; Make SP an offset from SS + sub esp, 4 ; + .endif ; endif + ; else + ; Default is to use Protected 32b Mode + .endif + ; + ; Clear The Stack + ; Now that we have set the location and the MTRRs, initialize the cache by + ; reading then writing to zero all of the stack area. + ; review: + ; ss - Stack base + ; esp - stack pointer + ; ebx - size of stack block + ; esi[31:24]=Flags; esi[15,8]= Node#; esi[7,0]= core# (relative to node) + ; edi - address of start of stack block + ; + shr ebx, 2 ; + mov cx, bx ; set cx for size count of DWORDS + ; Check our flags - Don't clear an existing stack + .if ( !(esi & (1 SHL FLAG_STACK_REENTRY)) ) + cld + mov esi, edi + rep lods DWORD PTR [esi] ; Pre-load the range + xor eax, eax + mov cx, bx + mov esi, edi ; Preserve base for push on stack + rep stos DWORD PTR [edi] ; Clear the range + mov DWORD PTR [esp], 0ABCDDCBAh ; Put marker in top stack dword + shl ebx, 2 ; Put stack size and base + push ebx ; in top of stack + push esi + + mov ecx, ebx ; Return size of stack in bytes + mov eax, AGESA_SUCCESS ; eax = AGESA_SUCCESS : no error return code + .else + movzx ecx, cx + shl ecx, 2 ; Return size of stack, in bytes + mov edx, CPU_EVENT_STACK_REENTRY + mov eax, AGESA_WARNING ; eax = AGESA_WARNING (Stack has already been set up) + .endif + +AmdEnableStackExit: + movd ebx, mm0 ; Restore return address + movd ebp, mm1 +ENDM + +;====================================================================== +; AMD_DISABLE_STACK: Destroy the stack inside the cache. This routine +; should only be executed on the BSP +; +; In: +; none +; +; Out: +; EAX = AGESA_SUCCESS +; +; Preserved: +; ebx +; Destroyed: +; eax, ecx, edx, esp, mmx5 +;====================================================================== +AMD_DISABLE_STACK MACRO + + mov esp, ebx ; Save return address + + ; get node/core/flags of current executing core + GET_NODE_ID_CORE_ID ; Sets ESI[15,8]= Node#; ESI[7,0]= core# (relative to node) + + ; Turn on modification enable bit + mov ecx, MTRR_SYS_CFG ; MSR:C001_0010 + _RDMSR + bts eax, MTRR_FIX_DRAM_MOD_EN ; Enable modifications + _WRMSR + + ; Set lower 640K MTRRs for Write-Back memory caching + mov ecx, AMD_MTRR_FIX64k_00000 + mov eax, 1E1E1E1Eh + mov edx, eax + _WRMSR ; 0 - 512K = WB Mem + mov ecx, AMD_MTRR_FIX16k_80000 + _WRMSR ; 512K - 640K = WB Mem + + ; Turn off modification enable bit + mov ecx, MTRR_SYS_CFG ; MSR:C001_0010 + _RDMSR + btr eax, MTRR_FIX_DRAM_MOD_EN ; Disable modification + _WRMSR + + AMD_DISABLE_STACK_FAMILY_HOOK ; Re-Enable 'normal' cache operations + + mov ebx, esp ; restore return address (ebx) + xor eax, eax + +ENDM |