mirror of https://github.com/acidanthera/audk.git
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
|
@ -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 ();
|
||||
}
|
|
@ -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
|
|
@ -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…
Reference in New Issue