From: Jinjie Ruan <[email protected]> Add the memory-bandwidth controls: MPAMF_MBW_IDR (16-bit BWA_WD fraction, MIN/MAX/PBM/PROP support, BWPBM_WD = MPAM_MBW_PART) with HAS_MBW_PART on the memory subtype, and read/write handling for MBW_MIN, MBW_MAX, MBW_PROP and the MBW_PBM bitmap per selected internal PARTID.
Note the MBW_MIN write mask check references the CMIN mask -- a leftover fixed later by the CMIN/CASSOC patch. Signed-off-by: Jinjie Ruan <[email protected]> --- hw/arm/mpam.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/hw/arm/mpam.c b/hw/arm/mpam.c index 2b1401e..7c33ec4 100644 --- a/hw/arm/mpam.c +++ b/hw/arm/mpam.c @@ -363,6 +363,8 @@ static uint64_t mpam_msc_read_reg(void *opaque, hwaddr offset, return 0; } return mpamf->cpor_idr; + case A_MPAMF_MBW_IDR: + return mpamf->mbw_idr; case A_MPAMF_PARTID_NRW_IDR: { return mpamf->partid_nrw_idr; } @@ -374,6 +376,12 @@ 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_MBW_MIN: + return mpamf->per_nrw_id[nrw_part_sel].cfg_mbw_min; + case A_MPAMF_MPAMCFG_MBW_MAX: + return mpamf->per_nrw_id[nrw_part_sel].cfg_mbw_max; + case A_MPAMF_MPAMCFG_MBW_PROP: + return mpamf->per_nrw_id[nrw_part_sel].cfg_mbw_prop; case A_MPAMF_MPAMCFG_CPBM0... (A_MPAMF_MPAMCFG_CPBM0 + ((MPAM_CACHE_PART + 31) / 32 - 1) * 4): { @@ -387,6 +395,19 @@ static uint64_t mpam_msc_read_reg(void *opaque, hwaddr offset, array_offset = (offset - A_MPAMF_MPAMCFG_CPBM0) / sizeof(uint32_t); return mpamf->per_nrw_id[nrw_part_sel].cfg_cpbm[array_offset]; } + case A_MPAMF_MPAMCFG_MBW_PBM0... + (A_MPAMF_MPAMCFG_MBW_PBM0 + ((MPAM_MBW_PART + 31) / 32 - 1) * 4): + { + uint32_t array_offset; + + if (!FIELD_EX32(mpamf->idr, MPAMF_IDR, HAS_MBW_PART)) { + qemu_log_mask(LOG_UNIMP, + "MPAM: Unexpected read of MBW_PBM with no MBW_PART support\n"); + return 0; + } + array_offset = (offset - A_MPAMF_MPAMCFG_MBW_PBM0) / sizeof(uint32_t); + return mpamf->per_nrw_id[nrw_part_sel].cfg_mbw_pbm[array_offset]; + } default: qemu_log_mask(LOG_UNIMP, "MPAM: Unexpected read of %lx\n", offset); @@ -430,6 +451,30 @@ 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_MBW_MIN: + if (value & ~MPAMF_MPAMCFG_CMIN_WRITE_MASK) { + qemu_log_mask(LOG_UNIMP, + "MPAM: Unexpected write to CMAX Mask=%x Value=%lx\n", + MPAMF_MPAMCFG_CMIN_WRITE_MASK, value); + } + mpamf->per_nrw_id[nrw_part_sel].cfg_mbw_min = value; + return; + case A_MPAMF_MPAMCFG_MBW_MAX: + if (value & ~MPAMF_MPAMCFG_MBW_MAX_WRITE_MASK) { + qemu_log_mask(LOG_UNIMP, + "MPAM: Unexpected write to MBW_MAX Mask=%x Value=%lx\n", + MPAMF_MPAMCFG_MBW_MAX_WRITE_MASK, value); + } + mpamf->per_nrw_id[nrw_part_sel].cfg_mbw_max = value; + return; + case A_MPAMF_MPAMCFG_MBW_PROP: + if (value & ~MPAMF_MPAMCFG_MBW_PROP_WRITE_MASK) { + qemu_log_mask(LOG_UNIMP, + "MPAM: Unexpected write to MBW_PROP Mask=%x Value=%lx\n", + MPAMF_MPAMCFG_MBW_MAX_WRITE_MASK, value); + } + mpamf->per_nrw_id[nrw_part_sel].cfg_mbw_prop = value; + return; case A_MPAMF_MPAMCFG_CPBM0... (A_MPAMF_MPAMCFG_CPBM0 + ((MPAM_CACHE_PART + 31) / 32 - 1) * 4): { @@ -445,6 +490,22 @@ static void mpam_msc_write_reg(void *opaque, hwaddr offset, uint64_t value, mpamf->per_nrw_id[nrw_part_sel].cfg_cpbm[array_offset] = value; return; } + case A_MPAMF_MPAMCFG_MBW_PBM0... + (A_MPAMF_MPAMCFG_MBW_PBM0 + ((MPAM_MBW_PART + 31) / 32 - 1) * 4): + { + uint32_t array_offset; + + if (!FIELD_EX32(mpamf->idr, MPAMF_IDR, HAS_MBW_PART)) { + qemu_log_mask(LOG_UNIMP, + "MPAM: Unexpected write to MBW_PBM when !HAS_MBW_PART\n"); + return; + } + /* TODO: Figure out write mask to check this stays in write bits */ + array_offset = (offset - A_MPAMF_MPAMCFG_MBW_PBM0) / sizeof(uint32_t); + + mpamf->per_nrw_id[nrw_part_sel].cfg_mbw_pbm[array_offset] = value; + return; + } default: qemu_log_mask(LOG_UNIMP, "MPAM: Write to unexpected register Addr %lx Value=%lx\n", @@ -522,6 +583,8 @@ static void mpam_msc_mem_realize(DeviceState *dev, Error **errp) /* We won't implement any implementation specific stuff */ mpamf->idr = FIELD_DP64(mpamf->idr, MPAMF_IDR, NO_IMPL_PART, 1); mpamf->idr = FIELD_DP64(mpamf->idr, MPAMF_IDR, NO_IMPL_MSMON, 1); + /* Memory specific bit */ + mpamf->idr = FIELD_DP64(mpamf->idr, MPAMF_IDR, HAS_MBW_PART, 1); mpamf->iidr = FIELD_DP64(mpamf->iidr, MPAMF_IIDR, IMPLEMENTER, MPAM_IIDR_IMPLEMENTER); @@ -533,6 +596,16 @@ static void mpam_msc_mem_realize(DeviceState *dev, Error **errp) mpamf->aidr = FIELD_DP64(mpamf->aidr, MPAMF_AIDR, ARCH_MINOR_REV, 1); mpamf->aidr = FIELD_DP64(mpamf->aidr, MPAMF_AIDR, ARCH_MAJOR_REV, 1); + mpamf->mbw_idr = FIELD_DP32(mpamf->mbw_idr, MPAMF_MBW_IDR, BWA_WD, 16); + mpamf->mbw_idr = FIELD_DP32(mpamf->mbw_idr, MPAMF_MBW_IDR, HAS_MIN, 1); + mpamf->mbw_idr = FIELD_DP32(mpamf->mbw_idr, MPAMF_MBW_IDR, HAS_MAX, 1); + mpamf->mbw_idr = FIELD_DP32(mpamf->mbw_idr, MPAMF_MBW_IDR, HAS_PBM, 1); + mpamf->mbw_idr = FIELD_DP32(mpamf->mbw_idr, MPAMF_MBW_IDR, HAS_PROP, 1); + + mpamf->mbw_idr = FIELD_DP32(mpamf->mbw_idr, MPAMF_MBW_IDR, WINDWR, 0); + mpamf->mbw_idr = FIELD_DP32(mpamf->mbw_idr, MPAMF_MBW_IDR, + BWPBM_WD, MPAM_MBW_PART); + if (s->num_int_partid < s->num_partid) { mpamf->partid_nrw_idr = FIELD_DP32(mpamf->partid_nrw_idr, MPAMF_PARTID_NRW_IDR, -- 2.43.0
