X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FLibrary%2FMpInitLib%2FX64%2FMpFuncs.nasm;h=1daaa72b1e58eb5ce435eb29e67c969d9a710a5d;hb=b4d7b9d2b50f12d34f00afc7c7b4710778209521;hp=aecfd07bc077160a47e7e18a3346769b2fb8b6d1;hpb=edd74ad3ad79b855f76d9cf60a96c405cb3e863b;p=mirror_edk2.git
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
index aecfd07bc0..1daaa72b1e 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
@@ -1,5 +1,5 @@
;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
+; Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
@@ -15,6 +15,15 @@
%include "MpEqu.inc"
extern ASM_PFX(InitializeFloatingPointUnits)
+%macro OneTimeCall 1
+ jmp %1
+%1 %+ OneTimerCallReturn:
+%endmacro
+
+%macro OneTimeCallRet 1
+ jmp %1 %+ OneTimerCallReturn
+%endmacro
+
DEFAULT REL
SECTION .text
@@ -26,8 +35,6 @@ SECTION .text
;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
;IS IN MACHINE CODE.
;-------------------------------------------------------------------------------------
-global ASM_PFX(RendezvousFunnelProc)
-ASM_PFX(RendezvousFunnelProc):
RendezvousFunnelProcStart:
; At this point CS = 0x(vv00) and ip= 0x0.
; Save BIST information to ebp firstly
@@ -43,21 +50,21 @@ BITS 16
mov fs, ax
mov gs, ax
- mov si, BufferStartLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (BufferStart)
mov ebx, [si]
- mov si, DataSegmentLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (DataSegment)
mov edx, [si]
;
; Get start address of 32-bit code in low memory (<1MB)
;
- mov edi, ModeTransitionMemoryLocation
+ mov edi, MP_CPU_EXCHANGE_INFO_FIELD (ModeTransitionMemory)
- mov si, GdtrLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (GdtrProfile)
o32 lgdt [cs:si]
- mov si, IdtrLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (IdtrProfile)
o32 lidt [cs:si]
;
@@ -85,7 +92,7 @@ Flat32Start: ; protected mode entry point
;
; Enable execute disable bit
;
- mov esi, EnableExecuteDisableLocation
+ mov esi, MP_CPU_EXCHANGE_INFO_FIELD (EnableExecuteDisable)
cmp byte [ebx + esi], 0
jz SkipEnableExecuteDisableBit
@@ -101,7 +108,7 @@ SkipEnableExecuteDisableBit:
mov eax, cr4
bts eax, 5
- mov esi, Enable5LevelPagingLocation
+ mov esi, MP_CPU_EXCHANGE_INFO_FIELD (Enable5LevelPaging)
cmp byte [ebx + esi], 0
jz SkipEnable5LevelPaging
@@ -117,7 +124,7 @@ SkipEnable5LevelPaging:
;
; Load page table
;
- mov esi, Cr3Location ; Save CR3 in ecx
+ mov esi, MP_CPU_EXCHANGE_INFO_FIELD (Cr3) ; Save CR3 in ecx
mov ecx, [ebx + esi]
mov cr3, ecx ; Load CR3
@@ -139,140 +146,54 @@ SkipEnable5LevelPaging:
;
; Far jump to 64-bit code
;
- mov edi, ModeHighMemoryLocation
+ mov edi, MP_CPU_EXCHANGE_INFO_FIELD (ModeHighMemory)
add edi, ebx
jmp far [edi]
BITS 64
+
LongModeStart:
mov esi, ebx
- lea edi, [esi + InitFlagLocation]
+ lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (InitFlag)]
cmp qword [edi], 1 ; ApInitConfig
jnz GetApicId
; Increment the number of APs executing here as early as possible
; This is decremented in C code when AP is finished executing
mov edi, esi
- add edi, NumApsExecutingLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (NumApsExecuting)
lock inc dword [edi]
; AP init
mov edi, esi
- add edi, LockLocation
- mov rax, NotVacantFlag
-
-TestLock:
- xchg qword [edi], rax
- cmp rax, NotVacantFlag
- jz TestLock
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (ApIndex)
+ mov ebx, 1
+ lock xadd dword [edi], ebx ; EBX = ApIndex++
+ inc ebx ; EBX is CpuNumber
- lea ecx, [esi + ApIndexLocation]
- inc dword [ecx]
- mov ebx, [ecx]
-
-Releaselock:
- mov rax, VacantFlag
- xchg qword [edi], rax
; program stack
mov edi, esi
- add edi, StackSizeLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackSize)
mov eax, dword [edi]
mov ecx, ebx
inc ecx
mul ecx ; EAX = StackSize * (CpuNumber + 1)
mov edi, esi
- add edi, StackStartAddressLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackStart)
add rax, qword [edi]
mov rsp, rax
- lea edi, [esi + SevEsIsEnabledLocation]
- cmp byte [edi], 1 ; SevEsIsEnabled
- jne CProcedureInvoke
-
;
- ; program GHCB
- ; Each page after the GHCB is a per-CPU page, so the calculation programs
- ; a GHCB to be every 8KB.
+ ; Setup the GHCB when AMD SEV-ES active.
;
- mov eax, SIZE_4KB
- shl eax, 1 ; EAX = SIZE_4K * 2
- mov ecx, ebx
- mul ecx ; EAX = SIZE_4K * 2 * CpuNumber
- mov edi, esi
- add edi, GhcbBaseLocation
- add rax, qword [edi]
- mov rdx, rax
- shr rdx, 32
- mov rcx, 0xc0010130
- wrmsr
+ OneTimeCall SevEsSetupGhcb
jmp CProcedureInvoke
GetApicId:
- lea edi, [esi + SevEsIsEnabledLocation]
- cmp byte [edi], 1 ; SevEsIsEnabled
- jne DoCpuid
-
;
- ; Since we don't have a stack yet, we can't take a #VC
- ; exception. Use the GHCB protocol to perform the CPUID
- ; calls.
+ ; Use the GHCB protocol to get the ApicId when SEV-ES is active.
;
- mov rcx, 0xc0010130
- rdmsr
- shl rdx, 32
- or rax, rdx
- mov rdi, rax ; RDI now holds the original GHCB GPA
-
- mov rdx, 0 ; CPUID function 0
- mov rax, 0 ; RAX register requested
- or rax, 4
- wrmsr
- rep vmmcall
- rdmsr
- cmp edx, 0bh
- jb NoX2ApicSevEs ; CPUID level below CPUID_EXTENDED_TOPOLOGY
-
- mov rdx, 0bh ; CPUID function 0x0b
- mov rax, 040000000h ; RBX register requested
- or rax, 4
- wrmsr
- rep vmmcall
- rdmsr
- test edx, 0ffffh
- jz NoX2ApicSevEs ; CPUID.0BH:EBX[15:0] is zero
-
- mov rdx, 0bh ; CPUID function 0x0b
- mov rax, 0c0000000h ; RDX register requested
- or rax, 4
- wrmsr
- rep vmmcall
- rdmsr
-
- ; Processor is x2APIC capable; 32-bit x2APIC ID is now in EDX
- jmp RestoreGhcb
-
-NoX2ApicSevEs:
- ; Processor is not x2APIC capable, so get 8-bit APIC ID
- mov rdx, 1 ; CPUID function 1
- mov rax, 040000000h ; RBX register requested
- or rax, 4
- wrmsr
- rep vmmcall
- rdmsr
- shr edx, 24
-
-RestoreGhcb:
- mov rbx, rdx ; Save x2APIC/APIC ID
-
- mov rdx, rdi ; RDI holds the saved GHCB GPA
- shr rdx, 32
- mov eax, edi
- wrmsr
-
- mov rdx, rbx
-
- ; x2APIC ID or APIC ID is in EDX
- jmp GetProcessorNumber
+ OneTimeCall SevEsGetApicId
DoCpuid:
mov eax, 0
@@ -302,18 +223,18 @@ GetProcessorNumber:
; Note that BSP may become an AP due to SwitchBsp()
;
xor ebx, ebx
- lea eax, [esi + CpuInfoLocation]
+ lea eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (CpuInfo)]
mov rdi, [eax]
GetNextProcNumber:
- cmp dword [rdi], edx ; APIC ID match?
+ cmp dword [rdi + CPU_INFO_IN_HOB.InitialApicId], edx ; APIC ID match?
jz ProgramStack
- add rdi, 20
+ add rdi, CPU_INFO_IN_HOB_size
inc ebx
jmp GetNextProcNumber
ProgramStack:
- mov rsp, qword [rdi + 12]
+ mov rsp, qword [rdi + CPU_INFO_IN_HOB.ApTopOfStack]
CProcedureInvoke:
push rbp ; Push BIST data at top of AP stack
@@ -321,17 +242,17 @@ CProcedureInvoke:
push rbp
mov rbp, rsp
- mov rax, qword [esi + InitializeFloatingPointUnitsAddress]
+ mov rax, qword [esi + MP_CPU_EXCHANGE_INFO_FIELD (InitializeFloatingPointUnits)]
sub rsp, 20h
call rax ; Call assembly function to initialize FPU per UEFI spec
add rsp, 20h
mov edx, ebx ; edx is ApIndex
mov ecx, esi
- add ecx, LockLocation ; rcx is address of exchange info data buffer
+ add ecx, MP_CPU_EXCHANGE_INFO_OFFSET ; rcx is address of exchange info data buffer
mov edi, esi
- add edi, ApProcedureLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (CFunction)
mov rax, qword [edi]
sub rsp, 20h
@@ -339,162 +260,16 @@ CProcedureInvoke:
add rsp, 20h
jmp $ ; Should never reach here
-RendezvousFunnelProcEnd:
-
-;-------------------------------------------------------------------------------------
-;SwitchToRealProc procedure follows.
-;ALSO THIS PROCEDURE IS EXECUTED BY APs TRANSITIONING TO 16 BIT MODE. HENCE THIS PROC
-;IS IN MACHINE CODE.
-; SwitchToRealProc (UINTN BufferStart, UINT16 Code16, UINT16 Code32, UINTN StackStart)
-; rcx - Buffer Start
-; rdx - Code16 Selector Offset
-; r8 - Code32 Selector Offset
-; r9 - Stack Start
-;-------------------------------------------------------------------------------------
-global ASM_PFX(SwitchToRealProc)
-ASM_PFX(SwitchToRealProc):
-SwitchToRealProcStart:
-BITS 64
- cli
-
- ;
- ; Get RDX reset value before changing stacks since the
- ; new stack won't be able to accomodate a #VC exception.
- ;
- push rax
- push rbx
- push rcx
- push rdx
-
- mov rax, 1
- cpuid
- mov rsi, rax ; Save off the reset value for RDX
-
- pop rdx
- pop rcx
- pop rbx
- pop rax
-
- ;
- ; Establish stack below 1MB
- ;
- mov rsp, r9
-
- ;
- ; Push ultimate Reset Vector onto the stack
- ;
- mov rax, rcx
- shr rax, 4
- push word 0x0002 ; RFLAGS
- push ax ; CS
- push word 0x0000 ; RIP
- push word 0x0000 ; For alignment, will be discarded
-
- ;
- ; Get address of "16-bit operand size" label
- ;
- lea rbx, [PM16Mode]
-
- ;
- ; Push addresses used to change to compatibility mode
- ;
- lea rax, [CompatMode]
- push r8
- push rax
-
- ;
- ; Clear R8 - R15, for reset, before going into 32-bit mode
- ;
- xor r8, r8
- xor r9, r9
- xor r10, r10
- xor r11, r11
- xor r12, r12
- xor r13, r13
- xor r14, r14
- xor r15, r15
-
- ;
- ; Far return into 32-bit mode
- ;
-o64 retf
-
-BITS 32
-CompatMode:
- ;
- ; Set up stack to prepare for exiting protected mode
- ;
- push edx ; Code16 CS
- push ebx ; PM16Mode label address
-
- ;
- ; Disable paging
- ;
- mov eax, cr0 ; Read CR0
- btr eax, 31 ; Set PG=0
- mov cr0, eax ; Write CR0
-
- ;
- ; Disable long mode
- ;
- mov ecx, 0c0000080h ; EFER MSR number
- rdmsr ; Read EFER
- btr eax, 8 ; Set LME=0
- wrmsr ; Write EFER
-
- ;
- ; Disable PAE
- ;
- mov eax, cr4 ; Read CR4
- btr eax, 5 ; Set PAE=0
- mov cr4, eax ; Write CR4
-
- mov edx, esi ; Restore RDX reset value
-
- ;
- ; Switch to 16-bit operand size
- ;
- retf
-
-BITS 16
- ;
- ; At entry to this label
- ; - RDX will have its reset value
- ; - On the top of the stack
- ; - Alignment data (two bytes) to be discarded
- ; - IP for Real Mode (two bytes)
- ; - CS for Real Mode (two bytes)
- ;
- ; This label is also used with AsmRelocateApLoop. During MP finalization,
- ; the code from PM16Mode to SwitchToRealProcEnd is copied to the start of
- ; the WakeupBuffer, allowing a parked AP to be booted by an OS.
- ;
-PM16Mode:
- mov eax, cr0 ; Read CR0
- btr eax, 0 ; Set PE=0
- mov cr0, eax ; Write CR0
-
- pop ax ; Discard alignment data
-
- ;
- ; Clear registers (except RDX and RSP) before going into 16-bit mode
- ;
- xor eax, eax
- xor ebx, ebx
- xor ecx, ecx
- xor esi, esi
- xor edi, edi
- xor ebp, ebp
-
- iret
+;
+; Required for the AMD SEV helper functions
+;
+%include "AmdSev.nasm"
-SwitchToRealProcEnd:
+RendezvousFunnelProcEnd:
;-------------------------------------------------------------------------------------
; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);
;-------------------------------------------------------------------------------------
-global ASM_PFX(AsmRelocateApLoop)
-ASM_PFX(AsmRelocateApLoop):
AsmRelocateApLoopStart:
BITS 64
cmp qword [rsp + 56], 0 ; SevEsAPJumpTable
@@ -579,7 +354,7 @@ NoSevEs:
;
; Far return into 32-bit mode
;
-o64 retf
+ retfq
BITS 32
PmEntry:
@@ -666,19 +441,17 @@ AsmRelocateApLoopEnd:
;-------------------------------------------------------------------------------------
global ASM_PFX(AsmGetAddressMap)
ASM_PFX(AsmGetAddressMap):
- lea rax, [ASM_PFX(RendezvousFunnelProc)]
- mov qword [rcx], rax
- mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
- mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
- lea rax, [ASM_PFX(AsmRelocateApLoop)]
- mov qword [rcx + 18h], rax
- mov qword [rcx + 20h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
- mov qword [rcx + 28h], Flat32Start - RendezvousFunnelProcStart
- mov qword [rcx + 30h], SwitchToRealProcEnd - SwitchToRealProcStart ; SwitchToRealSize
- mov qword [rcx + 38h], SwitchToRealProcStart - RendezvousFunnelProcStart ; SwitchToRealOffset
- mov qword [rcx + 40h], SwitchToRealProcStart - Flat32Start ; SwitchToRealNoNxOffset
- mov qword [rcx + 48h], PM16Mode - RendezvousFunnelProcStart ; SwitchToRealPM16ModeOffset
- mov qword [rcx + 50h], SwitchToRealProcEnd - PM16Mode ; SwitchToRealPM16ModeSize
+ lea rax, [RendezvousFunnelProcStart]
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelAddress], rax
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], LongModeStart - RendezvousFunnelProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+ lea rax, [AsmRelocateApLoopStart]
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], rax
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeOffset], PM16Mode - RendezvousFunnelProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeSize], SwitchToRealProcEnd - PM16Mode
ret
;-------------------------------------------------------------------------------------
@@ -721,18 +494,18 @@ ASM_PFX(AsmExchangeRole):
;Store EFLAGS, GDTR and IDTR regiter to stack
pushfq
- sgdt [rsi + 16]
- sidt [rsi + 26]
+ sgdt [rsi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
+ sidt [rsi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; Store the its StackPointer
- mov [rsi + 8], rsp
+ mov [rsi + CPU_EXCHANGE_ROLE_INFO.StackPointer], rsp
; update its switch state to STORED
- mov byte [rsi], CPU_SWITCH_STATE_STORED
+ mov byte [rsi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED
WaitForOtherStored:
; wait until the other CPU finish storing its state
- cmp byte [rdi], CPU_SWITCH_STATE_STORED
+ cmp byte [rdi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED
jz OtherStored
pause
jmp WaitForOtherStored
@@ -740,21 +513,21 @@ WaitForOtherStored:
OtherStored:
; Since another CPU already stored its state, load them
; load GDTR value
- lgdt [rdi + 16]
+ lgdt [rdi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
; load IDTR value
- lidt [rdi + 26]
+ lidt [rdi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; load its future StackPointer
- mov rsp, [rdi + 8]
+ mov rsp, [rdi + CPU_EXCHANGE_ROLE_INFO.StackPointer]
; update the other CPU's switch state to LOADED
- mov byte [rdi], CPU_SWITCH_STATE_LOADED
+ mov byte [rdi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED
WaitForOtherLoaded:
; wait until the other CPU finish loading new state,
; otherwise the data in stack may corrupt
- cmp byte [rsi], CPU_SWITCH_STATE_LOADED
+ cmp byte [rsi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED
jz OtherLoaded
pause
jmp WaitForOtherLoaded