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:
@@ -63,6 +63,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
UINT8 *RelocateApLoopFuncAddress;
|
||||
UINTN RelocateApLoopFuncSize;
|
||||
UINT8 *RelocateApResetVector;
|
||||
} MP_RELOCATION_MAP;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,3 +71,7 @@
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user