On Fri, 16 Oct 2026 18:10:41 +0800 Jinjie Ruan <[email protected]> wrote:
> 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]> Trivial stuff only. I wonder a bit how fragile the topology counting approach will be if we get more sophisticated controls on the cache topology but for now this seems fine. Reviewed-by: Jonathan Cameron <[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) { for (int i = 0; .. Perhaps bring dev into this scope as well. > + 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); Look to rewrap these. This one fits below 80 chars and IIRC qemu is a bit relaxed on just over 80 anyway. > + 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; > + } > +}
