[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH RFC v2 5/6] hw/i386/acpi-build: Add explicit scope in DMAR table
From: |
Wang Xingang |
Subject: |
[PATCH RFC v2 5/6] hw/i386/acpi-build: Add explicit scope in DMAR table |
Date: |
Wed, 24 Mar 2021 13:16:34 +0000 |
From: Xingang Wang <wangxingang5@huawei.com>
In DMAR table, the drhd is set to cover all pci devices when intel_iommu
is on. This patch add explicit scope data, including only the pci devices
that go through iommu.
Signed-off-by: Xingang Wang <wangxingang5@huawei.com>
Signed-off-by: Jiahui Cen <cenjiahui@huawei.com>
---
hw/i386/acpi-build.c | 68 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 66 insertions(+), 2 deletions(-)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 442b4629a9..7729c96489 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1878,6 +1878,56 @@ build_srat(GArray *table_data, BIOSLinker *linker,
MachineState *machine)
pcms->oem_table_id);
}
+/*
+ * Insert DMAR scope for PCI bridges and endpoint devcie
+ */
+static void
+insert_scope(PCIBus *bus, PCIDevice *dev, void *opaque)
+{
+ GArray *scope_blob = opaque;
+ AcpiDmarDeviceScope *scope = NULL;
+
+ if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
+ /* Dmar Scope Type: 0x02 for PCI Bridge */
+ build_append_int_noprefix(scope_blob, 0x02, 1);
+ } else {
+ /* Dmar Scope Type: 0x01 for PCI Endpoint Device */
+ build_append_int_noprefix(scope_blob, 0x01, 1);
+ }
+
+ /* length */
+ build_append_int_noprefix(scope_blob,
+ sizeof(*scope) + sizeof(scope->path[0]), 1);
+ /* reserved */
+ build_append_int_noprefix(scope_blob, 0, 2);
+ /* enumeration_id */
+ build_append_int_noprefix(scope_blob, 0, 1);
+ /* bus */
+ build_append_int_noprefix(scope_blob, pci_bus_num(bus), 1);
+ /* device */
+ build_append_int_noprefix(scope_blob, PCI_SLOT(dev->devfn), 1);
+ /* function */
+ build_append_int_noprefix(scope_blob, PCI_FUNC(dev->devfn), 1);
+}
+
+/* For all PCI host bridges, walk and insert DMAR scope */
+static int
+dmar_host_bridges(Object *obj, void *opaque)
+{
+ GArray *scope_blob = opaque;
+
+ if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) {
+ PCIBus *bus = PCI_HOST_BRIDGE(obj)->bus;
+
+ if (bus && pci_root_bus_has_iommu(bus)) {
+ pci_for_each_device(bus, pci_bus_num(bus), insert_scope,
+ scope_blob);
+ }
+ }
+
+ return 0;
+}
+
/*
* VT-d spec 8.1 DMA Remapping Reporting Structure
* (version Oct. 2014 or later)
@@ -1897,6 +1947,15 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker,
const char *oem_id,
/* Root complex IOAPIC use one path[0] only */
size_t ioapic_scope_size = sizeof(*scope) + sizeof(scope->path[0]);
IntelIOMMUState *intel_iommu = INTEL_IOMMU_DEVICE(iommu);
+ GArray *scope_blob = g_array_new(false, true, 1);
+
+ /*
+ * A PCI bus walk, for each PCI host bridge.
+ * Insert scope for each PCI bridge and endpoint device which
+ * is attached to a bus with iommu enabled.
+ */
+ object_child_foreach_recursive(object_get_root(),
+ dmar_host_bridges, scope_blob);
assert(iommu);
if (x86_iommu_ir_supported(iommu)) {
@@ -1910,8 +1969,9 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker,
const char *oem_id,
/* DMAR Remapping Hardware Unit Definition structure */
drhd = acpi_data_push(table_data, sizeof(*drhd) + ioapic_scope_size);
drhd->type = cpu_to_le16(ACPI_DMAR_TYPE_HARDWARE_UNIT);
- drhd->length = cpu_to_le16(sizeof(*drhd) + ioapic_scope_size);
- drhd->flags = ACPI_DMAR_INCLUDE_PCI_ALL;
+ drhd->length =
+ cpu_to_le16(sizeof(*drhd) + ioapic_scope_size + scope_blob->len);
+ drhd->flags = 0; /* Don't include all pci device */
drhd->pci_segment = cpu_to_le16(0);
drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
@@ -1925,6 +1985,10 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker,
const char *oem_id,
scope->path[0].device = PCI_SLOT(Q35_PSEUDO_DEVFN_IOAPIC);
scope->path[0].function = PCI_FUNC(Q35_PSEUDO_DEVFN_IOAPIC);
+ /* Add scope found above */
+ g_array_append_vals(table_data, scope_blob->data, scope_blob->len);
+ g_array_free(scope_blob, true);
+
if (iommu->dt_supported) {
atsr = acpi_data_push(table_data, sizeof(*atsr));
atsr->type = cpu_to_le16(ACPI_DMAR_TYPE_ATSR);
--
2.19.1
- [PATCH RFC v2 0/6] Introduce IOMMU Option For PCI Root Bus, Wang Xingang, 2021/03/24
- [PATCH RFC v2 1/6] hw/pci/pci_host: Add iommu property for pci host, Wang Xingang, 2021/03/24
- [PATCH RFC v2 2/6] hw/pci: Add iommu option for pci root bus, Wang Xingang, 2021/03/24
- [PATCH RFC v2 6/6] hw/i386/acpi-build: Add iommu filter in IVRS table, Wang Xingang, 2021/03/24
- [PATCH RFC v2 3/6] hw/pci: Add pci_root_bus_max_bus, Wang Xingang, 2021/03/24
- [PATCH RFC v2 5/6] hw/i386/acpi-build: Add explicit scope in DMAR table,
Wang Xingang <=
- [PATCH RFC v2 4/6] hw/arm/virt-acpi-build: Add explicit idmap info in IORT table, Wang Xingang, 2021/03/24