156 lines
6.5 KiB
Diff
156 lines
6.5 KiB
Diff
|
|
From a7ffb5856940a1515ef84a4d4644b7c7c07afb8f Mon Sep 17 00:00:00 2001
|
|||
|
|
From: Nicolin Chen <nicolinc@nvidia.com>
|
|||
|
|
Date: Wed, 6 Nov 2024 19:22:13 +0000
|
|||
|
|
Subject: [PATCH] hw/arm/virt-acpi-build: Build IORT with multiple SMMU nodes
|
|||
|
|
MIME-Version: 1.0
|
|||
|
|
Content-Type: text/plain; charset=UTF-8
|
|||
|
|
Content-Transfer-Encoding: 8bit
|
|||
|
|
|
|||
|
|
Now that we can have multiple user-creatable smmuv3-nested
|
|||
|
|
devices, each associated with different pci buses, update
|
|||
|
|
IORT ID mappings accordingly.
|
|||
|
|
|
|||
|
|
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
|
|||
|
|
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
|
|||
|
|
---
|
|||
|
|
hw/arm/virt-acpi-build.c | 43 ++++++++++++++++++++++++++++------------
|
|||
|
|
include/hw/arm/virt.h | 6 ++++++
|
|||
|
|
2 files changed, 36 insertions(+), 13 deletions(-)
|
|||
|
|
|
|||
|
|
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
|||
|
|
index 076781423b..1d7839e4a0 100644
|
|||
|
|
--- a/hw/arm/virt-acpi-build.c
|
|||
|
|
+++ b/hw/arm/virt-acpi-build.c
|
|||
|
|
@@ -555,8 +555,10 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
|
|
{
|
|||
|
|
int i, nb_nodes, rc_mapping_count;
|
|||
|
|
const uint32_t iort_node_offset = IORT_NODE_OFFSET;
|
|||
|
|
- size_t node_size, smmu_offset = 0;
|
|||
|
|
+ size_t node_size, *smmu_offset;
|
|||
|
|
AcpiIortIdMapping *idmap;
|
|||
|
|
+ hwaddr base;
|
|||
|
|
+ int irq, num_smmus = 0;
|
|||
|
|
uint32_t id = 0;
|
|||
|
|
GArray *smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping));
|
|||
|
|
GArray *its_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping));
|
|||
|
|
@@ -566,7 +568,21 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
|
|
/* Table 2 The IORT */
|
|||
|
|
acpi_table_begin(&table, table_data);
|
|||
|
|
|
|||
|
|
- if (vms->iommu == VIRT_IOMMU_SMMUV3) {
|
|||
|
|
+ if (vms->smmu_nested_count) {
|
|||
|
|
+ irq = vms->irqmap[VIRT_SMMU_NESTED] + ARM_SPI_BASE;
|
|||
|
|
+ base = vms->memmap[VIRT_SMMU_NESTED].base;
|
|||
|
|
+ num_smmus = vms->smmu_nested_count;
|
|||
|
|
+ } else if (virt_has_smmuv3(vms)) {
|
|||
|
|
+ irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE;
|
|||
|
|
+ base = vms->memmap[VIRT_SMMU].base;
|
|||
|
|
+ num_smmus = 1;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ smmu_offset = g_new0(size_t, num_smmus);
|
|||
|
|
+ nb_nodes = 2; /* RC, ITS */
|
|||
|
|
+ nb_nodes += num_smmus; /* SMMU nodes */
|
|||
|
|
+
|
|||
|
|
+ if (virt_has_smmuv3(vms)) {
|
|||
|
|
AcpiIortIdMapping next_range = {0};
|
|||
|
|
|
|||
|
|
object_child_foreach_recursive(object_get_root(),
|
|||
|
|
@@ -588,18 +604,19 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
next_range.input_base = idmap->input_base + idmap->id_count;
|
|||
|
|
+ if (vms->iommu == VIRT_IOMMU_SMMUV3_NESTED) {
|
|||
|
|
+ nb_nodes++; /* RMR node per SMMU */
|
|||
|
|
+ }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Append the last RC -> ITS ID mapping */
|
|||
|
|
- if (next_range.input_base < 0xFFFF) {
|
|||
|
|
- next_range.id_count = 0xFFFF - next_range.input_base;
|
|||
|
|
+ if (next_range.input_base < 0x10000) {
|
|||
|
|
+ next_range.id_count = 0x10000 - next_range.input_base;
|
|||
|
|
g_array_append_val(its_idmaps, next_range);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- nb_nodes = 3; /* RC, ITS, SMMUv3 */
|
|||
|
|
rc_mapping_count = smmu_idmaps->len + its_idmaps->len;
|
|||
|
|
} else {
|
|||
|
|
- nb_nodes = 2; /* RC, ITS */
|
|||
|
|
rc_mapping_count = 1;
|
|||
|
|
}
|
|||
|
|
/* Number of IORT Nodes */
|
|||
|
|
@@ -621,10 +638,9 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
|
|
/* GIC ITS Identifier Array */
|
|||
|
|
build_append_int_noprefix(table_data, 0 /* MADT translation_id */, 4);
|
|||
|
|
|
|||
|
|
- if (vms->iommu == VIRT_IOMMU_SMMUV3) {
|
|||
|
|
- int irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE;
|
|||
|
|
+ for (i = 0; i < num_smmus; i++) {
|
|||
|
|
+ smmu_offset[i] = table_data->len - table.table_offset;
|
|||
|
|
|
|||
|
|
- smmu_offset = table_data->len - table.table_offset;
|
|||
|
|
/* Table 9 SMMUv3 Format */
|
|||
|
|
build_append_int_noprefix(table_data, 4 /* SMMUv3 */, 1); /* Type */
|
|||
|
|
node_size = SMMU_V3_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE;
|
|||
|
|
@@ -635,7 +651,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
|
|
/* Reference to ID Array */
|
|||
|
|
build_append_int_noprefix(table_data, SMMU_V3_ENTRY_SIZE, 4);
|
|||
|
|
/* Base address */
|
|||
|
|
- build_append_int_noprefix(table_data, vms->memmap[VIRT_SMMU].base, 8);
|
|||
|
|
+ build_append_int_noprefix(table_data, base + (i * SMMU_IO_LEN), 8);
|
|||
|
|
/* Flags */
|
|||
|
|
build_append_int_noprefix(table_data, 1 /* COHACC Override */, 4);
|
|||
|
|
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
|
|||
|
|
@@ -646,12 +662,13 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
|
|
build_append_int_noprefix(table_data, irq + 1, 4); /* PRI */
|
|||
|
|
build_append_int_noprefix(table_data, irq + 3, 4); /* GERR */
|
|||
|
|
build_append_int_noprefix(table_data, irq + 2, 4); /* Sync */
|
|||
|
|
+ irq += NUM_SMMU_IRQS;
|
|||
|
|
build_append_int_noprefix(table_data, 0, 4); /* Proximity domain */
|
|||
|
|
/* DeviceID mapping index (ignored since interrupts are GSIV based) */
|
|||
|
|
build_append_int_noprefix(table_data, 0, 4);
|
|||
|
|
|
|||
|
|
/* output IORT node is the ITS group node (the first node) */
|
|||
|
|
- build_iort_id_mapping(table_data, 0, 0xFFFF, IORT_NODE_OFFSET);
|
|||
|
|
+ build_iort_id_mapping(table_data, 0, 0x10000, IORT_NODE_OFFSET);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Table 17 Root Complex Node */
|
|||
|
|
@@ -684,7 +701,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
|
|
build_append_int_noprefix(table_data, 0, 3); /* Reserved */
|
|||
|
|
|
|||
|
|
/* Output Reference */
|
|||
|
|
- if (vms->iommu == VIRT_IOMMU_SMMUV3) {
|
|||
|
|
+ if (virt_has_smmuv3(vms)) {
|
|||
|
|
AcpiIortIdMapping *range;
|
|||
|
|
|
|||
|
|
/* translated RIDs connect to SMMUv3 node: RC -> SMMUv3 -> ITS */
|
|||
|
|
@@ -692,7 +709,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
|
|
range = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i);
|
|||
|
|
/* output IORT node is the smmuv3 node */
|
|||
|
|
build_iort_id_mapping(table_data, range->input_base,
|
|||
|
|
- range->id_count, smmu_offset);
|
|||
|
|
+ range->id_count, smmu_offset[i]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* bypassed RIDs connect to ITS group node directly: RC -> ITS */
|
|||
|
|
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
|||
|
|
index cd41e28202..bc3c8b70da 100644
|
|||
|
|
--- a/include/hw/arm/virt.h
|
|||
|
|
+++ b/include/hw/arm/virt.h
|
|||
|
|
@@ -295,4 +295,10 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
|
|||
|
|
vms->highmem_redists) ? 2 : 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
+static inline bool virt_has_smmuv3(const VirtMachineState *vms)
|
|||
|
|
+{
|
|||
|
|
+ return vms->iommu == VIRT_IOMMU_SMMUV3 ||
|
|||
|
|
+ vms->iommu == VIRT_IOMMU_SMMUV3_NESTED;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
#endif /* QEMU_ARM_VIRT_H */
|
|||
|
|
--
|
|||
|
|
2.41.0.windows.1
|
|||
|
|
|