Skip to content

Commit

Permalink
OvmfPkg: Add the ResetVector in TDX MailBox
Browse files Browse the repository at this point in the history
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 <cepingx.sun@intel.com>
reviewed-by: Min Xu <min.m.xu@intel.com>
tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
  • Loading branch information
sunceping authored and mxu9 committed Jan 5, 2024
1 parent 912c70b commit aaac8f2
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 5 deletions.
1 change: 1 addition & 0 deletions OvmfPkg/Include/IndustryStandard/IntelTdx.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ typedef struct {
typedef struct {
UINT8 *RelocateApLoopFuncAddress;
UINTN RelocateApLoopFuncSize;
UINT8 *RelocateApResetVector;
} MP_RELOCATION_MAP;

#pragma pack()
Expand Down
58 changes: 55 additions & 3 deletions OvmfPkg/TdxDxe/TdxAcpiTable.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,46 @@
#include <Uefi.h>
#include <TdxAcpiTable.h>


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
Expand All @@ -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;
Expand Down Expand Up @@ -92,6 +134,7 @@ RelocateMailbox (
ApLoopFunc
));

SetMailboxResetVectorGDT();
//
// Initialize mailbox
//
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;

Expand All @@ -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"));
Expand Down Expand Up @@ -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)) {
Expand Down
4 changes: 3 additions & 1 deletion OvmfPkg/TdxDxe/TdxAcpiTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -41,7 +43,7 @@ AsmGetRelocationMap (
EFI_PHYSICAL_ADDRESS
EFIAPI
RelocateMailbox (
VOID
EFI_PHYSICAL_ADDRESS *ResetVector
);

/**
Expand Down
4 changes: 4 additions & 0 deletions OvmfPkg/TdxDxe/TdxDxe.inf
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack
gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
100 changes: 99 additions & 1 deletion OvmfPkg/TdxDxe/X64/ApRunLoop.nasm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -49,6 +59,7 @@ AsmRelocateApMailBoxLoopStart:
test r10, r10
jnz Panic
mov r8, r15
mov qword[rel mailbox_address], rbx

MailBoxLoop:
; Spin until command set
Expand Down Expand Up @@ -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:

Expand All @@ -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

0 comments on commit aaac8f2

Please sign in to comment.