On Fri, 16 Oct 2026 17:46:59 +0800 Jinjie Ruan <[email protected]> wrote:
> From: Jonathan Cameron <[email protected]> > > Add the MMIO register map of an MPAM 1.1 Memory System Component > (IHI 0099 sections 4-6) as registerfields definitions: > - The feature IDRs (MPAMF_IDR, IIDR/AIDR, CPOR/CCAP/MBW/PRI/PARTID_NRW, > MSMON family) > - The error registers (ERR_MSI block, ECR, ESR) > - The configuration registers (PART_SEL, CMAX/CMIN/CASSOC, > MBW_MIN/MAX/PBM/PROP, PRI, INTPARTID, CPBM/MBW_PBM arrays) and their > write masks > - The portion-width constants of this model. > > Based on an RFC series by Jonathan Cameron. Maybe a link tag to that old piece of garbage - might be more useful than referring to it like this. A few typos in here that should be tidied up. I clearly didn't check this closely enough at the time. Nothing major but need tidying up. Also, an LLM pointed out that some of the write masks are more complex that this implies as depend on other register values. Maybe add comments where that is true as enforcement will be needed in the writing code - what we have here just acts as some sort of worst case masking. I guess you could define some macros to create the masks here. Thanks, Jonathan > > Signed-off-by: Jonathan Cameron <[email protected]> > Signed-off-by: Jinjie Ruan <[email protected]> > diff --git a/hw/arm/meson.build b/hw/arm/meson.build > index bcc068d..42ca75b 100644 > --- a/hw/arm/meson.build > +++ b/hw/arm/meson.build > @@ -106,6 +106,7 @@ arm_common_ss.add(when: 'CONFIG_NETDUINO2', if_true: > files('netduino2.c')) > arm_common_ss.add(when: 'CONFIG_RASPI', if_true: > files('bcm2835_peripherals.c')) > arm_common_ss.add(when: 'CONFIG_RASPI', if_true: > files('bcm2838_peripherals.c')) > arm_common_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c')) > +arm_common_ss.add(when: 'CONFIG_MPAM', if_true: files('mpam.c')) > arm_common_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c')) > arm_common_ss.add(when: 'CONFIG_VERSATILE', if_true: files('versatilepb.c')) > arm_common_ss.add(when: 'CONFIG_VEXPRESS', if_true: files('vexpress.c')) > diff --git a/hw/arm/mpam.c b/hw/arm/mpam.c > new file mode 100644 > index 0000000..772a120 > --- /dev/null > +++ b/hw/arm/mpam.c > @@ -0,0 +1,223 @@ > +/* > + * ARM MPAM emulation > + * > + * Copyright (c) 2023 Huawei > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > +#include "qemu/osdep.h" > +#include "qapi/error.h" > +#include "qemu/log.h" > +#include "hw/core/irq.h" > +#include "hw/core/qdev-properties.h" > +#include "hw/core/registerfields.h" > +#include "hw/core/sysbus.h" > +#include "qom/object.h" > +#include "hw/arm/mpam.h" > + > +REG64(MPAMF_IDR, 0) > + FIELD(MPAMF_IDR, PART_ID_MAX, 0, 16) Maybe call it PARTID_MAX given spec naming. > + FIELD(MPAMF_IDR, PMG_MAX, 16, 8) > + FIELD(MPAMF_IDR, HAS_CCAP_PART, 24, 1) > + FIELD(MPAMF_IDR, HAS_CPOR_PART, 25, 1) > + FIELD(MPAMF_IDR, HAS_MBW_PART, 26, 1) > + FIELD(MPAMF_IDR, HAS_PRI_PART, 27, 1) > + FIELD(MPAMF_IDR, EXT, 28, 1) > + FIELD(MPAMF_IDR, HAS_IMPL_IDR, 29, 1) > + FIELD(MPAMF_IDR, HAS_MSMON, 30, 1) > + FIELD(MPAMF_IDR, HAS_PARTID_NRW, 31, 1) > + FIELD(MPAMF_IDR, HAS_RIS, 32, 1) > + FIELD(MPAMF_IDR, NO_IMPL_PART, 36, 1) > + FIELD(MPAMF_IDR, NO_IMPL_MSMON, 37, 1) > + FIELD(MPAMF_IDR, HAS_EXTD_ESR, 38, 1) > + FIELD(MPAMF_IDR, HAS_ESR, 39, 1) > + FIELD(MPAMF_IDR, HAS_ERR_MS, 40, 1) > + FIELD(MPAMF_IDR, SP4, 41, 1) > + FIELD(MPAMF_IDR, HAS_ENDIS, 42, 1) > + FIELD(MPAMF_IDR, HAS_NFU, 43, 1) > + FIELD(MPAMF_IDR, RIS_MAX, 56, 4) > + > +REG32(MPAMF_MSMON_IDR, 0x080) An LLM pointed out I was really inconsistent in numbers of digits. 0x0080 Ah the heady days of copying typing specs. > + FIELD(MPAMF_MSMON_IDR, MSMON_CSU, 16, 1) > + FIELD(MPAMF_MSMON_IDR, MSMON_MBWU, 17, 1) > + FIELD(MPAMF_MSMON_IDR, HAS_OFLOW_SR, 28, 1) > + FIELD(MPAMF_MSMON_IDR, HAS_OFLW_MS, 29, 1) _MSI > + FIELD(MPAMF_MSMON_IDR, NO_OFLW_INTR, 30, 1) > + FIELD(MPAMF_MSMON_IDR, HAS_LOCAL_CAPT_EVNT, 31, 1) ... > +REG32(MPAMF_MPAMCFG_WINWD, 0x0220) > + FIELD(MPAMF_MPAMCFG_WINWD, US_FRAC, 0, 8) > + FIELD(MPAMF_MPAMCFG_WINWD, US_INT, 8, 16) > +#define MPAMF_MPAMCFG_WINWD_WRITE_MASK ( \ > + R_MPAMF_MPAMCFG_WINWD_US_FRAC | \ > + R_MPAMF_MPAMCFG_WINWD_US_INT) Those need _MASK suffix. > + > +REG32(MPAMF_MPAMCFG_EN, 0x0300) > + FIELD(MPAMF_MPAMCFG_EN, PARTID, 0, 16) > +#define MPAMF_MPAMCFG_EN_WRITE_MASK ( \ > + R_MPAMF_MPAMCFG_EN_PARTID_MASK) > + > +REG32(MPAMF_MPAMCFG_DIS, 0x0310) /* WHat is this for? */ > + FIELD(MPAMF_MPAMCFG_DIS, PARTID, 0, 16) > + FIELD(MPAMF_MPAMCFG_DIS, NFU, 31, 1) > +#define MPAMF_MPAMCFG_DIS_WRITE_MASK ( \ > + R_MPAMF_MPAMCFG_DIS_PARTID_MASK | \ > + R_MPAMF_MPAMCFG_DIS_NFU) Needs a _MASK suffic. > + > +REG32(MPAMF_MPAMCFG_EN_FLAGS, 0x320) Lots of 3 digit addresses scattered through here that should all be 4 digits. > + > +#define TYPE_MPAM_MSC "mpam-msc" > +/* > + * Max number of portions this model exposes for the cache-portion (CPOR) > + * bitmap and the memory-bandwidth-portion (MBW_PBM) bitmap. IHI 0099 > + * dimensions CPBM_WD/BWPBM_WD by these widths (see MPAMF_CPOR/MBW_IDR). > + */ > +#define MPAM_MBW_PART 4 > +#define MPAM_CACHE_PART 32 > +/* MPAMF_IIDR.IMPLEMENTER: ARM JEP106 code for Huawei (0x736). */ > +#define MPAM_IIDR_IMPLEMENTER 0x736 > diff --git a/include/hw/arm/mpam.h b/include/hw/arm/mpam.h > new file mode 100644 > index 0000000..e7557a9 > --- /dev/null > +++ b/include/hw/arm/mpam.h > @@ -0,0 +1,20 @@ > +/* > + * QEMU MPAM emulation Come to think of it, why have QEMU in a QEMU header. MPAM emulation. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > +#ifndef _MPAM_H_ > +#define _MPAM_H_ > + > +#include "qom/object.h" > + > +#define TYPE_MPAM_MSC_MEM "mpam-msc-mem" > +#define TYPE_MPAM_MSC_CACHE "mpam-msc-cache" > + > +/* > + * MMIO window of one MSC: IHI 0099 places the register block in a 16 KiB > + * region (0x4000). The virt board reserves a 1 MiB slot for up to 256 MSCs. > + */ > +#define MPAM_SIZE 0x4000 > + > +#endif /* _MPAM_H_ */
