From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web09.20836.1633405265395581286 for ; Mon, 04 Oct 2021 20:41:06 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.115, mailfrom: min.m.xu@intel.com) X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958250" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958250" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:01 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828800" Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:58 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [PATCH V2 24/28] OvmfPkg: Add TdxDxe driver Date: Tue, 5 Oct 2021 11:39:35 +0800 Message-Id: X-Mailer: git-send-email 2.29.2.windows.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429 TdxDxe driver is dispatched early in DXE, due to being list in APRIORI. This module is responsible for below features: - Sets max logical cpus based on TDINFO - Sets PCI PCDs based on resource hobs Besides above features, TdxDxe driver will update the ACPI MADT Mutiprocessor Wakeup Table. In TDX the guest firmware is designed to publish a multiprocessor-wakeup structure to let the guest-bootstrap processor wake up guest-application processors with a mailbox. The mailbox is memory that the guest firmware can reserve so each guest virtual processor can have the guest OS send a message to them. The address of the mailbox is recorded in the MADT table. See [ACPI]. TdxDxe registers for protocol notification (gQemuAcpiTableNotifyProtocolGuid) to call the AlterAcpiTable(), in which MADT table is altered by the above Mailbox address. The protocol will be installed in AcpiPlatformDxe when the MADT table provided by Qemu is ready. This is to maintain the simplicity of the AcpiPlatformDxe. AlterAcpiTable is the registered function which traverses the ACPI table list to find the original MADT from Qemu. After the new MADT is configured and installed, the original one will be uninstalled. [ACPI] https://uefi.org/specs/ACPI/6.4/05_ACPI_Software_Programming_Model /ACPI_Software_Programming_Model.html#multiprocessor-wakeup-structure Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/Include/IndustryStandard/AcpiTdx.h | 23 +++ OvmfPkg/Include/IndustryStandard/IntelTdx.h | 5 +- OvmfPkg/OvmfPkg.dec | 4 + OvmfPkg/OvmfPkgX64.dsc | 2 + OvmfPkg/OvmfPkgX64.fdf | 3 + OvmfPkg/TdxDxe/TdxAcpiTable.c | 207 ++++++++++++++++++++ OvmfPkg/TdxDxe/TdxAcpiTable.h | 38 ++++ OvmfPkg/TdxDxe/TdxDxe.c | 207 ++++++++++++++++++++ OvmfPkg/TdxDxe/TdxDxe.inf | 62 ++++++ 9 files changed, 548 insertions(+), 3 deletions(-) create mode 100644 OvmfPkg/Include/IndustryStandard/AcpiTdx.h create mode 100644 OvmfPkg/TdxDxe/TdxAcpiTable.c create mode 100644 OvmfPkg/TdxDxe/TdxAcpiTable.h create mode 100644 OvmfPkg/TdxDxe/TdxDxe.c create mode 100644 OvmfPkg/TdxDxe/TdxDxe.inf diff --git a/OvmfPkg/Include/IndustryStandard/AcpiTdx.h b/OvmfPkg/Include/IndustryStandard/AcpiTdx.h new file mode 100644 index 000000000000..9e2753bbe52a --- /dev/null +++ b/OvmfPkg/Include/IndustryStandard/AcpiTdx.h @@ -0,0 +1,23 @@ +/** @file + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef ACPI_TDX_H_ +#define ACPI_TDX_H_ + +#define ACPI_MADT_MPWK_STRUCT_TYPE 0x10 + +#pragma pack(1) + +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 MailBoxVersion; + UINT32 Reserved2; + UINT64 MailBoxAddress; +} ACPI_MADT_MPWK_STRUCT; + +#pragma pack() +#endif diff --git a/OvmfPkg/Include/IndustryStandard/IntelTdx.h b/OvmfPkg/Include/IndustryStandard/IntelTdx.h index 2370f18289a1..bb02970394d7 100644 --- a/OvmfPkg/Include/IndustryStandard/IntelTdx.h +++ b/OvmfPkg/Include/IndustryStandard/IntelTdx.h @@ -6,8 +6,8 @@ **/ -#ifndef _OVMF_INTEL_TDX__H_ -#define _OVMF_INTEL_TDX__H_ +#ifndef OVMF_INTEL_TDX_H_ +#define OVMF_INTEL_TDX_H_ #include #include @@ -52,7 +52,6 @@ typedef enum { UINT8 Pad3[0xf8]; } MP_WAKEUP_MAILBOX; - // // AP relocation code information including code address and size, // this structure will be shared be C code and assembly code. diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index b489c69a736e..cc5087da6aa2 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -153,6 +153,7 @@ gEfiLegacyInterruptProtocolGuid = {0x31ce593d, 0x108a, 0x485d, {0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe}} gEfiVgaMiniPortProtocolGuid = {0xc7735a2f, 0x88f5, 0x4882, {0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3}} gOvmfLoadedX86LinuxKernelProtocolGuid = {0xa3edc05d, 0xb618, 0x4ff6, {0x95, 0x52, 0x76, 0xd7, 0x88, 0x63, 0x43, 0xc8}} + gQemuAcpiTableNotifyProtocolGuid = {0x928939b2, 0x4235, 0x462f, {0x95, 0x80, 0xf6, 0xa2, 0xb2, 0xc2, 0x1a, 0x4f}} [PcdsFixedAtBuild] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0 @@ -403,6 +404,9 @@ # instance in PiSmmCpuDxeSmm, and CpuHotplugSmm. gUefiOvmfPkgTokenSpaceGuid.PcdCpuHotEjectDataAddress|0|UINT64|0x46 + ## TDX relocated Mailbox base address + gUefiOvmfPkgTokenSpaceGuid.PcdTdRelocatedMailboxBase|0|UINT64|0x60 + [PcdsFeatureFlag] gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 12ebde74433d..2c4a6613b1ea 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -977,6 +977,8 @@ OvmfPkg/AmdSevDxe/AmdSevDxe.inf OvmfPkg/IoMmuDxe/IoMmuDxe.inf + OvmfPkg/TdxDxe/TdxDxe.inf + !if $(SMM_REQUIRE) == TRUE OvmfPkg/SmmAccess/SmmAccess2Dxe.inf OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index b6cc3cabdd69..bbd9303ab14f 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -214,6 +214,7 @@ READ_LOCK_STATUS = TRUE APRIORI DXE { INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF OvmfPkg/TdxDxe/TdxDxe.inf INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf !if $(SMM_REQUIRE) == FALSE INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf @@ -319,6 +320,8 @@ INF ShellPkg/Application/Shell/Shell.inf INF MdeModulePkg/Logo/LogoDxe.inf +INF OvmfPkg/TdxDxe/TdxDxe.inf + # # Network modules # diff --git a/OvmfPkg/TdxDxe/TdxAcpiTable.c b/OvmfPkg/TdxDxe/TdxAcpiTable.c new file mode 100644 index 000000000000..249dbbb9128f --- /dev/null +++ b/OvmfPkg/TdxDxe/TdxAcpiTable.c @@ -0,0 +1,207 @@ +/** @file + OVMF ACPI QEMU support + + Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+ + Copyright (C) 2012-2014, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +STATIC +EFI_STATUS +EFIAPI +QemuInstallAcpiMadtTable ( + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol, + IN VOID *AcpiTableBuffer, + IN UINTN AcpiTableBufferSize, + OUT UINTN *TableKey + ) +{ + UINTN CpuCount; + UINTN NewBufferSize; + EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt; + EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic; + EFI_ACPI_1_0_IO_APIC_STRUCTURE *IoApic; + EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *Iso; + EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE *LocalApicNmi; + VOID *Ptr; + UINTN Loop; + EFI_STATUS Status; + ACPI_MADT_MPWK_STRUCT *MadtMpWk; + + ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER)); + + CpuCount = TdVCpuNum(); + + ASSERT (CpuCount >= 1); + +#define NUM_8259_IRQS 16 + NewBufferSize = 1 * sizeof (*Madt) + + CpuCount * sizeof (*LocalApic) + + 1 * sizeof (*IoApic) + + NUM_8259_IRQS * sizeof (*Iso) + + 1 * sizeof (*LocalApicNmi); + + NewBufferSize += sizeof(ACPI_MADT_MPWK_STRUCT); + + Madt = AllocatePool (NewBufferSize); + if (Madt == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (&(Madt->Header), AcpiTableBuffer, sizeof (EFI_ACPI_DESCRIPTION_HEADER)); + Madt->Header.Length = (UINT32) NewBufferSize; + Madt->LocalApicAddress = PcdGet32 (PcdCpuLocalApicBaseAddress); + Madt->Flags = EFI_ACPI_1_0_PCAT_COMPAT; + Ptr = Madt + 1; + + LocalApic = Ptr; + for (Loop = 0; Loop < CpuCount; ++Loop) { + LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC; + LocalApic->Length = sizeof (*LocalApic); + LocalApic->AcpiProcessorId = (UINT8) Loop; + LocalApic->ApicId = (UINT8) Loop; + LocalApic->Flags = 1; // enabled + ++LocalApic; + } + Ptr = LocalApic; + + IoApic = Ptr; + IoApic->Type = EFI_ACPI_1_0_IO_APIC; + IoApic->Length = sizeof (*IoApic); + IoApic->IoApicId = (UINT8) CpuCount; + IoApic->Reserved = EFI_ACPI_RESERVED_BYTE; + IoApic->IoApicAddress = 0xFEC00000; + IoApic->SystemVectorBase = 0x00000000; + Ptr = IoApic + 1; + + // + // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure + // + Iso = Ptr; + Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE; + Iso->Length = sizeof (*Iso); + Iso->Bus = 0x00; // ISA + Iso->Source = 0x00; // IRQ0 + Iso->GlobalSystemInterruptVector = 0x00000002; + Iso->Flags = 0x0005; // Edge-triggered, Active High + ++Iso; + + for (Loop = 1; Loop < NUM_8259_IRQS; ++Loop) { + Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE; + Iso->Length = sizeof (*Iso); + Iso->Bus = 0x00; // ISA + Iso->Source = (UINT8) Loop; + Iso->GlobalSystemInterruptVector = (UINT32) Loop; + Iso->Flags = 0x0005; // Edge-triggered, Active High + ++Iso; + } + Ptr = Iso; + + LocalApicNmi = Ptr; + LocalApicNmi->Type = EFI_ACPI_1_0_LOCAL_APIC_NMI; + LocalApicNmi->Length = sizeof (*LocalApicNmi); + LocalApicNmi->AcpiProcessorId = 0xFF; // applies to all processors + // + // polarity and trigger mode of the APIC I/O input signals conform to the + // specifications of the bus + // + LocalApicNmi->Flags = 0x0000; + // + // Local APIC interrupt input LINTn to which NMI is connected. + // + LocalApicNmi->LocalApicInti = 0x01; + Ptr = LocalApicNmi + 1; + + MadtMpWk = Ptr; + MadtMpWk->Type = ACPI_MADT_MPWK_STRUCT_TYPE; + MadtMpWk->Length = sizeof(ACPI_MADT_MPWK_STRUCT); + MadtMpWk->MailBoxVersion = 1; + MadtMpWk->Reserved2 = 0; + MadtMpWk->MailBoxAddress = PcdGet64 (PcdTdRelocatedMailboxBase); + Ptr = MadtMpWk + 1; + + ASSERT ((UINTN) ((UINT8 *)Ptr - (UINT8 *)Madt) == NewBufferSize); + Status = AcpiProtocol->InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey); + + FreePool (Madt); + + return Status; +} + +/** + Alter the MADT when ACPI Table from QEMU is available. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +AlterAcpiTable ( + IN EFI_EVENT Event, + IN VOID* Context + ) +{ + EFI_ACPI_SDT_PROTOCOL *AcpiSdtTable; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_STATUS Status; + UINTN Index; + EFI_ACPI_SDT_HEADER *Table; + EFI_ACPI_TABLE_VERSION Version; + UINTN OriginalTableKey; + UINTN UpdatedTableKey; + + Index = 0; + + Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (void **) &AcpiSdtTable); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to locate ACPI SDT protocol.\n")); + return; + } + + do { + Status = AcpiSdtTable->GetAcpiTable (Index, &Table, &Version, &OriginalTableKey); + + if (!EFI_ERROR (Status) && Table->Signature == EFI_ACPI_1_0_APIC_SIGNATURE) { + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (void **) &AcpiTable); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to locate ACPI Table protocol.\n")); + return; + } + + // + // The altered MADT should be rebuilt and installed before uninstall the + // original one, because unintall table will free the memory which will be + // copied in QemuInstallAcpiMadtTable(). + // + QemuInstallAcpiMadtTable (AcpiTable, Table, Table->Length, &UpdatedTableKey); + Status = AcpiTable->UninstallAcpiTable (AcpiTable, OriginalTableKey); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Uninstall MADT table error.\n")); + } + break; + } + Index ++; + } while (!EFI_ERROR (Status)); +} diff --git a/OvmfPkg/TdxDxe/TdxAcpiTable.h b/OvmfPkg/TdxDxe/TdxAcpiTable.h new file mode 100644 index 000000000000..36aaab9d1f41 --- /dev/null +++ b/OvmfPkg/TdxDxe/TdxAcpiTable.h @@ -0,0 +1,38 @@ +/** @file + Sample ACPI Platform Driver + + Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _TDX_QEMU_ACPI_H_INCLUDED_ +#define _TDX_QEMU_ACPI_H_INCLUDED_ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +/** + Alter the MADT when ACPI Table from QEMU is available. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +AlterAcpiTable ( + IN EFI_EVENT Event, + IN VOID* Context + ); + +#endif diff --git a/OvmfPkg/TdxDxe/TdxDxe.c b/OvmfPkg/TdxDxe/TdxDxe.c new file mode 100644 index 000000000000..eecad8f6e050 --- /dev/null +++ b/OvmfPkg/TdxDxe/TdxDxe.c @@ -0,0 +1,207 @@ +/** @file + + TDX Dxe driver. This driver is dispatched early in DXE, due to being list + in APRIORI. + + This module is responsible for: + - Sets max logical cpus based on TDINFO + - Sets PCI PCDs based on resource hobs + - Alter MATD table to record address of Mailbox + + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Location of resource hob matching type and starting address + + @param[in] Type The type of resource hob to locate. + + @param[in] Start The resource hob must at least begin at address. + + @retval pointer to resource Return pointer to a resource hob that matches or NULL. +**/ +STATIC +EFI_HOB_RESOURCE_DESCRIPTOR * +GetResourceDescriptor( + EFI_RESOURCE_TYPE Type, + EFI_PHYSICAL_ADDRESS Start, + EFI_PHYSICAL_ADDRESS End + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor = NULL; + + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); + while (Hob.Raw != NULL) { + + DEBUG ((DEBUG_INFO, "%a:%d: resource type 0x%x %llx %llx\n", + __func__, __LINE__, + Hob.ResourceDescriptor->ResourceType, + Hob.ResourceDescriptor->PhysicalStart, + Hob.ResourceDescriptor->ResourceLength)); + + if ((Hob.ResourceDescriptor->ResourceType == Type) && + (Hob.ResourceDescriptor->PhysicalStart >= Start) && + ((Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength) < End)) { + ResourceDescriptor = Hob.ResourceDescriptor; + break; + } + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw); + } + + return ResourceDescriptor; +} + +/** + Location of resource hob matching type and highest address below end + + @param[in] Type The type of resource hob to locate. + + @param[in] End The resource hob return is the closest to the End address + + @retval pointer to resource Return pointer to a resource hob that matches or NULL. +**/ +STATIC +EFI_HOB_RESOURCE_DESCRIPTOR * +GetHighestResourceDescriptor( + EFI_RESOURCE_TYPE Type, + EFI_PHYSICAL_ADDRESS End + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor = NULL; + + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); + while (Hob.Raw != NULL) { + if ((Hob.ResourceDescriptor->ResourceType == Type) && + (Hob.ResourceDescriptor->PhysicalStart < End)) { + if (!ResourceDescriptor || + (ResourceDescriptor->PhysicalStart < Hob.ResourceDescriptor->PhysicalStart)) { + ResourceDescriptor = Hob.ResourceDescriptor; + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw); + } + + return ResourceDescriptor; +} + +EFI_STATUS +EFIAPI +TdxDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + EFI_STATUS Status; + RETURN_STATUS PcdStatus; + EFI_HOB_RESOURCE_DESCRIPTOR *Res = NULL; + EFI_HOB_RESOURCE_DESCRIPTOR *MemRes = NULL; + EFI_HOB_PLATFORM_INFO *PlatformInfo = NULL; + EFI_HOB_GUID_TYPE *GuidHob; + UINT32 CpuMaxLogicalProcessorNumber; + TD_RETURN_DATA TdReturnData; + EFI_EVENT QemuAcpiTableEvent; + void *Registration; + + GuidHob = GetFirstGuidHob (&gUefiOvmfPkgTdxPlatformGuid); + + if(GuidHob == NULL) { + return EFI_UNSUPPORTED; + } + + PlatformInfo = (EFI_HOB_PLATFORM_INFO *) GET_GUID_HOB_DATA (GuidHob); + + // + // Call TDINFO to get actual number of cpus in domain + // + Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + ASSERT(Status == EFI_SUCCESS); + + CpuMaxLogicalProcessorNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber); + + // + // Adjust PcdCpuMaxLogicalProcessorNumber, if needed. If firmware is configured for + // more than number of reported cpus, update. + // + if (CpuMaxLogicalProcessorNumber > TdReturnData.TdInfo.NumVcpus) { + PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, TdReturnData.TdInfo.NumVcpus); + ASSERT_RETURN_ERROR(PcdStatus); + } + + // + // Register for protocol notifications to call the AlterAcpiTable(), + // the protocol will be installed in AcpiPlatformDxe when the ACPI + // table provided by Qemu is ready. + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + AlterAcpiTable, + NULL, + &QemuAcpiTableEvent + ); + + Status = gBS->RegisterProtocolNotify ( + &gQemuAcpiTableNotifyProtocolGuid, + QemuAcpiTableEvent, + &Registration + ); + +#define INIT_PCDSET(NAME, RES) do { \ + PcdStatus = PcdSet64S (NAME##Base, (RES)->PhysicalStart); \ + ASSERT_RETURN_ERROR (PcdStatus); \ + PcdStatus = PcdSet64S (NAME##Size, (RES)->ResourceLength); \ + ASSERT_RETURN_ERROR (PcdStatus); \ +} while(0) + + if (PlatformInfo) { + PcdSet16S (PcdOvmfHostBridgePciDevId, PlatformInfo->HostBridgePciDevId); + + if ((Res = GetResourceDescriptor(EFI_RESOURCE_MEMORY_MAPPED_IO, (EFI_PHYSICAL_ADDRESS)0x100000000, (EFI_PHYSICAL_ADDRESS)-1)) != NULL) { + INIT_PCDSET(PcdPciMmio64, Res); + } + + if ((Res = GetResourceDescriptor(EFI_RESOURCE_IO, 0, 0x10001)) != NULL) { + INIT_PCDSET(PcdPciIo, Res); + } + + // + // To find low mmio, first find top of low memory, and then search for io space. + // + if ((MemRes = GetHighestResourceDescriptor(EFI_RESOURCE_SYSTEM_MEMORY, 0xffc00000)) != NULL) { + if ((Res = GetResourceDescriptor(EFI_RESOURCE_MEMORY_MAPPED_IO, MemRes->PhysicalStart, 0x100000000)) != NULL) { + INIT_PCDSET(PcdPciMmio32, Res); + } + } + // + // Set initial protected mode reset address to our initial mailbox + // After DXE, will update address before exiting + // + PcdStatus = PcdSet64S (PcdTdRelocatedMailboxBase, PlatformInfo->RelocatedMailBox); + ASSERT_RETURN_ERROR(PcdStatus); + } + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/TdxDxe/TdxDxe.inf b/OvmfPkg/TdxDxe/TdxDxe.inf new file mode 100644 index 000000000000..b77c6e5e9252 --- /dev/null +++ b/OvmfPkg/TdxDxe/TdxDxe.inf @@ -0,0 +1,62 @@ +#/** @file +# +# Driver clears the encryption attribute from MMIO regions when TDX is enabled +# +# Copyright (c) 2017, AMD Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION = 1.25 + BASE_NAME = TdxDxe + FILE_GUID = E750224E-7BCE-40AF-B5BB-47E3611EB5C2 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = TdxDxeEntryPoint + +[Sources] + TdxDxe.c + TdxAcpiTable.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DxeServicesTableLib + MemoryAllocationLib + PcdLib + UefiDriverEntryPoint + TdxLib + HobLib + +[Depex] + TRUE + +[Guids] + gUefiOvmfPkgTdxPlatformGuid ## CONSUMES + +[Protocols] + gQemuAcpiTableNotifyProtocolGuid ## CONSUMES + gEfiAcpiSdtProtocolGuid ## CONSUMES + gEfiAcpiTableProtocolGuid ## CONSUMES + +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId + gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber + gUefiOvmfPkgTokenSpaceGuid.PcdTdRelocatedMailboxBase + gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress -- 2.29.2.windows.2