aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Romero <gustavo.romero@linaro.org>2025-07-01 15:08:30 +0100
committerPeter Maydell <peter.maydell@linaro.org>2025-07-01 15:08:30 +0100
commit1c41eaa5fe03cbe9f60edb8f0414c1ad6d7fd786 (patch)
tree693485cf4d430e83354d9fe6d328f494d487a9b1
parent67473d32f020a3c62e24790ab93eb6086a8c8283 (diff)
downloadqemu-1c41eaa5fe03cbe9f60edb8f0414c1ad6d7fd786.zip
qemu-1c41eaa5fe03cbe9f60edb8f0414c1ad6d7fd786.tar.gz
qemu-1c41eaa5fe03cbe9f60edb8f0414c1ad6d7fd786.tar.bz2
hw/arm/virt-acpi-build: Factor out create_its_idmaps
Factor out a new function, create_its_idmaps(), from the current build_iort code. Add proper comments to it clarifying how the ID ranges that go directly to the ITS Group node are computed based on the ones that are directed to the SMMU node. Suggested-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org> Message-id: 20250628195722.977078-6-gustavo.romero@linaro.org [PMM: drop hardcoded tabs] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm/virt-acpi-build.c61
1 files changed, 40 insertions, 21 deletions
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index e9cd3fb..5886192 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -266,6 +266,43 @@ static int iort_idmap_compare(gconstpointer a, gconstpointer b)
return idmap_a->input_base - idmap_b->input_base;
}
+/* Compute ID ranges (RIDs) from RC that are directed to the ITS Group node */
+static void create_its_idmaps(GArray *its_idmaps, GArray *smmu_idmaps)
+{
+ AcpiIortIdMapping *idmap;
+ AcpiIortIdMapping next_range = {0};
+
+ /*
+ * Based on the RID ranges that are directed to the SMMU, determine the
+ * bypassed RID ranges, i.e., the ones that are directed to the ITS Group
+ * node and do not pass through the SMMU, by subtracting the SMMU-bound
+ * ranges from the full RID range (0x0000–0xFFFF).
+ */
+ for (int i = 0; i < smmu_idmaps->len; i++) {
+ idmap = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i);
+
+ if (next_range.input_base < idmap->input_base) {
+ next_range.id_count = idmap->input_base - next_range.input_base;
+ g_array_append_val(its_idmaps, next_range);
+ }
+
+ next_range.input_base = idmap->input_base + idmap->id_count;
+ }
+
+ /*
+ * Append the last RC -> ITS ID mapping.
+ *
+ * RIDs are 16-bit, according to the PCI Express 2.0 Base Specification, rev
+ * 0.9, section 2.2.6.2, "Transaction Descriptor - Transaction ID Field",
+ * hence the end of the range is 0x10000.
+ */
+ if (next_range.input_base < 0x10000) {
+ next_range.id_count = 0x10000 - next_range.input_base;
+ g_array_append_val(its_idmaps, next_range);
+ }
+}
+
+
/*
* Input Output Remapping Table (IORT)
* Conforms to "IO Remapping Table System Software on ARM Platforms",
@@ -276,7 +313,6 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
{
int i, nb_nodes, rc_mapping_count;
size_t node_size, smmu_offset = 0;
- AcpiIortIdMapping *idmap;
uint32_t id = 0;
GArray *smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping));
GArray *its_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping));
@@ -287,8 +323,6 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
acpi_table_begin(&table, table_data);
if (vms->iommu == VIRT_IOMMU_SMMUV3) {
- AcpiIortIdMapping next_range = {0};
-
object_child_foreach_recursive(object_get_root(),
iort_host_bridges, smmu_idmaps);
@@ -296,25 +330,10 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
g_array_sort(smmu_idmaps, iort_idmap_compare);
/*
- * Split the whole RIDs by mapping from RC to SMMU,
- * build the ID mapping from RC to ITS directly.
+ * Knowing the ID ranges from the RC to the SMMU, it's possible to
+ * determine the ID ranges from RC that are directed to the ITS.
*/
- for (i = 0; i < smmu_idmaps->len; i++) {
- idmap = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i);
-
- if (next_range.input_base < idmap->input_base) {
- next_range.id_count = idmap->input_base - next_range.input_base;
- g_array_append_val(its_idmaps, next_range);
- }
-
- next_range.input_base = idmap->input_base + idmap->id_count;
- }
-
- /* Append the last RC -> ITS ID mapping */
- if (next_range.input_base < 0x10000) {
- next_range.id_count = 0x10000 - next_range.input_base;
- g_array_append_val(its_idmaps, next_range);
- }
+ create_its_idmaps(its_idmaps, smmu_idmaps);
nb_nodes = 3; /* RC, ITS, SMMUv3 */
rc_mapping_count = smmu_idmaps->len + its_idmaps->len;