From: Jinjie Ruan <[email protected]>

Each board-created MSC gets two free SPIs above the platform bus range
(MPAM_SPI_BASE = 112 + PLATFORM_BUS_NUM_IRQS), connected to the GIC
(sysbus irq outputs [0] error, [1] overflow, both level).  The
assigned GSIVs (SPI + 32) are recorded as err-gsiv/oflow-gsiv qdev
properties, which the ACPI MPAM table already reports.

Guest-verified on virt,mpam=on gic-v3 with linux 7.3.0-rc6:
/proc/interrupts lists mpam:msc:error on hwirq 208/210/212 Level, no
error storms, full resctrl regression suite passes.

Signed-off-by: Jinjie Ruan <[email protected]>
---
 hw/arm/virt.c | 59 +++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 53 insertions(+), 6 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 1bcdd20..4ef7aed 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2144,8 +2144,35 @@ static void 
create_virtio_iommu_dt_bindings(VirtMachineState *vms)
 #define MPAM_VIRT_NUM_PARTID     256
 #define MPAM_VIRT_NUM_INTPARTID  32
 
+/*
+ * MPAM MSC wired interrupts start above the platform bus SPI range
+ * (112 .. 112 + PLATFORM_BUS_NUM_IRQS - 1).  Two lines per MSC.
+ */
+#define MPAM_SPI_BASE   (112 + PLATFORM_BUS_NUM_IRQS)
+
+/*
+ * Hand a not-yet-realized MSC its two wired interrupt SPIs (error first,
+ * overflow second — the sysbus_init_irq() order in hw/arm/mpam.c), and
+ * record the GSIVs (INTID = SPI + 32) the ACPI MPAM table must report.
+ */
+static void mpam_msc_assign_irqs(DeviceState *dev,
+                                 int *err_spi, int *oflow_spi, int *next_spi)
+{
+    if (*next_spi + 1 >= NUM_IRQS) {
+        error_report("virt: out of SPIs for MPAM MSC interrupts");
+        exit(1);
+    }
+    *err_spi = (*next_spi)++;
+    *oflow_spi = (*next_spi)++;
+
+    object_property_set_int(OBJECT(dev), "err-gsiv", *err_spi + 32,
+                            &error_fatal);
+    object_property_set_int(OBJECT(dev), "oflow-gsiv", *oflow_spi + 32,
+                            &error_fatal);
+}
+
 static void create_mpam_msc_cache(VirtMachineState *vms, int level,
-                                  hwaddr *base)
+                                  hwaddr *base, int *next_spi)
 {
     MachineState *ms = MACHINE(vms);
     const CPUArchIdList *cpu_list = ms->possible_cpus;
@@ -2180,13 +2207,14 @@ static void create_mpam_msc_cache(VirtMachineState 
*vms, int level,
     }
 
     for (i = 0; i < cpu_list->len; i += step) {
+        int err_spi, oflow_spi;
+
         dev = qdev_new(TYPE_MPAM_MSC_CACHE);
         object_property_set_uint(OBJECT(dev), "num-ris", 1, &error_fatal);
         object_property_set_uint(OBJECT(dev), "num-partid",
                                  MPAM_VIRT_NUM_PARTID, &error_fatal);
         object_property_set_uint(OBJECT(dev), "num-int-partid",
-                                 MPAM_VIRT_NUM_INTPARTID,
-                                 &error_fatal);
+                                 MPAM_VIRT_NUM_INTPARTID, &error_fatal);
         object_property_set_uint(OBJECT(dev), "cache-level", level,
                                  &error_fatal);
         object_property_set_uint(OBJECT(dev), "cache-type", UNIFIED_CACHE,
@@ -2196,8 +2224,13 @@ static void create_mpam_msc_cache(VirtMachineState *vms, 
int level,
         object_property_set_uint(OBJECT(dev), "csu-capacity-bytes",
                                  level == 2 ? 512 * KiB : 32 * MiB,
                                  &error_fatal);
+        mpam_msc_assign_irqs(dev, &err_spi, &oflow_spi, next_spi);
         sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
         sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, *base);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
+                           qdev_get_gpio_in(vms->gic, err_spi));
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1,
+                           qdev_get_gpio_in(vms->gic, oflow_spi));
         *base += MPAM_SIZE;
     }
 }
@@ -2207,6 +2240,7 @@ static void create_mpam_msc(VirtMachineState *vms, Error 
**errp)
     MachineState *ms = MACHINE(vms);
     DeviceState *dev;
     int i, count = 0;
+    int next_spi = MPAM_SPI_BASE;
     hwaddr base = vms->memmap[VIRT_MPAM_MSC].base;
 
     if (ms->numa_state->num_nodes == 0) {
@@ -2218,6 +2252,8 @@ static void create_mpam_msc(VirtMachineState *vms, Error 
**errp)
         for (i = 0; i < ms->numa_state->num_nodes; i++) {
             /* at most 16 mem MSCs (4-bit selector space, SPI budget) */
             if (ms->numa_state->nodes[i].node_mem > 0 && count < 16) {
+                int err_spi, oflow_spi;
+
                 dev = qdev_new(TYPE_MPAM_MSC_MEM);
 
                 object_property_set_uint(OBJECT(dev), "node", i,
@@ -2230,14 +2266,21 @@ static void create_mpam_msc(VirtMachineState *vms, 
Error **errp)
                 object_property_set_uint(OBJECT(dev), "num-int-partid",
                                          MPAM_VIRT_NUM_INTPARTID,
                                          &error_fatal);
+                mpam_msc_assign_irqs(dev, &err_spi, &oflow_spi,
+                                     &next_spi);
                 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
                 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+                sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
+                                   qdev_get_gpio_in(vms->gic, err_spi));
+                sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1,
+                                   qdev_get_gpio_in(vms->gic, oflow_spi));
                 base += MPAM_SIZE;
                 count++;
             }
         }
     } else {
         int count_with_mem = 0;
+        int err_spi, oflow_spi;
 
         for (i = 0; i < ms->numa_state->num_nodes; i++) {
             if (ms->numa_state->nodes[i].node_mem) {
@@ -2252,14 +2295,18 @@ static void create_mpam_msc(VirtMachineState *vms, 
Error **errp)
         object_property_set_uint(OBJECT(dev), "num-int-partid",
                                  2, /* extreme narrowing */
                                  &error_fatal);
-
+        mpam_msc_assign_irqs(dev, &err_spi, &oflow_spi, &next_spi);
         sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
         sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
+                           qdev_get_gpio_in(vms->gic, err_spi));
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1,
+                           qdev_get_gpio_in(vms->gic, oflow_spi));
         base += MPAM_SIZE;
     }
 
-    create_mpam_msc_cache(vms, 3, &base);
-    create_mpam_msc_cache(vms, 2, &base);
+    create_mpam_msc_cache(vms, 3, &base, &next_spi);
+    create_mpam_msc_cache(vms, 2, &base, &next_spi);
 }
 
 static void create_pcie(VirtMachineState *vms)
-- 
2.43.0


Reply via email to