From: Sean Christopherson
Add MMIO HOB entries, which are needed to enumerate legal MMIO ranges to
early TDVF.
Note, the attribute absolutely must include UNCACHEABLE, else TDVF will
effectively consider it a bad HOB entry and ignore it.
Signed-off-by: Sean Christopherson
Signed-off-by: Isaku Yamahata
---
hw/i386/tdvf-hob.c | 69 ++
hw/i386/tdvf-hob.h | 5
2 files changed, 74 insertions(+)
diff --git a/hw/i386/tdvf-hob.c b/hw/i386/tdvf-hob.c
index 5e0bf807f7..60c5ed0e03 100644
--- a/hw/i386/tdvf-hob.c
+++ b/hw/i386/tdvf-hob.c
@@ -22,7 +22,10 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "e820_memory_layout.h"
+#include "hw/i386/pc.h"
#include "hw/i386/x86.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_host.h"
#include "sysemu/tdx.h"
#include "tdvf-hob.h"
#include "uefi.h"
@@ -62,6 +65,70 @@ static void *tdvf_get_area(TdvfHob *hob, uint64_t size)
return ret;
}
+static void tdvf_hob_add_mmio_resource(TdvfHob *hob, uint64_t start,
+ uint64_t end)
+{
+EFI_HOB_RESOURCE_DESCRIPTOR *region;
+
+if (!start) {
+return;
+}
+
+region = tdvf_get_area(hob, sizeof(*region));
+*region = (EFI_HOB_RESOURCE_DESCRIPTOR) {
+.Header = {
+.HobType = EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
+.HobLength = cpu_to_le16(sizeof(*region)),
+.Reserved = cpu_to_le32(0),
+},
+.Owner = EFI_HOB_OWNER_ZERO,
+.ResourceType = cpu_to_le32(EFI_RESOURCE_MEMORY_MAPPED_IO),
+.ResourceAttribute = cpu_to_le32(EFI_RESOURCE_ATTRIBUTE_TDVF_MMIO),
+.PhysicalStart = cpu_to_le64(start),
+.ResourceLength = cpu_to_le64(end - start),
+};
+}
+
+static void tdvf_hob_add_mmio_resources(TdvfHob *hob)
+{
+MachineState *ms = MACHINE(qdev_get_machine());
+X86MachineState *x86ms = X86_MACHINE(ms);
+PCIHostState *pci_host;
+uint64_t start, end;
+uint64_t mcfg_base, mcfg_size;
+Object *host;
+
+/* Effectively PCI hole + other MMIO devices. */
+tdvf_hob_add_mmio_resource(hob, x86ms->below_4g_mem_size,
+ APIC_DEFAULT_ADDRESS);
+
+/* Stolen from acpi_get_i386_pci_host(), there's gotta be an easier way. */
+pci_host = OBJECT_CHECK(PCIHostState,
+object_resolve_path("/machine/i440fx", NULL),
+TYPE_PCI_HOST_BRIDGE);
+if (!pci_host) {
+pci_host = OBJECT_CHECK(PCIHostState,
+object_resolve_path("/machine/q35", NULL),
+TYPE_PCI_HOST_BRIDGE);
+}
+g_assert(pci_host);
+
+host = OBJECT(pci_host);
+
+/* PCI hole above 4gb. */
+start = object_property_get_uint(host, PCI_HOST_PROP_PCI_HOLE64_START,
+ NULL);
+end = object_property_get_uint(host, PCI_HOST_PROP_PCI_HOLE64_END, NULL);
+tdvf_hob_add_mmio_resource(hob, start, end);
+
+/* MMCFG region */
+mcfg_base = object_property_get_uint(host, PCIE_HOST_MCFG_BASE, NULL);
+mcfg_size = object_property_get_uint(host, PCIE_HOST_MCFG_SIZE, NULL);
+if (mcfg_base && mcfg_base != PCIE_BASE_ADDR_UNMAPPED && mcfg_size) {
+tdvf_hob_add_mmio_resource(hob, mcfg_base, mcfg_base + mcfg_size);
+}
+}
+
static int tdvf_e820_compare(const void *lhs_, const void* rhs_)
{
const struct e820_entry *lhs = lhs_;
@@ -156,6 +223,8 @@ void tdvf_hob_create(TdxGuest *tdx, TdxFirmwareEntry
*hob_entry)
tdvf_hob_add_memory_resources(&hob);
+tdvf_hob_add_mmio_resources(&hob);
+
last_hob = tdvf_get_area(&hob, sizeof(*last_hob));
*last_hob = (EFI_HOB_GENERIC_HEADER) {
.HobType = EFI_HOB_TYPE_END_OF_HOB_LIST,
diff --git a/hw/i386/tdvf-hob.h b/hw/i386/tdvf-hob.h
index c6c5c1d564..9967dbfe5a 100644
--- a/hw/i386/tdvf-hob.h
+++ b/hw/i386/tdvf-hob.h
@@ -17,4 +17,9 @@ void tdvf_hob_create(TdxGuest *tdx, TdxFirmwareEntry
*hob_entry);
EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
EFI_RESOURCE_ATTRIBUTE_UNACCEPTED)
+#define EFI_RESOURCE_ATTRIBUTE_TDVF_MMIO\
+(EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE)
+
#endif
--
2.25.1