qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu
@ 2025-07-14 15:58 Richard Henderson
  2025-07-14 15:58 ` [PATCH v8 1/4] target/arm: Implement FEAT_SCTLR2 and enable with -cpu max Richard Henderson
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Richard Henderson @ 2025-07-14 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, gustavo.romero, pierrick.bouvier

Changes for v8:
  - Re-order SCTLR2 and TCR2 so that they are independent of MEC.
  - Enable the SCTLR2 and TCR2 enable bits.
  - Squash 3 smaller MEC patches together.

This still fails the RME tests, because we still need TF-A rebuilt
with ENABLE_FEAT_SCTLR2 and ENABLE_FEAT_TCR2.  Pierrick, since you
have just done such a build, could you re-test with this series?


r~


Gustavo Romero (4):
  target/arm: Implement FEAT_SCTLR2 and enable with -cpu max
  target/arm: Implement FEAT_TCR2 and enable with -cpu max
  target/arm: Implement FEAT_MEC registers
  target/arm: Enable FEAT_MEC in -cpu max

 target/arm/cpu-features.h     |  15 ++
 target/arm/cpu.h              |  27 ++++
 target/arm/internals.h        |  23 +++
 target/arm/cpu.c              |   9 ++
 target/arm/helper.c           | 259 +++++++++++++++++++++++++++++++++-
 target/arm/tcg/cpu64.c        |   7 +-
 docs/system/arm/emulation.rst |   5 +
 7 files changed, 339 insertions(+), 6 deletions(-)

-- 
2.43.0



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v8 1/4] target/arm: Implement FEAT_SCTLR2 and enable with -cpu max
  2025-07-14 15:58 [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Richard Henderson
@ 2025-07-14 15:58 ` Richard Henderson
  2025-07-14 15:58 ` [PATCH v8 2/4] target/arm: Implement FEAT_TCR2 " Richard Henderson
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2025-07-14 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, gustavo.romero, pierrick.bouvier

From: Gustavo Romero <gustavo.romero@linaro.org>

Add FEAT_SCTLR2, which introduces the SCTLR2_EL1, SCTLR2_EL2, and
SCTLR2_EL3 registers. These registers are extensions of the SCTLR_ELx
ones.

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20250711140828.1714666-4-gustavo.romero@linaro.org>
[rth: Remove FEAT_MEC code; handle SCR and HCRX enable bits.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu-features.h     |  5 ++
 target/arm/cpu.h              | 15 ++++++
 target/arm/internals.h        |  1 +
 target/arm/cpu.c              |  3 ++
 target/arm/helper.c           | 88 +++++++++++++++++++++++++++++++++--
 target/arm/tcg/cpu64.c        |  5 +-
 docs/system/arm/emulation.rst |  1 +
 7 files changed, 112 insertions(+), 6 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 5876162428..e372543bf3 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -904,6 +904,11 @@ static inline bool isar_feature_aa64_nv2(const ARMISARegisters *id)
     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, NV) >= 2;
 }
 
+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_pmuv3p1(const ARMISARegisters *id)
 {
     return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 4 &&
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index dc9b6dce4c..dda5f275fb 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 */
@@ -1420,6 +1421,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)
@@ -1712,6 +1726,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_NSE               (1ULL << 62)
 
diff --git a/target/arm/internals.h b/target/arm/internals.h
index c4765e4489..fcaad39371 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/cpu.c b/target/arm/cpu.c
index 08c43f674a..2ee895fbc4 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -645,6 +645,9 @@ void arm_emulate_firmware_reset(CPUState *cpustate, int target_el)
             if (cpu_isar_feature(aa64_fgt, cpu)) {
                 env->cp15.scr_el3 |= SCR_FGTEN;
             }
+            if (cpu_isar_feature(aa64_sctlr2, cpu)) {
+                env->cp15.scr_el3 |= SCR_SCTLR2EN;
+            }
         }
 
         if (target_el == 2) {
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0c1299ff84..d0cfef1dd6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -741,6 +741,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
         if (cpu_isar_feature(aa64_ecv, cpu)) {
             valid_mask |= SCR_ECVEN;
         }
+        if (cpu_isar_feature(aa64_sctlr2, cpu)) {
+            valid_mask |= SCR_SCTLR2EN;
+        }
     } else {
         valid_mask &= ~(SCR_RW | SCR_ST);
         if (cpu_isar_feature(aa32_ras, cpu)) {
@@ -3907,23 +3910,21 @@ static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
     ARMCPU *cpu = env_archcpu(env);
     uint64_t valid_mask = 0;
 
-    /* FEAT_MOPS adds MSCEn and MCE2 */
     if (cpu_isar_feature(aa64_mops, cpu)) {
         valid_mask |= HCRX_MSCEN | HCRX_MCE2;
     }
-
-    /* FEAT_NMI adds TALLINT, VINMI and VFNMI */
     if (cpu_isar_feature(aa64_nmi, cpu)) {
         valid_mask |= HCRX_TALLINT | HCRX_VINMI | HCRX_VFNMI;
     }
-    /* FEAT_CMOW adds CMOW */
     if (cpu_isar_feature(aa64_cmow, cpu)) {
         valid_mask |= HCRX_CMOW;
     }
-    /* FEAT_XS adds FGTnXS, FnXS */
     if (cpu_isar_feature(aa64_xs, cpu)) {
         valid_mask |= HCRX_FGTNXS | HCRX_FNXS;
     }
+    if (cpu_isar_feature(aa64_sctlr2, cpu)) {
+        valid_mask |= HCRX_SCTLR2EN;
+    }
 
     /* Clear RES0 bits.  */
     env->cp15.hcrx_el2 = value & valid_mask;
@@ -4513,6 +4514,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", isar_feature_aa64_sctlr2 },
         { 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),
@@ -5994,6 +5997,77 @@ 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
+        && arm_feature(env, ARM_FEATURE_EL3)
+        && !(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)
+{
+    uint64_t valid_mask = 0;
+
+    value &= valid_mask;
+    raw_write(env, ri, value);
+}
+
+static void sctlr2_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                             uint64_t value)
+{
+    uint64_t valid_mask = 0;
+
+    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;
+
+    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 */
@@ -7223,6 +7297,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         define_arm_cp_regs(cpu, nmi_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/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 35cddbafa4..f4efff03a5 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1247,7 +1247,10 @@ 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, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
+    t = GET_IDREG(isar, ID_AA64MMFR3);
+    t = FIELD_DP64(t, ID_AA64MMFR3, SCTLRX, 1);     /* FEAT_SCTLR2 */
+    t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
+    SET_IDREG(isar, ID_AA64MMFR3, t);
 
     t = GET_IDREG(isar, ID_AA64ZFR0);
     t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 2);    /* FEAT_SVE2p1 */
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)
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v8 2/4] target/arm: Implement FEAT_TCR2 and enable with -cpu max
  2025-07-14 15:58 [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Richard Henderson
  2025-07-14 15:58 ` [PATCH v8 1/4] target/arm: Implement FEAT_SCTLR2 and enable with -cpu max Richard Henderson
@ 2025-07-14 15:58 ` Richard Henderson
  2025-07-14 15:58 ` [PATCH v8 3/4] target/arm: Implement FEAT_MEC registers Richard Henderson
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2025-07-14 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, gustavo.romero, pierrick.bouvier

From: Gustavo Romero <gustavo.romero@linaro.org>

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.

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
Message-ID: <20250711140828.1714666-5-gustavo.romero@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
[rth: Remove FEAT_MEC code; handle SCR and HCRX enable bits.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu-features.h     |  5 +++
 target/arm/cpu.h              |  2 ++
 target/arm/internals.h        | 19 ++++++++++
 target/arm/cpu.c              |  3 ++
 target/arm/helper.c           | 68 +++++++++++++++++++++++++++++++++++
 target/arm/tcg/cpu64.c        |  1 +
 docs/system/arm/emulation.rst |  1 +
 7 files changed, 99 insertions(+)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index e372543bf3..8ec8c3feb3 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -904,6 +904,11 @@ static inline bool isar_feature_aa64_nv2(const ARMISARegisters *id)
     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, NV) >= 2;
 }
 
+static inline bool isar_feature_aa64_tcr2(const ARMISARegisters *id)
+{
+    return FIELD_EX64_IDREG(id, ID_AA64MMFR3, TCRX) != 0;
+}
+
 static inline bool isar_feature_aa64_sctlr2(const ARMISARegisters *id)
 {
     return FIELD_EX64_IDREG(id, ID_AA64MMFR3, SCTLRX) != 0;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index dda5f275fb..0e247f50c7 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.  */
@@ -1726,6 +1727,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_NSE               (1ULL << 62)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index fcaad39371..b4cd03df69 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/cpu.c b/target/arm/cpu.c
index 2ee895fbc4..e709ca74da 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -645,6 +645,9 @@ void arm_emulate_firmware_reset(CPUState *cpustate, int target_el)
             if (cpu_isar_feature(aa64_fgt, cpu)) {
                 env->cp15.scr_el3 |= SCR_FGTEN;
             }
+            if (cpu_isar_feature(aa64_tcr2, cpu)) {
+               env->cp15.scr_el3 |= SCR_TCR2EN;
+            }
             if (cpu_isar_feature(aa64_sctlr2, cpu)) {
                 env->cp15.scr_el3 |= SCR_SCTLR2EN;
             }
diff --git a/target/arm/helper.c b/target/arm/helper.c
index d0cfef1dd6..1e0e747146 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -741,6 +741,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
         if (cpu_isar_feature(aa64_ecv, cpu)) {
             valid_mask |= SCR_ECVEN;
         }
+        if (cpu_isar_feature(aa64_tcr2, cpu)) {
+            valid_mask |= SCR_TCR2EN;
+        }
         if (cpu_isar_feature(aa64_sctlr2, cpu)) {
             valid_mask |= SCR_SCTLR2EN;
         }
@@ -3922,6 +3925,9 @@ static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
     if (cpu_isar_feature(aa64_xs, cpu)) {
         valid_mask |= HCRX_FGTNXS | HCRX_FNXS;
     }
+    if (cpu_isar_feature(aa64_tcr2, cpu)) {
+        valid_mask |= HCRX_TCR2EN;
+    }
     if (cpu_isar_feature(aa64_sctlr2, cpu)) {
         valid_mask |= HCRX_SCTLR2EN;
     }
@@ -4524,6 +4530,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", isar_feature_aa64_tcr2 },
         { 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),
@@ -6068,6 +6076,62 @@ 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
+        && arm_feature(env, ARM_FEATURE_EL3)
+        && !(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)
+{
+    uint64_t valid_mask = 0;
+
+    value &= valid_mask;
+    raw_write(env, ri, value);
+}
+
+static void tcr2_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                           uint64_t value)
+{
+    uint64_t valid_mask = 0;
+
+    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 */
@@ -7301,6 +7365,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/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index f4efff03a5..4eb51420ef 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1248,6 +1248,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     SET_IDREG(isar, ID_AA64MMFR2, t);
 
     t = GET_IDREG(isar, ID_AA64MMFR3);
+    t = FIELD_DP64(t, ID_AA64MMFR3, TCRX, 1);       /* FEAT_TCR2 */
     t = FIELD_DP64(t, ID_AA64MMFR3, SCTLRX, 1);     /* FEAT_SCTLR2 */
     t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
     SET_IDREG(isar, ID_AA64MMFR3, t);
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)
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v8 3/4] target/arm: Implement FEAT_MEC registers
  2025-07-14 15:58 [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Richard Henderson
  2025-07-14 15:58 ` [PATCH v8 1/4] target/arm: Implement FEAT_SCTLR2 and enable with -cpu max Richard Henderson
  2025-07-14 15:58 ` [PATCH v8 2/4] target/arm: Implement FEAT_TCR2 " Richard Henderson
@ 2025-07-14 15:58 ` Richard Henderson
  2025-07-14 15:58 ` [PATCH v8 4/4] target/arm: Enable FEAT_MEC in -cpu max Richard Henderson
  2025-07-14 17:09 ` [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Pierrick Bouvier
  4 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2025-07-14 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, gustavo.romero, pierrick.bouvier

From: Gustavo Romero <gustavo.romero@linaro.org>

Add all FEAT_MEC registers.  Enable access to the registers via the
SCTLR2 and TCR2 control bits.  Add the two new cache management
instructions, which are nops in QEMU because we do not model caches.

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
Message-ID: <20250711140828.1714666-3-gustavo.romero@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
[rth: Squash 3 patches to add all registers at once.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu-features.h |   5 ++
 target/arm/cpu.h          |  10 ++++
 target/arm/internals.h    |   3 ++
 target/arm/cpu.c          |   3 ++
 target/arm/helper.c       | 103 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 124 insertions(+)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 8ec8c3feb3..9579d93cec 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -914,6 +914,11 @@ 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_mec(const ARMISARegisters *id)
+{
+    return FIELD_EX64_IDREG(id, ID_AA64MMFR3, MEC) != 0;
+}
+
 static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id)
 {
     return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 4 &&
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0e247f50c7..5156120b50 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -578,6 +578,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 {
@@ -1730,6 +1739,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
 #define SCR_TCR2EN            (1ULL << 43)
 #define SCR_SCTLR2EN          (1ULL << 44)
 #define SCR_GPF               (1ULL << 48)
+#define SCR_MECEN             (1ULL << 49)
 #define SCR_NSE               (1ULL << 62)
 
 /* Return the current FPSCR value.  */
diff --git a/target/arm/internals.h b/target/arm/internals.h
index b4cd03df69..6c1112e641 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -2007,4 +2007,7 @@ void vfp_clear_float_status_exc_flags(CPUARMState *env);
 void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask);
 bool arm_pan_enabled(CPUARMState *env);
 
+/* Used in FEAT_MEC to set the MECIDWidthm1 field in the MECIDR_EL2 register. */
+#define MECID_WIDTH 16
+
 #endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index e709ca74da..34638ea100 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -651,6 +651,9 @@ void arm_emulate_firmware_reset(CPUState *cpustate, int target_el)
             if (cpu_isar_feature(aa64_sctlr2, cpu)) {
                 env->cp15.scr_el3 |= SCR_SCTLR2EN;
             }
+            if (cpu_isar_feature(aa64_mec, cpu)) {
+                env->cp15.scr_el3 |= SCR_MECEN;
+            }
         }
 
         if (target_el == 2) {
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 1e0e747146..dd7beba079 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5207,6 +5207,93 @@ 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 CPAccessResult cipae_access(CPUARMState *env, const ARMCPRegInfo *ri,
+                                   bool isread)
+{
+    switch (arm_security_space(env)) {
+    case ARMSS_Root:  /* EL3 */
+    case ARMSS_Realm: /* Realm EL2 */
+        return CP_ACCESS_OK;
+    default:
+        return CP_ACCESS_UNDEFINED;
+    }
+}
+
+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) },
+    { .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 },
+};
+
+static const ARMCPRegInfo mec_mte_reginfo[] = {
+    { .name = "DC_CIGDPAE", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 7,
+      .access = PL2_W, .accessfn = cipae_access, .type = ARM_CP_NOP },
+};
+
 #ifndef CONFIG_USER_ONLY
 /*
  * We don't know until after realize whether there's a GICv3
@@ -6045,6 +6132,9 @@ static void sctlr2_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     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);
 }
@@ -6054,6 +6144,9 @@ static void sctlr2_el3_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     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);
 }
@@ -6114,6 +6207,9 @@ static void tcr2_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     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);
 }
@@ -7369,6 +7465,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         define_arm_cp_regs(cpu, tcr2_reginfo);
     }
 
+    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);
+        }
+    }
+
     if (cpu_isar_feature(any_predinv, cpu)) {
         define_arm_cp_regs(cpu, predinv_reginfo);
     }
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v8 4/4] target/arm: Enable FEAT_MEC in -cpu max
  2025-07-14 15:58 [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Richard Henderson
                   ` (2 preceding siblings ...)
  2025-07-14 15:58 ` [PATCH v8 3/4] target/arm: Implement FEAT_MEC registers Richard Henderson
@ 2025-07-14 15:58 ` Richard Henderson
  2025-07-14 17:09 ` [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Pierrick Bouvier
  4 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2025-07-14 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, gustavo.romero, pierrick.bouvier

From: Gustavo Romero <gustavo.romero@linaro.org>

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 software
stacks that rely on FEAT_MEC should work properly.

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20250711140828.1714666-7-gustavo.romero@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/tcg/cpu64.c        | 1 +
 docs/system/arm/emulation.rst | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 4eb51420ef..c54aa528c6 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1250,6 +1250,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = GET_IDREG(isar, ID_AA64MMFR3);
     t = FIELD_DP64(t, ID_AA64MMFR3, TCRX, 1);       /* FEAT_TCR2 */
     t = FIELD_DP64(t, ID_AA64MMFR3, SCTLRX, 1);     /* FEAT_SCTLR2 */
+    t = FIELD_DP64(t, ID_AA64MMFR3, MEC, 1);        /* FEAT_MEC */
     t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
     SET_IDREG(isar, ID_AA64MMFR3, t);
 
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)
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu
  2025-07-14 15:58 [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Richard Henderson
                   ` (3 preceding siblings ...)
  2025-07-14 15:58 ` [PATCH v8 4/4] target/arm: Enable FEAT_MEC in -cpu max Richard Henderson
@ 2025-07-14 17:09 ` Pierrick Bouvier
  2025-07-14 23:31   ` Gustavo Romero
  2025-07-15 21:29   ` Pierrick Bouvier
  4 siblings, 2 replies; 12+ messages in thread
From: Pierrick Bouvier @ 2025-07-14 17:09 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: qemu-arm, gustavo.romero

On 7/14/25 8:58 AM, Richard Henderson wrote:
> Changes for v8:
>    - Re-order SCTLR2 and TCR2 so that they are independent of MEC.
>    - Enable the SCTLR2 and TCR2 enable bits.
>    - Squash 3 smaller MEC patches together.
> 
> This still fails the RME tests, because we still need TF-A rebuilt
> with ENABLE_FEAT_SCTLR2 and ENABLE_FEAT_TCR2.  Pierrick, since you
> have just done such a build, could you re-test with this series?
>

I tested that on my local Realm enabled setup and I can confirm this 
solved the issue and current series works.
Both flags are needed in TF-A. ENABLE_FEAT_TCR2 is needed to boot host, 
and ENABLE_FEAT_SCTLR2 is needed to boot nested guest.

As I'm off today, I'll update that properly tomorrow when I have time, 
and not rush things. I'll update RME images for sbsa and virt tests + 
device passthrough test, and post associated patches.

Thanks,
Pierrick


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu
  2025-07-14 17:09 ` [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Pierrick Bouvier
@ 2025-07-14 23:31   ` Gustavo Romero
  2025-07-15  1:26     ` Pierrick Bouvier
  2025-07-15 21:29   ` Pierrick Bouvier
  1 sibling, 1 reply; 12+ messages in thread
From: Gustavo Romero @ 2025-07-14 23:31 UTC (permalink / raw)
  To: Pierrick Bouvier, Richard Henderson, qemu-devel; +Cc: qemu-arm

Hi folks,

Richard, thanks for v8. Pierrick, thanks for testing it. :)

On 7/14/25 14:09, Pierrick Bouvier wrote:
> On 7/14/25 8:58 AM, Richard Henderson wrote:
>> Changes for v8:
>>    - Re-order SCTLR2 and TCR2 so that they are independent of MEC.
>>    - Enable the SCTLR2 and TCR2 enable bits.
>>    - Squash 3 smaller MEC patches together.
>>
>> This still fails the RME tests, because we still need TF-A rebuilt
>> with ENABLE_FEAT_SCTLR2 and ENABLE_FEAT_TCR2.  Pierrick, since you
>> have just done such a build, could you re-test with this series?
>>
> 
> I tested that on my local Realm enabled setup and I can confirm this solved the issue and current series works.
> Both flags are needed in TF-A. ENABLE_FEAT_TCR2 is needed to boot host, and ENABLE_FEAT_SCTLR2 is needed to boot nested guest.

I'm a bit confused because the QEMU RME tests, afaics, uses OP-TEE, not TF-A. I've built TF-A
using the scripts in [0], enabling ENABLE_FEAT_TCR2 and ENABLE_FEAT_SCTLR2, but no way to get
it booting. I understand we can embed a OP-TEE into the TF_A via BL32=<optee_image> when
building TF-A. Is that what you're using?

Thanks.


Cheers,
Gustavo

[0] https://github.com/pbo-linaro/qemu-linux-stack.git

> As I'm off today, I'll update that properly tomorrow when I have time, and not rush things. I'll update RME images for sbsa and virt tests + device passthrough test, and post associated patches.
> 
> Thanks,
> Pierrick



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu
  2025-07-14 23:31   ` Gustavo Romero
@ 2025-07-15  1:26     ` Pierrick Bouvier
  2025-07-16  3:13       ` Gustavo Romero
  0 siblings, 1 reply; 12+ messages in thread
From: Pierrick Bouvier @ 2025-07-15  1:26 UTC (permalink / raw)
  To: Gustavo Romero, Richard Henderson, qemu-devel; +Cc: qemu-arm

On 7/14/25 4:31 PM, Gustavo Romero wrote:
> Hi folks,
> 
> Richard, thanks for v8. Pierrick, thanks for testing it. :)
> 
> On 7/14/25 14:09, Pierrick Bouvier wrote:
>> On 7/14/25 8:58 AM, Richard Henderson wrote:
>>> Changes for v8:
>>>     - Re-order SCTLR2 and TCR2 so that they are independent of MEC.
>>>     - Enable the SCTLR2 and TCR2 enable bits.
>>>     - Squash 3 smaller MEC patches together.
>>>
>>> This still fails the RME tests, because we still need TF-A rebuilt
>>> with ENABLE_FEAT_SCTLR2 and ENABLE_FEAT_TCR2.  Pierrick, since you
>>> have just done such a build, could you re-test with this series?
>>>
>>
>> I tested that on my local Realm enabled setup and I can confirm this solved the issue and current series works.
>> Both flags are needed in TF-A. ENABLE_FEAT_TCR2 is needed to boot host, and ENABLE_FEAT_SCTLR2 is needed to boot nested guest.
> 
> I'm a bit confused because the QEMU RME tests, afaics, uses OP-TEE, not TF-A. I've built TF-A
> using the scripts in [0], enabling ENABLE_FEAT_TCR2 and ENABLE_FEAT_SCTLR2, but no way to get
> it booting. I understand we can embed a OP-TEE into the TF_A via BL32=<optee_image> when
> building TF-A. Is that what you're using?
> 

I agree it's confusing. In short, no, OP-TEE is not used anywhere for 
Realms, only TF-A and RMM are used in our images. It seems that OP-TEE 
is a term used generically to represent any firmware running in secure 
mode, but it's a *totally* different software than TF-A + RMM. Naming 
OP-TEE like this is like if Linux would have been named "OP-kernel".

The RME tests we have are based on this excellent tutorial [0], and 
build is automated with 'qemu-rme-stack' [1], that simply follows those 
instructions.

[0] 
https://linaro.atlassian.net/wiki/spaces/QEMU/pages/30128767027/Device+Assignment+Enabled+RME+Stack+on+QEMU
[1] https://github.com/pbo-linaro/qemu-rme-stack

To add to the confusion (*get ready*), [0] uses OP-TEE build, which is 
simply a build system for op-tee + other things, but in the variant it 
generates, OP-TEE itself is not included. Yes, that's utterly confusing 
and took me quite some time to discover it, after talking with Mathieu 
himself. They removed it explicitely to make the stack more simple. In 
short, for Realms, forget about OP-TEE.

If you want to see it by yourself:

https://git.codelinaro.org/linaro/dcap/op-tee-4.2.0/build/-/blob/cca/v8/qemu_v8_cca.mk?ref_type=heads#L172

...
TF_A_FLAGS ?= \
	BL33=$(BL33_BIN) \
	PLAT=qemu \
	QEMU_USE_GIC_DRIVER=$(TFA_GIC_DRIVER) \
	DEBUG=$(TF_A_DEBUG) \
	LOG_LEVEL=$(TF_A_LOGLVL) \
	ENABLE_RME=1 \
	RMM=$(RMM_BIN)
...
TF_A_FLAGS_BL32_OPTEE  = BL32=$(OPTEE_OS_HEADER_V2_BIN)
TF_A_FLAGS_BL32_OPTEE += BL32_EXTRA1=$(OPTEE_OS_PAGER_V2_BIN)
TF_A_FLAGS_BL32_OPTEE += BL32_EXTRA2=$(OPTEE_OS_PAGEABLE_V2_BIN)
TF_A_FLAGS_SPMC_AT_EL_n  = $(TF_A_FLAGS_BL32_OPTEE) SPD=opteed
...
#TF_A_FLAGS += $(TF_A_FLAGS_SPMC_AT_EL_$(SPMC_AT_EL))

The last line shows that OP_TEE flags are **NOT** added to TF_A_FLAGS 
build flags.
The qemu_v8_cca.mk build file was copied from qemu_v8.mk, which itself 
has the OP-TEE inclusion.

---

Recently, I had to generate a custom rootfs, and I experimented 
generating it directly from docker images, to avoid rebuilding the world 
using Buildroot. Once it worked, I realized it was a good opportunity to 
rebuild the rest of the stack too. The result is 'qemu-linux-stack' [2].

Master branch has only tf-a + uboot (no Realm support), while rme branch 
[3], which supports Realm, uses tf-a + rmm + edk2 instead. I removed 
u-boot as I couldn't get it to boot, and I knew that edk2 worked.

One branch is only one configuration (and it will stay this way).

[2] https://github.com/pbo-linaro/qemu-linux-stack
[3] https://github.com/pbo-linaro/qemu-linux-stack/tree/rme

Beyond the personal knowledge I got through that, I hope it can be used 
for others for who it's confusing about what runs before start_kernel, 
and I guess I'm not the only one who didn't know about that. In the end, 
things are not too complicated, but as most of the build systems out 
there (OP-TEE build, shrinkwrap, ...) try to be "generic and versatile", 
it ends up being complicated. I prefer basic and straightforward script 
shells to lenghty documentation and wiki pages, but it's a personal choice.

---

Now, coming to the change introduced by this series, and supporting 
FEAT_SCTRL2 and FEAT_TCR2, all those images need to be updated [0], [1], 
[2], [3], because essentially, TF-A itself must be patched to support 
this. I was about to mention that, and mention that I can send a PR 
directly to it once we have this merged on QEMU side.

The change in arm-trusted-firmware is quite simple:

+diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
+index 751511cf8..6bc108492 100644
+--- a/plat/qemu/common/common.mk
++++ b/plat/qemu/common/common.mk
+@@ -122,6 +122,10 @@ ENABLE_FEAT_FGT         :=      2
+ # 8.7
+ ENABLE_FEAT_HCX             :=      2
+
++# 8.8
++ENABLE_FEAT_TCR2    :=      2
++ENABLE_FEAT_SCTLR2  :=      2
++

I'll push all that tomorrow on master, and rebase rmm and 
device_passthrough on top of it.
I'll add this to original RME images, it's less direct though, as it's 
needed to update the tf-a fork, and then the optee build system.

Sorry for this very long email. At least, all is there.

> Thanks.
> 
> 
> Cheers,
> Gustavo
> 
> [0] https://github.com/pbo-linaro/qemu-linux-stack.git
> 
>> As I'm off today, I'll update that properly tomorrow when I have time, and not rush things. I'll update RME images for sbsa and virt tests + device passthrough test, and post associated patches.
>>
>> Thanks,
>> Pierrick
> 



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu
  2025-07-14 17:09 ` [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Pierrick Bouvier
  2025-07-14 23:31   ` Gustavo Romero
@ 2025-07-15 21:29   ` Pierrick Bouvier
  1 sibling, 0 replies; 12+ messages in thread
From: Pierrick Bouvier @ 2025-07-15 21:29 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: qemu-arm, gustavo.romero

On 7/14/25 10:09 AM, Pierrick Bouvier wrote:
> On 7/14/25 8:58 AM, Richard Henderson wrote:
>> Changes for v8:
>>     - Re-order SCTLR2 and TCR2 so that they are independent of MEC.
>>     - Enable the SCTLR2 and TCR2 enable bits.
>>     - Squash 3 smaller MEC patches together.
>>
>> This still fails the RME tests, because we still need TF-A rebuilt
>> with ENABLE_FEAT_SCTLR2 and ENABLE_FEAT_TCR2.  Pierrick, since you
>> have just done such a build, could you re-test with this series?
>>
> 
> I tested that on my local Realm enabled setup and I can confirm this
> solved the issue and current series works.
> Both flags are needed in TF-A. ENABLE_FEAT_TCR2 is needed to boot host,
> and ENABLE_FEAT_SCTLR2 is needed to boot nested guest.
> 
> As I'm off today, I'll update that properly tomorrow when I have time,
> and not rush things. I'll update RME images for sbsa and virt tests +
> device passthrough test, and post associated patches.
>

Richard, patches updating tests images have been sent [1].
I tested them with and without current series.

You're welcome to merge that in current series (preferably before the 
current series, to not break bisection for concerned tests).

[1] 
https://lore.kernel.org/qemu-devel/20250715212335.2215509-1-pierrick.bouvier@linaro.org/T/#t

Regards,
Pierrick


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu
  2025-07-15  1:26     ` Pierrick Bouvier
@ 2025-07-16  3:13       ` Gustavo Romero
  2025-07-16  5:56         ` Pierrick Bouvier
  0 siblings, 1 reply; 12+ messages in thread
From: Gustavo Romero @ 2025-07-16  3:13 UTC (permalink / raw)
  To: Pierrick Bouvier, Richard Henderson, qemu-devel; +Cc: qemu-arm

Hi Pierrick,

On 7/14/25 22:26, Pierrick Bouvier wrote:
> On 7/14/25 4:31 PM, Gustavo Romero wrote:
>> Hi folks,
>>
>> Richard, thanks for v8. Pierrick, thanks for testing it. :)
>>
>> On 7/14/25 14:09, Pierrick Bouvier wrote:
>>> On 7/14/25 8:58 AM, Richard Henderson wrote:
>>>> Changes for v8:
>>>>     - Re-order SCTLR2 and TCR2 so that they are independent of MEC.
>>>>     - Enable the SCTLR2 and TCR2 enable bits.
>>>>     - Squash 3 smaller MEC patches together.
>>>>
>>>> This still fails the RME tests, because we still need TF-A rebuilt
>>>> with ENABLE_FEAT_SCTLR2 and ENABLE_FEAT_TCR2.  Pierrick, since you
>>>> have just done such a build, could you re-test with this series?
>>>>
>>>
>>> I tested that on my local Realm enabled setup and I can confirm this solved the issue and current series works.
>>> Both flags are needed in TF-A. ENABLE_FEAT_TCR2 is needed to boot host, and ENABLE_FEAT_SCTLR2 is needed to boot nested guest.
>>
>> I'm a bit confused because the QEMU RME tests, afaics, uses OP-TEE, not TF-A. I've built TF-A
>> using the scripts in [0], enabling ENABLE_FEAT_TCR2 and ENABLE_FEAT_SCTLR2, but no way to get
>> it booting. I understand we can embed a OP-TEE into the TF_A via BL32=<optee_image> when
>> building TF-A. Is that what you're using?
>>
> 
> I agree it's confusing. In short, no, OP-TEE is not used anywhere for Realms, only TF-A and RMM are used in our images. It seems that OP-TEE is a term used generically to represent any firmware running in secure mode, but it's a *totally* different software than TF-A + RMM. Naming OP-TEE like this is like if Linux would have been named "OP-kernel".

Got it, so we use TF-A + RMM in the test images. Thanks for the clarifications.

Isn't the generic term (or concept) actually TEE (not OP-TEE) and OP-TEE is a real software stack that implements the TEE spec, i.e., OP-TEE is code in https://github.com/OP-TEE)?


> The RME tests we have are based on this excellent tutorial [0], and build is automated with 'qemu-rme-stack' [1], that simply follows those instructions.
> 
> [0] https://linaro.atlassian.net/wiki/spaces/QEMU/pages/30128767027/Device+Assignment+Enabled+RME+Stack+on+QEMU

Should [0] be:

https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/Building+an+RME+stack+for+QEMU ?


> [1] https://github.com/pbo-linaro/qemu-rme-stack
> 
> To add to the confusion (*get ready*), [0] uses OP-TEE build, which is simply a build system for op-tee + other things, but in the variant it generates, OP-TEE itself is not included. Yes, that's utterly confusing and took me quite some time to discover it, after talking with Mathieu himself. They removed it explicitely to make the stack more simple. In short, for Realms, forget about OP-TEE.

ah, that's what confused me! I see now.


> If you want to see it by yourself:
> 
> https://git.codelinaro.org/linaro/dcap/op-tee-4.2.0/build/-/blob/cca/v8/qemu_v8_cca.mk?ref_type=heads#L172
> 
> ...
> TF_A_FLAGS ?= \
>      BL33=$(BL33_BIN) \
>      PLAT=qemu \
>      QEMU_USE_GIC_DRIVER=$(TFA_GIC_DRIVER) \
>      DEBUG=$(TF_A_DEBUG) \
>      LOG_LEVEL=$(TF_A_LOGLVL) \
>      ENABLE_RME=1 \
>      RMM=$(RMM_BIN)
> ...
> TF_A_FLAGS_BL32_OPTEE  = BL32=$(OPTEE_OS_HEADER_V2_BIN)
> TF_A_FLAGS_BL32_OPTEE += BL32_EXTRA1=$(OPTEE_OS_PAGER_V2_BIN)
> TF_A_FLAGS_BL32_OPTEE += BL32_EXTRA2=$(OPTEE_OS_PAGEABLE_V2_BIN)
> TF_A_FLAGS_SPMC_AT_EL_n  = $(TF_A_FLAGS_BL32_OPTEE) SPD=opteed
> ...
> #TF_A_FLAGS += $(TF_A_FLAGS_SPMC_AT_EL_$(SPMC_AT_EL))
> 
> The last line shows that OP_TEE flags are **NOT** added to TF_A_FLAGS build flags.
> The qemu_v8_cca.mk build file was copied from qemu_v8.mk, which itself has the OP-TEE inclusion.
> 
> ---
> 
> Recently, I had to generate a custom rootfs, and I experimented generating it directly from docker images, to avoid rebuilding the world using Buildroot. Once it worked, I realized it was a good opportunity to rebuild the rest of the stack too. The result is 'qemu-linux-stack' [2].
> 
> Master branch has only tf-a + uboot (no Realm support), while rme branch [3], which supports Realm, uses tf-a + rmm + edk2 instead. I removed u-boot as I couldn't get it to boot, and I knew that edk2 worked.
> 
> One branch is only one configuration (and it will stay this way).
> 
> [2] https://github.com/pbo-linaro/qemu-linux-stack
> [3] https://github.com/pbo-linaro/qemu-linux-stack/tree/rme
> 
> Beyond the personal knowledge I got through that, I hope it can be used for others for who it's confusing about what runs before start_kernel, and I guess I'm not the only one who didn't know about that. In the end, things are not too complicated, but as most of the build systems out there (OP-TEE build, shrinkwrap, ...) try to be "generic and versatile", it ends up being complicated. I prefer basic and straightforward script shells to lenghty documentation and wiki pages, but it's a personal choice.
> 
> ---
> 
> Now, coming to the change introduced by this series, and supporting FEAT_SCTRL2 and FEAT_TCR2, all those images need to be updated [0], [1], [2], [3], because essentially, TF-A itself must be patched to support this. I was about to mention that, and mention that I can send a PR directly to it once we have this merged on QEMU side.
> 
> The change in arm-trusted-firmware is quite simple:
> 
> +diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
> +index 751511cf8..6bc108492 100644
> +--- a/plat/qemu/common/common.mk
> ++++ b/plat/qemu/common/common.mk
> +@@ -122,6 +122,10 @@ ENABLE_FEAT_FGT         :=      2
> + # 8.7
> + ENABLE_FEAT_HCX             :=      2
> +
> ++# 8.8
> ++ENABLE_FEAT_TCR2    :=      2
> ++ENABLE_FEAT_SCTLR2  :=      2
> ++
> 
> I'll push all that tomorrow on master, and rebase rmm and device_passthrough on top of it.
> I'll add this to original RME images, it's less direct though, as it's needed to update the tf-a fork, and then the optee build system.

So, I still fail to understand how you are generating the out/bin/flash.bin used in our images.

First I tried to use the https://github.com/pbo-linaro/qemu-rme-stack, since it's cited in the tests. I tried:

$ ./container.sh ./build_virt.sh

and get an error which seems a commit mismatch in some of branches used by repo:

repo: reusing existing repo client checkout in /mnt/git/qemu-rme-stack
Traceback (most recent call last):
   File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 869, in <module>
     _Main(sys.argv[1:])
   File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 845, in _Main
     result = repo._Run(name, gopts, argv) or 0
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 293, in _Run
     result = run()
              ^^^^^
   File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 274, in <lambda>
     lambda: self._RunLong(name, gopts, argv, git_trace2_event_log) or 0
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 437, in _RunLong
     execute_command()
   File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 403, in execute_command
     execute_command_helper()
   File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 369, in execute_command_helper
     result = cmd.Execute(copts, cargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/mnt/git/qemu-rme-stack/.repo/repo/subcmds/init.py", line 400, in Execute
     self._SyncManifest(opt)
   File "/mnt/git/qemu-rme-stack/.repo/repo/subcmds/init.py", line 146, in _SyncManifest
     if not self.manifest.manifestProject.Sync(
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 4704, in Sync
     self.MetaBranchSwitch(submodules=submodules, verbose=verbose)
   File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 4173, in MetaBranchSwitch
     self.Sync_LocalHalf(syncbuf, submodules=submodules, verbose=verbose)
   File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 1636, in Sync_LocalHalf
     lost = self._revlist(not_rev(revid), HEAD)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 3676, in _revlist
     return self.work_git.rev_list(*a, **kw)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 3908, in rev_list
     p.Wait()
   File "/mnt/git/qemu-rme-stack/.repo/repo/git_command.py", line 556, in Wait
     self.VerifyCommand()
   File "/mnt/git/qemu-rme-stack/.repo/repo/git_command.py", line 546, in VerifyCommand
     raise GitCommandError(
git_command.GitCommandError: GitCommandError: 'rev-list ^6fd1cc667671a12cfc8789a390c990446e621f8f HEAD --' on manifests failed
stderr: fatal: bad revision 'HEAD'


Then I tried to build it from https://github.com/pbo-linaro/qemu-linux-stack/tree/rme and out/flash.bin
simply doesn't boot the kernel...


> Sorry for this very long email. At least, all is there.

Nope, that's quite helpful. This firmware stack is a mess :)


Cheers,
Gustavo


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu
  2025-07-16  3:13       ` Gustavo Romero
@ 2025-07-16  5:56         ` Pierrick Bouvier
  2025-07-16 13:02           ` Gustavo Romero
  0 siblings, 1 reply; 12+ messages in thread
From: Pierrick Bouvier @ 2025-07-16  5:56 UTC (permalink / raw)
  To: Gustavo Romero, Richard Henderson, qemu-devel; +Cc: qemu-arm

On 7/15/25 8:13 PM, Gustavo Romero wrote:
> Hi Pierrick,
> 
> On 7/14/25 22:26, Pierrick Bouvier wrote:
>> On 7/14/25 4:31 PM, Gustavo Romero wrote:
>>> Hi folks,
>>>
>>> Richard, thanks for v8. Pierrick, thanks for testing it. :)
>>>
>>> On 7/14/25 14:09, Pierrick Bouvier wrote:
>>>> On 7/14/25 8:58 AM, Richard Henderson wrote:
>>>>> Changes for v8:
>>>>>      - Re-order SCTLR2 and TCR2 so that they are independent of MEC.
>>>>>      - Enable the SCTLR2 and TCR2 enable bits.
>>>>>      - Squash 3 smaller MEC patches together.
>>>>>
>>>>> This still fails the RME tests, because we still need TF-A rebuilt
>>>>> with ENABLE_FEAT_SCTLR2 and ENABLE_FEAT_TCR2.  Pierrick, since you
>>>>> have just done such a build, could you re-test with this series?
>>>>>
>>>>
>>>> I tested that on my local Realm enabled setup and I can confirm this solved the issue and current series works.
>>>> Both flags are needed in TF-A. ENABLE_FEAT_TCR2 is needed to boot host, and ENABLE_FEAT_SCTLR2 is needed to boot nested guest.
>>>
>>> I'm a bit confused because the QEMU RME tests, afaics, uses OP-TEE, not TF-A. I've built TF-A
>>> using the scripts in [0], enabling ENABLE_FEAT_TCR2 and ENABLE_FEAT_SCTLR2, but no way to get
>>> it booting. I understand we can embed a OP-TEE into the TF_A via BL32=<optee_image> when
>>> building TF-A. Is that what you're using?
>>>
>>
>> I agree it's confusing. In short, no, OP-TEE is not used anywhere for Realms, only TF-A and RMM are used in our images. It seems that OP-TEE is a term used generically to represent any firmware running in secure mode, but it's a *totally* different software than TF-A + RMM. Naming OP-TEE like this is like if Linux would have been named "OP-kernel".
> 
> Got it, so we use TF-A + RMM in the test images. Thanks for the clarifications.
> 
> Isn't the generic term (or concept) actually TEE (not OP-TEE) and OP-TEE is a real software stack that implements the TEE spec, i.e., OP-TEE is code in https://github.com/OP-TEE)?
> 

Yes, correct. The term is TEE, OP-TEE is the project you mentioned. For 
some reason, everybody seems to think that OP-TEE is *the* unique TEE 
implementation is Arm world.
Thus my analogy with Linux that would be named OP-Kernel.

> 
>> The RME tests we have are based on this excellent tutorial [0], and build is automated with 'qemu-rme-stack' [1], that simply follows those instructions.
>>
>> [0] https://linaro.atlassian.net/wiki/spaces/QEMU/pages/30128767027/Device+Assignment+Enabled+RME+Stack+on+QEMU
> 
> Should [0] be:
> 
> https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/Building+an+RME+stack+for+QEMU ?
> 

Correct, bad copy paste sorry.

> 
>> [1] https://github.com/pbo-linaro/qemu-rme-stack
>>
>> To add to the confusion (*get ready*), [0] uses OP-TEE build, which is simply a build system for op-tee + other things, but in the variant it generates, OP-TEE itself is not included. Yes, that's utterly confusing and took me quite some time to discover it, after talking with Mathieu himself. They removed it explicitely to make the stack more simple. In short, for Realms, forget about OP-TEE.
> 
> ah, that's what confused me! I see now.
> 
> 
>> If you want to see it by yourself:
>>
>> https://git.codelinaro.org/linaro/dcap/op-tee-4.2.0/build/-/blob/cca/v8/qemu_v8_cca.mk?ref_type=heads#L172
>>
>> ...
>> TF_A_FLAGS ?= \
>>       BL33=$(BL33_BIN) \
>>       PLAT=qemu \
>>       QEMU_USE_GIC_DRIVER=$(TFA_GIC_DRIVER) \
>>       DEBUG=$(TF_A_DEBUG) \
>>       LOG_LEVEL=$(TF_A_LOGLVL) \
>>       ENABLE_RME=1 \
>>       RMM=$(RMM_BIN)
>> ...
>> TF_A_FLAGS_BL32_OPTEE  = BL32=$(OPTEE_OS_HEADER_V2_BIN)
>> TF_A_FLAGS_BL32_OPTEE += BL32_EXTRA1=$(OPTEE_OS_PAGER_V2_BIN)
>> TF_A_FLAGS_BL32_OPTEE += BL32_EXTRA2=$(OPTEE_OS_PAGEABLE_V2_BIN)
>> TF_A_FLAGS_SPMC_AT_EL_n  = $(TF_A_FLAGS_BL32_OPTEE) SPD=opteed
>> ...
>> #TF_A_FLAGS += $(TF_A_FLAGS_SPMC_AT_EL_$(SPMC_AT_EL))
>>
>> The last line shows that OP_TEE flags are **NOT** added to TF_A_FLAGS build flags.
>> The qemu_v8_cca.mk build file was copied from qemu_v8.mk, which itself has the OP-TEE inclusion.
>>
>> ---
>>
>> Recently, I had to generate a custom rootfs, and I experimented generating it directly from docker images, to avoid rebuilding the world using Buildroot. Once it worked, I realized it was a good opportunity to rebuild the rest of the stack too. The result is 'qemu-linux-stack' [2].
>>
>> Master branch has only tf-a + uboot (no Realm support), while rme branch [3], which supports Realm, uses tf-a + rmm + edk2 instead. I removed u-boot as I couldn't get it to boot, and I knew that edk2 worked.
>>
>> One branch is only one configuration (and it will stay this way).
>>
>> [2] https://github.com/pbo-linaro/qemu-linux-stack
>> [3] https://github.com/pbo-linaro/qemu-linux-stack/tree/rme
>>
>> Beyond the personal knowledge I got through that, I hope it can be used for others for who it's confusing about what runs before start_kernel, and I guess I'm not the only one who didn't know about that. In the end, things are not too complicated, but as most of the build systems out there (OP-TEE build, shrinkwrap, ...) try to be "generic and versatile", it ends up being complicated. I prefer basic and straightforward script shells to lenghty documentation and wiki pages, but it's a personal choice.
>>
>> ---
>>
>> Now, coming to the change introduced by this series, and supporting FEAT_SCTRL2 and FEAT_TCR2, all those images need to be updated [0], [1], [2], [3], because essentially, TF-A itself must be patched to support this. I was about to mention that, and mention that I can send a PR directly to it once we have this merged on QEMU side.
>>
>> The change in arm-trusted-firmware is quite simple:
>>
>> +diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
>> +index 751511cf8..6bc108492 100644
>> +--- a/plat/qemu/common/common.mk
>> ++++ b/plat/qemu/common/common.mk
>> +@@ -122,6 +122,10 @@ ENABLE_FEAT_FGT         :=      2
>> + # 8.7
>> + ENABLE_FEAT_HCX             :=      2
>> +
>> ++# 8.8
>> ++ENABLE_FEAT_TCR2    :=      2
>> ++ENABLE_FEAT_SCTLR2  :=      2
>> ++
>>
>> I'll push all that tomorrow on master, and rebase rmm and device_passthrough on top of it.
>> I'll add this to original RME images, it's less direct though, as it's needed to update the tf-a fork, and then the optee build system.
> 
> So, I still fail to understand how you are generating the out/bin/flash.bin used in our images.
> 
> First I tried to use the https://github.com/pbo-linaro/qemu-rme-stack, since it's cited in the tests. I tried:
> 
> $ ./container.sh ./build_virt.sh
> 
> and get an error which seems a commit mismatch in some of branches used by repo:
> 
> repo: reusing existing repo client checkout in /mnt/git/qemu-rme-stack
> Traceback (most recent call last):
>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 869, in <module>
>       _Main(sys.argv[1:])
>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 845, in _Main
>       result = repo._Run(name, gopts, argv) or 0
>                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 293, in _Run
>       result = run()
>                ^^^^^
>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 274, in <lambda>
>       lambda: self._RunLong(name, gopts, argv, git_trace2_event_log) or 0
>               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 437, in _RunLong
>       execute_command()
>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 403, in execute_command
>       execute_command_helper()
>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 369, in execute_command_helper
>       result = cmd.Execute(copts, cargs)
>                ^^^^^^^^^^^^^^^^^^^^^^^^^
>     File "/mnt/git/qemu-rme-stack/.repo/repo/subcmds/init.py", line 400, in Execute
>       self._SyncManifest(opt)
>     File "/mnt/git/qemu-rme-stack/.repo/repo/subcmds/init.py", line 146, in _SyncManifest
>       if not self.manifest.manifestProject.Sync(
>              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 4704, in Sync
>       self.MetaBranchSwitch(submodules=submodules, verbose=verbose)
>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 4173, in MetaBranchSwitch
>       self.Sync_LocalHalf(syncbuf, submodules=submodules, verbose=verbose)
>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 1636, in Sync_LocalHalf
>       lost = self._revlist(not_rev(revid), HEAD)
>              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 3676, in _revlist
>       return self.work_git.rev_list(*a, **kw)
>              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 3908, in rev_list
>       p.Wait()
>     File "/mnt/git/qemu-rme-stack/.repo/repo/git_command.py", line 556, in Wait
>       self.VerifyCommand()
>     File "/mnt/git/qemu-rme-stack/.repo/repo/git_command.py", line 546, in VerifyCommand
>       raise GitCommandError(
> git_command.GitCommandError: GitCommandError: 'rev-list ^6fd1cc667671a12cfc8789a390c990446e621f8f HEAD --' on manifests failed
> stderr: fatal: bad revision 'HEAD'
> 

I'm not sure what is happening. I gave it a try now (from a clean repo), 
and it works as expected. I had weird errors when stopping sync with 
ctrl-c in the past too. Anyway, clean and retry.

> 
> Then I tried to build it from https://github.com/pbo-linaro/qemu-linux-stack/tree/rme and out/flash.bin
> simply doesn't boot the kernel...
>

Maybe you built previously master branch, then switched to rme and 
rebuilt. In this case, your kernel and tf-a are not updated. I added a 
note in README, there is no dependency check when switching branches, 
you're expected to run git clean by yourself.
Both shrinkwrap and OP-TEE build don't really handle that properly to be 
honest...

It's not ideal, but I don't want to go down the rabbit hole of 
reimplementing any kind of half baked Make based dependency graph.
Maybe we could use git submodules or repo in the future, but both have 
their own drawbacks too.

> 
>> Sorry for this very long email. At least, all is there.
> 
> Nope, that's quite helpful. This firmware stack is a mess :)
> 
> 
> Cheers,
> Gustavo



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu
  2025-07-16  5:56         ` Pierrick Bouvier
@ 2025-07-16 13:02           ` Gustavo Romero
  0 siblings, 0 replies; 12+ messages in thread
From: Gustavo Romero @ 2025-07-16 13:02 UTC (permalink / raw)
  To: Pierrick Bouvier, Richard Henderson, qemu-devel; +Cc: qemu-arm

Hi Pierrick!

On 7/16/25 02:56, Pierrick Bouvier wrote:
> On 7/15/25 8:13 PM, Gustavo Romero wrote:
>> Hi Pierrick,
>>
>> On 7/14/25 22:26, Pierrick Bouvier wrote:
>>> On 7/14/25 4:31 PM, Gustavo Romero wrote:
>>>> Hi folks,
>>>>
>>>> Richard, thanks for v8. Pierrick, thanks for testing it. :)
>>>>
>>>> On 7/14/25 14:09, Pierrick Bouvier wrote:
>>>>> On 7/14/25 8:58 AM, Richard Henderson wrote:
>>>>>> Changes for v8:
>>>>>>      - Re-order SCTLR2 and TCR2 so that they are independent of MEC.
>>>>>>      - Enable the SCTLR2 and TCR2 enable bits.
>>>>>>      - Squash 3 smaller MEC patches together.
>>>>>>
>>>>>> This still fails the RME tests, because we still need TF-A rebuilt
>>>>>> with ENABLE_FEAT_SCTLR2 and ENABLE_FEAT_TCR2.  Pierrick, since you
>>>>>> have just done such a build, could you re-test with this series?
>>>>>>
>>>>>
>>>>> I tested that on my local Realm enabled setup and I can confirm this solved the issue and current series works.
>>>>> Both flags are needed in TF-A. ENABLE_FEAT_TCR2 is needed to boot host, and ENABLE_FEAT_SCTLR2 is needed to boot nested guest.
>>>>
>>>> I'm a bit confused because the QEMU RME tests, afaics, uses OP-TEE, not TF-A. I've built TF-A
>>>> using the scripts in [0], enabling ENABLE_FEAT_TCR2 and ENABLE_FEAT_SCTLR2, but no way to get
>>>> it booting. I understand we can embed a OP-TEE into the TF_A via BL32=<optee_image> when
>>>> building TF-A. Is that what you're using?
>>>>
>>>
>>> I agree it's confusing. In short, no, OP-TEE is not used anywhere for Realms, only TF-A and RMM are used in our images. It seems that OP-TEE is a term used generically to represent any firmware running in secure mode, but it's a *totally* different software than TF-A + RMM. Naming OP-TEE like this is like if Linux would have been named "OP-kernel".
>>
>> Got it, so we use TF-A + RMM in the test images. Thanks for the clarifications.
>>
>> Isn't the generic term (or concept) actually TEE (not OP-TEE) and OP-TEE is a real software stack that implements the TEE spec, i.e., OP-TEE is code in https://github.com/OP-TEE)?
>>
> 
> Yes, correct. The term is TEE, OP-TEE is the project you mentioned. For some reason, everybody seems to think that OP-TEE is *the* unique TEE implementation is Arm world.
> Thus my analogy with Linux that would be named OP-Kernel.
> 
>>
>>> The RME tests we have are based on this excellent tutorial [0], and build is automated with 'qemu-rme-stack' [1], that simply follows those instructions.
>>>
>>> [0] https://linaro.atlassian.net/wiki/spaces/QEMU/pages/30128767027/Device+Assignment+Enabled+RME+Stack+on+QEMU
>>
>> Should [0] be:
>>
>> https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/Building+an+RME+stack+for+QEMU ?
>>
> 
> Correct, bad copy paste sorry.
> 
>>
>>> [1] https://github.com/pbo-linaro/qemu-rme-stack
>>>
>>> To add to the confusion (*get ready*), [0] uses OP-TEE build, which is simply a build system for op-tee + other things, but in the variant it generates, OP-TEE itself is not included. Yes, that's utterly confusing and took me quite some time to discover it, after talking with Mathieu himself. They removed it explicitely to make the stack more simple. In short, for Realms, forget about OP-TEE.
>>
>> ah, that's what confused me! I see now.
>>
>>
>>> If you want to see it by yourself:
>>>
>>> https://git.codelinaro.org/linaro/dcap/op-tee-4.2.0/build/-/blob/cca/v8/qemu_v8_cca.mk?ref_type=heads#L172
>>>
>>> ...
>>> TF_A_FLAGS ?= \
>>>       BL33=$(BL33_BIN) \
>>>       PLAT=qemu \
>>>       QEMU_USE_GIC_DRIVER=$(TFA_GIC_DRIVER) \
>>>       DEBUG=$(TF_A_DEBUG) \
>>>       LOG_LEVEL=$(TF_A_LOGLVL) \
>>>       ENABLE_RME=1 \
>>>       RMM=$(RMM_BIN)
>>> ...
>>> TF_A_FLAGS_BL32_OPTEE  = BL32=$(OPTEE_OS_HEADER_V2_BIN)
>>> TF_A_FLAGS_BL32_OPTEE += BL32_EXTRA1=$(OPTEE_OS_PAGER_V2_BIN)
>>> TF_A_FLAGS_BL32_OPTEE += BL32_EXTRA2=$(OPTEE_OS_PAGEABLE_V2_BIN)
>>> TF_A_FLAGS_SPMC_AT_EL_n  = $(TF_A_FLAGS_BL32_OPTEE) SPD=opteed
>>> ...
>>> #TF_A_FLAGS += $(TF_A_FLAGS_SPMC_AT_EL_$(SPMC_AT_EL))
>>>
>>> The last line shows that OP_TEE flags are **NOT** added to TF_A_FLAGS build flags.
>>> The qemu_v8_cca.mk build file was copied from qemu_v8.mk, which itself has the OP-TEE inclusion.
>>>
>>> ---
>>>
>>> Recently, I had to generate a custom rootfs, and I experimented generating it directly from docker images, to avoid rebuilding the world using Buildroot. Once it worked, I realized it was a good opportunity to rebuild the rest of the stack too. The result is 'qemu-linux-stack' [2].
>>>
>>> Master branch has only tf-a + uboot (no Realm support), while rme branch [3], which supports Realm, uses tf-a + rmm + edk2 instead. I removed u-boot as I couldn't get it to boot, and I knew that edk2 worked.
>>>
>>> One branch is only one configuration (and it will stay this way).
>>>
>>> [2] https://github.com/pbo-linaro/qemu-linux-stack
>>> [3] https://github.com/pbo-linaro/qemu-linux-stack/tree/rme
>>>
>>> Beyond the personal knowledge I got through that, I hope it can be used for others for who it's confusing about what runs before start_kernel, and I guess I'm not the only one who didn't know about that. In the end, things are not too complicated, but as most of the build systems out there (OP-TEE build, shrinkwrap, ...) try to be "generic and versatile", it ends up being complicated. I prefer basic and straightforward script shells to lenghty documentation and wiki pages, but it's a personal choice.
>>>
>>> ---
>>>
>>> Now, coming to the change introduced by this series, and supporting FEAT_SCTRL2 and FEAT_TCR2, all those images need to be updated [0], [1], [2], [3], because essentially, TF-A itself must be patched to support this. I was about to mention that, and mention that I can send a PR directly to it once we have this merged on QEMU side.
>>>
>>> The change in arm-trusted-firmware is quite simple:
>>>
>>> +diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
>>> +index 751511cf8..6bc108492 100644
>>> +--- a/plat/qemu/common/common.mk
>>> ++++ b/plat/qemu/common/common.mk
>>> +@@ -122,6 +122,10 @@ ENABLE_FEAT_FGT         :=      2
>>> + # 8.7
>>> + ENABLE_FEAT_HCX             :=      2
>>> +
>>> ++# 8.8
>>> ++ENABLE_FEAT_TCR2    :=      2
>>> ++ENABLE_FEAT_SCTLR2  :=      2
>>> ++
>>>
>>> I'll push all that tomorrow on master, and rebase rmm and device_passthrough on top of it.
>>> I'll add this to original RME images, it's less direct though, as it's needed to update the tf-a fork, and then the optee build system.
>>
>> So, I still fail to understand how you are generating the out/bin/flash.bin used in our images.
>>
>> First I tried to use the https://github.com/pbo-linaro/qemu-rme-stack, since it's cited in the tests. I tried:
>>
>> $ ./container.sh ./build_virt.sh
>>
>> and get an error which seems a commit mismatch in some of branches used by repo:
>>
>> repo: reusing existing repo client checkout in /mnt/git/qemu-rme-stack
>> Traceback (most recent call last):
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 869, in <module>
>>       _Main(sys.argv[1:])
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 845, in _Main
>>       result = repo._Run(name, gopts, argv) or 0
>>                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 293, in _Run
>>       result = run()
>>                ^^^^^
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 274, in <lambda>
>>       lambda: self._RunLong(name, gopts, argv, git_trace2_event_log) or 0
>>               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 437, in _RunLong
>>       execute_command()
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 403, in execute_command
>>       execute_command_helper()
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/main.py", line 369, in execute_command_helper
>>       result = cmd.Execute(copts, cargs)
>>                ^^^^^^^^^^^^^^^^^^^^^^^^^
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/subcmds/init.py", line 400, in Execute
>>       self._SyncManifest(opt)
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/subcmds/init.py", line 146, in _SyncManifest
>>       if not self.manifest.manifestProject.Sync(
>>              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 4704, in Sync
>>       self.MetaBranchSwitch(submodules=submodules, verbose=verbose)
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 4173, in MetaBranchSwitch
>>       self.Sync_LocalHalf(syncbuf, submodules=submodules, verbose=verbose)
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 1636, in Sync_LocalHalf
>>       lost = self._revlist(not_rev(revid), HEAD)
>>              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 3676, in _revlist
>>       return self.work_git.rev_list(*a, **kw)
>>              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/project.py", line 3908, in rev_list
>>       p.Wait()
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/git_command.py", line 556, in Wait
>>       self.VerifyCommand()
>>     File "/mnt/git/qemu-rme-stack/.repo/repo/git_command.py", line 546, in VerifyCommand
>>       raise GitCommandError(
>> git_command.GitCommandError: GitCommandError: 'rev-list ^6fd1cc667671a12cfc8789a390c990446e621f8f HEAD --' on manifests failed
>> stderr: fatal: bad revision 'HEAD'
>>
> 
> I'm not sure what is happening. I gave it a try now (from a clean repo), and it works as expected. I had weird errors when stopping sync with ctrl-c in the past too. Anyway, clean and retry.

OK


>>
>> Then I tried to build it from https://github.com/pbo-linaro/qemu-linux-stack/tree/rme and out/flash.bin
>> simply doesn't boot the kernel...
>>
> 
> Maybe you built previously master branch, then switched to rme and rebuilt. In this case, your kernel and tf-a are not updated. I added a note in README, there is no dependency check when switching branches, you're expected to run git clean by yourself.
> Both shrinkwrap and OP-TEE build don't really handle that properly to be honest...
> 
> It's not ideal, but I don't want to go down the rabbit hole of reimplementing any kind of half baked Make based dependency graph.
> Maybe we could use git submodules or repo in the future, but both have their own drawbacks too.

Won't dare to blame you for it, we need to keep ourselves sane XD

You did a great work already putting it in a single place and using bash scripts as much as possible :)


Cheers,
Gustavo

>>
>>> Sorry for this very long email. At least, all is there.
>>
>> Nope, that's quite helpful. This firmware stack is a mess :)
>>
>>
>> Cheers,
>> Gustavo
> 



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2025-07-16 13:07 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-14 15:58 [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Richard Henderson
2025-07-14 15:58 ` [PATCH v8 1/4] target/arm: Implement FEAT_SCTLR2 and enable with -cpu max Richard Henderson
2025-07-14 15:58 ` [PATCH v8 2/4] target/arm: Implement FEAT_TCR2 " Richard Henderson
2025-07-14 15:58 ` [PATCH v8 3/4] target/arm: Implement FEAT_MEC registers Richard Henderson
2025-07-14 15:58 ` [PATCH v8 4/4] target/arm: Enable FEAT_MEC in -cpu max Richard Henderson
2025-07-14 17:09 ` [PATCH v8 0/4] target/arm: Add FEAT_MEC to max cpu Pierrick Bouvier
2025-07-14 23:31   ` Gustavo Romero
2025-07-15  1:26     ` Pierrick Bouvier
2025-07-16  3:13       ` Gustavo Romero
2025-07-16  5:56         ` Pierrick Bouvier
2025-07-16 13:02           ` Gustavo Romero
2025-07-15 21:29   ` Pierrick Bouvier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).