[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