On Fri, 16 Oct 2026 18:10:51 +0800 Jinjie Ruan <[email protected]> wrote:
> From: Jinjie Ruan <[email protected]> > > Move the power-on initialisation out of realize into > mpam_msc_state_init() (shared with the new legacy reset callback): > selection state and ECR/ESR cleared, per-RIS partition and monitor > storage zeroed, the PARTID narrowing map identity-wrapped so the > indirection is always in range before the driver programs it, and > MBW_MAX reset to 0xffff (full bandwidth) -- an unprogrammed PARTID > must not read as zero bandwidth. > > Also fix the realize error message for num-partid == 0, which > repeated the num-ris text. > > Signed-off-by: Jinjie Ruan <[email protected]> I'd push the refactor back to the original introduction. Reduces churn and then is trivial to use here in the reset. > --- > hw/arm/mpam.c | 78 +++++++++++++++++++++++++++++++++++++++------------ > 1 file changed, 60 insertions(+), 18 deletions(-) > > diff --git a/hw/arm/mpam.c b/hw/arm/mpam.c > index fe78adb..c4a7567 100644 > --- a/hw/arm/mpam.c > +++ b/hw/arm/mpam.c > @@ -1041,6 +1041,63 @@ static const MemoryRegionOps mpam_msc_ops = { > }, > }; > > + > +/* > + * Power-on state of the MSC, shared between realize and reset: ID narrowing > + * map identity-wrapped, partition config at reset values, monitors off. > + */ > +static void mpam_msc_state_init(MPAMMSCState *s) > +{ > + int i; > + > + s->ris = 0; > + s->part_sel = 0; > + s->internal_part_sel = false; > + s->mon_sel = 0; > + s->ecr = 0; > + s->esr = 0; > + > + for (i = 0; i < s->num_ris; i++) { > + Mpamf *mpamf = &s->mpamf[i]; > + int p; > + > + mpamf->ecr = 0; > + mpamf->esr = 0; > + memset(mpamf->per_nrw_id, 0, > + sizeof(MpamfPerNrwId) * s->num_int_partid); > + memset(mpamf->cfg_intpartid, 0, > + sizeof(uint32_t) * s->num_partid); > + memset(mpamf->mbwu_mons, 0, > + sizeof(MpamMbwuMon) * s->num_mbwu_mon); > + memset(mpamf->csu_mons, 0, sizeof(MpamCsuMon) * s->num_csu_mon); > + > + /* > + * Until resctrl programs the map, wrap each request PARTID onto an > + * internal PARTID so the narrowing indirection is always in range. > + */ > + for (p = 0; p < s->num_partid; p++) { > + mpamf->cfg_intpartid[p] = p % s->num_int_partid; > + } > + /* > + * per_nrw_id is indexed by INTERNAL PARTID: it has > + * num_int_partid entries, not num_partid. Writing it with the > + * request-PARTID count overflowed the allocation by 224 entries > + * (malloc(): corrupted top size once the struct grew). > + */ > + for (p = 0; p < s->num_int_partid; p++) { > + /* MBW_MAX resets to full bandwidth on real hardware */ > + mpamf->per_nrw_id[p].cfg_mbw_max = 0xffff; > + } > + } > +} > + > +static void mpam_msc_reset(DeviceState *dev) > +{ > + MPAMMSCState *s = MPAM_MSC_DEVICE(dev); > + > + mpam_msc_state_init(s); > +} > + > static void mpam_msc_realize(DeviceState *dev, Error **errp) > { > MPAMMSCState *s = MPAM_MSC_DEVICE(dev); > @@ -1052,7 +1109,7 @@ static void mpam_msc_realize(DeviceState *dev, Error > **errp) > return; > } > if (s->num_partid == 0) { > - error_setg(errp, "num-ris must be <= 16"); > + error_setg(errp, "num-partid must be nonzero"); > return; > } > if (s->num_int_partid == 0) { > @@ -1061,28 +1118,12 @@ static void mpam_msc_realize(DeviceState *dev, Error > **errp) > > s->mpamf = g_new0(Mpamf, s->num_ris); > for (i = 0; i < s->num_ris; i++) { > - int p; > - > s->mpamf[i].per_nrw_id = g_new0(MpamfPerNrwId, s->num_int_partid); > s->mpamf[i].cfg_intpartid = g_new0(uint32_t, s->num_partid); > s->mpamf[i].mbwu_mons = g_new0(MpamMbwuMon, s->num_mbwu_mon); > s->mpamf[i].csu_mons = g_new0(MpamCsuMon, s->num_csu_mon); > - /* > - * Until resctrl programs the map, wrap each request PARTID onto an > - * internal PARTID so the narrowing indirection is always in range. > - */ > - for (p = 0; p < s->num_partid; p++) { > - s->mpamf[i].cfg_intpartid[p] = p % s->num_int_partid; > - } > - /* > - * per_nrw_id is indexed by INTERNAL PARTID: it has num_int_partid > - * entries, not num_partid. > - */ > - for (p = 0; p < s->num_int_partid; p++) { > - /* MBW_MAX resets to full bandwidth on real hardware */ > - s->mpamf[i].per_nrw_id[p].cfg_mbw_max = 0xffff; > - } > } > + mpam_msc_state_init(s); > > memory_region_init_io(&s->mr, OBJECT(s), &mpam_msc_ops, s, "mpam_msc", > MPAM_SIZE); > @@ -1301,6 +1342,7 @@ static void mpam_msc_init(ObjectClass *klass, const > void *data) > DeviceClass *dc = DEVICE_CLASS(klass); > > device_class_set_props(dc, mpam_msc_props); > + device_class_set_legacy_reset(dc, mpam_msc_reset); > } > > static void mpam_msc_mem_init(ObjectClass *klass, const void *data)
