* [PATCH v4 1/6] target/arm: Add the MECEn SCR_EL3 bit
2025-07-09 18:03 [PATCH-for-10.1 v4 0/6] target/arm: Add FEAT_MEC to max cpu Gustavo Romero
@ 2025-07-09 18:03 ` Gustavo Romero
2025-07-09 18:03 ` [PATCH v4 2/6] target/arm: Add FEAT_MEC registers Gustavo Romero
` (4 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Gustavo Romero @ 2025-07-09 18:03 UTC (permalink / raw)
To: qemu-arm, richard.henderson, alex.bennee; +Cc: qemu-devel, gustavo.romero
The MECEn bit in SCR_EL3 enables access to the EL2 MECID registers from
EL2, so add it to the SCR mask list to use it later on.
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c8cf0ab417..0f64c7b163 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1717,6 +1717,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define SCR_TRNDR (1ULL << 40)
#define SCR_ENTP2 (1ULL << 41)
#define SCR_GPF (1ULL << 48)
+#define SCR_MECEN (1ULL << 49)
#define SCR_NSE (1ULL << 62)
/* Return the current FPSCR value. */
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v4 2/6] target/arm: Add FEAT_MEC registers
2025-07-09 18:03 [PATCH-for-10.1 v4 0/6] target/arm: Add FEAT_MEC to max cpu Gustavo Romero
2025-07-09 18:03 ` [PATCH v4 1/6] target/arm: Add the MECEn SCR_EL3 bit Gustavo Romero
@ 2025-07-09 18:03 ` Gustavo Romero
2025-07-09 20:26 ` Richard Henderson
2025-07-09 18:03 ` [PATCH v4 3/6] target/arm: Add FEAT_SCTLR2 Gustavo Romero
` (3 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Gustavo Romero @ 2025-07-09 18:03 UTC (permalink / raw)
To: qemu-arm, richard.henderson, alex.bennee; +Cc: qemu-devel, gustavo.romero
Add all FEAT_MEC registers.
To work properly, FEAT_MEC also depends on FEAT_SCTLR2 and FEAT_TCR2,
which are not implemented in this commit. The bits in SCTLR2 and TCR2
control which translation regimes use MECIDs, and determine which MECID
is selected.
FEAT_MEC also requires two new cache management instructions, not
included in this commit, that will be implemented in subsequent commits.
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
---
target/arm/cpu-features.h | 5 +++
target/arm/cpu.h | 11 ++++++
target/arm/helper.c | 70 +++++++++++++++++++++++++++++++++++++++
3 files changed, 86 insertions(+)
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 5876162428..552d8757b7 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -594,6 +594,11 @@ static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id)
return FIELD_EX64_IDREG(id, ID_AA64ISAR2, BC) != 0;
}
+static inline bool isar_feature_aa64_mec(const ARMISARegisters *id)
+{
+ return FIELD_EX64_IDREG(id, ID_AA64MMFR3, MEC) != 0;
+}
+
static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
{
return FIELD_EX64_IDREG(id, ID_AA64ISAR2, MOPS);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0f64c7b163..a93eebe077 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -576,6 +576,15 @@ typedef struct CPUArchState {
/* NV2 register */
uint64_t vncr_el2;
+
+ /* MEC registers */
+ uint64_t mecid_p0_el2;
+ uint64_t mecid_a0_el2;
+ uint64_t mecid_p1_el2;
+ uint64_t mecid_a1_el2;
+ uint64_t mecid_rl_a_el3;
+ uint64_t vmecid_p_el2;
+ uint64_t vmecid_a_el2;
} cp15;
struct {
@@ -2424,6 +2433,8 @@ FIELD(MFAR, FPA, 12, 40)
FIELD(MFAR, NSE, 62, 1)
FIELD(MFAR, NS, 63, 1)
+#define MECID_WIDTH 16
+
QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
/* If adding a feature bit which corresponds to a Linux ELF
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b3f0d6f17a..984406c945 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6827,6 +6827,72 @@ static const ARMCPRegInfo nmi_reginfo[] = {
.resetfn = arm_cp_reset_ignore },
};
+static CPAccessResult mecid_access(CPUARMState *env,
+ const ARMCPRegInfo *ri, bool isread)
+{
+ int el = arm_current_el(env);
+
+ if (el == 2) {
+ if (arm_security_space(env) != ARMSS_Realm) {
+ return CP_ACCESS_UNDEFINED;
+ }
+
+ if (!(env->cp15.scr_el3 & SCR_MECEN)) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ }
+
+ return CP_ACCESS_OK;
+}
+
+static void mecid_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ value = extract64(value, 0, MECID_WIDTH);
+ raw_write(env, ri, value);
+}
+
+static const ARMCPRegInfo mec_reginfo[] = {
+ { .name = "MECIDR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 7, .crn = 10, .crm = 8,
+ .access = PL2_R, .type = ARM_CP_CONST, .resetvalue = MECID_WIDTH - 1 },
+ { .name = "MECID_P0_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 0, .crn = 10, .crm = 8,
+ .access = PL2_RW, .accessfn = mecid_access,
+ .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_p0_el2) },
+ { .name = "MECID_A0_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 1, .crn = 10, .crm = 8,
+ .access = PL2_RW, .accessfn = mecid_access,
+ .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_a0_el2) },
+ { .name = "MECID_P1_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 2, .crn = 10, .crm = 8,
+ .access = PL2_RW, .accessfn = mecid_access,
+ .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_p1_el2) },
+ { .name = "MECID_A1_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 3, .crn = 10, .crm = 8,
+ .access = PL2_RW, .accessfn = mecid_access,
+ .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_a1_el2) },
+ { .name = "MECID_RL_A_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .opc2 = 1, .crn = 10, .crm = 10,
+ .access = PL3_RW, .accessfn = mecid_access,
+ .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_rl_a_el3) },
+ { .name = "VMECID_P_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 0, .crn = 10, .crm = 9,
+ .access = PL2_RW, .accessfn = mecid_access,
+ .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.vmecid_p_el2) },
+ { .name = "VMECID_A_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 1, .crn = 10, .crm = 9,
+ .access = PL2_RW, .accessfn = mecid_access,
+ .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.vmecid_a_el2) },
+};
+
static void define_pmu_regs(ARMCPU *cpu)
{
/*
@@ -9014,6 +9080,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_arm_cp_regs(cpu, nmi_reginfo);
}
+ if (cpu_isar_feature(aa64_mec, cpu)) {
+ define_arm_cp_regs(cpu, mec_reginfo);
+ }
+
if (cpu_isar_feature(any_predinv, cpu)) {
define_arm_cp_regs(cpu, predinv_reginfo);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v4 2/6] target/arm: Add FEAT_MEC registers
2025-07-09 18:03 ` [PATCH v4 2/6] target/arm: Add FEAT_MEC registers Gustavo Romero
@ 2025-07-09 20:26 ` Richard Henderson
0 siblings, 0 replies; 14+ messages in thread
From: Richard Henderson @ 2025-07-09 20:26 UTC (permalink / raw)
To: Gustavo Romero, qemu-arm, alex.bennee; +Cc: qemu-devel
On 7/9/25 12:03, Gustavo Romero wrote:
> Add all FEAT_MEC registers.
>
> To work properly, FEAT_MEC also depends on FEAT_SCTLR2 and FEAT_TCR2,
> which are not implemented in this commit. The bits in SCTLR2 and TCR2
> control which translation regimes use MECIDs, and determine which MECID
> is selected.
>
> FEAT_MEC also requires two new cache management instructions, not
> included in this commit, that will be implemented in subsequent commits.
>
> Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
> ---
> target/arm/cpu-features.h | 5 +++
> target/arm/cpu.h | 11 ++++++
> target/arm/helper.c | 70 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 86 insertions(+)
>
> diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
> index 5876162428..552d8757b7 100644
> --- a/target/arm/cpu-features.h
> +++ b/target/arm/cpu-features.h
> @@ -594,6 +594,11 @@ static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id)
> return FIELD_EX64_IDREG(id, ID_AA64ISAR2, BC) != 0;
> }
>
> +static inline bool isar_feature_aa64_mec(const ARMISARegisters *id)
> +{
> + return FIELD_EX64_IDREG(id, ID_AA64MMFR3, MEC) != 0;
> +}
> +
> static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
> {
> return FIELD_EX64_IDREG(id, ID_AA64ISAR2, MOPS);
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 0f64c7b163..a93eebe077 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -576,6 +576,15 @@ typedef struct CPUArchState {
>
> /* NV2 register */
> uint64_t vncr_el2;
> +
> + /* MEC registers */
> + uint64_t mecid_p0_el2;
> + uint64_t mecid_a0_el2;
> + uint64_t mecid_p1_el2;
> + uint64_t mecid_a1_el2;
> + uint64_t mecid_rl_a_el3;
> + uint64_t vmecid_p_el2;
> + uint64_t vmecid_a_el2;
> } cp15;
>
> struct {
> @@ -2424,6 +2433,8 @@ FIELD(MFAR, FPA, 12, 40)
> FIELD(MFAR, NSE, 62, 1)
> FIELD(MFAR, NS, 63, 1)
>
> +#define MECID_WIDTH 16
This could go in internals.h.
Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v4 3/6] target/arm: Add FEAT_SCTLR2
2025-07-09 18:03 [PATCH-for-10.1 v4 0/6] target/arm: Add FEAT_MEC to max cpu Gustavo Romero
2025-07-09 18:03 ` [PATCH v4 1/6] target/arm: Add the MECEn SCR_EL3 bit Gustavo Romero
2025-07-09 18:03 ` [PATCH v4 2/6] target/arm: Add FEAT_MEC registers Gustavo Romero
@ 2025-07-09 18:03 ` Gustavo Romero
2025-07-09 20:30 ` Richard Henderson
2025-07-09 20:31 ` Richard Henderson
2025-07-09 18:03 ` [PATCH v4 4/6] target/arm: Add FEAT_TCR2 Gustavo Romero
` (2 subsequent siblings)
5 siblings, 2 replies; 14+ messages in thread
From: Gustavo Romero @ 2025-07-09 18:03 UTC (permalink / raw)
To: qemu-arm, richard.henderson, alex.bennee; +Cc: qemu-devel, gustavo.romero
Add FEAT_SCTLR2, which introduces the SCTLR2_EL1, SCTLR2_EL2, and
SCTLR2_EL3 registers. These registers are extensions of the SCTLR_ELx
ones.
Because the bits in these registers depend on other CPU features, and
only FEAT_MEC is supported at the moment, this commit only implements
the EMEC bits in CTLR2_EL2 and SCTLR2_EL3.
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
---
docs/system/arm/emulation.rst | 1 +
target/arm/cpu-features.h | 5 +++
target/arm/cpu.h | 15 +++++++
target/arm/helper.c | 78 +++++++++++++++++++++++++++++++++++
target/arm/internals.h | 1 +
target/arm/tcg/cpu64.c | 1 +
6 files changed, 101 insertions(+)
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 890dc6fee2..66043b0747 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -121,6 +121,7 @@ the following architecture extensions:
- FEAT_RPRES (Increased precision of FRECPE and FRSQRTE)
- FEAT_S2FWB (Stage 2 forced Write-Back)
- FEAT_SB (Speculation Barrier)
+- FEAT_SCTLR2 (Extension to SCTLR_ELx)
- FEAT_SEL2 (Secure EL2)
- FEAT_SHA1 (SHA1 instructions)
- FEAT_SHA256 (SHA256 instructions)
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 552d8757b7..44d6b655a9 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -416,6 +416,11 @@ static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id)
return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RDM) != 0;
}
+static inline bool isar_feature_aa64_sctlr2(const ARMISARegisters *id)
+{
+ return FIELD_EX64_IDREG(id, ID_AA64MMFR3, SCTLRX) != 0;
+}
+
static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id)
{
return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA3) != 0;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index a93eebe077..32d30b7bb9 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -337,6 +337,7 @@ typedef struct CPUArchState {
};
uint64_t sctlr_el[4];
};
+ uint64_t sctlr2_el[4]; /* Extension to System control register. */
uint64_t vsctlr; /* Virtualization System control register. */
uint64_t cpacr_el1; /* Architectural feature access control register */
uint64_t cptr_el[4]; /* ARMv8 feature trap registers */
@@ -1433,6 +1434,19 @@ void pmu_init(ARMCPU *cpu);
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
+#define SCTLR2_EMEC (1ULL << 1) /* FEAT_MEC */
+#define SCTLR2_NMEA (1ULL << 2) /* FEAT_DoubleFault2 */
+#define SCTLR2_ENADERR (1ULL << 3) /* FEAT_ADERR */
+#define SCTLR2_ENANERR (1ULL << 4) /* FEAT_ANERR */
+#define SCTLR2_EASE (1ULL << 5) /* FEAT_DoubleFault2 */
+#define SCTLR2_ENIDCP128 (1ULL << 6) /* FEAT_SYSREG128 */
+#define SCTLR2_ENPACM (1ULL << 7) /* FEAT_PAuth_LR */
+#define SCTLR2_ENPACM0 (1ULL << 8 /* FEAT_PAuth_LR */
+#define SCTLR2_CPTA (1ULL << 9) /* FEAT_CPA2 */
+#define SCTLR2_CPTA0 (1ULL << 10) /* FEAT_CPA2 */
+#define SCTLR2_CPTM (1ULL << 11) /* FEAT_CPA2 */
+#define SCTLR2_CPTM0 (1ULL << 12) /* FEAT_CAP2 */
+
#define CPSR_M (0x1fU)
#define CPSR_T (1U << 5)
#define CPSR_F (1U << 6)
@@ -1725,6 +1739,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define SCR_HXEN (1ULL << 38)
#define SCR_TRNDR (1ULL << 40)
#define SCR_ENTP2 (1ULL << 41)
+#define SCR_SCTLR2EN (1ULL << 44)
#define SCR_GPF (1ULL << 48)
#define SCR_MECEN (1ULL << 49)
#define SCR_NSE (1ULL << 62)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 984406c945..5707eea822 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6144,6 +6144,8 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
static const struct E2HAlias aliases[] = {
{ K(3, 0, 1, 0, 0), K(3, 4, 1, 0, 0), K(3, 5, 1, 0, 0),
"SCTLR", "SCTLR_EL2", "SCTLR_EL12" },
+ { K(3, 0, 1, 0, 3), K(3, 4, 1, 0, 3), K(3, 5, 1, 0, 3),
+ "SCTLR2_EL1", "SCTLR2_EL2", "SCTLR2_EL12" },
{ K(3, 0, 1, 0, 2), K(3, 4, 1, 1, 2), K(3, 5, 1, 0, 2),
"CPACR", "CPTR_EL2", "CPACR_EL12" },
{ K(3, 0, 2, 0, 0), K(3, 4, 2, 0, 0), K(3, 5, 2, 0, 0),
@@ -7816,6 +7818,78 @@ static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
.resetvalue = 0 },
};
+static CPAccessResult sctlr2_el2_access(CPUARMState *env,
+ const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_current_el(env) < 3 && !(env->cp15.scr_el3 & SCR_SCTLR2EN)) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ return CP_ACCESS_OK;
+};
+
+static CPAccessResult sctlr2_el1_access(CPUARMState *env,
+ const ARMCPRegInfo *ri,
+ bool isread)
+{
+ CPAccessResult ret = access_tvm_trvm(env, ri, isread);
+ if (ret != CP_ACCESS_OK) {
+ return ret;
+ }
+ if (arm_current_el(env) < 2 && !(arm_hcrx_el2_eff(env) & HCRX_SCTLR2EN)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ return sctlr2_el2_access(env, ri, isread);
+};
+
+static void sctlr2_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /* This register does not control any feature yet. */
+};
+
+static void sctlr2_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ uint64_t valid_mask = 0;
+
+ if (cpu_isar_feature(aa64_mec, env_archcpu(env))) {
+ valid_mask |= SCTLR2_EMEC;
+ }
+ value &= valid_mask;
+ raw_write(env, ri, value);
+};
+
+static void sctlr2_el3_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ uint64_t valid_mask = 0;
+
+ if (cpu_isar_feature(aa64_mec, env_archcpu(env))) {
+ valid_mask |= SCTLR2_EMEC;
+ }
+ value &= valid_mask;
+ raw_write(env, ri, value);
+};
+
+static const ARMCPRegInfo sctlr2_reginfo[] = {
+ { .name = "SCTLR2_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .opc2 = 3, .crn = 1, .crm = 0,
+ .access = PL1_RW, .accessfn = sctlr2_el1_access,
+ .writefn = sctlr2_el1_write, .fgt = FGT_SCTLR_EL1,
+ .nv2_redirect_offset = 0x278 | NV2_REDIR_NV1,
+ .fieldoffset = offsetof(CPUARMState, cp15.sctlr2_el[1]) },
+ { .name = "SCTLR2_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 3, .crn = 1, .crm = 0,
+ .access = PL2_RW, .accessfn = sctlr2_el2_access,
+ .writefn = sctlr2_el2_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.sctlr2_el[2]) },
+ { .name = "SCTLR2_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .opc2 = 3, .crn = 1, .crm = 0,
+ .access = PL3_RW, .writefn = sctlr2_el3_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.sctlr2_el[3]) },
+};
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
@@ -9084,6 +9158,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_arm_cp_regs(cpu, mec_reginfo);
}
+ if (cpu_isar_feature(aa64_sctlr2, cpu)) {
+ define_arm_cp_regs(cpu, sctlr2_reginfo);
+ }
+
if (cpu_isar_feature(any_predinv, cpu)) {
define_arm_cp_regs(cpu, predinv_reginfo);
}
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 21a8d67edd..398e0b4a7d 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -232,6 +232,7 @@ FIELD(VTCR, SL2, 33, 1)
#define HCRX_CMOW (1ULL << 9)
#define HCRX_MCE2 (1ULL << 10)
#define HCRX_MSCEN (1ULL << 11)
+#define HCRX_SCTLR2EN (1ULL << 15)
#define HPFAR_NS (1ULL << 63)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index d0df50a2f3..bdd2fe7f5b 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1247,6 +1247,7 @@ void aarch64_max_tcg_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */
SET_IDREG(isar, ID_AA64MMFR2, t);
+ FIELD_DP64_IDREG(isar, ID_AA64MMFR3, SCTLRX, 1); /* FEAT_SCTLR2 */
FIELD_DP64_IDREG(isar, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
t = GET_IDREG(isar, ID_AA64ZFR0);
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v4 3/6] target/arm: Add FEAT_SCTLR2
2025-07-09 18:03 ` [PATCH v4 3/6] target/arm: Add FEAT_SCTLR2 Gustavo Romero
@ 2025-07-09 20:30 ` Richard Henderson
2025-07-09 20:31 ` Richard Henderson
1 sibling, 0 replies; 14+ messages in thread
From: Richard Henderson @ 2025-07-09 20:30 UTC (permalink / raw)
To: Gustavo Romero, qemu-arm, alex.bennee; +Cc: qemu-devel
On 7/9/25 12:03, Gustavo Romero wrote:
> @@ -7816,6 +7818,78 @@ static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
> .resetvalue = 0 },
> };
>
> +static CPAccessResult sctlr2_el2_access(CPUARMState *env,
> + const ARMCPRegInfo *ri,
> + bool isread)
> +{
> + if (arm_current_el(env) < 3 && !(env->cp15.scr_el3 & SCR_SCTLR2EN)) {
> + return CP_ACCESS_TRAP_EL3;
> + }
> + return CP_ACCESS_OK;
> +};
Stray ;
And on every other function until sctlr2_reginfo.
Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 3/6] target/arm: Add FEAT_SCTLR2
2025-07-09 18:03 ` [PATCH v4 3/6] target/arm: Add FEAT_SCTLR2 Gustavo Romero
2025-07-09 20:30 ` Richard Henderson
@ 2025-07-09 20:31 ` Richard Henderson
1 sibling, 0 replies; 14+ messages in thread
From: Richard Henderson @ 2025-07-09 20:31 UTC (permalink / raw)
To: Gustavo Romero, qemu-arm, alex.bennee; +Cc: qemu-devel
On 7/9/25 12:03, Gustavo Romero wrote:
> diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
> index 552d8757b7..44d6b655a9 100644
> --- a/target/arm/cpu-features.h
> +++ b/target/arm/cpu-features.h
> @@ -416,6 +416,11 @@ static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id)
> return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RDM) != 0;
> }
>
> +static inline bool isar_feature_aa64_sctlr2(const ARMISARegisters *id)
> +{
> + return FIELD_EX64_IDREG(id, ID_AA64MMFR3, SCTLRX) != 0;
> +}
Should be sorted just below the ID_AA64MMFR2 tests.
r~
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v4 4/6] target/arm: Add FEAT_TCR2
2025-07-09 18:03 [PATCH-for-10.1 v4 0/6] target/arm: Add FEAT_MEC to max cpu Gustavo Romero
` (2 preceding siblings ...)
2025-07-09 18:03 ` [PATCH v4 3/6] target/arm: Add FEAT_SCTLR2 Gustavo Romero
@ 2025-07-09 18:03 ` Gustavo Romero
2025-07-09 20:39 ` Richard Henderson
2025-07-09 18:03 ` [PATCH v4 5/6] target/arm: Implement FEAT_MEC cache instructions Gustavo Romero
2025-07-09 18:03 ` [PATCH v4 6/6] target/arm: Advertise FEAT_MEC in cpu max Gustavo Romero
5 siblings, 1 reply; 14+ messages in thread
From: Gustavo Romero @ 2025-07-09 18:03 UTC (permalink / raw)
To: qemu-arm, richard.henderson, alex.bennee; +Cc: qemu-devel, gustavo.romero
Add FEAT_TCR2, which introduces the TCR2_EL1 and TCR2_EL2 registers.
These registers are extensions of the TCR_ELx registers and provide
top-level control of the EL10 and EL20 translation regimes.
Since the bits in these registers depend on other CPU features, and only
FEAT_MEC is supported at the moment, the FEAT_TCR2 only implements the
AMEC bits for now.
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
---
docs/system/arm/emulation.rst | 1 +
target/arm/cpu-features.h | 5 +++
target/arm/cpu.h | 2 ++
target/arm/helper.c | 60 +++++++++++++++++++++++++++++++++++
target/arm/internals.h | 19 +++++++++++
target/arm/tcg/cpu64.c | 1 +
6 files changed, 88 insertions(+)
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 66043b0747..1c597d8673 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -149,6 +149,7 @@ the following architecture extensions:
- FEAT_SPECRES (Speculation restriction instructions)
- FEAT_SSBS (Speculative Store Bypass Safe)
- FEAT_SSBS2 (MRS and MSR instructions for SSBS version 2)
+- FEAT_TCR2 (Support for TCR2_ELx)
- FEAT_TGran16K (Support for 16KB memory translation granule size at stage 1)
- FEAT_TGran4K (Support for 4KB memory translation granule size at stage 1)
- FEAT_TGran64K (Support for 64KB memory translation granule size at stage 1)
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 44d6b655a9..3878aed589 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -486,6 +486,11 @@ static inline bool isar_feature_aa64_xs(const ARMISARegisters *id)
return FIELD_EX64_IDREG(id, ID_AA64ISAR1, XS) != 0;
}
+static inline bool isar_feature_aa64_tcr2(const ARMISARegisters *id)
+{
+ return FIELD_EX64_IDREG(id, ID_AA64MMFR3, TCRX) != 0;
+}
+
/*
* These are the values from APA/API/APA3.
* In general these must be compared '>=', per the normal Arm ARM
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 32d30b7bb9..5c13f89b29 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -366,6 +366,7 @@ typedef struct CPUArchState {
uint64_t vsttbr_el2; /* Secure Virtualization Translation Table. */
/* MMU translation table base control. */
uint64_t tcr_el[4];
+ uint64_t tcr2_el[3];
uint64_t vtcr_el2; /* Virtualization Translation Control. */
uint64_t vstcr_el2; /* Secure Virtualization Translation Control. */
uint32_t c2_data; /* MPU data cacheable bits. */
@@ -1739,6 +1740,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define SCR_HXEN (1ULL << 38)
#define SCR_TRNDR (1ULL << 40)
#define SCR_ENTP2 (1ULL << 41)
+#define SCR_TCR2EN (1ULL << 43)
#define SCR_SCTLR2EN (1ULL << 44)
#define SCR_GPF (1ULL << 48)
#define SCR_MECEN (1ULL << 49)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 5707eea822..34e12bde90 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6154,6 +6154,8 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
"TTBR1_EL1", "TTBR1_EL2", "TTBR1_EL12" },
{ K(3, 0, 2, 0, 2), K(3, 4, 2, 0, 2), K(3, 5, 2, 0, 2),
"TCR_EL1", "TCR_EL2", "TCR_EL12" },
+ { K(3, 0, 2, 0, 3), K(3, 4, 2, 0, 3), K(3, 5, 2, 0, 3),
+ "TCR2_EL1", "TCR2_EL2", "TCR2_EL12" },
{ K(3, 0, 4, 0, 0), K(3, 4, 4, 0, 0), K(3, 5, 4, 0, 0),
"SPSR_EL1", "SPSR_EL2", "SPSR_EL12" },
{ K(3, 0, 4, 0, 1), K(3, 4, 4, 0, 1), K(3, 5, 4, 0, 1),
@@ -7890,6 +7892,60 @@ static const ARMCPRegInfo sctlr2_reginfo[] = {
.fieldoffset = offsetof(CPUARMState, cp15.sctlr2_el[3]) },
};
+static CPAccessResult tcr2_el2_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_current_el(env) < 3 && !(env->cp15.scr_el3 & SCR_TCR2EN)) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ return CP_ACCESS_OK;
+};
+
+static CPAccessResult tcr2_el1_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ CPAccessResult ret = access_tvm_trvm(env, ri, isread);
+ if (ret != CP_ACCESS_OK) {
+ return ret;
+ }
+ if (arm_current_el(env) < 2 && !(arm_hcrx_el2_eff(env) & HCRX_TCR2EN)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ return tcr2_el2_access(env, ri, isread);
+}
+
+static void tcr2_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /* This register does not control any feature yet. */
+}
+
+static void tcr2_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ uint64_t valid_mask = 0;
+
+ if (cpu_isar_feature(aa64_mec, env_archcpu(env))) {
+ valid_mask |= TCR2_AMEC0 | TCR2_AMEC1;
+ }
+ value &= valid_mask;
+ raw_write(env, ri, value);
+}
+
+static const ARMCPRegInfo tcr2_reginfo[] = {
+ { .name = "TCR2_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .opc2 = 3, .crn = 2, .crm = 0,
+ .access = PL1_RW, .accessfn = tcr2_el1_access,
+ .writefn = tcr2_el1_write, .fgt = FGT_TCR_EL1,
+ .nv2_redirect_offset = 0x270 | NV2_REDIR_NV1,
+ .fieldoffset = offsetof(CPUARMState, cp15.tcr2_el[1]) },
+ { .name = "TCR2_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 3, .crn = 2, .crm = 0,
+ .access = PL2_RW, .accessfn = tcr2_el2_access,
+ .writefn = tcr2_el2_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.tcr2_el[2]) },
+};
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
@@ -9162,6 +9218,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_arm_cp_regs(cpu, sctlr2_reginfo);
}
+ if (cpu_isar_feature(aa64_tcr2, cpu)) {
+ define_arm_cp_regs(cpu, tcr2_reginfo);
+ }
+
if (cpu_isar_feature(any_predinv, cpu)) {
define_arm_cp_regs(cpu, predinv_reginfo);
}
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 398e0b4a7d..4b3dde82c6 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -201,6 +201,24 @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
#define TTBCR_SH1 (1U << 28)
#define TTBCR_EAE (1U << 31)
+#define TCR2_PNCH (1ULL << 0)
+#define TCR2_PIE (1ULL << 1)
+#define TCR2_E0POE (1ULL << 2)
+#define TCR2_POE (1ULL << 3)
+#define TCR2_AIE (1ULL << 4)
+#define TCR2_D128 (1ULL << 5)
+#define TCR2_PTTWI (1ULL << 10)
+#define TCR2_HAFT (1ULL << 11)
+#define TCR2_AMEC0 (1ULL << 12)
+#define TCR2_AMEC1 (1ULL << 13)
+#define TCR2_DISCH0 (1ULL << 14)
+#define TCR2_DISCH1 (1ULL << 15)
+#define TCR2_A2 (1ULL << 16)
+#define TCR2_FNG0 (1ULL << 17)
+#define TCR2_FNG1 (1ULL << 18)
+#define TCR2_FNGNA0 (1ULL << 20)
+#define TCR2_FNGNA1 (1ULL << 21)
+
FIELD(VTCR, T0SZ, 0, 6)
FIELD(VTCR, SL0, 6, 2)
FIELD(VTCR, IRGN0, 8, 2)
@@ -232,6 +250,7 @@ FIELD(VTCR, SL2, 33, 1)
#define HCRX_CMOW (1ULL << 9)
#define HCRX_MCE2 (1ULL << 10)
#define HCRX_MSCEN (1ULL << 11)
+#define HCRX_TCR2EN (1ULL << 14)
#define HCRX_SCTLR2EN (1ULL << 15)
#define HPFAR_NS (1ULL << 63)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index bdd2fe7f5b..173528175a 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1247,6 +1247,7 @@ void aarch64_max_tcg_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */
SET_IDREG(isar, ID_AA64MMFR2, t);
+ FIELD_DP64_IDREG(isar, ID_AA64MMFR3, TCRX, 1); /* FEAT_TCR2 */
FIELD_DP64_IDREG(isar, ID_AA64MMFR3, SCTLRX, 1); /* FEAT_SCTLR2 */
FIELD_DP64_IDREG(isar, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v4 4/6] target/arm: Add FEAT_TCR2
2025-07-09 18:03 ` [PATCH v4 4/6] target/arm: Add FEAT_TCR2 Gustavo Romero
@ 2025-07-09 20:39 ` Richard Henderson
0 siblings, 0 replies; 14+ messages in thread
From: Richard Henderson @ 2025-07-09 20:39 UTC (permalink / raw)
To: Gustavo Romero, qemu-arm, alex.bennee; +Cc: qemu-devel
On 7/9/25 12:03, Gustavo Romero wrote:
> Add FEAT_TCR2, which introduces the TCR2_EL1 and TCR2_EL2 registers.
> These registers are extensions of the TCR_ELx registers and provide
> top-level control of the EL10 and EL20 translation regimes.
>
> Since the bits in these registers depend on other CPU features, and only
> FEAT_MEC is supported at the moment, the FEAT_TCR2 only implements the
> AMEC bits for now.
>
> Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
> ---
> docs/system/arm/emulation.rst | 1 +
> target/arm/cpu-features.h | 5 +++
> target/arm/cpu.h | 2 ++
> target/arm/helper.c | 60 +++++++++++++++++++++++++++++++++++
> target/arm/internals.h | 19 +++++++++++
> target/arm/tcg/cpu64.c | 1 +
> 6 files changed, 88 insertions(+)
>
> diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
> index 66043b0747..1c597d8673 100644
> --- a/docs/system/arm/emulation.rst
> +++ b/docs/system/arm/emulation.rst
> @@ -149,6 +149,7 @@ the following architecture extensions:
> - FEAT_SPECRES (Speculation restriction instructions)
> - FEAT_SSBS (Speculative Store Bypass Safe)
> - FEAT_SSBS2 (MRS and MSR instructions for SSBS version 2)
> +- FEAT_TCR2 (Support for TCR2_ELx)
> - FEAT_TGran16K (Support for 16KB memory translation granule size at stage 1)
> - FEAT_TGran4K (Support for 4KB memory translation granule size at stage 1)
> - FEAT_TGran64K (Support for 64KB memory translation granule size at stage 1)
> diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
> index 44d6b655a9..3878aed589 100644
> --- a/target/arm/cpu-features.h
> +++ b/target/arm/cpu-features.h
> @@ -486,6 +486,11 @@ static inline bool isar_feature_aa64_xs(const ARMISARegisters *id)
> return FIELD_EX64_IDREG(id, ID_AA64ISAR1, XS) != 0;
> }
>
> +static inline bool isar_feature_aa64_tcr2(const ARMISARegisters *id)
> +{
> + return FIELD_EX64_IDREG(id, ID_AA64MMFR3, TCRX) != 0;
> +}
Should be sorted with other ID_AA64MMFR3 tests (just SCTLR2 so far, which you just added).
Secondary sorting by the bit offset (TCRX < SCTLRx). This tends to place everything in
a predictable order.
> diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
> index bdd2fe7f5b..173528175a 100644
> --- a/target/arm/tcg/cpu64.c
> +++ b/target/arm/tcg/cpu64.c
> @@ -1247,6 +1247,7 @@ void aarch64_max_tcg_initfn(Object *obj)
> t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */
> SET_IDREG(isar, ID_AA64MMFR2, t);
>
> + FIELD_DP64_IDREG(isar, ID_AA64MMFR3, TCRX, 1); /* FEAT_TCR2 */
> FIELD_DP64_IDREG(isar, ID_AA64MMFR3, SCTLRX, 1); /* FEAT_SCTLR2 */
> FIELD_DP64_IDREG(isar, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
It would be better to use GET_IDREG / FIELD_DP64 / SET_IDREG, as we do for MMFR2 above.
That would begin with the previous patch.
r~
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v4 5/6] target/arm: Implement FEAT_MEC cache instructions
2025-07-09 18:03 [PATCH-for-10.1 v4 0/6] target/arm: Add FEAT_MEC to max cpu Gustavo Romero
` (3 preceding siblings ...)
2025-07-09 18:03 ` [PATCH v4 4/6] target/arm: Add FEAT_TCR2 Gustavo Romero
@ 2025-07-09 18:03 ` Gustavo Romero
2025-07-09 20:52 ` Richard Henderson
2025-07-09 18:03 ` [PATCH v4 6/6] target/arm: Advertise FEAT_MEC in cpu max Gustavo Romero
5 siblings, 1 reply; 14+ messages in thread
From: Gustavo Romero @ 2025-07-09 18:03 UTC (permalink / raw)
To: qemu-arm, richard.henderson, alex.bennee; +Cc: qemu-devel, gustavo.romero
This commit implements the two cache maintenance instructions introduced
by FEAT_MEC, DC CIPAE and DC CIGDPAE.
Because QEMU does not model the cache topology, all cache maintenance
instructions are implemented as NOPs, hence these new instructions are
implemented as NOPs too.
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
---
target/arm/helper.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 34e12bde90..36cf2b6415 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4996,6 +4996,34 @@ static void ic_ivau_write(CPUARMState *env, const ARMCPRegInfo *ri,
}
#endif
+static CPAccessResult cipae_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ int el = arm_current_el(env);
+
+ if (!cpu_isar_feature(aa64_mec, env_archcpu(env))) {
+ return CP_ACCESS_UNDEFINED;
+ }
+ if (el < 3 && arm_security_space(env) != ARMSS_Realm) {
+ return CP_ACCESS_UNDEFINED;
+ }
+ return CP_ACCESS_OK;
+}
+
+static CPAccessResult cigdpae_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ CPAccessResult ret = cipae_access(env, ri, isread);
+
+ if (ret != CP_ACCESS_OK) {
+ return ret;
+ }
+ if (!cpu_isar_feature(aa64_mte, env_archcpu(env))) {
+ return CP_ACCESS_UNDEFINED;
+ }
+ return CP_ACCESS_OK;
+}
+
static const ARMCPRegInfo v8_cp_reginfo[] = {
/*
* Minimal set of EL0-visible registers. This will need to be expanded
@@ -5094,6 +5122,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
.fgt = FGT_DCCISW,
.access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
+ { .name = "DC_CIPAE", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 0,
+ .access = PL2_W, .accessfn = cipae_access, .type = ARM_CP_NOP },
+ { .name = "DC_CIGDPAE", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 7,
+ .access = PL2_W, .accessfn = cigdpae_access, .type = ARM_CP_NOP },
#ifndef CONFIG_USER_ONLY
/* 64 bit address translation operations */
{ .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64,
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v4 5/6] target/arm: Implement FEAT_MEC cache instructions
2025-07-09 18:03 ` [PATCH v4 5/6] target/arm: Implement FEAT_MEC cache instructions Gustavo Romero
@ 2025-07-09 20:52 ` Richard Henderson
0 siblings, 0 replies; 14+ messages in thread
From: Richard Henderson @ 2025-07-09 20:52 UTC (permalink / raw)
To: Gustavo Romero, qemu-arm, alex.bennee; +Cc: qemu-devel
On 7/9/25 12:03, Gustavo Romero wrote:
> This commit implements the two cache maintenance instructions introduced
> by FEAT_MEC, DC CIPAE and DC CIGDPAE.
>
> Because QEMU does not model the cache topology, all cache maintenance
> instructions are implemented as NOPs, hence these new instructions are
> implemented as NOPs too.
>
> Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
> ---
> target/arm/helper.c | 34 ++++++++++++++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 34e12bde90..36cf2b6415 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -4996,6 +4996,34 @@ static void ic_ivau_write(CPUARMState *env, const ARMCPRegInfo *ri,
> }
> #endif
>
> +static CPAccessResult cipae_access(CPUARMState *env, const ARMCPRegInfo *ri,
> + bool isread)
> +{
> + int el = arm_current_el(env);
> +
> + if (!cpu_isar_feature(aa64_mec, env_archcpu(env))) {
> + return CP_ACCESS_UNDEFINED;
> + }
Not required, because the cpreg should not be registered in this case.
> + if (el < 3 && arm_security_space(env) != ARMSS_Realm) {
> + return CP_ACCESS_UNDEFINED;
> + }
Correct, but we can simplify this to
switch (arm_security_space(env)) {
case ARMSS_Root: /* EL3 */
case ARMSS_Realm: /* Realm EL2 */
return CP_ACCESS_OK;
default:
return CP_ACCESS_UNDEFINED;
}
> +static CPAccessResult cigdpae_access(CPUARMState *env, const ARMCPRegInfo *ri,
> + bool isread)
> +{
> + CPAccessResult ret = cipae_access(env, ri, isread);
> +
> + if (ret != CP_ACCESS_OK) {
> + return ret;
> + }
> + if (!cpu_isar_feature(aa64_mte, env_archcpu(env))) {
> + return CP_ACCESS_UNDEFINED;
> + }
Likewise not required. Therefore the two cpregs can share the same accessfn.
> @@ -5094,6 +5122,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
> .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
> .fgt = FGT_DCCISW,
> .access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
> + { .name = "DC_CIPAE", .state = ARM_CP_STATE_AA64,
> + .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 0,
> + .access = PL2_W, .accessfn = cipae_access, .type = ARM_CP_NOP },
> + { .name = "DC_CIGDPAE", .state = ARM_CP_STATE_AA64,
> + .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 7,
> + .access = PL2_W, .accessfn = cigdpae_access, .type = ARM_CP_NOP },
You should insert the first into the same mec_reginfo[] structure that you introduced in
patch 1. The second must be in a separate array, like so:
if (cpu_isar_feature(aa64_mec, cpu)) {
define_arm_cp_regs(cpu, mec_reginfo);
if (cpu_isar_feature(aa64_mte, cpu)) {
define_arm_cp_regs(cpu, mec_mte_reginfo);
}
}
r~
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v4 6/6] target/arm: Advertise FEAT_MEC in cpu max
2025-07-09 18:03 [PATCH-for-10.1 v4 0/6] target/arm: Add FEAT_MEC to max cpu Gustavo Romero
` (4 preceding siblings ...)
2025-07-09 18:03 ` [PATCH v4 5/6] target/arm: Implement FEAT_MEC cache instructions Gustavo Romero
@ 2025-07-09 18:03 ` Gustavo Romero
2025-07-09 20:54 ` Richard Henderson
5 siblings, 1 reply; 14+ messages in thread
From: Gustavo Romero @ 2025-07-09 18:03 UTC (permalink / raw)
To: qemu-arm, richard.henderson, alex.bennee; +Cc: qemu-devel, gustavo.romero
Advertise FEAT_MEC in AA64MMFR3 ID register for the Arm64 cpu max as a
first step to fully support FEAT_MEC.
The FEAT_MEC is an extension to FEAT_RME that implements multiple
Memory Encryption Contexts (MEC) so the memory in a realm can be
encrypted and accessing it from the wrong encryption context is not
possible. An encryption context allow the selection of a memory
encryption engine.
At this point, no real memory encryption is supported, but most software
stacks that rely on FEAT_MEC to run should work properly.
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
---
docs/system/arm/emulation.rst | 3 +++
target/arm/tcg/cpu64.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 1c597d8673..d207a9f266 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -89,6 +89,9 @@ the following architecture extensions:
- FEAT_LSE (Large System Extensions)
- FEAT_LSE2 (Large System Extensions v2)
- FEAT_LVA (Large Virtual Address space)
+- FEAT_MEC (Memory Encryption Contexts)
+
+ * This is a register-only implementation without encryption.
- FEAT_MixedEnd (Mixed-endian support)
- FEAT_MixedEndEL0 (Mixed-endian support at EL0)
- FEAT_MOPS (Standardization of memory operations)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 173528175a..2c63940878 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1249,6 +1249,7 @@ void aarch64_max_tcg_initfn(Object *obj)
FIELD_DP64_IDREG(isar, ID_AA64MMFR3, TCRX, 1); /* FEAT_TCR2 */
FIELD_DP64_IDREG(isar, ID_AA64MMFR3, SCTLRX, 1); /* FEAT_SCTLR2 */
+ FIELD_DP64_IDREG(isar, ID_AA64MMFR3, MEC, 1); /* FEAT_MEC */
FIELD_DP64_IDREG(isar, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
t = GET_IDREG(isar, ID_AA64ZFR0);
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v4 6/6] target/arm: Advertise FEAT_MEC in cpu max
2025-07-09 18:03 ` [PATCH v4 6/6] target/arm: Advertise FEAT_MEC in cpu max Gustavo Romero
@ 2025-07-09 20:54 ` Richard Henderson
2025-07-10 16:29 ` Gustavo Romero
0 siblings, 1 reply; 14+ messages in thread
From: Richard Henderson @ 2025-07-09 20:54 UTC (permalink / raw)
To: Gustavo Romero, qemu-arm, alex.bennee; +Cc: qemu-devel
On 7/9/25 12:03, Gustavo Romero wrote:
> At this point, no real memory encryption is supported, but most software
> stacks that rely on FEAT_MEC to run should work properly.
s/most //?
Anyway,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 6/6] target/arm: Advertise FEAT_MEC in cpu max
2025-07-09 20:54 ` Richard Henderson
@ 2025-07-10 16:29 ` Gustavo Romero
0 siblings, 0 replies; 14+ messages in thread
From: Gustavo Romero @ 2025-07-10 16:29 UTC (permalink / raw)
To: Richard Henderson, qemu-arm, alex.bennee; +Cc: qemu-devel
Hi Richard!
On 7/9/25 17:54, Richard Henderson wrote:
> On 7/9/25 12:03, Gustavo Romero wrote:
>> At this point, no real memory encryption is supported, but most software
>> stacks that rely on FEAT_MEC to run should work properly.
>
> s/most //?
>
> Anyway,
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Thanks a lot for the reviews :)
I'm sending v5 addressing your comments.
Cheers
Gustavo
^ permalink raw reply [flat|nested] 14+ messages in thread