[edk2-devel] [PATCH V3 10/10] OvmfPkg: Update ResetVector to support Tdx

Min Xu min.m.xu at intel.com
Tue Jul 27 05:42:27 UTC 2021


RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429

In the previous ResetVector code there are many SEV stuff mixed in common
routines, such as SetCr3ForPageTables64. If Tdx stuff is added in this way
then it is very hard to review and maintain.

According to the suggestion (https://edk2.groups.io/g/devel/message/78151)
below changes are included in this commit:
1. AmdSev.asm is created to hold the SEV related codes
2. IntelTdx.asm is created to hold the TDX related codes
3. Transition32FlatTo64Flat in Flat32ToFlat64.asm is refactor to the
   pattern described in above link.
4. SetCr3ForPageTables64 in PageTables64.asm is refactor to the pattern
   described in above link.

Put all above together, the code flow is described below:

1) ResetVector/Ia16/ResetVectorVtf0.asm
   In Tdx all CPUs "reset" to run on 32-bit protected mode with flat
descriptor (paging disabled). But in Non-Td guest the initial state of
CPUs is 16-bit real mode. To resolve this conflict, BITS 16/32 is used
in the very beginning of ResetVector. It will check the 32-bit protected
mode or 16-bit real mode, then jump to the corresponding entry point.

2) ReloadFlat32.asm load the GDT and set the CR0, then jump to Flat32.

3) Init32.asm is the entry point of doing the 32-bit protected mode
initialization. Here ReloadFlat32 is called. After that InitTdx is called
to do Tdx initialization if it is Tdx guests.

4) Transition32FlatTo64Flat does the transition from 32-bit to 64-bit.
The Pre/Post functions are called in turn, according to the suggestion in
above link.

After all above is successfully done, Tdx jump to SecEntry.

Cc: Ard Biesheuvel <ardb+tianocore at kernel.org>
Cc: Jordan Justen <jordan.l.justen at intel.com>
Cc: Brijesh Singh <brijesh.singh at amd.com>
Cc: Erdem Aktas <erdemaktas at google.com>
Cc: James Bottomley <jejb at linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao at intel.com>
Cc: Tom Lendacky <thomas.lendacky at amd.com>
Signed-off-by: Min Xu <min.m.xu at intel.com>
---
 OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm |  21 +
 OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm  | 110 +----
 OvmfPkg/ResetVector/Ia32/PageTables64.asm    | 478 +++----------------
 OvmfPkg/ResetVector/Main.asm                 |  14 +
 OvmfPkg/ResetVector/ResetVector.nasmb        |   4 +
 5 files changed, 131 insertions(+), 496 deletions(-)

diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
index ac86ce69ebe8..a390ed81d021 100644
--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
@@ -155,10 +155,31 @@ resetVector:
 ;
 ; This is where the processor will begin execution
 ;
+; In IA32 we follow the standard reset vector flow. While in X64, Td guest
+; may be supported. Td guest requires the startup mode to be 32-bit
+; protected mode but the legacy VM startup mode is 16-bit real mode.
+; To make NASM generate such shared entry code that behaves correctly in
+; both 16-bit and 32-bit mode, more BITS directives are added.
+;
+%ifdef ARCH_IA32
+
     nop
     nop
     jmp     EarlyBspInitReal16
 
+%else
+
+    smsw    ax
+    test    al, 1
+    jz      .Real
+BITS 32
+    jmp     Main32
+BITS 16
+.Real:
+    jmp     EarlyBspInitReal16
+
+%endif
+
 ALIGN   16
 
 fourGigabytes:
diff --git a/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm b/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
index c6d0d898bcd1..40cf6cea55bb 100644
--- a/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
+++ b/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
@@ -11,107 +11,39 @@
 BITS    32
 
 ;
-; Modified:  EAX, ECX, EDX
+; Transition from 32 bit flat protected mode into 64 bit flag protected mode
+;
+; To handle the situations of Tdx/SEV/Legacy guests, Pre/Post routines are
+; called. For example, SevPreSetCr3ForPageTables64 check the Sev features
+; and set the EAX value. TdxPostSetCr3PageTables64 set the CR0/CR4 and adjust
+; the CR3 if GPAW is 52.
+;
+; But in Tdx guest, memory region cannot be accessed before it is accepted
+; (except the case that the memory region is initialized by host VMM before
+; the guest is launched.) So in the beginning of Pre/Post routines it would
+; check if it is Tdx guest by checking the TDX_WORK_AREA.
+;
+; Modified:  EAX, EBX, ECX, EDX, ESP
 ;
 Transition32FlatTo64Flat:
 
+    OneTimeCall PreSetCr3ForPageTables64Sev
+
+SetPageTables64:
     OneTimeCall SetCr3ForPageTables64
 
-    mov     eax, cr4
-    bts     eax, 5                      ; enable PAE
-    mov     cr4, eax
+    OneTimeCall PostSetCr3PageTables64Tdx
 
-    mov     ecx, 0xc0000080
-    rdmsr
-    bts     eax, 8                      ; set LME
-    wrmsr
-
-    ;
-    ; SEV-ES mitigation check support
-    ;
-    xor     ebx, ebx
-
-    cmp     byte[SEV_ES_WORK_AREA], 0
-    jz      EnablePaging
-
-    ;
-    ; SEV-ES is active, perform a quick sanity check against the reported
-    ; encryption bit position. This is to help mitigate against attacks where
-    ; the hypervisor reports an incorrect encryption bit position.
-    ;
-    ; This is the first step in a two step process. Before paging is enabled
-    ; writes to memory are encrypted. Using the RDRAND instruction (available
-    ; on all SEV capable processors), write 64-bits of random data to the
-    ; SEV_ES_WORK_AREA and maintain the random data in registers (register
-    ; state is protected under SEV-ES). This will be used in the second step.
-    ;
-RdRand1:
-    rdrand  ecx
-    jnc     RdRand1
-    mov     dword[SEV_ES_WORK_AREA_RDRAND], ecx
-RdRand2:
-    rdrand  edx
-    jnc     RdRand2
-    mov     dword[SEV_ES_WORK_AREA_RDRAND + 4], edx
-
-    ;
-    ; Use EBX instead of the SEV_ES_WORK_AREA memory to determine whether to
-    ; perform the second step.
-    ;
-    mov     ebx, 1
-
-EnablePaging:
-    mov     eax, cr0
-    bts     eax, 31                     ; set PG
-    mov     cr0, eax                    ; enable paging
+    OneTimeCall PostSetCr3PageTables64Sev
 
     jmp     LINEAR_CODE64_SEL:ADDR_OF(jumpTo64BitAndLandHere)
+
 BITS    64
+
 jumpTo64BitAndLandHere:
 
-    ;
-    ; Check if the second step of the SEV-ES mitigation is to be performed.
-    ;
-    test    ebx, ebx
-    jz      InsnCompare
+    OneTimeCall PostJump64BitAndLandHereSev
 
-    ;
-    ; SEV-ES is active, perform the second step of the encryption bit postion
-    ; mitigation check. The ECX and EDX register contain data from RDRAND that
-    ; was stored to memory in encrypted form. If the encryption bit position is
-    ; valid, the contents of ECX and EDX will match the memory location.
-    ;
-    cmp     dword[SEV_ES_WORK_AREA_RDRAND], ecx
-    jne     SevEncBitHlt
-    cmp     dword[SEV_ES_WORK_AREA_RDRAND + 4], edx
-    jne     SevEncBitHlt
-
-    ;
-    ; If SEV or SEV-ES is active, perform a quick sanity check against
-    ; the reported encryption bit position. This is to help mitigate
-    ; against attacks where the hypervisor reports an incorrect encryption
-    ; bit position. If SEV is not active, this check will always succeed.
-    ;
-    ; The cmp instruction compares the first four bytes of the cmp instruction
-    ; itself (which will be read decrypted if SEV or SEV-ES is active and the
-    ; encryption bit position is valid) against the immediate within the
-    ; instruction (an instruction fetch is always decrypted correctly by
-    ; hardware) based on RIP relative addressing.
-    ;
-InsnCompare:
-    cmp     dword[rel InsnCompare], 0xFFF63D81
-    je      GoodCompare
-
-    ;
-    ; The hypervisor provided an incorrect encryption bit position, do not
-    ; proceed.
-    ;
-SevEncBitHlt:
-    cli
-    hlt
-    jmp     SevEncBitHlt
-
-GoodCompare:
     debugShowPostCode POSTCODE_64BIT_MODE
 
     OneTimeCallRet Transition32FlatTo64Flat
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 5fae8986d9da..ac365b114ee5 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -36,198 +36,97 @@ BITS    32
 %define PAGE_PDP_ATTR (PAGE_ACCESSED + \
                        PAGE_READ_WRITE + \
                        PAGE_PRESENT)
-
-;
-; SEV-ES #VC exception handler support
-;
-; #VC handler local variable locations
-;
-%define VC_CPUID_RESULT_EAX         0
-%define VC_CPUID_RESULT_EBX         4
-%define VC_CPUID_RESULT_ECX         8
-%define VC_CPUID_RESULT_EDX        12
-%define VC_GHCB_MSR_EDX            16
-%define VC_GHCB_MSR_EAX            20
-%define VC_CPUID_REQUEST_REGISTER  24
-%define VC_CPUID_FUNCTION          28
-
-; #VC handler total local variable size
-;
-%define VC_VARIABLE_SIZE           32
-
-; #VC handler GHCB CPUID request/response protocol values
-;
-%define GHCB_CPUID_REQUEST          4
-%define GHCB_CPUID_RESPONSE         5
-%define GHCB_CPUID_REGISTER_SHIFT  30
-%define CPUID_INSN_LEN              2
-
-
-; Check if Secure Encrypted Virtualization (SEV) features are enabled.
-;
-; Register usage is tight in this routine, so multiple calls for the
-; same CPUID and MSR data are performed to keep things simple.
-;
-; Modified:  EAX, EBX, ECX, EDX, ESP
 ;
-; If SEV is enabled then EAX will be at least 32.
-; If SEV is disabled then EAX will be zero.
+; Extra page tables built by Tdx guests
 ;
-CheckSevFeatures:
-    ; Set the first byte of the workarea to zero to communicate to the SEC
-    ; phase that SEV-ES is not enabled. If SEV-ES is enabled, the CPUID
-    ; instruction will trigger a #VC exception where the first byte of the
-    ; workarea will be set to one or, if CPUID is not being intercepted,
-    ; the MSR check below will set the first byte of the workarea to one.
-    mov     byte[SEV_ES_WORK_AREA], 0
+TdxBuildExtraPageTables:
+    xor     eax, eax
+    mov     ecx, 0x400
+tdClearTdxPageTablesMemoryLoop:
+    mov     dword [ecx * 4 + TDX_PT_ADDR (0) - 4], eax
+    loop    tdClearTdxPageTablesMemoryLoop
 
+    ;xor     edx, edx
     ;
-    ; Set up exception handlers to check for SEV-ES
-    ;   Load temporary RAM stack based on PCDs (see SevEsIdtVmmComm for
-    ;   stack usage)
-    ;   Establish exception handlers
-    ;
-    mov       esp, SEV_ES_VC_TOP_OF_STACK
-    mov       eax, ADDR_OF(Idtr)
-    lidt      [cs:eax]
-
-    ; Check if we have a valid (0x8000_001F) CPUID leaf
-    ;   CPUID raises a #VC exception if running as an SEV-ES guest
-    mov       eax, 0x80000000
-    cpuid
-
-    ; This check should fail on Intel or Non SEV AMD CPUs. In future if
-    ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact
-    ; same bit definition.
-    cmp       eax, 0x8000001f
-    jl        NoSev
-
-    ; Check for SEV memory encryption feature:
-    ; CPUID  Fn8000_001F[EAX] - Bit 1
-    ;   CPUID raises a #VC exception if running as an SEV-ES guest
-    mov       eax, 0x8000001f
-    cpuid
-    bt        eax, 1
-    jnc       NoSev
-
-    ; Check if SEV memory encryption is enabled
-    ;  MSR_0xC0010131 - Bit 0 (SEV enabled)
-    mov       ecx, 0xc0010131
-    rdmsr
-    bt        eax, 0
-    jnc       NoSev
-
-    ; Check for SEV-ES memory encryption feature:
-    ; CPUID  Fn8000_001F[EAX] - Bit 3
-    ;   CPUID raises a #VC exception if running as an SEV-ES guest
-    mov       eax, 0x8000001f
-    cpuid
-    bt        eax, 3
-    jnc       GetSevEncBit
-
-    ; Check if SEV-ES is enabled
-    ;  MSR_0xC0010131 - Bit 1 (SEV-ES enabled)
-    mov       ecx, 0xc0010131
-    rdmsr
-    bt        eax, 1
-    jnc       GetSevEncBit
-
-    ; Set the first byte of the workarea to one to communicate to the SEC
-    ; phase that SEV-ES is enabled.
-    mov       byte[SEV_ES_WORK_AREA], 1
-
-GetSevEncBit:
-    ; Get pte bit position to enable memory encryption
-    ; CPUID Fn8000_001F[EBX] - Bits 5:0
+    ; Top level Page Directory Pointers (1 * 256TB entry)
     ;
-    and       ebx, 0x3f
-    mov       eax, ebx
-
-    ; The encryption bit position is always above 31
-    sub       ebx, 32
-    jns       SevSaveMask
+    mov     dword[TDX_PT_ADDR (0)], PT_ADDR (0) + PAGE_PDP_ATTR
+    ;mov     dword[TDX_PT_ADDR (4)], edx
 
-    ; Encryption bit was reported as 31 or below, enter a HLT loop
-SevEncBitLowHlt:
-    cli
-    hlt
-    jmp       SevEncBitLowHlt
+    mov     byte[TDX_WORK_AREA_PGTBL_READY], 1
 
-SevSaveMask:
-    xor       edx, edx
-    bts       edx, ebx
+    OneTimeCallRet TdxBuildExtraPageTables
 
-    mov       dword[SEV_ES_WORK_AREA_ENC_MASK], 0
-    mov       dword[SEV_ES_WORK_AREA_ENC_MASK + 4], edx
-    jmp       SevExit
-
-NoSev:
+;
+; Ghcb page tables built by SEV
+;
+SevBuildGhcbPageTables:
     ;
-    ; Perform an SEV-ES sanity check by seeing if a #VC exception occurred.
+    ; The initial GHCB will live at GHCB_BASE and needs to be un-encrypted.
+    ; This requires the 2MB page for this range be broken down into 512 4KB
+    ; pages.  All will be marked encrypted, except for the GHCB.
     ;
-    cmp       byte[SEV_ES_WORK_AREA], 0
-    jz        NoSevPass
+    mov     ecx, (GHCB_BASE >> 21)
+    mov     eax, GHCB_PT_ADDR + PAGE_PDP_ATTR
+    mov     [ecx * 8 + PT_ADDR (0x2000)], eax
 
     ;
-    ; A #VC was received, yet CPUID indicates no SEV-ES support, something
-    ; isn't right.
+    ; Page Table Entries (512 * 4KB entries => 2MB)
     ;
-NoSevEsVcHlt:
-    cli
-    hlt
-    jmp       NoSevEsVcHlt
-
-NoSevPass:
-    xor       eax, eax
+    mov     ecx, 512
+pageTableEntries4kLoop:
+    mov     eax, ecx
+    dec     eax
+    shl     eax, 12
+    add     eax, GHCB_BASE & 0xFFE0_0000
+    add     eax, PAGE_4K_PDE_ATTR
+    mov     [ecx * 8 + GHCB_PT_ADDR - 8], eax
+    mov     [(ecx * 8 + GHCB_PT_ADDR - 8) + 4], edx
+    loop    pageTableEntries4kLoop
 
-SevExit:
     ;
-    ; Clear exception handlers and stack
+    ; Clear the encryption bit from the GHCB entry
     ;
-    push      eax
-    mov       eax, ADDR_OF(IdtrClear)
-    lidt      [cs:eax]
-    pop       eax
-    mov       esp, 0
-
-    OneTimeCallRet CheckSevFeatures
-
-; Check if Secure Encrypted Virtualization - Encrypted State (SEV-ES) feature
-; is enabled.
-;
-; Modified:  EAX
-;
-; If SEV-ES is enabled then EAX will be non-zero.
-; If SEV-ES is disabled then EAX will be zero.
-;
-IsSevEsEnabled:
-    xor       eax, eax
-
-    ; During CheckSevFeatures, the SEV_ES_WORK_AREA was set to 1 if
-    ; SEV-ES is enabled.
-    cmp       byte[SEV_ES_WORK_AREA], 1
-    jne       SevEsDisabled
+    mov     ecx, (GHCB_BASE & 0x1F_FFFF) >> 12
+    mov     [ecx * 8 + GHCB_PT_ADDR + 4], strict dword 0
 
-    mov       eax, 1
+    mov     ecx, GHCB_SIZE / 4
+    xor     eax, eax
+clearGhcbMemoryLoop:
+    mov     dword[ecx * 4 + GHCB_BASE - 4], eax
+    loop    clearGhcbMemoryLoop
 
-SevEsDisabled:
-    OneTimeCallRet IsSevEsEnabled
+    OneTimeCallRet  SevBuildGhcbPageTables
 
 ;
 ; Modified:  EAX, EBX, ECX, EDX
 ;
 SetCr3ForPageTables64:
 
-    OneTimeCall   CheckSevFeatures
     xor     edx, edx
+
+CheckTdx:
+    cmp     dword[TDX_WORK_AREA], 0x47584454 ; 'TDXG'
+    jnz     CheckSev
+
+    ;
+    ; In Td guest, BSP builds the page table and set the flag of
+    ; TDX_WORK_AREA_PGTBL_READY. APs check this flag and then set
+    ; cr3 directly.
+    ;
+    cmp     byte[TDX_WORK_AREA_PGTBL_READY], 1
+    jz      SetCr3
+    jmp     BuildPageTables
+
+CheckSev:
     test    eax, eax
-    jz      SevNotActive
+    jz      BuildPageTables
 
     ; If SEV is enabled, C-bit is always above 31
     sub     eax, 32
     bts     edx, eax
 
-SevNotActive:
+BuildPageTables:
 
     ;
     ; For OVMF, build some initial page tables at
@@ -277,44 +176,22 @@ pageTableEntriesLoop:
     mov     [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
     loop    pageTableEntriesLoop
 
-    OneTimeCall   IsSevEsEnabled
-    test    eax, eax
-    jz      SetCr3
-
     ;
-    ; The initial GHCB will live at GHCB_BASE and needs to be un-encrypted.
-    ; This requires the 2MB page for this range be broken down into 512 4KB
-    ; pages.  All will be marked encrypted, except for the GHCB.
+    ; If it is Td guest, TdxExtraPageTable should be initialized as well
     ;
-    mov     ecx, (GHCB_BASE >> 21)
-    mov     eax, GHCB_PT_ADDR + PAGE_PDP_ATTR
-    mov     [ecx * 8 + PT_ADDR (0x2000)], eax
+    cmp     dword[TDX_WORK_AREA], 0x47584454 ; 'TDXG'
+    jnz     IsSevEs
 
-    ;
-    ; Page Table Entries (512 * 4KB entries => 2MB)
-    ;
-    mov     ecx, 512
-pageTableEntries4kLoop:
-    mov     eax, ecx
-    dec     eax
-    shl     eax, 12
-    add     eax, GHCB_BASE & 0xFFE0_0000
-    add     eax, PAGE_4K_PDE_ATTR
-    mov     [ecx * 8 + GHCB_PT_ADDR - 8], eax
-    mov     [(ecx * 8 + GHCB_PT_ADDR - 8) + 4], edx
-    loop    pageTableEntries4kLoop
+    OneTimeCall TdxBuildExtraPageTables
+    jmp     SetCr3
 
-    ;
-    ; Clear the encryption bit from the GHCB entry
-    ;
-    mov     ecx, (GHCB_BASE & 0x1F_FFFF) >> 12
-    mov     [ecx * 8 + GHCB_PT_ADDR + 4], strict dword 0
+IsSevEs:
+    ; During CheckSevFeatures, the SEV_ES_WORK_AREA was set to 1 if
+    ; SEV-ES is enabled.
+    cmp       byte[SEV_ES_WORK_AREA], 1
+    jne       SetCr3
 
-    mov     ecx, GHCB_SIZE / 4
-    xor     eax, eax
-clearGhcbMemoryLoop:
-    mov     dword[ecx * 4 + GHCB_BASE - 4], eax
-    loop    clearGhcbMemoryLoop
+    OneTimeCall SevBuildGhcbPageTables
 
 SetCr3:
     ;
@@ -325,217 +202,4 @@ SetCr3:
 
     OneTimeCallRet SetCr3ForPageTables64
 
-;
-; Start of #VC exception handling routines
-;
 
-SevEsIdtNotCpuid:
-    ;
-    ; Use VMGEXIT to request termination.
-    ;   1 - #VC was not for CPUID
-    ;
-    mov     eax, 1
-    jmp     SevEsIdtTerminate
-
-SevEsIdtNoCpuidResponse:
-    ;
-    ; Use VMGEXIT to request termination.
-    ;   2 - GHCB_CPUID_RESPONSE not received
-    ;
-    mov     eax, 2
-
-SevEsIdtTerminate:
-    ;
-    ; Use VMGEXIT to request termination. At this point the reason code is
-    ; located in EAX, so shift it left 16 bits to the proper location.
-    ;
-    ; EAX[11:0]  => 0x100 - request termination
-    ; EAX[15:12] => 0x1   - OVMF
-    ; EAX[23:16] => 0xXX  - REASON CODE
-    ;
-    shl     eax, 16
-    or      eax, 0x1100
-    xor     edx, edx
-    mov     ecx, 0xc0010130
-    wrmsr
-    ;
-    ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
-    ; mode, so work around this by temporarily switching to 64-bit mode.
-    ;
-BITS    64
-    rep     vmmcall
-BITS    32
-
-    ;
-    ; We shouldn't come back from the VMGEXIT, but if we do, just loop.
-    ;
-SevEsIdtHlt:
-    hlt
-    jmp     SevEsIdtHlt
-    iret
-
-    ;
-    ; Total stack usage for the #VC handler is 44 bytes:
-    ;   - 12 bytes for the exception IRET (after popping error code)
-    ;   - 32 bytes for the local variables.
-    ;
-SevEsIdtVmmComm:
-    ;
-    ; If we're here, then we are an SEV-ES guest and this
-    ; was triggered by a CPUID instruction
-    ;
-    ; Set the first byte of the workarea to one to communicate that
-    ; a #VC was taken.
-    mov     byte[SEV_ES_WORK_AREA], 1
-
-    pop     ecx                     ; Error code
-    cmp     ecx, 0x72               ; Be sure it was CPUID
-    jne     SevEsIdtNotCpuid
-
-    ; Set up local variable room on the stack
-    ;   CPUID function         : + 28
-    ;   CPUID request register : + 24
-    ;   GHCB MSR (EAX)         : + 20
-    ;   GHCB MSR (EDX)         : + 16
-    ;   CPUID result (EDX)     : + 12
-    ;   CPUID result (ECX)     : + 8
-    ;   CPUID result (EBX)     : + 4
-    ;   CPUID result (EAX)     : + 0
-    sub     esp, VC_VARIABLE_SIZE
-
-    ; Save the CPUID function being requested
-    mov     [esp + VC_CPUID_FUNCTION], eax
-
-    ; The GHCB CPUID protocol uses the following mapping to request
-    ; a specific register:
-    ;   0 => EAX, 1 => EBX, 2 => ECX, 3 => EDX
-    ;
-    ; Set EAX as the first register to request. This will also be used as a
-    ; loop variable to request all register values (EAX to EDX).
-    xor     eax, eax
-    mov     [esp + VC_CPUID_REQUEST_REGISTER], eax
-
-    ; Save current GHCB MSR value
-    mov     ecx, 0xc0010130
-    rdmsr
-    mov     [esp + VC_GHCB_MSR_EAX], eax
-    mov     [esp + VC_GHCB_MSR_EDX], edx
-
-NextReg:
-    ;
-    ; Setup GHCB MSR
-    ;   GHCB_MSR[63:32] = CPUID function
-    ;   GHCB_MSR[31:30] = CPUID register
-    ;   GHCB_MSR[11:0]  = CPUID request protocol
-    ;
-    mov     eax, [esp + VC_CPUID_REQUEST_REGISTER]
-    cmp     eax, 4
-    jge     VmmDone
-
-    shl     eax, GHCB_CPUID_REGISTER_SHIFT
-    or      eax, GHCB_CPUID_REQUEST
-    mov     edx, [esp + VC_CPUID_FUNCTION]
-    mov     ecx, 0xc0010130
-    wrmsr
-
-    ;
-    ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
-    ; mode, so work around this by temporarily switching to 64-bit mode.
-    ;
-BITS    64
-    rep     vmmcall
-BITS    32
-
-    ;
-    ; Read GHCB MSR
-    ;   GHCB_MSR[63:32] = CPUID register value
-    ;   GHCB_MSR[31:30] = CPUID register
-    ;   GHCB_MSR[11:0]  = CPUID response protocol
-    ;
-    mov     ecx, 0xc0010130
-    rdmsr
-    mov     ecx, eax
-    and     ecx, 0xfff
-    cmp     ecx, GHCB_CPUID_RESPONSE
-    jne     SevEsIdtNoCpuidResponse
-
-    ; Save returned value
-    shr     eax, GHCB_CPUID_REGISTER_SHIFT
-    mov     [esp + eax * 4], edx
-
-    ; Next register
-    inc     word [esp + VC_CPUID_REQUEST_REGISTER]
-
-    jmp     NextReg
-
-VmmDone:
-    ;
-    ; At this point we have all CPUID register values. Restore the GHCB MSR,
-    ; set the return register values and return.
-    ;
-    mov     eax, [esp + VC_GHCB_MSR_EAX]
-    mov     edx, [esp + VC_GHCB_MSR_EDX]
-    mov     ecx, 0xc0010130
-    wrmsr
-
-    mov     eax, [esp + VC_CPUID_RESULT_EAX]
-    mov     ebx, [esp + VC_CPUID_RESULT_EBX]
-    mov     ecx, [esp + VC_CPUID_RESULT_ECX]
-    mov     edx, [esp + VC_CPUID_RESULT_EDX]
-
-    add     esp, VC_VARIABLE_SIZE
-
-    ; Update the EIP value to skip over the now handled CPUID instruction
-    ; (the CPUID instruction has a length of 2)
-    add     word [esp], CPUID_INSN_LEN
-    iret
-
-ALIGN   2
-
-Idtr:
-    dw      IDT_END - IDT_BASE - 1  ; Limit
-    dd      ADDR_OF(IDT_BASE)       ; Base
-
-IdtrClear:
-    dw      0                       ; Limit
-    dd      0                       ; Base
-
-ALIGN   16
-
-;
-; The Interrupt Descriptor Table (IDT)
-;   This will be used to determine if SEV-ES is enabled.  Upon execution
-;   of the CPUID instruction, a VMM Communication Exception will occur.
-;   This will tell us if SEV-ES is enabled.  We can use the current value
-;   of the GHCB MSR to determine the SEV attributes.
-;
-IDT_BASE:
-;
-; Vectors 0 - 28 (No handlers)
-;
-%rep 29
-    dw      0                                    ; Offset low bits 15..0
-    dw      0x10                                 ; Selector
-    db      0                                    ; Reserved
-    db      0x8E                                 ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
-    dw      0                                    ; Offset high bits 31..16
-%endrep
-;
-; Vector 29 (VMM Communication Exception)
-;
-    dw      (ADDR_OF(SevEsIdtVmmComm) & 0xffff)  ; Offset low bits 15..0
-    dw      0x10                                 ; Selector
-    db      0                                    ; Reserved
-    db      0x8E                                 ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
-    dw      (ADDR_OF(SevEsIdtVmmComm) >> 16)     ; Offset high bits 31..16
-;
-; Vectors 30 - 31 (No handlers)
-;
-%rep 2
-    dw      0                                    ; Offset low bits 15..0
-    dw      0x10                                 ; Selector
-    db      0                                    ; Reserved
-    db      0x8E                                 ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
-    dw      0                                    ; Offset high bits 31..16
-%endrep
-IDT_END:
diff --git a/OvmfPkg/ResetVector/Main.asm b/OvmfPkg/ResetVector/Main.asm
index dbebfb9e5d29..0418e0294920 100644
--- a/OvmfPkg/ResetVector/Main.asm
+++ b/OvmfPkg/ResetVector/Main.asm
@@ -36,6 +36,20 @@ Main16:
 
 BITS    32
 
+%ifdef ARCH_X64
+
+    jmp SearchBfv
+
+;
+; Entry point of Main32
+;
+Main32:
+
+    OneTimeCall Init32
+
+%endif
+
+SearchBfv:
     ;
     ; Search for the Boot Firmware Volume (BFV)
     ;
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 0ac6d7a6fd33..ade8ce6f08a5 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -132,6 +132,10 @@
   %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))
 
   %include "X64/TdxMetadata.asm"
+  %include "Ia32/Init32.asm"
+  %include "Ia32/IntelTdx.asm"
+  %include "Ia32/AmdSev.asm"
+  %include "Ia32/ReloadFlat32.asm"
 
   %include "Ia32/Flat32ToFlat64.asm"
   %include "Ia32/PageTables64.asm"
-- 
2.29.2.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#78200): https://edk2.groups.io/g/devel/message/78200
Mute This Topic: https://groups.io/mt/84476069/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