]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / Ia32 / MpFuncs.nasm
index 4bfa084c85a91457a1e60bc5cb5be217ca6fb3a7..59db4081d62f4ac1ee829430313b2fb916426676 100644 (file)
@@ -1,12 +1,6 @@
 ;------------------------------------------------------------------------------ ;\r
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
-; This program and the accompanying materials\r
-; are licensed and made available under the terms and conditions of the BSD License\r
-; which accompanies this distribution.  The full text of the license may be found at\r
-; http://opensource.org/licenses/bsd-license.php.\r
-;\r
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
 ;\r
 ; Module Name:\r
 ;\r
@@ -30,8 +24,6 @@ SECTION .text
 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC\r
 ;IS IN MACHINE CODE.\r
 ;-------------------------------------------------------------------------------------\r
-global ASM_PFX(RendezvousFunnelProc)\r
-ASM_PFX(RendezvousFunnelProc):\r
 RendezvousFunnelProcStart:\r
 ; At this point CS = 0x(vv00) and ip= 0x0.\r
 BITS 16\r
@@ -45,37 +37,38 @@ BITS 16
     mov        fs, ax\r
     mov        gs, ax\r
 \r
-    mov        si,  BufferStartLocation\r
+    mov        si,  MP_CPU_EXCHANGE_INFO_FIELD (BufferStart)\r
     mov        ebx, [si]\r
 \r
-    mov        si,  ModeOffsetLocation\r
-    mov        eax, [si]\r
-    mov        si,  CodeSegmentLocation\r
-    mov        edx, [si]\r
-    mov        di,  ax\r
-    sub        di,  02h\r
-    mov        [di], dx\r
-    sub        di,  04h\r
-    add        eax, ebx\r
-    mov        [di],eax\r
-\r
-    mov        si,  DataSegmentLocation\r
+    mov        si,  MP_CPU_EXCHANGE_INFO_FIELD (DataSegment)\r
     mov        edx, [si]\r
 \r
-    mov        si, GdtrLocation\r
+    ;\r
+    ; Get start address of 32-bit code in low memory (<1MB)\r
+    ;\r
+    mov        edi, MP_CPU_EXCHANGE_INFO_FIELD (ModeTransitionMemory)\r
+\r
+    mov        si, MP_CPU_EXCHANGE_INFO_FIELD (GdtrProfile)\r
 o32 lgdt       [cs:si]\r
 \r
-    mov        si, IdtrLocation\r
+    mov        si, MP_CPU_EXCHANGE_INFO_FIELD (IdtrProfile)\r
 o32 lidt       [cs:si]\r
 \r
-    xor        ax,  ax\r
-    mov        ds,  ax\r
-\r
+    ;\r
+    ; Switch to protected mode\r
+    ;\r
     mov        eax, cr0                        ; Get control register 0\r
     or         eax, 000000003h                 ; Set PE bit (bit #0) & MP\r
     mov        cr0, eax\r
 \r
-    jmp        0:strict dword 0                ; far jump to protected mode\r
+    ; Switch to 32-bit code in executable memory (>1MB)\r
+o32 jmp far    [cs:di]\r
+\r
+;\r
+; Following code may be copied to memory with type of EfiBootServicesCode.\r
+; This is required at DXE phase if NX is enabled for EfiBootServicesCode of\r
+; memory.\r
+;\r
 BITS 32\r
 Flat32Start:                                   ; protected mode entry point\r
     mov        ds, dx\r
@@ -87,7 +80,7 @@ Flat32Start:                                   ; protected mode entry point
     mov        esi, ebx\r
 \r
     mov         edi, esi\r
-    add         edi, EnableExecuteDisableLocation\r
+    add         edi, MP_CPU_EXCHANGE_INFO_FIELD (EnableExecuteDisable)\r
     cmp         byte [edi], 0\r
     jz          SkipEnableExecuteDisable\r
 \r
@@ -101,7 +94,7 @@ Flat32Start:                                   ; protected mode entry point
     wrmsr\r
 \r
     mov         edi, esi\r
-    add         edi, Cr3Location\r
+    add         edi, MP_CPU_EXCHANGE_INFO_FIELD (Cr3)\r
     mov         eax, dword [edi]\r
     mov         cr3, eax\r
 \r
@@ -115,37 +108,31 @@ Flat32Start:                                   ; protected mode entry point
 \r
 SkipEnableExecuteDisable:\r
     mov        edi, esi\r
-    add        edi, InitFlagLocation\r
+    add        edi, MP_CPU_EXCHANGE_INFO_FIELD (InitFlag)\r
     cmp        dword [edi], 1       ; 1 == ApInitConfig\r
     jnz        GetApicId\r
 \r
-    ; AP init\r
+    ; Increment the number of APs executing here as early as possible\r
+    ; This is decremented in C code when AP is finished executing\r
     mov        edi, esi\r
-    add        edi, LockLocation\r
-    mov        eax, NotVacantFlag\r
-\r
-TestLock:\r
-    xchg       [edi], eax\r
-    cmp        eax, NotVacantFlag\r
-    jz         TestLock\r
-\r
-    mov        ecx, esi\r
-    add        ecx, NumApsExecutingLocation\r
-    inc        dword [ecx]\r
-    mov        ebx, [ecx]\r
+    add        edi, MP_CPU_EXCHANGE_INFO_FIELD (NumApsExecuting)\r
+    lock inc   dword [edi]\r
 \r
-Releaselock:\r
-    mov        eax, VacantFlag\r
-    xchg       [edi], eax\r
+    ; AP init\r
+    mov        edi, esi\r
+    add        edi, MP_CPU_EXCHANGE_INFO_FIELD (ApIndex)\r
+    mov        ebx, 1\r
+    lock xadd  dword [edi], ebx                 ; EBX = ApIndex++\r
+    inc        ebx                              ; EBX is CpuNumber\r
 \r
     mov        edi, esi\r
-    add        edi, StackSizeLocation\r
+    add        edi, MP_CPU_EXCHANGE_INFO_FIELD (StackSize)\r
     mov        eax, [edi]\r
     mov        ecx, ebx\r
     inc        ecx\r
     mul        ecx                               ; EAX = StackSize * (CpuNumber + 1)\r
     mov        edi, esi\r
-    add        edi, StackStartAddressLocation\r
+    add        edi, MP_CPU_EXCHANGE_INFO_FIELD (StackStart)\r
     add        eax, [edi]\r
     mov        esp, eax\r
     jmp        CProcedureInvoke\r
@@ -154,41 +141,52 @@ GetApicId:
     mov        eax, 0\r
     cpuid\r
     cmp        eax, 0bh\r
-    jnb        X2Apic\r
+    jb         NoX2Apic             ; CPUID level below CPUID_EXTENDED_TOPOLOGY\r
+\r
+    mov        eax, 0bh\r
+    xor        ecx, ecx\r
+    cpuid\r
+    test       ebx, 0ffffh\r
+    jz         NoX2Apic             ; CPUID.0BH:EBX[15:0] is zero\r
+\r
+    ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX\r
+    jmp        GetProcessorNumber\r
+\r
+NoX2Apic:\r
     ; Processor is not x2APIC capable, so get 8-bit APIC ID\r
     mov        eax, 1\r
     cpuid\r
     shr        ebx, 24\r
     mov        edx, ebx\r
-    jmp        GetProcessorNumber\r
 \r
-X2Apic:\r
-    ; Processor is x2APIC capable, so get 32-bit x2APIC ID\r
-    mov        eax, 0bh\r
-    xor        ecx, ecx\r
-    cpuid                   \r
-    ; edx save x2APIC ID\r
-    \r
 GetProcessorNumber:\r
     ;\r
     ; Get processor number for this AP\r
     ; Note that BSP may become an AP due to SwitchBsp()\r
     ;\r
     xor         ebx, ebx\r
-    lea         eax, [esi + CpuInfoLocation]\r
+    lea         eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (CpuInfo)]\r
     mov         edi, [eax]\r
 \r
 GetNextProcNumber:\r
-    cmp         [edi], edx                       ; APIC ID match?\r
+    cmp         dword [edi + CPU_INFO_IN_HOB.InitialApicId], edx ; APIC ID match?\r
     jz          ProgramStack\r
-    add         edi, 16\r
+    add         edi, CPU_INFO_IN_HOB_size\r
     inc         ebx\r
-    jmp         GetNextProcNumber    \r
+    jmp         GetNextProcNumber\r
 \r
 ProgramStack:\r
-    mov         esp, [edi + 12]\r
-   \r
+    mov         esp, dword [edi + CPU_INFO_IN_HOB.ApTopOfStack]\r
+\r
 CProcedureInvoke:\r
+    ;\r
+    ; Reserve 4 bytes for CpuMpData.\r
+    ; When the AP wakes up again via INIT-SIPI-SIPI, push 0 will cause the existing CpuMpData to be overwritten with 0.\r
+    ; CpuMpData is filled in via InitializeApData() during the first time INIT-SIPI-SIPI,\r
+    ; while overwirrten may occurs when under ApInHltLoop but InitFlag is not set to ApInitConfig.\r
+    ; Therefore reservation is implemented by sub esp instead of push 0.\r
+    ;\r
+    sub        esp, 4\r
     push       ebp               ; push BIST data at top of AP stack\r
     xor        ebp, ebp          ; clear ebp for call stack trace\r
     push       ebp\r
@@ -197,43 +195,62 @@ CProcedureInvoke:
     mov        eax, ASM_PFX(InitializeFloatingPointUnits)\r
     call       eax               ; Call assembly function to initialize FPU per UEFI spec\r
 \r
-    push       ebx               ; Push NumApsExecuting\r
+    push       ebx               ; Push ApIndex\r
     mov        eax, esi\r
-    add        eax, LockLocation\r
+    add        eax, MP_CPU_EXCHANGE_INFO_OFFSET\r
     push       eax               ; push address of exchange info data buffer\r
 \r
     mov        edi, esi\r
-    add        edi, ApProcedureLocation\r
+    add        edi, MP_CPU_EXCHANGE_INFO_FIELD (CFunction)\r
     mov        eax, [edi]\r
 \r
     call       eax               ; Invoke C function\r
 \r
     jmp        $                 ; Never reach here\r
+\r
+;-------------------------------------------------------------------------------------\r
+;SwitchToRealProc procedure follows.\r
+;NOT USED IN 32 BIT MODE.\r
+;-------------------------------------------------------------------------------------\r
+SwitchToRealProcStart:\r
+    jmp        $                 ; Never reach here\r
+SwitchToRealProcEnd:\r
+\r
 RendezvousFunnelProcEnd:\r
 \r
 ;-------------------------------------------------------------------------------------\r
-;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);\r
+;  AsmRelocateApLoopGeneric (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);\r
+;\r
+;  The last three parameters (Pm16CodeSegment, SevEsAPJumpTable and WakeupBuffer) are\r
+;  specific to SEV-ES support and are not applicable on IA32.\r
 ;-------------------------------------------------------------------------------------\r
-global ASM_PFX(AsmRelocateApLoop)\r
-ASM_PFX(AsmRelocateApLoop):\r
-AsmRelocateApLoopStart:\r
-    cmp        byte [esp + 4], 1\r
-    jnz        HltLoop\r
-MwaitLoop:\r
+AsmRelocateApLoopGenericStart:\r
+    mov        eax, esp\r
+    mov        esp, [eax + 12]     ; TopOfApStack\r
+    push       dword [eax]         ; push return address for stack trace\r
+    push       ebp\r
+    mov        ebp, esp\r
+    mov        ebx, [eax + 8]      ; ApTargetCState\r
+    mov        ecx, [eax + 4]      ; MwaitSupport\r
+    mov        eax, [eax + 16]     ; CountTofinish\r
+    lock dec   dword [eax]         ; (*CountTofinish)--\r
+    cmp        cl,  1              ; Check mwait-monitor support\r
+    jnz        HltLoopGeneric\r
+MwaitLoopGeneric:\r
+    cli\r
     mov        eax, esp\r
     xor        ecx, ecx\r
     xor        edx, edx\r
     monitor\r
-    mov        eax, [esp + 8]    ; Mwait Cx, Target C-State per eax[7:4]\r
+    mov        eax, ebx            ; Mwait Cx, Target C-State per eax[7:4]\r
     shl        eax, 4\r
     mwait\r
-    jmp        MwaitLoop\r
-HltLoop:\r
+    jmp        MwaitLoopGeneric\r
+HltLoopGeneric:\r
     cli\r
     hlt\r
-    jmp        HltLoop\r
-    ret\r
-AsmRelocateApLoopEnd:\r
+    jmp        HltLoopGeneric\r
+AsmRelocateApLoopGenericEnd:\r
 \r
 ;-------------------------------------------------------------------------------------\r
 ;  AsmGetAddressMap (&AddressMap);\r
@@ -244,11 +261,15 @@ ASM_PFX(AsmGetAddressMap):
     mov        ebp,esp\r
 \r
     mov        ebx,  [ebp + 24h]\r
-    mov        dword [ebx], RendezvousFunnelProcStart\r
-    mov        dword [ebx +  4h], Flat32Start - RendezvousFunnelProcStart\r
-    mov        dword [ebx +  8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
-    mov        dword [ebx + 0Ch], AsmRelocateApLoopStart\r
-    mov        dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart\r
+    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelAddress], RendezvousFunnelProcStart\r
+    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], Flat32Start - RendezvousFunnelProcStart\r
+    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
+    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressGeneric], AsmRelocateApLoopGenericStart\r
+    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeGeneric], AsmRelocateApLoopGenericEnd - AsmRelocateApLoopGenericStart\r
+    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart\r
+    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start\r
+    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeOffset], 0\r
+    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeSize], 0\r
 \r
     popad\r
     ret\r
@@ -271,57 +292,39 @@ ASM_PFX(AsmExchangeRole):
     ; edi contains OthersInfo pointer\r
     mov        edi, [ebp + 28h]\r
 \r
-    ;Store EFLAGS, GDTR and IDTR register to stack\r
+    ;Store EFLAGS to stack\r
     pushfd\r
-    mov        eax, cr4\r
-    push       eax       ; push cr4 firstly\r
-    mov        eax, cr0\r
-    push       eax\r
-\r
-    sgdt       [esi + 8]\r
-    sidt       [esi + 14]\r
 \r
     ; Store the its StackPointer\r
-    mov        [esi + 4],esp\r
+    mov        [esi + CPU_EXCHANGE_ROLE_INFO.StackPointer],esp\r
 \r
     ; update its switch state to STORED\r
-    mov        byte [esi], CPU_SWITCH_STATE_STORED\r
+    mov        byte [esi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED\r
 \r
 WaitForOtherStored:\r
     ; wait until the other CPU finish storing its state\r
-    cmp        byte [edi], CPU_SWITCH_STATE_STORED\r
+    cmp        byte [edi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED\r
     jz         OtherStored\r
     pause\r
     jmp        WaitForOtherStored\r
 \r
 OtherStored:\r
-    ; Since another CPU already stored its state, load them\r
-    ; load GDTR value\r
-    lgdt       [edi + 8]\r
-\r
-    ; load IDTR value\r
-    lidt       [edi + 14]\r
-\r
     ; load its future StackPointer\r
-    mov        esp, [edi + 4]\r
+    mov        esp, [edi + CPU_EXCHANGE_ROLE_INFO.StackPointer]\r
 \r
     ; update the other CPU's switch state to LOADED\r
-    mov        byte [edi], CPU_SWITCH_STATE_LOADED\r
+    mov        byte [edi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED\r
 \r
 WaitForOtherLoaded:\r
     ; wait until the other CPU finish loading new state,\r
     ; otherwise the data in stack may corrupt\r
-    cmp        byte [esi], CPU_SWITCH_STATE_LOADED\r
+    cmp        byte [esi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED\r
     jz         OtherLoaded\r
     pause\r
     jmp        WaitForOtherLoaded\r
 \r
 OtherLoaded:\r
     ; since the other CPU already get the data it want, leave this procedure\r
-    pop        eax\r
-    mov        cr0, eax\r
-    pop        eax\r
-    mov        cr4, eax\r
     popfd\r
 \r
     popad\r