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+tianoc...@kernel.org> > Cc: Brijesh Singh <brijesh.si...@amd.com> > Cc: Erdem Aktas <erdemak...@google.com> > Cc: James Bottomley <j...@linux.ibm.com> > Cc: Jiewen Yao <jiewen....@intel.com> > Cc: Tom Lendacky <thomas.lenda...@amd.com> > Signed-off-by: Min Xu <min.m...@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/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-