OvmfPkg: Add the ResetVector in TDX MailBox

Base on ACPI 6.6 Multiprocessor Wakeup Structure, TDVF needs to provide
a physical address of the ResetVector to OS. And it should allow the
Multiprocessor Wakeup Mailbox to be reset in order to be used once again
with a given AP.

Signed-off-by: Ceping Sun <cepingx.sun@intel.com>
Reviewed-by: Min Xu <min.m.xu@intel.com>
Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
This commit is contained in:
Ceping Sun
2023-11-30 21:00:32 -05:00
committed by Liming Gao
parent 41aaecbf59
commit 406f42cb74
6 changed files with 167 additions and 10 deletions

View File

@@ -63,6 +63,7 @@ typedef struct {
typedef struct {
UINT8 *RelocateApLoopFuncAddress;
UINTN RelocateApLoopFuncSize;
UINT8 *RelocateApResetVector;
} MP_RELOCATION_MAP;
#pragma pack()

View File

@@ -186,10 +186,13 @@ PlatformTdxPublishRamRegions (
// work area. We ought to prevent DXE from serving allocation requests
// such that they would overlap the work area.
//
// Since this memory range will be used by the Reset Vector on Maibox
// wakeup again, it must be reserved as ACPI NVS.
//
BuildMemoryAllocationHob (
(EFI_PHYSICAL_ADDRESS)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaBase),
(UINT64)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaSize),
EfiBootServicesData
EfiACPIMemoryNVS
);
}
}

View File

@@ -28,6 +28,43 @@
#include <Uefi.h>
#include <TdxAcpiTable.h>
IA32_SEGMENT_DESCRIPTOR 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 +74,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 +131,7 @@ RelocateMailbox (
ApLoopFunc
));
SetMailboxResetVectorGDT ();
//
// Initialize mailbox
//
@@ -115,6 +155,13 @@ RelocateMailbox (
0
);
*ResetVector = (UINT64)ApLoopFunc + (RelocationMap.RelocateApResetVector -
RelocationMap.RelocateApLoopFuncAddress);
DEBUG ((
DEBUG_INFO,
"Ap Relocation: reset_vector %llx\n",
*ResetVector
));
return Address;
}
@@ -142,7 +189,8 @@ AlterAcpiTable (
UINT8 *NewMadtTable;
UINTN NewMadtTableLength;
EFI_PHYSICAL_ADDRESS RelocateMailboxAddress;
EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE *MadtMpWk;
EFI_PHYSICAL_ADDRESS RelocateResetVector;
EFI_ACPI_6_6_MULTIPROCESSOR_WAKEUP_STRUCTURE *MadtMpWk;
EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtHeader;
Index = 0;
@@ -155,7 +203,7 @@ AlterAcpiTable (
return;
}
RelocateMailboxAddress = RelocateMailbox ();
RelocateMailboxAddress = RelocateMailbox (&RelocateResetVector);
if (RelocateMailboxAddress == 0) {
ASSERT (FALSE);
DEBUG ((DEBUG_ERROR, "Failed to relocate Td mailbox\n"));
@@ -172,7 +220,7 @@ AlterAcpiTable (
break;
}
NewMadtTableLength = Table->Length + sizeof (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE);
NewMadtTableLength = Table->Length + sizeof (EFI_ACPI_6_6_MULTIPROCESSOR_WAKEUP_STRUCTURE);
NewMadtTable = AllocatePool (NewMadtTableLength);
if (NewMadtTable == NULL) {
DEBUG ((DEBUG_ERROR, "%a: OUT_OF_SOURCES error.\n", __func__));
@@ -183,12 +231,13 @@ AlterAcpiTable (
MadtHeader = (EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)NewMadtTable;
MadtHeader->Header.Length = (UINT32)NewMadtTableLength;
MadtMpWk = (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE *)(NewMadtTable + Table->Length);
MadtMpWk = (EFI_ACPI_6_6_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->Length = sizeof (EFI_ACPI_6_6_MULTIPROCESSOR_WAKEUP_STRUCTURE);
MadtMpWk->MailBoxVersion = 1;
MadtMpWk->Reserved = 0;
MadtMpWk->MailBoxAddress = RelocateMailboxAddress;
MadtMpWk->ResetVector = RelocateResetVector;
Status = AcpiTableProtocol->InstallAcpiTable (AcpiTableProtocol, NewMadtTable, NewMadtTableLength, &NewTableKey);
if (EFI_ERROR (Status)) {

View File

@@ -18,6 +18,8 @@
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <WorkArea.h>
#include <IndustryStandard/IntelTdx.h>
#include <IndustryStandard/Acpi.h>
@@ -41,7 +43,7 @@ AsmGetRelocationMap (
EFI_PHYSICAL_ADDRESS
EFIAPI
RelocateMailbox (
VOID
EFI_PHYSICAL_ADDRESS *ResetVector
);
/**

View File

@@ -71,3 +71,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack
gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize

View File

@@ -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 0xffc4
@@ -76,6 +86,7 @@ AsmRelocateApMailBoxLoopStart:
test r10, r10
jnz Panic
mov r8, r15
mov qword[rel mailbox_address], rbx
MailBoxLoop:
; Spin until command set
@@ -104,6 +115,91 @@ MailBoxTest:
jmp MailBoxLoop
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:
@@ -112,8 +208,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