2021-12-18 14:36:08 +01:00
|
|
|
/** @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/BaseLib.h>
|
|
|
|
#include <Library/DebugLib.h>
|
|
|
|
#include <Library/BaseMemoryLib.h>
|
|
|
|
#include <Library/PcdLib.h>
|
2022-11-01 02:33:15 +01:00
|
|
|
#include <Library/CpuLib.h>
|
2021-12-18 14:36:08 +01:00
|
|
|
#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>
|
2023-02-03 04:31:42 +01:00
|
|
|
#include <Library/TdxHelperLib.h>
|
2022-04-19 02:26:28 +02:00
|
|
|
#include <Library/CcProbeLib.h>
|
2021-12-18 14:36:08 +01:00
|
|
|
#include <Library/PeilessStartupLib.h>
|
2024-01-23 15:33:51 +01:00
|
|
|
#include <Register/Intel/ArchitecturalMsr.h>
|
|
|
|
#include <Register/Intel/Cpuid.h>
|
2021-12-18 14:36:08 +01:00
|
|
|
|
|
|
|
#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
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-01-23 15:33:51 +01:00
|
|
|
//
|
|
|
|
// Enable MTRR early, set default type to write back.
|
|
|
|
// Needed to make sure caching is enabled,
|
|
|
|
// without this lzma decompress can be very slow.
|
|
|
|
//
|
|
|
|
STATIC
|
|
|
|
VOID
|
|
|
|
SecMtrrSetup (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
CPUID_VERSION_INFO_EDX Edx;
|
|
|
|
MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
|
|
|
|
|
|
|
|
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &Edx.Uint32);
|
|
|
|
if (!Edx.Bits.MTRR) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
OvmfPkg/Sec: Skip setup MTRR early in TD-Guest
With the commit ce4c76e (“OvmfPkg/Sec: Setup MTRR early
in the boot process.”), we find an unexpected #VE is triggered
in TD-Guest.
The background of importing the above commit is that:
Before running lzma uncompress of the main firmware volume,
if not correctly set MTRR, that would make the uncompress be
extremely slow.
Detailed discussion info can refer to below links:
https://edk2.groups.io/g/devel/message/114202
https://edk2.groups.io/g/devel/message/114977
Refer to [intel-tdx-module-1.5-base-spec] Section 11.3 and
section11.6.1, CR0.CD is enforced to 0 in TD-Guest.
And refer to section 18.2.1.4, TDX module MTRR emulation
enforces WB in VMM.
Currently the initial MTRR are:
- Td-Guest : MTRR disabled, Type is WB.
- Non-Td-Guest : MTRR disabled, Type is UC.
In DXE phase, OVMF/TDVF would check the MTRR Type for MMIO
(in CpuSetMemoryAttributes -> MtrrGetMemoryAttribute ->
MtrrGetMemoryAttributeworker:
https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/Library/MtrrLib/MtrrLib.c#L929
).
If MTRR is disabled, it always returns UC. Otherwise, it returns
the actual value.
If it checks that the type is not UC then the MTRR is programmed.
It is required to disable cache by setting CR0.CD to 1. That will trigger
an unexpected #VE in TD-Guest.
Based on above analysis we propose to skip "Setup MTRR early" in
TD-Guest because of:
- TD-Guest doesn’t have the issue that lzma uncompress extremely slow.
- This patch will trigger an unexpected #VE in TD-Guest.
intel-tdx-module-1.5-base-spec:
https://cdrdv2.intel.com/v1/dl/getContent/733575
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Ceping Sun <cepingx.sun@intel.com>
2024-07-01 19:50:10 +02:00
|
|
|
if (CcProbe () == CcGuestTypeIntelTdx) {
|
|
|
|
//
|
|
|
|
// According to TDX Spec, the default MTRR type is enforced to WB
|
|
|
|
// and CR0.CD is enforced to 0.
|
|
|
|
// The TD guest has to disable MTRR otherwise it tries to
|
|
|
|
// program MTRRs to disable caching. CR0.CD=1 results in the
|
|
|
|
// unexpected #VE.
|
|
|
|
//
|
|
|
|
DEBUG ((DEBUG_INFO, "%a: Skip TD-Guest\n", __func__));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-01-23 15:33:51 +01:00
|
|
|
DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
|
2024-01-25 08:39:18 +01:00
|
|
|
DefType.Bits.Type = MSR_IA32_MTRR_CACHE_WRITE_BACK;
|
2024-01-23 15:33:51 +01:00
|
|
|
DefType.Bits.E = 1; /* enable */
|
|
|
|
AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, DefType.Uint64);
|
|
|
|
}
|
|
|
|
|
2021-12-18 14:36:08 +01:00
|
|
|
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;
|
|
|
|
|
2022-04-19 02:26:28 +02:00
|
|
|
if (CcProbe () == CcGuestTypeIntelTdx) {
|
2023-02-03 04:31:43 +01:00
|
|
|
//
|
|
|
|
// From the security perspective all the external input should be measured before
|
|
|
|
// it is consumed. TdHob and Configuration FV (Cfv) image are passed from VMM
|
|
|
|
// and should be measured here.
|
|
|
|
//
|
|
|
|
if (EFI_ERROR (TdxHelperMeasureTdHob ())) {
|
|
|
|
CpuDeadLoop ();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EFI_ERROR (TdxHelperMeasureCfvImage ())) {
|
|
|
|
CpuDeadLoop ();
|
|
|
|
}
|
|
|
|
|
2021-12-18 14:36:08 +01:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
2023-02-03 04:31:42 +01:00
|
|
|
if (TdxHelperProcessTdHob () != EFI_SUCCESS) {
|
2021-12-18 14:36:08 +01:00
|
|
|
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);
|
|
|
|
|
2024-03-05 12:38:36 +01:00
|
|
|
ProcessLibraryConstructorList ();
|
2021-12-18 14:36:08 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Load the IDTR.
|
|
|
|
//
|
|
|
|
AsmWriteIdtr (&IdtDescriptor);
|
|
|
|
|
2022-04-19 02:26:28 +02:00
|
|
|
if (CcProbe () == CcGuestTypeIntelTdx) {
|
2021-12-18 14:36:08 +01:00
|
|
|
//
|
|
|
|
// 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 ();
|
|
|
|
|
2024-01-23 15:33:51 +01:00
|
|
|
//
|
|
|
|
// Initialize MTRR
|
|
|
|
//
|
|
|
|
SecMtrrSetup ();
|
|
|
|
|
2021-12-18 14:36:08 +01:00
|
|
|
PeilessStartup (&SecCoreData);
|
|
|
|
|
|
|
|
ASSERT (FALSE);
|
|
|
|
CpuDeadLoop ();
|
|
|
|
}
|