[edk2-devel] [PATCH V2 4/4] OvmfPkg/ResetVector: Update ResetVector to support Tdx

Lendacky, Thomas via groups.io thomas.lendacky=amd.com at groups.io
Thu Jul 22 17:07:49 UTC 2021


On 7/22/21 12:52 AM, Min Xu wrote:
> RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429
> 
> 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.
> This is done in OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm.
> 
> ReloadFlat32.asm load the GDT and set the CR0, then jump to Flat-32 mode.
> 
> InitTdx.asm is called to record the Tdx signature ('TDXG') and other tdx
> information in a TDX_WORK_AREA which can be used by the other routines in
> ResetVector.
> 
> Init32.asm is 32-bit initialization code in OvmfPkg. It puts above
> ReloadFlat32 and InitTdx together to do the initializaiton for Tdx.
> 
> After that Tdx jumps to 64-bit long mode by doing following tasks:
> 1. SetCr3ForPageTables64
>    For OVMF, some initial page tables is built at:
>      PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000)
>    This page table supports the 4-level page table.
>    But Tdx support 4-level and 5-level page table based on the CPU GPA width.
>    48bit is 4-level paging, 52-bit is 5-level paging.
>    If 5-level page table is supported (GPAW is 52), then a top level
>    page directory pointers (1 * 256TB entry) is generated in the
>    TdxPageTable.
> 2. Set Cr4
>    Enable PAE.
> 3. Adjust Cr3
>    If GPAW is 48, then Cr3 is PT_ADDR (0). If GPAW is 52, then Cr3 is
>    TDX_PT_ADDR (0).
> 
> Tdx MailBox [0x10, 0x800] is reserved for OS. So we initialize piece of this
> area ([0x10, 0x20]) to record the Tdx flag ('TDXG') and other Tdx info so that
> they can be used in the following flow.
> 
> After all above is successfully done, Tdx jump to SecEntry.
> 
> Cc: Ard Biesheuvel <ardb+tianocore at kernel.org>
> 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  | 47 ++++++++++++++++
>  OvmfPkg/ResetVector/Ia32/Init32.asm          | 34 ++++++++++++
>  OvmfPkg/ResetVector/Ia32/InitTdx.asm         | 57 ++++++++++++++++++++
>  OvmfPkg/ResetVector/Ia32/PageTables64.asm    | 41 ++++++++++++++
>  OvmfPkg/ResetVector/Ia32/ReloadFlat32.asm    | 44 +++++++++++++++
>  OvmfPkg/ResetVector/ResetVector.nasmb        | 18 +++++++
>  7 files changed, 262 insertions(+)
>  create mode 100644 OvmfPkg/ResetVector/Ia32/Init32.asm
>  create mode 100644 OvmfPkg/ResetVector/Ia32/InitTdx.asm
>  create mode 100644 OvmfPkg/ResetVector/Ia32/ReloadFlat32.asm
> 
> 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..2206ca719593 100644
> --- a/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
> +++ b/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
> @@ -17,6 +17,9 @@ Transition32FlatTo64Flat:
>  
>      OneTimeCall SetCr3ForPageTables64
>  
> +    cmp     dword[TDX_WORK_AREA], 0x47584454 ; 'TDXG'
> +    jz      TdxTransition32FlatTo64Flat
> +

Is the memory area guaranteed to be zeroed for legacy guests? Hopefully,
this won't trip up a non-TDX guest with a false match (highly unlikely,
though).

>      mov     eax, cr4
>      bts     eax, 5                      ; enable PAE
>      mov     cr4, eax
> @@ -65,10 +68,54 @@ EnablePaging:
>      bts     eax, 31                     ; set PG
>      mov     cr0, eax                    ; enable paging
>  
> +    jmp     _jumpTo64Bit
> +
> +;
> +; Tdx Transition from 32Flat to 64Flat
> +;
> +TdxTransition32FlatTo64Flat:
> +
> +    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      .set_cr4
> +    bts     eax, 12
> +.set_cr4:
> +    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     .set_cr3
> +    mov     ebx, TDX_PT_ADDR (0)
> +.set_cr3:
> +    mov     cr3, ebx
> +
> +    mov     eax, cr0
> +    bts     eax, 31                     ; set PG
> +    mov     cr0, eax                    ; enable paging

If you clear ebx here...

> +
> +_jumpTo64Bit:
>      jmp     LINEAR_CODE64_SEL:ADDR_OF(jumpTo64BitAndLandHere)
> +
>  BITS    64
>  jumpTo64BitAndLandHere:
>  
> +    ;
> +    ; For Td guest we are done and jump to the end
> +    ;
> +    mov     eax, TDX_WORK_AREA
> +    cmp     dword [eax], 0x47584454 ; 'TDXG'
> +    jz      GoodCompare
> +

... you can remove these instructions. You'll jump to InsnCompare and that
check should succeed, right?

Thanks,
Tom

>      ;
>      ; Check if the second step of the SEV-ES mitigation is to be performed.
>      ;


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