From: Jonathan Cameron <[email protected]>

Add the MPAM system registers for TCG: MPAMIDR_EL1 (RO) reporting 64
PARTIDs and 4 PMGs, and MPAM0_EL1/MPAM1_EL1 (RW, of which only
MPAM1_EL1.MPAMEN is architecturally reset). Advertise FEAT_MPAM via
ID_AA64PFR0.MPAM for TCG CPUs.

It is common to support MPAM on CPU cores, but not in the rest of the
system, so there is little disadvantage in always enabling these.

Based on an RFC series by Jonathan Cameron, adapted to the current
idregs[] storage and access_tid3() naming.

Signed-off-by: Jonathan Cameron <[email protected]>
Signed-off-by: Jinjie Ruan <[email protected]>
---
 target/arm/cpu-features.h | 11 +++++++++++
 target/arm/cpu.c          | 10 +++++++++-
 target/arm/cpu.h          |  3 +++
 target/arm/helper.c       | 17 +++++++++++++++++
 4 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index a9eebb4..4b7d47b 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -459,6 +459,17 @@ FIELD(DBGDEVID, DOUBLELOCK, 20, 4)
 FIELD(DBGDEVID, AUXREGS, 24, 4)
 FIELD(DBGDEVID, CIDMASK, 28, 4)
 
+FIELD(MPAMIDR, PARTID_MAX, 0, 16)
+FIELD(MPAMIDR, HAS_HCR, 17, 1)
+FIELD(MPAMIDR, VMR_MAX, 18, 3)
+FIELD(MPAMIDR, PMG_MAX, 32, 8)
+FIELD(MPAMIDR, HAS_ALTSP, 57, 1)
+FIELD(MPAMIDR, HAS_TIDR, 58, 1)
+FIELD(MPAMIDR, SP4, 59, 1)
+FIELD(MPAMIDR, HAS_FORCE_NS, 60, 1)
+FIELD(MPAMIDR, HAS_SDEFLT, 61, 1)
+FIELD(MPAM1_EL1, MPAMEN, 63, 1)
+
 FIELD(DBGDEVID1, PCSROFFSET, 0, 4)
 
 FIELD(MVFR0, SIMDREG, 0, 4)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 10ac6c9..e7529d5 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -439,6 +439,8 @@ static void arm_cpu_reset_hold(Object *obj, ResetType type)
         /* Sample rvbar at reset.  */
         env->cp15.rvbar = cpu->rvbar_prop;
         env->pc = env->cp15.rvbar;
+
+        env->mpam1_el1 = R_MPAM1_EL1_MPAMEN_MASK;
 #endif
     } else {
 #if defined(CONFIG_USER_ONLY)
@@ -452,6 +454,8 @@ static void arm_cpu_reset_hold(Object *obj, ResetType type)
             env->cp15.rvbar = cpu->rvbar_prop;
             env->regs[15] = cpu->rvbar_prop;
         }
+
+        env->mpam1_el1 = R_MPAM1_EL1_MPAMEN_MASK;
     }
 
 #if defined(CONFIG_USER_ONLY)
@@ -2333,7 +2337,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
         FIELD_DP64_IDREG(isar, ID_AA64PFR0, AMU, 0);
         FIELD_DP32_IDREG(isar, ID_PFR0, AMU, 0);
         /* FEAT_MPAM (Memory Partitioning and Monitoring Extension) */
-        FIELD_DP64_IDREG(isar, ID_AA64PFR0, MPAM, 0);
+        FIELD_DP64_IDREG(isar, ID_AA64PFR0, MPAM, 1);
+        cpu->isar.mpamidr_el1 =
+            FIELD_DP64(cpu->isar.mpamidr_el1, MPAMIDR, PARTID_MAX, 63);
+        cpu->isar.mpamidr_el1 =
+            FIELD_DP64(cpu->isar.mpamidr_el1, MPAMIDR, PMG_MAX, 3);
     }
 
     /* MPU can be configured out of a PMSA CPU either by setting has-mpu
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 06ebed4..51a36fa 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -757,6 +757,8 @@ typedef struct CPUArchState {
     struct CPUBreakpoint *cpu_breakpoint[16];
     struct CPUWatchpoint *cpu_watchpoint[16];
 
+    uint64_t mpam0_el1;
+    uint64_t mpam1_el1;
     /* Optional fault info across tlb lookup. */
     ARMMMUFaultInfo *tlb_fi;
 
@@ -1121,6 +1123,7 @@ struct ArchCPU {
         uint32_t dbgdevid;
         uint32_t dbgdevid1;
         uint64_t reset_pmcr_el0;
+        uint64_t mpamidr_el1;
         uint64_t idregs[NUM_ID_IDX];
     } isar;
     uint64_t midr;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index ff0b766..896ac0e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6907,6 +6907,23 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_tid3,
               .resetvalue = cpu->isar.mvfr0 },
+            { .name = "MPAMIDR_EL1", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 0, .crn = 0xa, .crm = 4, .opc2 = 4,
+              .access = PL1_R, .type = ARM_CP_CONST,
+              .accessfn = access_tid3,
+              .resetvalue = cpu->isar.mpamidr_el1 },
+            { .name = "MPAM0_EL1", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 0, .crn = 0xa, .crm = 5, .opc2 = 1,
+              .access = PL1_RW, .type = ARM_CP_ALIAS,
+              .accessfn = access_tid3,
+              .fieldoffset = offsetof(CPUARMState, mpam0_el1),
+            },
+            { .name = "MPAM1_EL1", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 0, .crn = 0xa, .crm = 5, .opc2 = 0,
+              .access = PL1_RW, .type = ARM_CP_ALIAS,
+              .accessfn = access_tid3,
+              .fieldoffset = offsetof(CPUARMState, mpam1_el1),
+            },
             { .name = "MVFR1_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
-- 
2.43.0


Reply via email to