From: Jinjie Ruan <[email protected]>

With mpam=on, create one mpam-msc-mem per NUMA node with memory
(256 request PARTIDs narrowed to 32 internal PARTIDs), or with
mpam-min-msc=on a single shared MSC with one RIS per memory node
and extreme narrowing (2 internal PARTIDs).  MSC creation requires
NUMA nodes to be specified.  Cache MSC creation arrives with the
next patch.

Based on an RFC series by Jonathan Cameron, adapted to the current
cache topology API (machine_get_cache_topo_level).

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

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 3ad7de8..77942e7 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2144,6 +2144,63 @@ static void 
create_virtio_iommu_dt_bindings(VirtMachineState *vms)
 #define MPAM_VIRT_NUM_PARTID     256
 #define MPAM_VIRT_NUM_INTPARTID  32
 
+static void create_mpam_msc(VirtMachineState *vms, Error **errp)
+{
+    MachineState *ms = MACHINE(vms);
+    DeviceState *dev;
+    int i, count = 0;
+    hwaddr base = vms->memmap[VIRT_MPAM_MSC].base;
+
+    if (ms->numa_state->num_nodes == 0) {
+        error_setg(errp,
+                   "MPAM support requires NUMA nodes to be specified");
+        return;
+    }
+    if (!vms->mpam_min_msc) {
+        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) {
+                dev = qdev_new(TYPE_MPAM_MSC_MEM);
+
+                object_property_set_uint(OBJECT(dev), "node", i,
+                                         &error_fatal);
+                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);
+                sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+                sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+                base += MPAM_SIZE;
+                count++;
+            }
+        }
+    } else {
+        int count_with_mem = 0;
+
+        for (i = 0; i < ms->numa_state->num_nodes; i++) {
+            if (ms->numa_state->nodes[i].node_mem) {
+                count_with_mem++;
+            }
+        }
+        dev = qdev_new(TYPE_MPAM_MSC_MEM);
+        object_property_set_uint(OBJECT(dev), "num-ris", count_with_mem,
+                                 &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",
+                                 2, /* extreme narrowing */
+                                 &error_fatal);
+
+        sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+        base += MPAM_SIZE;
+    }
+}
+
 static void create_pcie(VirtMachineState *vms)
 {
     hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
@@ -3216,6 +3273,10 @@ static void machvirt_init(MachineState *machine)
     create_pcie(vms);
     create_cxl_host_reg_region(vms);
 
+    if (vms->mpam) {
+        create_mpam_msc(vms, &error_fatal);
+    }
+
     if (aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
         vms->acpi_dev = create_acpi_ged(vms);
         vms->generic_error_notifier.notify = virt_generic_error_req;
-- 
2.43.0


Reply via email to