public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Erdem Aktas" <erdemaktas@google.com>
To: Min Xu <min.m.xu@intel.com>
Cc: devel@edk2.groups.io, Ard Biesheuvel <ardb+tianocore@kernel.org>,
	 Jordan Justen <jordan.l.justen@intel.com>,
	Brijesh Singh <brijesh.singh@amd.com>,
	 James Bottomley <jejb@linux.ibm.com>,
	Jiewen Yao <jiewen.yao@intel.com>,
	 Tom Lendacky <thomas.lendacky@amd.com>
Subject: Re: [PATCH V4 3/3] OvmfPkg/ResetVector: Enable Intel TDX in ResetVector of Ovmf
Date: Wed, 4 Aug 2021 03:01:21 -0700	[thread overview]
Message-ID: <CAAYXXYzBDKUQ-BMfSYWT0JDLONWt8pXdYbUdAHvefrg-JpCLPg@mail.gmail.com> (raw)
In-Reply-To: <7c60ce224e671dbca27f6dcc6c04e33ecd32ab33.1627951562.git.min.m.xu@intel.com>

I agree with Brijesh on that this patch should be divided into smaller ones.

On Mon, Aug 2, 2021 at 6:18 PM Min Xu <min.m.xu@intel.com> wrote:
>
> +    ;
> +    ; EBP[6:0] CPU supported GPA width
> +    ;
> +    and     ebp, 0x3f

Based on https://software.intel.com/content/dam/develop/external/us/en/documents/tdx-module-1eas-v0.85.039.pdf
 sec 8.1.2
Is not this EBP[5:0] for GPA width ? it should be "and ebp, 0x1f"

-Erdem

On Mon, Aug 2, 2021 at 6:18 PM Min Xu <min.m.xu@intel.com> wrote:
>
> RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429
>
> Intel's Trust Domain Extensions (Intel TDX) refers to an Intel technology
> that extends Virtual Machines Extensions (VMX) and Multi-Key Total Memory
> Encryption (MKTME) with a new kind of virutal machines guest called a
> Trust Domain (TD). A TD is desinged to run in a CPU mode that protects the
> confidentiality of TD memory contents and the TD's CPU state from other
> software, including the hosting Virtual-Machine Monitor (VMM), unless
> explicitly shared by the TD itself.
>
> Note: Intel TDX only is available on X64, so the Tdx related changes are
> in X64 path. In IA32 path, there may be null stub to make the build
> success.
>
> This patch includes below major changes.
>
> 1. CC_WORK_AREA
> Ovmf is able to run on different types of VM guest with ONE image. These
> VM guest includes the Legacy guest, SEV guest and TDX guest. In
> ResetVector CC_WORK_AREA is such a memory region to record the VM guest
> information. Below is the definition of the work area.
>
>  typedef struct {
>    UINT8   Type;     // 0 legacy, 1 SEV, 2 TDX
>    UINT8   SubType;  // Depends on Type
>    UINT8   Rsvd[2];  // Reserved
>    union VM_GUEST {
>      TDX_WORK_AREA Tdx;
>      SEV_WORK_AREA Sev;
>    } Guest;
>  } CC_WORK_AREA_HEAD;
>
>  typedef struct {
>    ... ...
>  } TDX_WORK_AREA
>
>  typedef struct {
>    ... ...
>  } SEV_WORK_AREA
>
> 2. X64/IntelTdxMetadata.asm
> IntelTdxMetadata describes the information about the image for VMM use.
> For example, the base address and length of the TdHob, TdMailbox, etc.
> Its offset is put in a GUID-ed structure which is appended in the GUID-ed
> chain from a fixed GPA (0xffffffd0). Below are the items in TdxMetadata:
>  _Bfv:
>     Boot Firmware Volume
>  _Cfv:
>     Configuration Firmware Volume
>  _Stack:
>     Initial stack
>  _Heap:
>     Initial heap
>  _MailBox:
>     TDVF reserves the memory region so each AP can receive the message
>     sent by the guest OS.
>  _CcWorkarea:
>     Compute Confidential work area which is consumed by CC technologies,
>     such as SEV, TDX.
>  _TdHob:
>     VMM pass the resource information in TdHob to TDVF.
>  _TdxPageTable:
>     If 5-level page table is supported (GPAW is 52), a top level page
>     directory pointers (1 * 256TB entry) is generated in this page.
>  _OvmfPageTable:
>     Initial page table for standard Ovmf.
>
> TDVF indicate above chunk of temporary initialized memory region (_Stack/
> _Heap/_MailBox/_CcWorkarea/_TdHob/_TdxPageTables/OvmfPageTable) to support
> TDVF code finishing the memory initialization. Because the other
> unaccepted memory cannot be accessed until they're accepted.
>
> Since AMD SEV has already defined some SEV specific memory region in
> MEMFD. TDX re-use the memory regions defined by SEV.
>  - MailBox      : PcdOvmfSecGhcbBackupBase|PcdOvmfSecGhcbBackupSize
>  - TdHob        : PcdOvmfSecGhcbBase|PcdOvmfSecGhcbSize
>  - TdxPageTable : PcdOvmfSecGhcbPageTableBase|PcdOvmfSecGhcbPageTableSize
>  - CcWorkArea   : PcdSevEsWorkAreaBase|PcdSevEsWorkAreaSize
>
> 3. Ia32/IntelTdx.asm
> IntelTdx.asm includes below routines used in ResetVector
>  - IsTdx
>    Check if the running system is Tdx guest.
>
>  - InitTdxWorkarea
>    It initialize the CC_WORK_AREA. Because it is called by both BSP and
>    APs and to avoid the race condition, only BSP can initialize the
>    WORK_AREA. AP will wait until the field of TDX_WORK_AREA_PGTBL_READY
>    is set.
>
>  - ReloadFlat32
>    After reset all CPUs in TDX are initialized to 32-bit protected mode.
>    But GDT register is not set. So this routine loads the GDT and set the
>    CR0, then jump to Flat 32 protected mode. After that CR4 and other
>    registers are set.
>
>  - InitTdx
>    This routine wrap above 3 routines together to do Tdx initialization
>    in ResetVector phase.
>
>  - PostSetCr3PageTables64Tdx
>    It is called after SetCr3PageTables64 in Tdx guest to set CR0/CR4.
>    If GPAW is 52, then CR3 is adjusted as well.
>
>  - IsTdxEnabled
>    It is a OneTimeCall to probe if TDX is enabled by checking the
>    CC_WORK_AREA.
>
> 4. Ia32/AmdSev.asm
> AmdSev.asm includes the SEV routines used in ResetVector. This patch
> remove the code of clearing SEV_ES_WORK_AREA in CheckSevFeatures. The
> clearing of SEV_ES_WORK_AREA is called at Main16 in Main.asm.
>
> 5. Main.asm
> Previously OvmfPkg/ResetVector use the Main.asm in UefiCpuPkg. There is
> only Main16 entry point. Main32 entry point is needed in Main.asm because
> of Intel TDX. To reduce the complexity of Main.asm in UefiCpuPkg, OvmfPkg
> create its own Main.asm to meet the requirement of Intel TDX. There are
> below changes in this Main.asm:
>  - A new entry point (Main32) is added. TDX guest will jump to Main32
>    from ResetVecotr.
>  - In Main16 entry point, after TransitionFromReal16To32BitFlat,
>    CC_WORK_AREA is cleared to 0.
>
> 6. Ia32/PageTables64.asm
> GPAW of TDX can be 48 or 52, which determines the level of page table.
> If Level-5(GPAW 52) paging is supported, then an extra page is needed
> to hold the top level Page Directory Pointers (1 * 256TB entry).
>
> 7. 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 ResetVectorVtf0.asm. It checks the 32-bit protected mode or 16-bit
> real mode, then jump to the corresponding entry point.
>
> 8. ResetVector.nasmb
> TDX related macros and files are added in ResetVecotr.nasmb.
>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Brijesh Singh <brijesh.singh@amd.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Min Xu <min.m.xu@intel.com>
> ---
>  OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm |  39 +++
>  OvmfPkg/ResetVector/Ia32/AmdSev.asm          |   7 -
>  OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm  |   9 +
>  OvmfPkg/ResetVector/Ia32/IntelTdx.asm        | 265 +++++++++++++++++++
>  OvmfPkg/ResetVector/Ia32/PageTables64.asm    | 113 +++++---
>  OvmfPkg/ResetVector/Main.asm                 | 121 +++++++++
>  OvmfPkg/ResetVector/ResetVector.inf          |  12 +-
>  OvmfPkg/ResetVector/ResetVector.nasmb        |  48 +++-
>  OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm | 110 ++++++++
>  9 files changed, 679 insertions(+), 45 deletions(-)
>  create mode 100644 OvmfPkg/ResetVector/Ia32/IntelTdx.asm
>  create mode 100644 OvmfPkg/ResetVector/Main.asm
>  create mode 100644 OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm
>
> diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
> index 7ec3c6e980c3..62feeacbee7b 100644
> --- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
> +++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
> @@ -47,6 +47,24 @@ TIMES (15 - ((guidedStructureEnd - guidedStructureStart + 15) % 16)) DB 0
>  ;
>  guidedStructureStart:
>
> +%ifdef ARCH_X64
> +;
> +; TDX Metadata offset block
> +;
> +; If TdxMetadata.asm is included then we need below block which describes
> +; the offset of TdxMetadata block in Ovmf image
> +;
> +; GUID : e47a6535-984a-4798-865e-4685a7bf8ec2
> +;
> +tdxMetadataOffsetStart:
> +    DD      (OVMF_IMAGE_SIZE_IN_KB * 1024 - (fourGigabytes - TdxMetadataGuid - 16))
> +    DD      tdxMetadataOffsetEnd - tdxMetadataOffsetStart
> +    DB      0x35, 0x65, 0x7a, 0xe4, 0x4a, 0x98, 0x98, 0x47
> +    DB      0x86, 0x5e, 0x46, 0x85, 0xa7, 0xbf, 0x8e, 0xc2
> +tdxMetadataOffsetEnd:
> +
> +%endif
> +
>  ; SEV Hash Table Block
>  ;
>  ; This describes the guest ram area where the hypervisor should
> @@ -158,10 +176,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/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
> index aa95d06eaddb..d0d9890d5c4b 100644
> --- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
> +++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
> @@ -128,13 +128,6 @@ SevEsUnexpectedRespTerminate:
>  ; If SEV is disabled then EAX will be zero.
>  ;
>  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
> -
>      ;
>      ; Set up exception handlers to check for SEV-ES
>      ;   Load temporary RAM stack based on PCDs (see SevEsIdtVmmComm for
> diff --git a/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm b/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
> index c6d0d898bcd1..ea8723efd417 100644
> --- a/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
> +++ b/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
> @@ -17,6 +17,14 @@ Transition32FlatTo64Flat:
>
>      OneTimeCall SetCr3ForPageTables64
>
> +    OneTimeCall PostSetCr3PageTables64Tdx
> +
> +    ;
> +    ; If it is TDX, we're done and jump to enable paging
> +    ;
> +    cmp     byte[CC_WORK_AREA], VM_GUEST_TDX
> +    je      EnablePaging
> +
>      mov     eax, cr4
>      bts     eax, 5                      ; enable PAE
>      mov     cr4, eax
> @@ -71,6 +79,7 @@ jumpTo64BitAndLandHere:
>
>      ;
>      ; Check if the second step of the SEV-ES mitigation is to be performed.
> +    ; If it is Tdx, ebx is cleared in PostSetCr3PageTables64Tdx.
>      ;
>      test    ebx, ebx
>      jz      InsnCompare
> diff --git a/OvmfPkg/ResetVector/Ia32/IntelTdx.asm b/OvmfPkg/ResetVector/Ia32/IntelTdx.asm
> new file mode 100644
> index 000000000000..f40331a5cbce
> --- /dev/null
> +++ b/OvmfPkg/ResetVector/Ia32/IntelTdx.asm
> @@ -0,0 +1,265 @@
> +;------------------------------------------------------------------------------
> +; @file
> +;   Intel TDX routines
> +;
> +; Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
> +; SPDX-License-Identifier: BSD-2-Clause-Patent
> +;
> +;------------------------------------------------------------------------------
> +
> +%define SEC_DEFAULT_CR0  0x00000023
> +%define SEC_DEFAULT_CR4  0x640
> +
> +%define VM_GUEST_TDX          2
> +
> +BITS 32
> +
> +;
> +; Check if it is Intel Tdx
> +;
> +; Modified: EAX, EBX, ECX, EDX
> +;
> +; If it is Intel Tdx, EAX is zero
> +; If it is not Intel Tdx, EAX is non-zero
> +;
> +IsTdx:
> +    ;
> +    ; CPUID (0)
> +    ;
> +    mov     eax, 0
> +    cpuid
> +    cmp     ebx, 0x756e6547  ; "Genu"
> +    jne     IsNotTdx
> +    cmp     edx, 0x49656e69  ; "ineI"
> +    jne     IsNotTdx
> +    cmp     ecx, 0x6c65746e  ; "ntel"
> +    jne     IsNotTdx
> +
> +    ;
> +    ; CPUID (1)
> +    ;
> +    mov     eax, 1
> +    cpuid
> +    test    ecx, 0x80000000
> +    jz      IsNotTdx
> +
> +    ;
> +    ; CPUID[0].EAX >= 0x21?
> +    ;
> +    mov     eax, 0
> +    cpuid
> +    cmp     eax, 0x21
> +    jl      IsNotTdx
> +
> +    ;
> +    ; CPUID (0x21,0)
> +    ;
> +    mov     eax, 0x21
> +    mov     ecx, 0
> +    cpuid
> +
> +    cmp     ebx, 0x65746E49   ; "Inte"
> +    jne     IsNotTdx
> +    cmp     edx, 0x5844546C   ; "lTDX"
> +    jne     IsNotTdx
> +    cmp     ecx, 0x20202020   ; "    "
> +    jne     IsNotTdx
> +
> +    mov     eax, 0
> +    jmp     ExitIsTdx
> +
> +IsNotTdx:
> +    mov     eax, 1
> +
> +ExitIsTdx:
> +
> +  OneTimeCallRet IsTdx
> +
> +;
> +; Initialize Tdx work area (CC_WORK_AREA) if it is Tdx guest.
> +; BSP and APs all go here. Only BSP can initialize the WORK_AREA
> +;
> +; typedef struct {
> +;   UINT8   Type;     // 0 legacy, 1 SEV, 2 TDX
> +;   UINT8   SubType;  // Depends on Type
> +;   UINT8   Rsvd[2];  // Reserved
> +;   union VM_GUEST {
> +;     TDX_WORK_AREA Tdx;
> +;     SEV_WORK_AREA Sev;
> +;   } Guest;
> +; } CC_WORK_AREA_HEAD;
> +;
> +; typedef struct {
> +;   UINT8    IsPageLevel5;
> +;   UINT8    IsPageTableReady;
> +;   UINT8    Rsvd[2];
> +;   UINT32   Gpaw;
> +; } TDX_WORK_AREA
> +;
> +; Param[in] EBP[6:0]    CPU Supported GPAW (48 or 52)
> +; Param[in] ESI[31:0]   vCPU ID (BSP is 0, others are AP)
> +;
> +; Modified:  EBP
> +;
> +InitTdxWorkarea:
> +
> +    ;
> +    ; First check if it is Tdx
> +    ;
> +    OneTimeCall IsTdx
> +
> +    test    eax, eax
> +    jnz     ExitInitTdxWorkarea
> +
> +    ;
> +    ; In Td guest, BSP/AP shares the same entry point
> +    ; BSP builds up the page table, while APs shouldn't do the same task.
> +    ; Instead, APs just leverage the page table which is built by BSP.
> +    ; APs will wait until the page table is ready.
> +    ;
> +    cmp     esi, 0
> +    je      TdxBspEntry
> +
> +TdxApWait:
> +    cmp     byte[TDX_WORK_AREA_PGTBL_READY], 0
> +    je      TdxApWait
> +    jmp     ExitInitTdxWorkarea
> +
> +TdxBspEntry:
> +    ;
> +    ; Set Type and SubType of CC_WORK_AREA so that the
> +    ; following code can use these information.
> +    ;
> +    mov     byte[CC_WORK_AREA], VM_GUEST_TDX
> +    mov     byte[CC_WORK_AREA_SUBTYPE], 0
> +
> +    ;
> +    ; EBP[6:0] CPU supported GPA width
> +    ;
> +    and     ebp, 0x3f
> +    cmp     ebp, 52
> +    jl      NotPageLevel5
> +    mov     byte[TDX_WORK_AREA_PAGELEVEL5], 1
> +
> +NotPageLevel5:
> +    mov     DWORD[TDX_WORK_AREA_GPAW], ebp
> +
> +ExitInitTdxWorkarea:
> +    OneTimeCallRet InitTdxWorkarea
> +
> +;
> +; Load the GDT and set the CR0, then jump to Flat 32 protected mode.
> +;
> +; Modified:  EAX, EBX, CR0, CR4, DS, ES, FS, GS, SS
> +;
> +ReloadFlat32:
> +
> +    cli
> +    mov     ebx, ADDR_OF(gdtr)
> +    lgdt    [ebx]
> +
> +    mov     eax, SEC_DEFAULT_CR0
> +    mov     cr0, eax
> +
> +    jmp     LINEAR_CODE_SEL:dword ADDR_OF(jumpToFlat32BitAndLandHere)
> +
> +jumpToFlat32BitAndLandHere:
> +
> +    mov     eax, SEC_DEFAULT_CR4
> +    mov     cr4, eax
> +
> +    debugShowPostCode POSTCODE_32BIT_MODE
> +
> +    mov     ax, LINEAR_SEL
> +    mov     ds, ax
> +    mov     es, ax
> +    mov     fs, ax
> +    mov     gs, ax
> +    mov     ss, ax
> +
> +    OneTimeCallRet ReloadFlat32
> +
> +;
> +; Tdx initialization after entering into ResetVector
> +;
> +; Modified:  EAX, EBX, ECX, EDX, EBP, EDI, ESP
> +;
> +InitTdx:
> +    ;
> +    ; Save EBX in EBP because EBX will be changed in ReloadFlat32
> +    ;
> +    mov     ebp, ebx
> +
> +    ;
> +    ; First load the GDT and jump to Flat32 mode
> +    ;
> +    OneTimeCall ReloadFlat32
> +
> +    ;
> +    ; Initialization of Tdx work area
> +    ;
> +    OneTimeCall  InitTdxWorkarea
> +
> +    OneTimeCallRet InitTdx
> +
> +;
> +; Called after SetCr3PageTables64 in Tdx guest to set CR0/CR4.
> +; If GPAW is 52, then CR3 is adjusted as well.
> +;
> +; Modified: EAX, EBX, CR0, CR3, CR4
> +;
> +PostSetCr3PageTables64Tdx:
> +    ;
> +    ; TDX_WORK_AREA was set in InitTdx if it is Tdx guest
> +    ;
> +    cmp     byte[CC_WORK_AREA], VM_GUEST_TDX
> +    jne     ExitPostSetCr3PageTables64Tdx
> +
> +    mov     eax, cr4
> +    bts     eax, 5                      ; enable PAE
> +
> +    ;
> +    ; byte[TDX_WORK_AREA_PAGELEVEL5] holds the indicator whether 52bit is
> +    ; supported. if it is the case, need to set LA57 and use 5-level paging
> +    ;
> +    cmp     byte[TDX_WORK_AREA_PAGELEVEL5], 0
> +    jz      TdxSetCr4
> +    bts     eax, 12
> +
> +TdxSetCr4:
> +    mov     cr4, eax
> +    mov     ebx, cr3
> +
> +    ;
> +    ; if la57 is not set, we are ok
> +    ; if using 5-level paging, adjust top-level page directory
> +    ;
> +    bt      eax, 12
> +    jnc     TdxSetCr3
> +    mov     ebx, TDX_PT_ADDR (0)
> +
> +TdxSetCr3:
> +    mov     cr3, ebx
> +
> +    xor     ebx, ebx
> +
> +ExitPostSetCr3PageTables64Tdx:
> +    OneTimeCallRet PostSetCr3PageTables64Tdx
> +
> +;
> +; Check if TDX is enabled
> +;
> +; Modified:  EAX
> +;
> +; If TDX is enabled then EAX will be 1
> +; If TDX is disabled then EAX will be 0.
> +;
> +IsTdxEnabled:
> +    xor     eax, eax
> +    cmp     byte[CC_WORK_AREA], VM_GUEST_TDX
> +    jne     NotTdx
> +    mov     eax, 1
> +
> +NotTdx:
> +    OneTimeCallRet IsTdxEnabled
> +
> diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
> index eacdb69ddb9f..1f4c0c50ac2e 100644
> --- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
> +++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
> @@ -37,11 +37,81 @@ BITS    32
>                         PAGE_READ_WRITE + \
>                         PAGE_PRESENT)
>
> +TdxBuildExtraPageTables:
> +    ;
> +    ; Extra page tables built by Tdx guests
> +    ;
> +    xor     eax, eax
> +    mov     ecx, 0x400
> +tdClearTdxPageTablesMemoryLoop:
> +    mov     dword [ecx * 4 + TDX_PT_ADDR(0) - 4], eax
> +    loop    tdClearTdxPageTablesMemoryLoop
> +
> +    ;
> +    ; Top level Page Directory Pointers (1 * 256TB entry)
> +    ;
> +    mov     dword[TDX_PT_ADDR (0)], PT_ADDR(0) + PAGE_PDP_ATTR
> +
> +    ;
> +    ; Set TDX_WORK_AREA_PGTBL_READY to notify APs to go
> +    ;
> +    mov     byte[TDX_WORK_AREA_PGTBL_READY], 1
> +
> +    OneTimeCallRet TdxBuildExtraPageTables
> +
> +SevBuildGhcbPageTables:
> +    ;
> +    ; 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.
> +    ;
> +    mov     ecx, (GHCB_BASE >> 21)
> +    mov     eax, GHCB_PT_ADDR + PAGE_PDP_ATTR
> +    mov     [ecx * 8 + PT_ADDR (0x2000)], eax
> +
> +    ;
> +    ; 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
> +
> +    ;
> +    ; 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
> +
> +    mov     ecx, GHCB_SIZE / 4
> +    xor     eax, eax
> +clearGhcbMemoryLoop:
> +    mov     dword[ecx * 4 + GHCB_BASE - 4], eax
> +    loop    clearGhcbMemoryLoop
> +
> +    OneTimeCallRet  SevBuildGhcbPageTables
> +
>  ;
>  ; Modified:  EAX, EBX, ECX, EDX
>  ;
>  SetCr3ForPageTables64:
>
> +    cmp     byte[CC_WORK_AREA], VM_GUEST_TDX
> +    jne     CheckSev
> +
> +    cmp     byte[TDX_WORK_AREA_PGTBL_READY], 1
> +    je      SetCr3
> +
> +    xor     edx, edx
> +    jmp     SevNotActive
> +
> +CheckSev:
>      OneTimeCall   CheckSevFeatures
>      xor     edx, edx
>      test    eax, eax
> @@ -101,44 +171,19 @@ pageTableEntriesLoop:
>      mov     [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
>      loop    pageTableEntriesLoop
>
> +    OneTimeCall IsTdxEnabled
> +    test    eax, eax
> +    jz      IsSevEs
> +
> +    OneTimeCall TdxBuildExtraPageTables
> +    jmp     SetCr3
> +
> +IsSevEs:
>      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.
> -    ;
> -    mov     ecx, (GHCB_BASE >> 21)
> -    mov     eax, GHCB_PT_ADDR + PAGE_PDP_ATTR
> -    mov     [ecx * 8 + PT_ADDR (0x2000)], eax
> -
> -    ;
> -    ; 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
> -
> -    ;
> -    ; 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
> -
> -    mov     ecx, GHCB_SIZE / 4
> -    xor     eax, eax
> -clearGhcbMemoryLoop:
> -    mov     dword[ecx * 4 + GHCB_BASE - 4], eax
> -    loop    clearGhcbMemoryLoop
> +    OneTimeCall   SevBuildGhcbPageTables
>
>  SetCr3:
>      ;
> diff --git a/OvmfPkg/ResetVector/Main.asm b/OvmfPkg/ResetVector/Main.asm
> new file mode 100644
> index 000000000000..fb1731728af5
> --- /dev/null
> +++ b/OvmfPkg/ResetVector/Main.asm
> @@ -0,0 +1,121 @@
> +;------------------------------------------------------------------------------
> +; @file
> +; Main routine of the pre-SEC code up through the jump into SEC
> +;
> +; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.<BR>
> +; SPDX-License-Identifier: BSD-2-Clause-Patent
> +;
> +;------------------------------------------------------------------------------
> +
> +
> +BITS    16
> +
> +;
> +; Modified:  EBX, ECX, EDX, EBP
> +;
> +; @param[in,out]  RAX/EAX  Initial value of the EAX register
> +;                          (BIST: Built-in Self Test)
> +; @param[in,out]  DI       'BP': boot-strap processor, or
> +;                          'AP': application processor
> +; @param[out]     RBP/EBP  Address of Boot Firmware Volume (BFV)
> +; @param[out]     DS       Selector allowing flat access to all addresses
> +; @param[out]     ES       Selector allowing flat access to all addresses
> +; @param[out]     FS       Selector allowing flat access to all addresses
> +; @param[out]     GS       Selector allowing flat access to all addresses
> +; @param[out]     SS       Selector allowing flat access to all addresses
> +;
> +; @return         None  This routine jumps to SEC and does not return
> +;
> +Main16:
> +    OneTimeCall EarlyInit16
> +
> +    ;
> +    ; Transition the processor from 16-bit real mode to 32-bit flat mode
> +    ;
> +    OneTimeCall TransitionFromReal16To32BitFlat
> +
> +BITS    32
> +%ifdef ARCH_X64
> +    ;
> +    ; Clear the first 2 bytes of CC_WORK_AREA.
> +    ;
> +    mov word[CC_WORK_AREA], 0
> +
> +    jmp SearchBfv
> +
> +;
> +; Entry point of Main32
> +;
> +Main32:
> +    OneTimeCall InitTdx
> +
> +SearchBfv:
> +
> +%endif
> +    ;
> +    ; Search for the Boot Firmware Volume (BFV)
> +    ;
> +    OneTimeCall Flat32SearchForBfvBase
> +
> +    ;
> +    ; EBP - Start of BFV
> +    ;
> +
> +    ;
> +    ; Search for the SEC entry point
> +    ;
> +    OneTimeCall Flat32SearchForSecEntryPoint
> +
> +    ;
> +    ; ESI - SEC Core entry point
> +    ; EBP - Start of BFV
> +    ;
> +
> +%ifdef ARCH_IA32
> +
> +    ;
> +    ; Restore initial EAX value into the EAX register
> +    ;
> +    mov     eax, esp
> +
> +    ;
> +    ; Jump to the 32-bit SEC entry point
> +    ;
> +    jmp     esi
> +
> +%else
> +
> +    ;
> +    ; Transition the processor from 32-bit flat mode to 64-bit flat mode
> +    ;
> +    OneTimeCall Transition32FlatTo64Flat
> +
> +BITS    64
> +
> +    ;
> +    ; Some values were calculated in 32-bit mode.  Make sure the upper
> +    ; 32-bits of 64-bit registers are zero for these values.
> +    ;
> +    mov     rax, 0x00000000ffffffff
> +    and     rsi, rax
> +    and     rbp, rax
> +    and     rsp, rax
> +
> +    ;
> +    ; RSI - SEC Core entry point
> +    ; RBP - Start of BFV
> +    ;
> +
> +    ;
> +    ; Restore initial EAX value into the RAX register
> +    ;
> +    mov     rax, rsp
> +
> +    ;
> +    ; Jump to the 64-bit SEC entry point
> +    ;
> +    jmp     rsi
> +
> +%endif
> +
> +
> diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf
> index d028c92d8cfa..0cf3a8036b97 100644
> --- a/OvmfPkg/ResetVector/ResetVector.inf
> +++ b/OvmfPkg/ResetVector/ResetVector.inf
> @@ -1,7 +1,7 @@
>  ## @file
>  #  Reset Vector
>  #
> -#  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
>  #
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -35,6 +35,7 @@
>
>  [Pcd]
>    gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
> +  gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase
> @@ -43,6 +44,15 @@
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfImageSizeInKb
> +  gUefiOvmfPkgTokenSpaceGuid.PcdCfvBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataOffset
> +  gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataSize
> +  gUefiOvmfPkgTokenSpaceGuid.PcdBfvBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataOffset
> +  gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataSize
>
>  [FixedPcd]
>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
> diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
> index acec46a32450..528a6603a20e 100644
> --- a/OvmfPkg/ResetVector/ResetVector.nasmb
> +++ b/OvmfPkg/ResetVector/ResetVector.nasmb
> @@ -67,6 +67,44 @@
>      %error "This implementation inherently depends on PcdOvmfSecGhcbBase not straddling a 2MB boundary"
>    %endif
>
> +  %define TDX_BFV_RAW_DATA_OFFSET   FixedPcdGet32 (PcdBfvRawDataOffset)
> +  %define TDX_BFV_RAW_DATA_SIZE     FixedPcdGet32 (PcdBfvRawDataSize)
> +  %define TDX_BFV_MEMORY_BASE       FixedPcdGet32 (PcdBfvBase)
> +  %define TDX_BFV_MEMORY_SIZE       FixedPcdGet32 (PcdBfvRawDataSize)
> +
> +  %define TDX_CFV_RAW_DATA_OFFSET   FixedPcdGet32 (PcdCfvRawDataOffset)
> +  %define TDX_CFV_RAW_DATA_SIZE     FixedPcdGet32 (PcdCfvRawDataSize)
> +  %define TDX_CFV_MEMORY_BASE       FixedPcdGet32 (PcdCfvBase),
> +  %define TDX_CFV_MEMORY_SIZE       FixedPcdGet32 (PcdCfvRawDataSize),
> +
> +  %define TDX_HEAP_MEMORY_BASE      FixedPcdGet32 (PcdOvmfSecPeiTempRamBase)
> +  %define TDX_HEAP_MEMORY_SIZE      FixedPcdGet32 (PcdOvmfSecPeiTempRamSize) / 2
> +
> +  %define TDX_STACK_MEMORY_BASE     (TDX_HEAP_MEMORY_BASE + TDX_HEAP_MEMORY_SIZE)
> +  %define TDX_STACK_MEMORY_SIZE     FixedPcdGet32 (PcdOvmfSecPeiTempRamSize) / 2
> +
> +  %define TDX_HOB_MEMORY_BASE       FixedPcdGet32 (PcdOvmfSecGhcbBase)
> +  %define TDX_HOB_MEMORY_SIZE       FixedPcdGet32 (PcdOvmfSecGhcbSize)
> +
> +  %define TDX_MAILBOX_MEMORY_BASE   FixedPcdGet32 (PcdOvmfSecGhcbBackupBase)
> +  %define TDX_MAILBOX_MEMORY_SIZE   FixedPcdGet32 (PcdOvmfSecGhcbBackupSize)
> +
> +  %define OVMF_PAGE_TABLE_BASE      FixedPcdGet32 (PcdOvmfSecPageTablesBase)
> +  %define OVMF_PAGE_TABLE_SIZE      FixedPcdGet32 (PcdOvmfSecPageTablesSize)
> +
> +  %define TDX_EXTRA_PAGE_TABLE_BASE FixedPcdGet32 (PcdOvmfSecGhcbPageTableBase)
> +  %define TDX_EXTRA_PAGE_TABLE_SIZE FixedPcdGet32 (PcdOvmfSecGhcbPageTableSize)
> +
> +  %define CC_WORK_AREA_MEMORY_BASE  FixedPcdGet32 (PcdSevEsWorkAreaBase)
> +  %define CC_WORK_AREA_MEMORY_SIZE  FixedPcdGet32 (PcdSevEsWorkAreaSize)
> +  %define CC_WORK_AREA              (CC_WORK_AREA_MEMORY_BASE)
> +  %define CC_WORK_AREA_SUBTYPE      (CC_WORK_AREA + 1)
> +  %define TDX_WORK_AREA_PAGELEVEL5  (CC_WORK_AREA + 4)
> +  %define TDX_WORK_AREA_PGTBL_READY (CC_WORK_AREA + 5)
> +  %define TDX_WORK_AREA_GPAW        (CC_WORK_AREA + 8)
> +
> +  %define TDX_PT_ADDR(Offset)       (TDX_EXTRA_PAGE_TABLE_BASE + (Offset))
> +
>    %define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Offset))
>
>    %define GHCB_PT_ADDR (FixedPcdGet32 (PcdOvmfSecGhcbPageTableBase))
> @@ -76,9 +114,12 @@
>    %define SEV_ES_WORK_AREA_RDRAND (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 8)
>    %define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16)
>    %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))
> -%include "Ia32/Flat32ToFlat64.asm"
> -%include "Ia32/AmdSev.asm"
> -%include "Ia32/PageTables64.asm"
> +
> +  %include "X64/IntelTdxMetadata.asm"
> +  %include "Ia32/IntelTdx.asm"
> +  %include "Ia32/Flat32ToFlat64.asm"
> +  %include "Ia32/AmdSev.asm"
> +  %include "Ia32/PageTables64.asm"
>  %endif
>
>  %include "Ia16/Real16ToFlat32.asm"
> @@ -91,5 +132,6 @@
>    %define SEV_LAUNCH_SECRET_SIZE  FixedPcdGet32 (PcdSevLaunchSecretSize)
>    %define SEV_FW_HASH_BLOCK_BASE  FixedPcdGet32 (PcdQemuHashTableBase)
>    %define SEV_FW_HASH_BLOCK_SIZE  FixedPcdGet32 (PcdQemuHashTableSize)
> +  %define OVMF_IMAGE_SIZE_IN_KB   FixedPcdGet32 (PcdOvmfImageSizeInKb)
>  %include "Ia16/ResetVectorVtf0.asm"
>
> diff --git a/OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm b/OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm
> new file mode 100644
> index 000000000000..97b1e915d899
> --- /dev/null
> +++ b/OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm
> @@ -0,0 +1,110 @@
> +;------------------------------------------------------------------------------
> +; @file
> +; Tdx Virtual Firmware metadata
> +;
> +; Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
> +; SPDX-License-Identifier: BSD-2-Clause-Patent
> +;
> +;------------------------------------------------------------------------------
> +
> +BITS    64
> +
> +%define TDX_METADATA_SECTION_TYPE_BFV       0
> +%define TDX_METADATA_SECTION_TYPE_CFV       1
> +%define TDX_METADATA_SECTION_TYPE_TD_HOB    2
> +%define TDX_METADATA_SECTION_TYPE_TEMP_MEM  3
> +%define TDX_METADATA_VERSION                1
> +%define TDX_METADATA_ATTRIBUTES_EXTENDMR    0x00000001
> +
> +ALIGN   16
> +TIMES (15 - ((TdxGuidedStructureEnd - TdxGuidedStructureStart + 15) % 16)) DB 0
> +
> +TdxGuidedStructureStart:
> +
> +;
> +; TDVF meta data
> +;
> +TdxMetadataGuid:
> +  DB  0xf3, 0xf9, 0xea, 0xe9, 0x8e, 0x16, 0xd5, 0x44
> +  DB  0xa8, 0xeb, 0x7f, 0x4d, 0x87, 0x38, 0xf6, 0xae
> +
> +_Descriptor:
> +  DB 'T','D','V','F'                                  ; Signature
> +  DD TdxGuidedStructureEnd - _Descriptor              ; Length
> +  DD TDX_METADATA_VERSION                             ; Version
> +  DD (TdxGuidedStructureEnd - _Descriptor - 16)/32    ; Number of sections
> +
> +_Bfv:
> +  DD TDX_BFV_RAW_DATA_OFFSET
> +  DD TDX_BFV_RAW_DATA_SIZE
> +  DQ TDX_BFV_MEMORY_BASE
> +  DQ TDX_BFV_MEMORY_SIZE
> +  DD TDX_METADATA_SECTION_TYPE_BFV
> +  DD TDX_METADATA_ATTRIBUTES_EXTENDMR
> +
> +_Cfv:
> +  DD TDX_CFV_RAW_DATA_OFFSET
> +  DD TDX_CFV_RAW_DATA_SIZE
> +  DQ TDX_CFV_MEMORY_BASE
> +  DQ TDX_CFV_MEMORY_SIZE
> +  DD TDX_METADATA_SECTION_TYPE_CFV
> +  DD 0
> +
> +_Stack:
> +  DD 0
> +  DD 0
> +  DQ TDX_STACK_MEMORY_BASE
> +  DQ TDX_STACK_MEMORY_SIZE
> +  DD TDX_METADATA_SECTION_TYPE_TEMP_MEM
> +  DD 0
> +
> +_Heap:
> +  DD 0
> +  DD 0
> +  DQ TDX_HEAP_MEMORY_BASE
> +  DQ TDX_HEAP_MEMORY_SIZE
> +  DD TDX_METADATA_SECTION_TYPE_TEMP_MEM
> +  DD 0
> +
> +_MailBox:
> +  DD 0
> +  DD 0
> +  DQ TDX_MAILBOX_MEMORY_BASE
> +  DQ TDX_MAILBOX_MEMORY_SIZE
> +  DD TDX_METADATA_SECTION_TYPE_TEMP_MEM
> +  DD 0
> +
> +_CcWorkarea:
> +  DD 0
> +  DD 0
> +  DQ CC_WORK_AREA_MEMORY_BASE
> +  DQ CC_WORK_AREA_MEMORY_SIZE
> +  DD TDX_METADATA_SECTION_TYPE_TEMP_MEM
> +  DD 0
> +
> +_TdHob:
> +  DD 0
> +  DD 0
> +  DQ TDX_HOB_MEMORY_BASE
> +  DQ TDX_HOB_MEMORY_SIZE
> +  DD TDX_METADATA_SECTION_TYPE_TD_HOB
> +  DD 0
> +
> +_TdxPageTable:
> +  DD 0
> +  DD 0
> +  DQ TDX_EXTRA_PAGE_TABLE_BASE
> +  DQ TDX_EXTRA_PAGE_TABLE_SIZE
> +  DD TDX_METADATA_SECTION_TYPE_TEMP_MEM
> +  DD 0
> +
> +_OvmfPageTable:
> +  DD 0
> +  DD 0
> +  DQ OVMF_PAGE_TABLE_BASE
> +  DQ OVMF_PAGE_TABLE_SIZE
> +  DD TDX_METADATA_SECTION_TYPE_TEMP_MEM
> +  DD 0
> +
> +TdxGuidedStructureEnd:
> +ALIGN   16
> --
> 2.29.2.windows.2
>

  parent reply	other threads:[~2021-08-04 10:01 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-03  1:18 [PATCH V4 0/3] Add Intel TDX support in OvmfPkg/ResetVector Min Xu
2021-08-03  1:18 ` [PATCH V4 1/3] OvmfPkg: Add Tdx BFV/CFV PCDs and PcdOvmfImageSizeInKb Min Xu
2021-08-04  9:25   ` Erdem Aktas
2021-08-03  1:18 ` [PATCH V4 2/3] OvmfPkg/Sec: Update the check logic in SevEsIsEnabled Min Xu
2021-08-03 19:23   ` Brijesh Singh
2021-08-03 23:54     ` Min Xu
2021-08-03  1:18 ` [PATCH V4 3/3] OvmfPkg/ResetVector: Enable Intel TDX in ResetVector of Ovmf Min Xu
2021-08-03 19:30   ` Brijesh Singh
2021-08-16  9:34     ` [edk2-devel] " Gerd Hoffmann
2021-08-04 10:01   ` Erdem Aktas [this message]
2021-08-04 12:50     ` Min Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAAYXXYzBDKUQ-BMfSYWT0JDLONWt8pXdYbUdAHvefrg-JpCLPg@mail.gmail.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox