From aaac8f2de72656471877cee0afcf62e2c71c0df1 Mon Sep 17 00:00:00 2001 From: Ceping Sun Date: Thu, 30 Nov 2023 21:00:32 -0500 Subject: [PATCH] OvmfPkg: Add the ResetVector in TDX MailBox Refer to the ACPI 6.6 changed, MADT table needs to provide the ResetVector address to OS and it should can make the AP to entry a state to check the mailbox. Signed-off-by: Ceping Sun reviewed-by: Min Xu tested-by: Kirill A. Shutemov --- OvmfPkg/Include/IndustryStandard/IntelTdx.h | 1 + OvmfPkg/TdxDxe/TdxAcpiTable.c | 58 +++++++++++- OvmfPkg/TdxDxe/TdxAcpiTable.h | 4 +- OvmfPkg/TdxDxe/TdxDxe.inf | 4 + OvmfPkg/TdxDxe/X64/ApRunLoop.nasm | 100 +++++++++++++++++++- 5 files changed, 162 insertions(+), 5 deletions(-) diff --git a/OvmfPkg/Include/IndustryStandard/IntelTdx.h b/OvmfPkg/Include/IndustryStandard/IntelTdx.h index fc383468489..68126b8a3cd 100644 --- a/OvmfPkg/Include/IndustryStandard/IntelTdx.h +++ b/OvmfPkg/Include/IndustryStandard/IntelTdx.h @@ -61,6 +61,7 @@ typedef struct { typedef struct { UINT8 *RelocateApLoopFuncAddress; UINTN RelocateApLoopFuncSize; + UINT8 *RelocateApResetVector; } MP_RELOCATION_MAP; #pragma pack() diff --git a/OvmfPkg/TdxDxe/TdxAcpiTable.c b/OvmfPkg/TdxDxe/TdxAcpiTable.c index d6d6975e567..ca977fb9265 100644 --- a/OvmfPkg/TdxDxe/TdxAcpiTable.c +++ b/OvmfPkg/TdxDxe/TdxAcpiTable.c @@ -28,6 +28,46 @@ #include #include + + IA32_GDT mGdtEntries[] = { + { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }, /* 0x0: reserve */ + { + { 0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0 } + }, /* 0x8: compatibility mode */ + { + { 0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0 } + }, /* 0x10: for long mode */ + { + { 0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0 } + }, /* 0x18: data */ + { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }, /* 0x20: reserve */ +}; + + +/** + At the beginning of ResetVector in OS, the GDT needs to be reloaded. +**/ +VOID +SetMailboxResetVectorGDT ( + VOID + ) +{ + TDX_WORK_AREA *TdxWorkArea; + + TdxWorkArea = (TDX_WORK_AREA *)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaBase); + ASSERT (TdxWorkArea != NULL); + ZeroMem ((VOID *)TdxWorkArea->MailboxGdt.Data, sizeof (TdxWorkArea->MailboxGdt.Data)); + + CopyMem((VOID *)TdxWorkArea->MailboxGdt.Data, (VOID *)mGdtEntries, sizeof(mGdtEntries)); + TdxWorkArea->MailboxGdt.Gdtr.Base = (UINTN)TdxWorkArea->MailboxGdt.Data; + TdxWorkArea->MailboxGdt.Gdtr.Limit = sizeof (mGdtEntries) - 1; +} + + /** At the beginning of system boot, a 4K-aligned, 4K-size memory (Td mailbox) is pre-allocated by host VMM. BSP & APs do the page accept together in that memory @@ -37,12 +77,14 @@ memory block which is allocated in the ACPI Nvs memory. APs are waken up and spin around the relocated mailbox for further command. + @param[in, out] ResetVector Pointer to the ResetVector + @return EFI_PHYSICAL_ADDRESS Address of the relocated mailbox **/ EFI_PHYSICAL_ADDRESS EFIAPI RelocateMailbox ( - VOID + EFI_PHYSICAL_ADDRESS *ResetVector ) { EFI_PHYSICAL_ADDRESS Address; @@ -92,6 +134,7 @@ RelocateMailbox ( ApLoopFunc )); + SetMailboxResetVectorGDT(); // // Initialize mailbox // @@ -115,6 +158,13 @@ RelocateMailbox ( 0 ); + *ResetVector = (UINT64)ApLoopFunc + (RelocationMap.RelocateApResetVector - + RelocationMap.RelocateApLoopFuncAddress); + DEBUG (( + DEBUG_INFO, + "Ap Relocation: reset_vector %llx\n", + *ResetVector + )); return Address; } @@ -142,6 +192,7 @@ AlterAcpiTable ( UINT8 *NewMadtTable; UINTN NewMadtTableLength; EFI_PHYSICAL_ADDRESS RelocateMailboxAddress; + EFI_PHYSICAL_ADDRESS RelocateResetVector; EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE *MadtMpWk; EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtHeader; @@ -155,7 +206,7 @@ AlterAcpiTable ( return; } - RelocateMailboxAddress = RelocateMailbox (); + RelocateMailboxAddress = RelocateMailbox (&RelocateResetVector); if (RelocateMailboxAddress == 0) { ASSERT (FALSE); DEBUG ((DEBUG_ERROR, "Failed to relocate Td mailbox\n")); @@ -186,9 +237,10 @@ AlterAcpiTable ( MadtMpWk = (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE *)(NewMadtTable + Table->Length); MadtMpWk->Type = EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP; MadtMpWk->Length = sizeof (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE); - MadtMpWk->MailBoxVersion = 0; + MadtMpWk->MailBoxVersion = 1; MadtMpWk->Reserved = 0; MadtMpWk->MailBoxAddress = RelocateMailboxAddress; + MadtMpWk->ResetVector = RelocateResetVector; Status = AcpiTableProtocol->InstallAcpiTable (AcpiTableProtocol, NewMadtTable, NewMadtTableLength, &NewTableKey); if (EFI_ERROR (Status)) { diff --git a/OvmfPkg/TdxDxe/TdxAcpiTable.h b/OvmfPkg/TdxDxe/TdxAcpiTable.h index 6b7615dc368..89fbe98d864 100644 --- a/OvmfPkg/TdxDxe/TdxAcpiTable.h +++ b/OvmfPkg/TdxDxe/TdxAcpiTable.h @@ -18,6 +18,8 @@ #include #include #include +#include + #include #include @@ -41,7 +43,7 @@ AsmGetRelocationMap ( EFI_PHYSICAL_ADDRESS EFIAPI RelocateMailbox ( - VOID + EFI_PHYSICAL_ADDRESS *ResetVector ); /** diff --git a/OvmfPkg/TdxDxe/TdxDxe.inf b/OvmfPkg/TdxDxe/TdxDxe.inf index 9793562884c..69e4c0bfa54 100644 --- a/OvmfPkg/TdxDxe/TdxDxe.inf +++ b/OvmfPkg/TdxDxe/TdxDxe.inf @@ -71,3 +71,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize diff --git a/OvmfPkg/TdxDxe/X64/ApRunLoop.nasm b/OvmfPkg/TdxDxe/X64/ApRunLoop.nasm index a398c1964bb..654d41d9330 100644 --- a/OvmfPkg/TdxDxe/X64/ApRunLoop.nasm +++ b/OvmfPkg/TdxDxe/X64/ApRunLoop.nasm @@ -16,8 +16,18 @@ DEFAULT REL +SECTION .bss +global STACK_BASE +STACK_BASE: + resb 1024 +STACK_TOP: + SECTION .text +%define TDX_WORK_AREA_MAILBOX_GDTR (FixedPcdGet32 (PcdOvmfWorkAreaBase) + 128) + +%define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Offset)) + BITS 64 %define TDVMCALL_EXPOSE_REGS_MASK 0xffec @@ -49,6 +59,7 @@ AsmRelocateApMailBoxLoopStart: test r10, r10 jnz Panic mov r8, r15 + mov qword[rel mailbox_address], rbx MailBoxLoop: ; Spin until command set @@ -81,6 +92,91 @@ MailBoxSleep: jmp $ Panic: ud2 + +AsmRelocateApResetVector: + +.prepareStack: + ; The stack can then be used to switch from long mode to compatibility mode + mov rsp, STACK_TOP + +.loadGDT: + cli + mov rax, TDX_WORK_AREA_MAILBOX_GDTR + lgdt [rax] + +.loadSwicthModeCode: + mov rcx, dword 0x10 ; load long mode selector + shl rcx, 32 + lea rdx, [LongMode] ; assume address < 4G + or rcx, rdx + push rcx + + mov rcx, dword 0x08 ; load compatible mode selector + shl rcx, 32 + lea rdx, [Compatible] ; assume address < 4G + or rcx, rdx + push rcx + retf + +BITS 32 +Compatible: + mov eax, dword 0x18 +; ; reload DS/ES/SS to make sure they are correct referred to current GDT + mov ds, ax + mov es, ax + mov ss, ax + ; reload the fs and gs + mov fs, ax + mov gs, ax + + ; Must clear the CR4.PCIDE before clearing paging + mov ecx, cr4 + btc ecx, 17 + mov cr4, ecx + ; + ; Disable paging + ; + mov ecx, cr0 + btc ecx, 31 + mov cr0, ecx + ; +RestoreCr0: + ; Only enable PE(bit 0), NE(bit 5), ET(bit 4) 0x31 + mov eax, dword 0x31 + mov cr0, eax + + + ; Only Enable MCE(bit 6), VMXE(bit 13) 0x2040 + ; TDX enforeced the VMXE = 1 and mask it in VMM, so not set it. +RestoreCr4: + mov eax, 0x40 + mov cr4, eax +SetCr3: + ; + ; Can use the boot page tables since it's reserved + + mov eax, PT_ADDR (0) + mov cr3, eax + +EnablePAE: + mov eax, cr4 + bts eax, 5 + mov cr4, eax + +EnablePaging: + mov eax, cr0 + bts eax, 31 ; set PG + mov cr0, eax ; enable paging + ; return to LongMode + retf + +BITS 64 +LongMode: + mov rbx, qword[rel mailbox_address] + jmp AsmRelocateApMailBoxLoopStart +align 16 +mailbox_address: + dq 0 BITS 64 AsmRelocateApMailBoxLoopEnd: @@ -89,8 +185,10 @@ AsmRelocateApMailBoxLoopEnd: ;------------------------------------------------------------------------------------- global ASM_PFX(AsmGetRelocationMap) ASM_PFX(AsmGetRelocationMap): + ; mov byte[TDX_WORK_AREA_MB_PGTBL_READY], 0 lea rax, [AsmRelocateApMailBoxLoopStart] mov qword [rcx], rax mov qword [rcx + 8h], AsmRelocateApMailBoxLoopEnd - AsmRelocateApMailBoxLoopStart + lea rax, [AsmRelocateApResetVector] + mov qword [rcx + 10h], rax ret -