[edk2-devel] [PATCH v8 42/46] UefiCpuPkg: Allow AP booting under SEV-ES
Dong, Eric
eric.dong at intel.com
Fri Jun 5 06:13:19 UTC 2020
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/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-
More information about the edk2-devel-archive
mailing list