From 6164a1110448d4e2e13963b69093950acdd2348c Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:27 +0100 Subject: hw/acpi/viot: rename build_pci_range_node() to enumerate_pci_host_bridges() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is in preparation for separating out the VIOT ACPI table build from the PCI host bridge numeration. Signed-off-by: Mark Cave-Ayland Reviewed-by: Ani Sinha Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-2-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/viot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw/acpi/viot.c') diff --git a/hw/acpi/viot.c b/hw/acpi/viot.c index c1af752..a41dade 100644 --- a/hw/acpi/viot.c +++ b/hw/acpi/viot.c @@ -17,7 +17,7 @@ struct viot_pci_ranges { }; /* Build PCI range for a given PCI host bridge */ -static int build_pci_range_node(Object *obj, void *opaque) +static int enumerate_pci_host_bridges(Object *obj, void *opaque) { struct viot_pci_ranges *pci_ranges = opaque; GArray *blob = pci_ranges->blob; @@ -78,7 +78,7 @@ void build_viot(MachineState *ms, GArray *table_data, BIOSLinker *linker, }; /* Build the list of PCI ranges that this viommu manages */ - object_child_foreach_recursive(OBJECT(ms), build_pci_range_node, + object_child_foreach_recursive(OBJECT(ms), enumerate_pci_host_bridges, &pci_ranges); /* ACPI table header */ -- cgit v1.1 From 1b805ab560d3c020377680742ae2a49c7eb417d0 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:28 +0100 Subject: hw/acpi/viot: move the individual PCI host bridge entry generation to a new function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of generating each table entry inline, move the individual PCI host bridge table entry generation to a separate build_pci_host_range() function. Signed-off-by: Mark Cave-Ayland Reviewed-by: Ani Sinha Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-3-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/viot.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'hw/acpi/viot.c') diff --git a/hw/acpi/viot.c b/hw/acpi/viot.c index a41dade..5dafcbf 100644 --- a/hw/acpi/viot.c +++ b/hw/acpi/viot.c @@ -16,6 +16,31 @@ struct viot_pci_ranges { uint16_t output_node; }; +static void build_pci_host_range(GArray *table_data, int min_bus, int max_bus, + uint16_t output_node) +{ + /* Type */ + build_append_int_noprefix(table_data, 1 /* PCI range */, 1); + /* Reserved */ + build_append_int_noprefix(table_data, 0, 1); + /* Length */ + build_append_int_noprefix(table_data, 24, 2); + /* Endpoint start */ + build_append_int_noprefix(table_data, PCI_BUILD_BDF(min_bus, 0), 4); + /* PCI Segment start */ + build_append_int_noprefix(table_data, 0, 2); + /* PCI Segment end */ + build_append_int_noprefix(table_data, 0, 2); + /* PCI BDF start */ + build_append_int_noprefix(table_data, PCI_BUILD_BDF(min_bus, 0), 2); + /* PCI BDF end */ + build_append_int_noprefix(table_data, PCI_BUILD_BDF(max_bus, 0xff), 2); + /* Output node */ + build_append_int_noprefix(table_data, output_node, 2); + /* Reserved */ + build_append_int_noprefix(table_data, 0, 6); +} + /* Build PCI range for a given PCI host bridge */ static int enumerate_pci_host_bridges(Object *obj, void *opaque) { @@ -30,27 +55,8 @@ static int enumerate_pci_host_bridges(Object *obj, void *opaque) pci_bus_range(bus, &min_bus, &max_bus); - /* Type */ - build_append_int_noprefix(blob, 1 /* PCI range */, 1); - /* Reserved */ - build_append_int_noprefix(blob, 0, 1); - /* Length */ - build_append_int_noprefix(blob, 24, 2); - /* Endpoint start */ - build_append_int_noprefix(blob, PCI_BUILD_BDF(min_bus, 0), 4); - /* PCI Segment start */ - build_append_int_noprefix(blob, 0, 2); - /* PCI Segment end */ - build_append_int_noprefix(blob, 0, 2); - /* PCI BDF start */ - build_append_int_noprefix(blob, PCI_BUILD_BDF(min_bus, 0), 2); - /* PCI BDF end */ - build_append_int_noprefix(blob, PCI_BUILD_BDF(max_bus, 0xff), 2); - /* Output node */ - build_append_int_noprefix(blob, pci_ranges->output_node, 2); - /* Reserved */ - build_append_int_noprefix(blob, 0, 6); - + build_pci_host_range(blob, min_bus, max_bus, + pci_ranges->output_node); pci_ranges->count++; } } -- cgit v1.1 From e5f73c8397dddef8fc4b2fca76ffc153070a5db1 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:29 +0100 Subject: hw/acpi/viot: build array of PCI host bridges before generating VIOT ACPI table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Perform the generation of the VIOT ACPI table in 2 separate passes: the first pass enumerates all of the PCI host bridges and adds the min_bus and max_bus information to an array. Once this is done the VIOT table header is generated using the size of the array to calculate the node count, which means it is no longer necessary to use a sub-array to hold the PCI host bridge range information along with viommu_off. Finally the PCI host bridge array is iterated again to add the required entries to the final VIOT ACPI table. Signed-off-by: Mark Cave-Ayland Reviewed-by: Ani Sinha Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-4-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/viot.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'hw/acpi/viot.c') diff --git a/hw/acpi/viot.c b/hw/acpi/viot.c index 5dafcbf..c32bbdd 100644 --- a/hw/acpi/viot.c +++ b/hw/acpi/viot.c @@ -10,10 +10,9 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" -struct viot_pci_ranges { - GArray *blob; - size_t count; - uint16_t output_node; +struct viot_pci_host_range { + int min_bus; + int max_bus; }; static void build_pci_host_range(GArray *table_data, int min_bus, int max_bus, @@ -44,8 +43,7 @@ static void build_pci_host_range(GArray *table_data, int min_bus, int max_bus, /* Build PCI range for a given PCI host bridge */ static int enumerate_pci_host_bridges(Object *obj, void *opaque) { - struct viot_pci_ranges *pci_ranges = opaque; - GArray *blob = pci_ranges->blob; + GArray *pci_host_ranges = opaque; if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) { PCIBus *bus = PCI_HOST_BRIDGE(obj)->bus; @@ -55,9 +53,11 @@ static int enumerate_pci_host_bridges(Object *obj, void *opaque) pci_bus_range(bus, &min_bus, &max_bus); - build_pci_host_range(blob, min_bus, max_bus, - pci_ranges->output_node); - pci_ranges->count++; + const struct viot_pci_host_range pci_host_range = { + .min_bus = min_bus, + .max_bus = max_bus, + }; + g_array_append_val(pci_host_ranges, pci_host_range); } } @@ -78,19 +78,19 @@ void build_viot(MachineState *ms, GArray *table_data, BIOSLinker *linker, int viommu_off = 48; AcpiTable table = { .sig = "VIOT", .rev = 0, .oem_id = oem_id, .oem_table_id = oem_table_id }; - struct viot_pci_ranges pci_ranges = { - .output_node = viommu_off, - .blob = g_array_new(false, true /* clear */, 1), - }; + GArray *pci_host_ranges = g_array_new(false, true, + sizeof(struct viot_pci_host_range)); + struct viot_pci_host_range *pci_host_range; + int i; /* Build the list of PCI ranges that this viommu manages */ object_child_foreach_recursive(OBJECT(ms), enumerate_pci_host_bridges, - &pci_ranges); + pci_host_ranges); /* ACPI table header */ acpi_table_begin(&table, table_data); /* Node count */ - build_append_int_noprefix(table_data, pci_ranges.count + 1, 2); + build_append_int_noprefix(table_data, pci_host_ranges->len + 1, 2); /* Node offset */ build_append_int_noprefix(table_data, viommu_off, 2); /* Reserved */ @@ -111,9 +111,15 @@ void build_viot(MachineState *ms, GArray *table_data, BIOSLinker *linker, build_append_int_noprefix(table_data, 0, 8); /* PCI ranges found above */ - g_array_append_vals(table_data, pci_ranges.blob->data, - pci_ranges.blob->len); - g_array_free(pci_ranges.blob, true); + for (i = 0; i < pci_host_ranges->len; i++) { + pci_host_range = &g_array_index(pci_host_ranges, + struct viot_pci_host_range, i); + + build_pci_host_range(table_data, pci_host_range->min_bus, + pci_host_range->max_bus, viommu_off); + } + + g_array_free(pci_host_ranges, true); acpi_table_end(linker, &table); } -- cgit v1.1 From 68f14a87291343bcec2bfcec7fdc0c8a3c01f66c Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:31 +0100 Subject: hw/acpi/viot: sort VIOT ACPI table entries by PCI host bridge min_bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures that the VIOT ACPI table output is always stable for a given PCI topology by ensuring that entries are ordered according to min_bus. Signed-off-by: Mark Cave-Ayland Reviewed-by: Ani Sinha Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-6-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/viot.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'hw/acpi/viot.c') diff --git a/hw/acpi/viot.c b/hw/acpi/viot.c index c32bbdd..4e0bf69 100644 --- a/hw/acpi/viot.c +++ b/hw/acpi/viot.c @@ -64,6 +64,20 @@ static int enumerate_pci_host_bridges(Object *obj, void *opaque) return 0; } +static gint pci_host_range_compare(gconstpointer a, gconstpointer b) +{ + struct viot_pci_host_range *range_a = (struct viot_pci_host_range *)a; + struct viot_pci_host_range *range_b = (struct viot_pci_host_range *)b; + + if (range_a->min_bus < range_b->min_bus) { + return -1; + } else if (range_a->min_bus > range_b->min_bus) { + return 1; + } else { + return 0; + } +} + /* * Generate a VIOT table with one PCI-based virtio-iommu that manages PCI * endpoints. @@ -87,6 +101,9 @@ void build_viot(MachineState *ms, GArray *table_data, BIOSLinker *linker, object_child_foreach_recursive(OBJECT(ms), enumerate_pci_host_bridges, pci_host_ranges); + /* Sort the pci host ranges by min_bus */ + g_array_sort(pci_host_ranges, pci_host_range_compare); + /* ACPI table header */ acpi_table_begin(&table, table_data); /* Node count */ -- cgit v1.1