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;
> +    }



Reply via email to