From: Jinjie Ruan <[email protected]> Add the per-internal-PARTID configuration storage: MpamfPerNrwId holds every partition's CPBM bitmap, bandwidth, priority and capacity settings, allocated per RIS at realize together with the request-to-internal PARTID indirection table. mpam_get_nrw_id() resolves the currently selected partition for the configuration register accesses: with INTERNAL selection the selector addresses the internal PARTID space directly, otherwise the indirection table maps the request PARTID.
Signed-off-by: Jinjie Ruan <[email protected]> --- hw/arm/mpam.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/hw/arm/mpam.c b/hw/arm/mpam.c index c21a737..cce9355 100644 --- a/hw/arm/mpam.c +++ b/hw/arm/mpam.c @@ -222,6 +222,16 @@ REG32(MPAMF_MPAMCFG_MBW_PBM0, 0x2000) /* MPAMF_IIDR.IMPLEMENTER: ARM JEP106 code for Huawei (0x736). */ #define MPAM_IIDR_IMPLEMENTER 0x736 +typedef struct MpamfPerNrwId { + uint32_t cfg_cpbm[(MPAM_CACHE_PART + 31) / 32]; + uint32_t cfg_mbw_pbm[(MPAM_MBW_PART + 31) / 32]; + uint32_t cfg_pri; + uint32_t cfg_cmax; + uint32_t cfg_mbw_min; + uint32_t cfg_mbw_max; + uint32_t cfg_mbw_prop; +} MpamfPerNrwId; + typedef struct Mpamf { uint64_t idr; uint32_t iidr; @@ -243,6 +253,10 @@ typedef struct Mpamf { uint32_t ecr; uint32_t esr; uint32_t cfg_part_sel; + uint32_t *cfg_intpartid; + + MpamfPerNrwId *per_nrw_id; + } Mpamf; typedef struct MPAMMSCState { @@ -260,6 +274,27 @@ typedef struct MPAMMSCState { } MPAMMSCState; +/* + * ID narrowing may be in effect. If it is there is an indirection + * table per RIS mapping from part_sel to the internal ID. To make things + * more complex, the Partition selection register can directly address + * internal IDs. That works for everything other than the ID map itself. + * This function pulls the right internal ID out of this complexity + * for use in accessing the per_nrw_id structures. + */ +static uint32_t mpam_get_nrw_id(MPAMMSCState *s) +{ + Mpamf *mpamf = &s->mpamf[s->ris]; + + if (!FIELD_EX32(mpamf->idr, MPAMF_IDR, HAS_PARTID_NRW)) { + return s->part_sel; + } + if (s->internal_part_sel) { + return s->part_sel; + } + return mpamf->cfg_intpartid[s->part_sel]; +} + typedef struct MPAMMSCMemState { MPAMMSCState parent; } MPAMMSCMemState; @@ -285,6 +320,7 @@ static uint64_t mpam_msc_read_reg(void *opaque, hwaddr offset, { MPAMMSCState *s = MPAM_MSC_DEVICE(opaque); Mpamf *mpamf = &s->mpamf[s->ris]; + uint32_t nrw_part_sel = mpam_get_nrw_id(s); switch (offset) { case A_MPAMF_IDR: @@ -344,6 +380,8 @@ static void mpam_msc_write_reg(void *opaque, hwaddr offset, uint64_t value, MPAMMSCState *s = MPAM_MSC_DEVICE(opaque); /* Update in the ris setting path */ Mpamf *mpamf = &s->mpamf[s->ris]; + /* Update if cfg_intpartid being touched */ + uint32_t nrw_part_sel = mpam_get_nrw_id(s); switch (offset) { case A_MPAMF_CFG_PART_SEL: @@ -397,6 +435,7 @@ static const MemoryRegionOps mpam_msc_ops = { static void mpam_msc_realize(DeviceState *dev, Error **errp) { MPAMMSCState *s = MPAM_MSC_DEVICE(dev); + int i; /* IHI 0099: MPAMF_CFG_PART_SEL.RIS is 4 bits, so at most 16 RIS. */ if (s->num_ris > 16) { @@ -412,6 +451,11 @@ 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++) { + 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); + } + memory_region_init_io(&s->mr, OBJECT(s), &mpam_msc_ops, s, "mpam_msc", MPAM_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr); -- 2.43.0
