mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-23 21:54:27 +02:00
OvmfPkg/IntelTdx: Add Sec to bring up both Legacy and Tdx guest
RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429 OvmfPkg/IntelTdx/Sec is a simplied version of OvmfPkg/Sec. There are below differences between these 2 Sec - IntelTdx/Sec only supports Legacy guest and Tdx guest in X64. - IntelTdx/Sec calls PeilessStartup () to jump from SEC to DXE directly. - IntelTdx/Sec uses MemoryAllocationLib / HobLib / PrePiLib in EmbeddedPkg. Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Erdem Aktas <erdemaktas@google.com> Cc: James Bottomley <jejb@linux.ibm.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Signed-off-by: Min Xu <min.m.xu@intel.com>
This commit is contained in:
parent
4fe2678411
commit
1f29de4d20
198
OvmfPkg/IntelTdx/Sec/SecMain.c
Normal file
198
OvmfPkg/IntelTdx/Sec/SecMain.c
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/** @file
|
||||||
|
Main SEC phase code. Transitions to PEI.
|
||||||
|
|
||||||
|
Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
|
||||||
|
Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <PiPei.h>
|
||||||
|
|
||||||
|
#include <Library/PeimEntryPoint.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/PcdLib.h>
|
||||||
|
#include <Library/UefiCpuLib.h>
|
||||||
|
#include <Library/DebugAgentLib.h>
|
||||||
|
#include <Library/IoLib.h>
|
||||||
|
#include <Library/PeCoffLib.h>
|
||||||
|
#include <Library/PeCoffGetEntryPointLib.h>
|
||||||
|
#include <Library/LocalApicLib.h>
|
||||||
|
#include <Library/CpuExceptionHandlerLib.h>
|
||||||
|
#include <IndustryStandard/Tdx.h>
|
||||||
|
#include <Library/PlatformInitLib.h>
|
||||||
|
|
||||||
|
#include <Library/PeilessStartupLib.h>
|
||||||
|
|
||||||
|
#define SEC_IDT_ENTRY_COUNT 34
|
||||||
|
|
||||||
|
typedef struct _SEC_IDT_TABLE {
|
||||||
|
EFI_PEI_SERVICES *PeiService;
|
||||||
|
IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];
|
||||||
|
} SEC_IDT_TABLE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Template of an IDT entry pointing to 10:FFFFFFE4h.
|
||||||
|
//
|
||||||
|
IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = {
|
||||||
|
{ // Bits
|
||||||
|
0xffe4, // OffsetLow
|
||||||
|
0x10, // Selector
|
||||||
|
0x0, // Reserved_0
|
||||||
|
IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType
|
||||||
|
0xffff // OffsetHigh
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SecCoreStartupWithStack (
|
||||||
|
IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,
|
||||||
|
IN VOID *TopOfCurrentStack
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_SEC_PEI_HAND_OFF SecCoreData;
|
||||||
|
SEC_IDT_TABLE IdtTableInStack;
|
||||||
|
IA32_DESCRIPTOR IdtDescriptor;
|
||||||
|
UINT32 Index;
|
||||||
|
volatile UINT8 *Table;
|
||||||
|
|
||||||
|
if (TdIsEnabled ()) {
|
||||||
|
//
|
||||||
|
// For Td guests, the memory map info is in TdHobLib. It should be processed
|
||||||
|
// first so that the memory is accepted. Otherwise access to the unaccepted
|
||||||
|
// memory will trigger tripple fault.
|
||||||
|
//
|
||||||
|
if (ProcessTdxHobList () != EFI_SUCCESS) {
|
||||||
|
CpuDeadLoop ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// To ensure SMM can't be compromised on S3 resume, we must force re-init of
|
||||||
|
// the BaseExtractGuidedSectionLib. Since this is before library contructors
|
||||||
|
// are called, we must use a loop rather than SetMem.
|
||||||
|
//
|
||||||
|
Table = (UINT8 *)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);
|
||||||
|
for (Index = 0;
|
||||||
|
Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);
|
||||||
|
++Index)
|
||||||
|
{
|
||||||
|
Table[Index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize IDT - Since this is before library constructors are called,
|
||||||
|
// we use a loop rather than CopyMem.
|
||||||
|
//
|
||||||
|
IdtTableInStack.PeiService = NULL;
|
||||||
|
|
||||||
|
for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {
|
||||||
|
//
|
||||||
|
// Declare the local variables that actually move the data elements as
|
||||||
|
// volatile to prevent the optimizer from replacing this function with
|
||||||
|
// the intrinsic memcpy()
|
||||||
|
//
|
||||||
|
CONST UINT8 *Src;
|
||||||
|
volatile UINT8 *Dst;
|
||||||
|
UINTN Byte;
|
||||||
|
|
||||||
|
Src = (CONST UINT8 *)&mIdtEntryTemplate;
|
||||||
|
Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index];
|
||||||
|
|
||||||
|
for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) {
|
||||||
|
Dst[Byte] = Src[Byte];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
|
||||||
|
IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
|
||||||
|
|
||||||
|
ProcessLibraryConstructorList (NULL, NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Load the IDTR.
|
||||||
|
//
|
||||||
|
AsmWriteIdtr (&IdtDescriptor);
|
||||||
|
|
||||||
|
if (TdIsEnabled ()) {
|
||||||
|
//
|
||||||
|
// InitializeCpuExceptionHandlers () should be called in Td guests so that
|
||||||
|
// #VE exceptions can be handled correctly.
|
||||||
|
//
|
||||||
|
InitializeCpuExceptionHandlers (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"SecCoreStartupWithStack(0x%x, 0x%x)\n",
|
||||||
|
(UINT32)(UINTN)BootFv,
|
||||||
|
(UINT32)(UINTN)TopOfCurrentStack
|
||||||
|
));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize floating point operating environment
|
||||||
|
// to be compliant with UEFI spec.
|
||||||
|
//
|
||||||
|
InitializeFloatingPointUnits ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// ASSERT that the Page Tables were set by the reset vector code to
|
||||||
|
// the address we expect.
|
||||||
|
//
|
||||||
|
ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase));
|
||||||
|
|
||||||
|
//
|
||||||
|
// |-------------| <-- TopOfCurrentStack
|
||||||
|
// | Stack | 32k
|
||||||
|
// |-------------|
|
||||||
|
// | Heap | 32k
|
||||||
|
// |-------------| <-- SecCoreData.TemporaryRamBase
|
||||||
|
//
|
||||||
|
|
||||||
|
ASSERT (
|
||||||
|
(UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) +
|
||||||
|
PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==
|
||||||
|
(UINTN)TopOfCurrentStack
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize SEC hand-off state
|
||||||
|
//
|
||||||
|
SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
|
||||||
|
|
||||||
|
SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize);
|
||||||
|
SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
|
||||||
|
|
||||||
|
SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
|
||||||
|
SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
|
||||||
|
|
||||||
|
SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
|
||||||
|
SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
|
||||||
|
|
||||||
|
SecCoreData.BootFirmwareVolumeBase = BootFv;
|
||||||
|
SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
|
||||||
|
//
|
||||||
|
IoWrite8 (0x21, 0xff);
|
||||||
|
IoWrite8 (0xA1, 0xff);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize Local APIC Timer hardware and disable Local APIC Timer
|
||||||
|
// interrupts before initializing the Debug Agent and the debug timer is
|
||||||
|
// enabled.
|
||||||
|
//
|
||||||
|
InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
|
||||||
|
DisableApicTimerInterrupt ();
|
||||||
|
|
||||||
|
PeilessStartup (&SecCoreData);
|
||||||
|
|
||||||
|
ASSERT (FALSE);
|
||||||
|
CpuDeadLoop ();
|
||||||
|
}
|
61
OvmfPkg/IntelTdx/Sec/SecMain.inf
Normal file
61
OvmfPkg/IntelTdx/Sec/SecMain.inf
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
## @file
|
||||||
|
# SEC Driver
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = SecMain
|
||||||
|
FILE_GUID = 69d96630-eb64-4b33-8491-13a5cf023dcf
|
||||||
|
MODULE_TYPE = SEC
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
ENTRY_POINT = SecMain
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = X64
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
SecMain.c
|
||||||
|
X64/SecEntry.nasm
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
UefiCpuPkg/UefiCpuPkg.dec
|
||||||
|
OvmfPkg/OvmfPkg.dec
|
||||||
|
EmbeddedPkg/EmbeddedPkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
BaseLib
|
||||||
|
DebugLib
|
||||||
|
BaseMemoryLib
|
||||||
|
PcdLib
|
||||||
|
UefiCpuLib
|
||||||
|
DebugAgentLib
|
||||||
|
IoLib
|
||||||
|
PeCoffLib
|
||||||
|
PeCoffGetEntryPointLib
|
||||||
|
PeCoffExtraActionLib
|
||||||
|
ExtractGuidedSectionLib
|
||||||
|
LocalApicLib
|
||||||
|
MemEncryptSevLib
|
||||||
|
CpuExceptionHandlerLib
|
||||||
|
PeilessStartupLib
|
||||||
|
PlatformInitLib
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
|
||||||
|
gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
|
151
OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm
Normal file
151
OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
;------------------------------------------------------------------------------
|
||||||
|
;*
|
||||||
|
;* Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||||
|
;* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
;*
|
||||||
|
;* CpuAsm.asm
|
||||||
|
;*
|
||||||
|
;* Abstract:
|
||||||
|
;*
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <Base.h>
|
||||||
|
%include "TdxCommondefs.inc"
|
||||||
|
|
||||||
|
DEFAULT REL
|
||||||
|
SECTION .text
|
||||||
|
|
||||||
|
extern ASM_PFX(SecCoreStartupWithStack)
|
||||||
|
|
||||||
|
%macro tdcall 0
|
||||||
|
db 0x66, 0x0f, 0x01, 0xcc
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
;
|
||||||
|
; SecCore Entry Point
|
||||||
|
;
|
||||||
|
; Processor is in flat protected mode
|
||||||
|
;
|
||||||
|
; @param[in] RAX Initial value of the EAX register (BIST: Built-in Self Test)
|
||||||
|
; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor
|
||||||
|
; @param[in] RBP Pointer to the start of the Boot Firmware Volume
|
||||||
|
; @param[in] DS Selector allowing flat access to all addresses
|
||||||
|
; @param[in] ES Selector allowing flat access to all addresses
|
||||||
|
; @param[in] FS Selector allowing flat access to all addresses
|
||||||
|
; @param[in] GS Selector allowing flat access to all addresses
|
||||||
|
; @param[in] SS Selector allowing flat access to all addresses
|
||||||
|
;
|
||||||
|
; @return None This routine does not return
|
||||||
|
;
|
||||||
|
global ASM_PFX(_ModuleEntryPoint)
|
||||||
|
ASM_PFX(_ModuleEntryPoint):
|
||||||
|
|
||||||
|
;
|
||||||
|
; Guest type is stored in OVMF_WORK_AREA
|
||||||
|
;
|
||||||
|
%define OVMF_WORK_AREA FixedPcdGet32 (PcdOvmfWorkAreaBase)
|
||||||
|
%define VM_GUEST_TYPE_TDX 2
|
||||||
|
mov eax, OVMF_WORK_AREA
|
||||||
|
cmp byte[eax], VM_GUEST_TYPE_TDX
|
||||||
|
jne InitStack
|
||||||
|
|
||||||
|
mov rax, TDCALL_TDINFO
|
||||||
|
tdcall
|
||||||
|
|
||||||
|
;
|
||||||
|
; R8 [31:0] NUM_VCPUS
|
||||||
|
; [63:32] MAX_VCPUS
|
||||||
|
; R9 [31:0] VCPU_INDEX
|
||||||
|
; Td Guest set the VCPU0 as the BSP, others are the APs
|
||||||
|
; APs jump to spinloop and get released by DXE's MpInitLib
|
||||||
|
;
|
||||||
|
mov rax, r9
|
||||||
|
and rax, 0xffff
|
||||||
|
test rax, rax
|
||||||
|
jne ParkAp
|
||||||
|
|
||||||
|
InitStack:
|
||||||
|
|
||||||
|
;
|
||||||
|
; Fill the temporary RAM with the initial stack value.
|
||||||
|
; The loop below will seed the heap as well, but that's harmless.
|
||||||
|
;
|
||||||
|
mov rax, (FixedPcdGet32 (PcdInitValueInTempStack) << 32) | FixedPcdGet32 (PcdInitValueInTempStack)
|
||||||
|
; qword to store
|
||||||
|
mov rdi, FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) ; base address,
|
||||||
|
; relative to
|
||||||
|
; ES
|
||||||
|
mov rcx, FixedPcdGet32 (PcdOvmfSecPeiTempRamSize) / 8 ; qword count
|
||||||
|
cld ; store from base
|
||||||
|
; up
|
||||||
|
rep stosq
|
||||||
|
|
||||||
|
;
|
||||||
|
; Load temporary RAM stack based on PCDs
|
||||||
|
;
|
||||||
|
%define SEC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + \
|
||||||
|
FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))
|
||||||
|
mov rsp, SEC_TOP_OF_STACK
|
||||||
|
nop
|
||||||
|
|
||||||
|
;
|
||||||
|
; Setup parameters and call SecCoreStartupWithStack
|
||||||
|
; rcx: BootFirmwareVolumePtr
|
||||||
|
; rdx: TopOfCurrentStack
|
||||||
|
;
|
||||||
|
mov rcx, rbp
|
||||||
|
mov rdx, rsp
|
||||||
|
sub rsp, 0x20
|
||||||
|
call ASM_PFX(SecCoreStartupWithStack)
|
||||||
|
|
||||||
|
;
|
||||||
|
; Note: BSP never gets here. APs will be unblocked by DXE
|
||||||
|
;
|
||||||
|
; R8 [31:0] NUM_VCPUS
|
||||||
|
; [63:32] MAX_VCPUS
|
||||||
|
; R9 [31:0] VCPU_INDEX
|
||||||
|
;
|
||||||
|
ParkAp:
|
||||||
|
|
||||||
|
mov rbp, r9
|
||||||
|
|
||||||
|
.do_wait_loop:
|
||||||
|
mov rsp, FixedPcdGet32 (PcdOvmfSecGhcbBackupBase)
|
||||||
|
|
||||||
|
;
|
||||||
|
; register itself in [rsp + CpuArrivalOffset]
|
||||||
|
;
|
||||||
|
mov rax, 1
|
||||||
|
lock xadd dword [rsp + CpuArrivalOffset], eax
|
||||||
|
inc eax
|
||||||
|
|
||||||
|
.check_arrival_cnt:
|
||||||
|
cmp eax, r8d
|
||||||
|
je .check_command
|
||||||
|
mov eax, dword[rsp + CpuArrivalOffset]
|
||||||
|
jmp .check_arrival_cnt
|
||||||
|
|
||||||
|
.check_command:
|
||||||
|
mov eax, dword[rsp + CommandOffset]
|
||||||
|
cmp eax, MpProtectedModeWakeupCommandNoop
|
||||||
|
je .check_command
|
||||||
|
|
||||||
|
cmp eax, MpProtectedModeWakeupCommandWakeup
|
||||||
|
je .do_wakeup
|
||||||
|
|
||||||
|
; Don't support this command, so ignore
|
||||||
|
jmp .check_command
|
||||||
|
|
||||||
|
.do_wakeup:
|
||||||
|
;
|
||||||
|
; BSP sets these variables before unblocking APs
|
||||||
|
; RAX: WakeupVectorOffset
|
||||||
|
; RBX: Relocated mailbox address
|
||||||
|
; RBP: vCpuId
|
||||||
|
;
|
||||||
|
mov rax, 0
|
||||||
|
mov eax, dword[rsp + WakeupVectorOffset]
|
||||||
|
mov rbx, [rsp + WakeupArgsRelocatedMailBox]
|
||||||
|
nop
|
||||||
|
jmp rax
|
||||||
|
jmp $
|
Loading…
x
Reference in New Issue
Block a user