From: Jinjie Ruan <[email protected]>

Derive the L2/L3 cache MSCs from the smp cache topology: the
sharing step comes from machine_get_cache_topo_level() so L3 MSCs
group per socket and L2 MSCs per cluster, and each MSC's cache id
(cpu | level << 16 | type << 24) matches the PPTT cache node the
MPAM table will point at.

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

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

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 77942e7..a57ba56 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2144,6 +2144,60 @@ 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_cache(VirtMachineState *vms, int level,
+                                  hwaddr *base)
+{
+    MachineState *ms = MACHINE(vms);
+    const CPUArchIdList *cpu_list = ms->possible_cpus;
+    DeviceState *dev;
+    int step, i;
+    CpuTopologyLevel topo;
+
+    /*
+     * Work out how many CPUs share a cache at this level, so each MSC
+     * covers exactly one cache, and the cache_id (derived from the
+     * first CPU of the group) matches the PPTT cache node the MPAM
+     * table points at.
+     */
+    topo = (level == 3) ?
+        machine_get_cache_topo_level(ms, CACHE_LEVEL_AND_TYPE_L3) :
+        machine_get_cache_topo_level(ms, CACHE_LEVEL_AND_TYPE_L2);
+
+    if (topo == CPU_TOPOLOGY_LEVEL_SOCKET && ms->smp.sockets > 0) {
+        step = cpu_list->len / ms->smp.sockets;
+    } else if (topo == CPU_TOPOLOGY_LEVEL_CLUSTER && ms->smp.clusters > 0) {
+        /*
+         * ms->smp.clusters is per socket; possible_cpus is ordered
+         * socket-major, so dividing by the total cluster count keeps
+         * each group inside one cluster.
+         */
+        step = cpu_list->len / (ms->smp.sockets * ms->smp.clusters);
+    } else {
+        step = ms->smp.threads;
+    }
+    if (step < 1) {
+        step = 1;
+    }
+
+    for (i = 0; i < cpu_list->len; i += step) {
+        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);
+        object_property_set_uint(OBJECT(dev), "cache-level", level,
+                                 &error_fatal);
+        object_property_set_uint(OBJECT(dev), "cache-type", UNIFIED_CACHE,
+                                 &error_fatal);
+        object_property_set_uint(OBJECT(dev), "cpu", i, &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_mpam_msc(VirtMachineState *vms, Error **errp)
 {
     MachineState *ms = MACHINE(vms);
@@ -2199,6 +2253,9 @@ static void create_mpam_msc(VirtMachineState *vms, Error 
**errp)
         sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
         base += MPAM_SIZE;
     }
+
+    create_mpam_msc_cache(vms, 3, &base);
+    create_mpam_msc_cache(vms, 2, &base);
 }
 
 static void create_pcie(VirtMachineState *vms)
-- 
2.43.0


Reply via email to