Hi Tom, > >> + // > >> + // Program the Segment/Rip based on the SIPI vector (always at > least > >> + // 16-byte aligned, so Rip is set to 0). > >> + // > >> + JmpFar->Rip = 0; > >> + JmpFar->Segment = (UINT16) (ExchangeInfo->BufferStart >> 4); > >> + } > > > > For this wake-up process, current code just handles the broadcast type. I > think it also needs to handle wake-up specific AP case. Right? > > Yes, it should be. I never encountered a non-broadcast call under OVMF, but > it should be supported for error cases, etc. and for any future changes in > support. > > I'll add it and make the above code a function so as not to duplicate it. >
Yes, that will be good. Thanks, Eric > Thanks, > Tom > > > > > Thanks, > > Eric > >> // > >> // Wakeup all APs > >> // > >> @@ -1669,7 +1956,7 @@ MpInitLibInitialize ( > >> ASSERT (MaxLogicalProcessorNumber != 0); > >> > >> AsmGetAddressMap (&AddressMap); > >> - ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof > >> (MP_CPU_EXCHANGE_INFO); > >> + ApResetVectorSize = GetApResetVectorSize (&AddressMap); > >> ApStackSize = PcdGet32(PcdCpuApStackSize); > >> ApLoopMode = GetApLoopMode (&MonitorFilterSize); > >> > >> @@ -1728,6 +2015,8 @@ MpInitLibInitialize ( > >> CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData- > >CpuData > >> + MaxLogicalProcessorNumber); > >> InitializeSpinLock(&CpuMpData->MpLock); > >> CpuMpData->SevEsIsEnabled = PcdGetBool (PcdSevEsIsEnabled); > >> + CpuMpData->SevEsAPBuffer = (UINTN) -1; > >> + CpuMpData->GhcbBase = PcdGet64 (PcdGhcbBase); > >> > >> // > >> // Make sure no memory usage outside of the allocated buffer. > >> @@ -1786,6 +2075,7 @@ MpInitLibInitialize ( > >> // APs have been wakeup before, just get the CPU Information > >> // from HOB > >> // > >> + OldCpuMpData->NewCpuMpData = CpuMpData; > >> CpuMpData->CpuCount = OldCpuMpData->CpuCount; > >> CpuMpData->BspNumber = OldCpuMpData->BspNumber; > >> CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob; diff --git > >> a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c > >> b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c > >> index a548fed23fa7..e17a351e5cfd 100644 > >> --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c > >> +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c > >> @@ -280,6 +280,25 @@ GetModeTransitionBuffer ( > >> return 0; > >> } > >> > >> +/** > >> + Return the address of the SEV-ES AP jump table. > >> + > >> + This buffer is required in order for an SEV-ES guest to transition > >> + from UEFI into an OS. > >> + > >> + @retval other Return SEV-ES AP jump table buffer > >> +**/ > >> +UINTN > >> +GetSevEsAPMemory ( > >> + VOID > >> + ) > >> +{ > >> + // > >> + // PEI phase doesn't need to do such transition. So simply return 0. > >> + // > >> + return 0; > >> +} > >> + > >> /** > >> Checks APs status and updates APs status if needed. > >> > >> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c > >> b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c > >> index 6298571e29b2..28f8e8e133e5 100644 > >> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c > >> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c > >> @@ -121,7 +121,7 @@ GetProtectedModeCS ( > >> GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base; > >> for (Index = 0; Index < GdtEntryCount; Index++) { > >> if (GdtEntry->Bits.L == 0) { > >> - if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) { > >> + if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.DB == 1) { > >> break; > >> } > >> } > >> diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc > >> b/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc > >> index efb1bc2bf7cb..4f5a7c859a56 100644 > >> --- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc > >> +++ b/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc > >> @@ -19,7 +19,7 @@ CPU_SWITCH_STATE_IDLE equ 0 > >> CPU_SWITCH_STATE_STORED equ 1 > >> CPU_SWITCH_STATE_LOADED equ 2 > >> > >> -LockLocation equ (RendezvousFunnelProcEnd - > >> RendezvousFunnelProcStart) > >> +LockLocation equ (SwitchToRealProcEnd - > >> RendezvousFunnelProcStart) > >> StackStartAddressLocation equ LockLocation + 04h > >> StackSizeLocation equ LockLocation + 08h > >> ApProcedureLocation equ LockLocation + 0Ch > >> diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm > >> b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm > >> index b74046b76af3..309d53bf3b37 100644 > >> --- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm > >> +++ b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm > >> @@ -215,6 +215,16 @@ CProcedureInvoke: > >> jmp $ ; Never reach here > >> RendezvousFunnelProcEnd: > >> > >> +;------------------------------------------------------------------- > >> +--- > >> +--------------- > >> +;SwitchToRealProc procedure follows. > >> +;NOT USED IN 32 BIT MODE. > >> +;------------------------------------------------------------------- > >> +--- > >> +--------------- > >> +global ASM_PFX(SwitchToRealProc) > >> +ASM_PFX(SwitchToRealProc): > >> +SwitchToRealProcStart: > >> + jmp $ ; Never reach here > >> +SwitchToRealProcEnd: > >> + > >> > >> ;-------------------------------------------------------------------- > >> ----------------- ; AsmRelocateApLoop (MwaitSupport, > >> ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish); > >> > >> ;-------------------------------------------------------------------- > >> ----------------- @@ -263,6 +273,11 @@ ASM_PFX(AsmGetAddressMap): > >> mov dword [ebx + 0Ch], AsmRelocateApLoopStart > >> mov dword [ebx + 10h], AsmRelocateApLoopEnd - > >> AsmRelocateApLoopStart > >> mov dword [ebx + 14h], Flat32Start - RendezvousFunnelProcStart > >> + mov dword [ebx + 18h], SwitchToRealProcEnd - > >> SwitchToRealProcStart ; SwitchToRealSize > >> + mov dword [ebx + 1Ch], SwitchToRealProcStart - > >> RendezvousFunnelProcStart ; SwitchToRealOffset > >> + mov dword [ebx + 20h], SwitchToRealProcStart - Flat32Start > >> ; > >> SwitchToRealNoNxOffset > >> + mov dword [ebx + 24h], 0 > >> ; > >> SwitchToRealPM16ModeOffset > >> + mov dword [ebx + 28h], 0 > >> ; > >> SwitchToRealPM16ModeSize > >> > >> popad > >> ret > >> diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc > >> b/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc > >> index 58ef369342a7..c92daaaffd6b 100644 > >> --- a/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc > >> +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc > >> @@ -19,7 +19,7 @@ CPU_SWITCH_STATE_IDLE equ 0 > >> CPU_SWITCH_STATE_STORED equ 1 > >> CPU_SWITCH_STATE_LOADED equ 2 > >> > >> -LockLocation equ (RendezvousFunnelProcEnd - > >> RendezvousFunnelProcStart) > >> +LockLocation equ (SwitchToRealProcEnd - > >> RendezvousFunnelProcStart) > >> StackStartAddressLocation equ LockLocation + 08h > >> StackSizeLocation equ LockLocation + 10h > >> ApProcedureLocation equ LockLocation + 18h > >> @@ -41,3 +41,5 @@ ModeTransitionSegmentLocation equ > LockLocation + > >> 98h > >> ModeHighMemoryLocation equ LockLocation + 9Ah > >> ModeHighSegmentLocation equ LockLocation + 9Eh > >> Enable5LevelPagingLocation equ LockLocation + 0A0h > >> +SevEsIsEnabledLocation equ LockLocation + 0A1h > >> +GhcbBaseLocation equ LockLocation + 0A2h > >> diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm > >> b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm > >> index 87f2523e856f..6956b408d004 100644 > >> --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm > >> +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm > >> @@ -184,9 +184,97 @@ Releaselock: > >> add edi, StackStartAddressLocation > >> 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. > >> + ; > >> + 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 > >> 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. > >> + ; > >> + 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 > >> + > >> +DoCpuid: > >> mov eax, 0 > >> cpuid > >> cmp eax, 0bh > >> @@ -253,12 +341,158 @@ CProcedureInvoke: > >> > >> 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) > >> + ; > >> +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 > >> + > >> +SwitchToRealProcEnd: > >> + > >> > >> ;-------------------------------------------------------------------- > >> ----------------- ; AsmRelocateApLoop (MwaitSupport, > >> ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish); > >> > >> ;-------------------------------------------------------------------- > >> ----------------- > >> global ASM_PFX(AsmRelocateApLoop) > >> ASM_PFX(AsmRelocateApLoop): > >> AsmRelocateApLoopStart: > >> +BITS 64 > >> cli ; Disable interrupt before switching to > >> 32-bit mode > >> mov rax, [rsp + 40] ; CountTofinish > >> lock dec dword [rax] ; (*CountTofinish)-- > >> @@ -324,6 +558,11 @@ ASM_PFX(AsmGetAddressMap): > >> 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 > >> ret > >> > >> > >> ;-------------------------------------------------------------------- > >> ----------------- > >> -- > >> 2.17.1 > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#60744): https://edk2.groups.io/g/devel/message/60744 Mute This Topic: https://groups.io/mt/74354974/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-