On Fri, 16 Oct 2026 17:47:05 +0800 Jinjie Ruan <[email protected]> wrote:
> From: Jinjie Ruan <[email protected]> > > Add the cache-portion controls: MPAMF_CPOR_IDR advertises the > CPBM bitmap width (MPAM_CACHE_PART portions) and the cache > subtype sets HAS_CPOR_PART, and the CPBM array registers become > readable and writable per selected internal PARTID. Reads and > writes of CPOR_IDR/CPBM on an MSC without CPOR support are > logged and ignored. > > Signed-off-by: Jinjie Ruan <[email protected]> Comment in here is fix the fixme ;) Otherwise looks fine to me and I think it is a wise decision to always allocate backing for the max sized bitmap rather than trying to do it dependent on what the width is for a particular instance. > --- > hw/arm/mpam.c | 41 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 41 insertions(+) > > diff --git a/hw/arm/mpam.c b/hw/arm/mpam.c > index cce9355..2b1401e 100644 > --- a/hw/arm/mpam.c > +++ b/hw/arm/mpam.c > @@ -356,6 +356,13 @@ static uint64_t mpam_msc_read_reg(void *opaque, hwaddr > offset, > return 0; > } > return mpamf->impl_idr; > + case A_MPAMF_CPOR_IDR: > + if (!FIELD_EX32(mpamf->idr, MPAMF_IDR, HAS_CPOR_PART)) { > + qemu_log_mask(LOG_UNIMP, > + "MPAM: Unexpected read of CPOR_IDR with no CPOR support\n"); > + return 0; > + } > + return mpamf->cpor_idr; > case A_MPAMF_PARTID_NRW_IDR: { > return mpamf->partid_nrw_idr; > } > @@ -367,6 +374,19 @@ static uint64_t mpam_msc_read_reg(void *opaque, hwaddr > offset, > return mpamf->mbwumon_idr; > case A_MPAMF_CFG_PART_SEL: > return mpamf->cfg_part_sel; > + case A_MPAMF_MPAMCFG_CPBM0... > + (A_MPAMF_MPAMCFG_CPBM0 + ((MPAM_CACHE_PART + 31) / 32 - 1) * 4): > + { > + uint32_t array_offset; > + > + if (!FIELD_EX32(mpamf->idr, MPAMF_IDR, HAS_CPOR_PART)) { > + qemu_log_mask(LOG_UNIMP, > + "MPAM: Unexpected read of CPBM with no CPOR support\n"); > + return 0; Sanity check for whether the width is large enough would just be informational here but it would I think be nice to have. > + } > + array_offset = (offset - A_MPAMF_MPAMCFG_CPBM0) / sizeof(uint32_t); > + return mpamf->per_nrw_id[nrw_part_sel].cfg_cpbm[array_offset]; > + } > default: > qemu_log_mask(LOG_UNIMP, > "MPAM: Unexpected read of %lx\n", offset); > @@ -410,6 +430,21 @@ static void mpam_msc_write_reg(void *opaque, hwaddr > offset, uint64_t value, > mpamf = &s->mpamf[s->ris]; > mpamf->cfg_part_sel = value; > return; > + case A_MPAMF_MPAMCFG_CPBM0... > + (A_MPAMF_MPAMCFG_CPBM0 + ((MPAM_CACHE_PART + 31) / 32 - 1) * 4): > + { > + uint32_t array_offset; > + > + /* TODO: Figure out write mask to check this stays in write bits */ Ah. Indeed, this is the thing the LLM was complaining about earlier. The width depends on how many partitions there are. Definitely need that enforced (and a log on going over it). Roughly speaking n such that (from the spec) When ((n * 32) + x) >= UInt(MPAMF_CPOR_IDR().CPBM_WD) is bad so either register out of range where n is the register offset and x is the bit in it. So shouldn't be too tricky to fix this. > + if (!FIELD_EX32(mpamf->idr, MPAMF_IDR, HAS_CPOR_PART)) { > + qemu_log_mask(LOG_UNIMP, > + "MPAM: Unexpected write to CPMB when > !HAS_CPORT_PART\n"); > + return; > + } > + array_offset = (offset - A_MPAMF_MPAMCFG_CPBM0) / sizeof(uint32_t); > + mpamf->per_nrw_id[nrw_part_sel].cfg_cpbm[array_offset] = value; > + return; > + }
