All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/22] target/arm: Implement FEAT_RME
@ 2023-01-24  0:00 Richard Henderson
  2023-01-24  0:00 ` [PATCH 01/22] target/arm: Fix pmsav8 stage2 secure parameter Richard Henderson
                   ` (21 more replies)
  0 siblings, 22 replies; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

This is based on mainline, without any extra ARMv9-A dependencies
which are still under development.  This is good enough to pass
all of the tests within

    https://github.com/Huawei/Huawei_CCA_QEMU

With the exception of the final patch, all of the code below is my own.
The Huawei code was based on last year's qemu-6.2, and the Granule
Protection Check was done at the wrong level.  I have integrated the
GPC into the normal arm_cpu_tlb_fill code path.

The first two patches are bug fixes that are unrelated to RME.
The bug fixed by the second patch was uncovered by the VTCR_EL2
setting used by the Realm Management Monitor included with TF-A.

The final patch is more or less a hack, required by Huawei's changes
to TF-A.  Given that current TF-A supports QEMU virt board, using FDT,
I think the correct solution going forward is to *not* skip creating
the fdt node.  I have not yet tried to build mainline TF-A and TF-RMM,
or see what has been integrated into TF-A-TESTS.  See

    https://git.trustedfirmware.org/

for the relevant repos.


r~


Richard Henderson (22):
  target/arm: Fix pmsav8 stage2 secure parameter
  target/arm: Rewrite check_s2_mmu_setup
  target/arm: Add isar_feature_aa64_rme
  target/arm: Update SCR and HCR for RME
  target/arm: SCR_EL3.NS may be RES1
  target/arm: Add RME cpregs
  target/arm: Introduce ARMSecuritySpace
  include/exec/memattrs: Add two bits of space to MemTxAttrs
  target/arm: Adjust the order of Phys and Stage2 ARMMMUIdx
  target/arm: Introduce ARMMMUIdx_Phys_{Realm,Root}
  target/arm: Pipe ARMSecuritySpace through ptw.c
  target/arm: NSTable is RES0 for the RME EL3 regime
  target/arm: Handle Block and Page bits for security space
  target/arm: Handle no-execute for Realm and Root regimes
  target/arm: Use get_phys_addr_with_struct in S1_ptw_translate
  target/arm: Move s1_is_El0 into S1Translate
  target/arm: Use get_phys_addr_with_struct for stage2
  target/arm: Add GPC syndrome
  target/arm: Implement GPC exceptions
  target/arm: Implement the granule protection check
  target/arm: Enable RME for -cpu max
  hw/arm/virt: Add some memory for Realm Management Monitor

 include/exec/memattrs.h |   9 +-
 include/hw/arm/virt.h   |   2 +
 target/arm/cpu-param.h  |   2 +-
 target/arm/cpu.h        | 143 ++++++--
 target/arm/internals.h  |  27 ++
 target/arm/syndrome.h   |   9 +
 hw/arm/virt.c           |  43 +++
 target/arm/cpu.c        |   4 +
 target/arm/cpu64.c      |  37 ++
 target/arm/helper.c     | 138 +++++++-
 target/arm/ptw.c        | 749 ++++++++++++++++++++++++++++++----------
 target/arm/tlb_helper.c |  92 ++++-
 12 files changed, 1030 insertions(+), 225 deletions(-)

-- 
2.34.1



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

* [PATCH 01/22] target/arm: Fix pmsav8 stage2 secure parameter
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 14:26   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 02/22] target/arm: Rewrite check_s2_mmu_setup Richard Henderson
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

We have computed the security state for the stage2 lookup
into s2walk_secure -- use it.

Fixes: fca45e3467f ("target/arm: Add PMSAv8r functionality")
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 57f3615a66..b0f8c59767 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -2727,7 +2727,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
 
     if (arm_feature(env, ARM_FEATURE_PMSA)) {
         ret = get_phys_addr_pmsav8(env, ipa, access_type,
-                                   ptw->in_mmu_idx, is_secure, result, fi);
+                                   ptw->in_mmu_idx, s2walk_secure, result, fi);
     } else {
         ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
                                  is_el0, result, fi);
-- 
2.34.1



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

* [PATCH 02/22] target/arm: Rewrite check_s2_mmu_setup
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
  2023-01-24  0:00 ` [PATCH 01/22] target/arm: Fix pmsav8 stage2 secure parameter Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 16:00   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 03/22] target/arm: Add isar_feature_aa64_rme Richard Henderson
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Integrate neighboring code from get_phys_addr_lpae which computed
starting level, as it is easier to validate when doing both at the
same time.  Mirror the checks at the start of AArch{64,32}.S2Walk,
especially S2InvalidESL and S2InconsistentSL.

This reverts 49ba115bb74, which was incorrect -- there is nothing
in the ARM pseudocode that depends on TxSZ, i.e. outputsize; the
pseudocode is consistent in referencing PAMax.

Fixes: 49ba115bb74 ("target/arm: Pass outputsize down to check_s2_mmu_setup")
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 173 ++++++++++++++++++++++++++---------------------
 1 file changed, 97 insertions(+), 76 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index b0f8c59767..437f6fefa9 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1077,70 +1077,119 @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
  * check_s2_mmu_setup
  * @cpu:        ARMCPU
  * @is_aa64:    True if the translation regime is in AArch64 state
- * @startlevel: Suggested starting level
- * @inputsize:  Bitsize of IPAs
+ * @tcr:        VTCR_EL2 or VSTCR_EL2
+ * @ds:         Effective value of TCR.DS.
+ * @iasize:     Bitsize of IPAs
  * @stride:     Page-table stride (See the ARM ARM)
  *
- * Returns true if the suggested S2 translation parameters are OK and
- * false otherwise.
+ * Decode the starting level of the S2 lookup, returning INT_MIN if
+ * the configuration is invalid.
  */
-static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
-                               int inputsize, int stride, int outputsize)
+static int check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, uint64_t tcr,
+                              bool ds, int iasize, int stride)
 {
-    const int grainsize = stride + 3;
-    int startsizecheck;
-
-    /*
-     * Negative levels are usually not allowed...
-     * Except for FEAT_LPA2, 4k page table, 52-bit address space, which
-     * begins with level -1.  Note that previous feature tests will have
-     * eliminated this combination if it is not enabled.
-     */
-    if (level < (inputsize == 52 && stride == 9 ? -1 : 0)) {
-        return false;
-    }
-
-    startsizecheck = inputsize - ((3 - level) * stride + grainsize);
-    if (startsizecheck < 1 || startsizecheck > stride + 4) {
-        return false;
-    }
+    int sl0, sl2, startlevel, granulebits, levels;
+    int s1_min_iasize, s1_max_iasize;
 
+    sl0 = extract32(tcr, 6, 2);
     if (is_aa64) {
+        /*
+         * AArch64.S2InvalidTxSZ: While we checked tsz_oob near the top of
+         * get_phys_addr_lpae, that used aa64_va_parameters which apply
+         * to aarch64.  If Stage1 is aarch32, the min_txsz is larger.
+         * See AArch64.S2MinTxSZ, where min_tsz is 24, translated to
+         * inputsize is 64 - 24 = 40.
+         */
+        if (iasize < 40 && !arm_el_is_aa64(&cpu->env, 1)) {
+            goto fail;
+        }
+
+        /*
+         * AArch64.S2InvalidSL: Interpretation of SL depends on the page size,
+         * so interleave AArch64.S2StartLevel.
+         */
         switch (stride) {
-        case 13: /* 64KB Pages.  */
-            if (level == 0 || (level == 1 && outputsize <= 42)) {
-                return false;
+        case 9: /* 4KB */
+            /* SL2 is RES0 unless DS=1 & 4KB granule. */
+            sl2 = extract64(tcr, 33, 1);
+            if (ds && sl2) {
+                if (sl0 != 0) {
+                    goto fail;
+                }
+                startlevel = -1;
+            } else {
+                startlevel = 2 - sl0;
+                switch (sl0) {
+                case 2:
+                    if (arm_pamax(cpu) < 44) {
+                        goto fail;
+                    }
+                    break;
+                case 3:
+                    if (!cpu_isar_feature(aa64_st, cpu)) {
+                        goto fail;
+                    }
+                    startlevel = 3;
+                    break;
+                }
             }
             break;
-        case 11: /* 16KB Pages.  */
-            if (level == 0 || (level == 1 && outputsize <= 40)) {
-                return false;
+        case 11: /* 16KB */
+            switch (sl0) {
+            case 2:
+                if (arm_pamax(cpu) < 42) {
+                    goto fail;
+                }
+                break;
+            case 3:
+                if (!ds) {
+                    goto fail;
+                }
+                break;
             }
+            startlevel = 3 - sl0;
             break;
-        case 9: /* 4KB Pages.  */
-            if (level == 0 && outputsize <= 42) {
-                return false;
+        case 13: /* 64KB */
+            switch (sl0) {
+            case 2:
+                if (arm_pamax(cpu) < 44) {
+                    goto fail;
+                }
+                break;
+            case 3:
+                goto fail;
             }
+            startlevel = 3 - sl0;
             break;
         default:
             g_assert_not_reached();
         }
-
-        /* Inputsize checks.  */
-        if (inputsize > outputsize &&
-            (arm_el_is_aa64(&cpu->env, 1) || inputsize > 40)) {
-            /* This is CONSTRAINED UNPREDICTABLE and we choose to fault.  */
-            return false;
-        }
     } else {
-        /* AArch32 only supports 4KB pages. Assert on that.  */
+        /*
+         * Things are simpler for AArch32 EL2, with only 4k pages.
+         * There is no separate S2InvalidSL function, but AArch32.S2Walk
+         * begins with walkparms.sl0 in {'1x'}.
+         */
         assert(stride == 9);
-
-        if (level == 0) {
-            return false;
+        if (sl0 >= 2) {
+            goto fail;
         }
+        startlevel = 2 - sl0;
     }
-    return true;
+
+    /* AArch{64,32}.S2InconsistentSL are functionally equivalent.  */
+    levels = 3 - startlevel;
+    granulebits = stride + 3;
+
+    s1_min_iasize = levels * stride + granulebits + 1;
+    s1_max_iasize = s1_min_iasize + (stride - 1) + 4;
+
+    if (iasize >= s1_min_iasize && iasize <= s1_max_iasize) {
+        return startlevel;
+    }
+
+ fail:
+    return INT_MIN;
 }
 
 /**
@@ -1296,38 +1345,10 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
          */
         level = 4 - (inputsize - 4) / stride;
     } else {
-        /*
-         * For stage 2 translations the starting level is specified by the
-         * VTCR_EL2.SL0 field (whose interpretation depends on the page size)
-         */
-        uint32_t sl0 = extract32(tcr, 6, 2);
-        uint32_t sl2 = extract64(tcr, 33, 1);
-        int32_t startlevel;
-        bool ok;
-
-        /* SL2 is RES0 unless DS=1 & 4kb granule. */
-        if (param.ds && stride == 9 && sl2) {
-            if (sl0 != 0) {
-                level = 0;
-                goto do_translation_fault;
-            }
-            startlevel = -1;
-        } else if (!aarch64 || stride == 9) {
-            /* AArch32 or 4KB pages */
-            startlevel = 2 - sl0;
-
-            if (cpu_isar_feature(aa64_st, cpu)) {
-                startlevel &= 3;
-            }
-        } else {
-            /* 16KB or 64KB pages */
-            startlevel = 3 - sl0;
-        }
-
-        /* Check that the starting level is valid. */
-        ok = check_s2_mmu_setup(cpu, aarch64, startlevel,
-                                inputsize, stride, outputsize);
-        if (!ok) {
+        int startlevel = check_s2_mmu_setup(cpu, aarch64, tcr, param.ds,
+                                            inputsize, stride);
+        if (startlevel == INT_MIN) {
+            level = 0;
             goto do_translation_fault;
         }
         level = startlevel;
-- 
2.34.1



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

* [PATCH 03/22] target/arm: Add isar_feature_aa64_rme
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
  2023-01-24  0:00 ` [PATCH 01/22] target/arm: Fix pmsav8 stage2 secure parameter Richard Henderson
  2023-01-24  0:00 ` [PATCH 02/22] target/arm: Rewrite check_s2_mmu_setup Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 14:31   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 04/22] target/arm: Update SCR and HCR for RME Richard Henderson
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Add the missing field for ID_AA64PFR0, and the predicate.
Disable it if EL3 is forced off by the board or command-line.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h | 6 ++++++
 target/arm/cpu.c | 4 ++++
 2 files changed, 10 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 8cf70693be..81d5a51b62 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2178,6 +2178,7 @@ FIELD(ID_AA64PFR0, SEL2, 36, 4)
 FIELD(ID_AA64PFR0, MPAM, 40, 4)
 FIELD(ID_AA64PFR0, AMU, 44, 4)
 FIELD(ID_AA64PFR0, DIT, 48, 4)
+FIELD(ID_AA64PFR0, RME, 52, 4)
 FIELD(ID_AA64PFR0, CSV2, 56, 4)
 FIELD(ID_AA64PFR0, CSV3, 60, 4)
 
@@ -4001,6 +4002,11 @@ static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id)
     return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0;
 }
 
+static inline bool isar_feature_aa64_rme(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0;
+}
+
 static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
 {
     return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 5f63316dbf..b10ace74cd 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1944,6 +1944,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0);
         cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
                                            ID_AA64PFR0, EL3, 0);
+
+        /* Disable the realm management extension, which requires EL3. */
+        cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
+                                           ID_AA64PFR0, RME, 0);
     }
 
     if (!cpu->has_el2) {
-- 
2.34.1



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

* [PATCH 04/22] target/arm: Update SCR and HCR for RME
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (2 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 03/22] target/arm: Add isar_feature_aa64_rme Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 14:34   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 05/22] target/arm: SCR_EL3.NS may be RES1 Richard Henderson
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Define the missing SCR and HCR bits, allow SCR_NSE and {SCR,HCR}_GPF
to be set, and invalidate TLBs when NSE changes.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h    |  5 +++--
 target/arm/helper.c | 10 ++++++++--
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 81d5a51b62..9d1a6b346d 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1638,7 +1638,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
 #define HCR_TERR      (1ULL << 36)
 #define HCR_TEA       (1ULL << 37)
 #define HCR_MIOCNCE   (1ULL << 38)
-/* RES0 bit 39 */
+#define HCR_TME       (1ULL << 39)
 #define HCR_APK       (1ULL << 40)
 #define HCR_API       (1ULL << 41)
 #define HCR_NV        (1ULL << 42)
@@ -1647,7 +1647,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
 #define HCR_NV2       (1ULL << 45)
 #define HCR_FWB       (1ULL << 46)
 #define HCR_FIEN      (1ULL << 47)
-/* RES0 bit 48 */
+#define HCR_GPF       (1ULL << 48)
 #define HCR_TID4      (1ULL << 49)
 #define HCR_TICAB     (1ULL << 50)
 #define HCR_AMVOFFEN  (1ULL << 51)
@@ -1712,6 +1712,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_NSE               (1ULL << 62)
 
 #define HSTR_TTEE (1 << 16)
 #define HSTR_TJDBX (1 << 17)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 72b37b7cf1..293f8eda8c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1869,6 +1869,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
         if (cpu_isar_feature(aa64_hcx, cpu)) {
             valid_mask |= SCR_HXEN;
         }
+        if (cpu_isar_feature(aa64_rme, cpu)) {
+            valid_mask |= SCR_NSE | SCR_GPF;
+        }
     } else {
         valid_mask &= ~(SCR_RW | SCR_ST);
         if (cpu_isar_feature(aa32_ras, cpu)) {
@@ -1898,10 +1901,10 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
     env->cp15.scr_el3 = value;
 
     /*
-     * If SCR_EL3.NS changes, i.e. arm_is_secure_below_el3, then
+     * If SCR_EL3.{NS,NSE} changes, i.e. change of security state,
      * we must invalidate all TLBs below EL3.
      */
-    if (changed & SCR_NS) {
+    if (changed & (SCR_NS | SCR_NSE)) {
         tlb_flush_by_mmuidx(env_cpu(env), (ARMMMUIdxBit_E10_0 |
                                            ARMMMUIdxBit_E20_0 |
                                            ARMMMUIdxBit_E10_1 |
@@ -5578,6 +5581,9 @@ static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
         if (cpu_isar_feature(aa64_fwb, cpu)) {
             valid_mask |= HCR_FWB;
         }
+        if (cpu_isar_feature(aa64_rme, cpu)) {
+            valid_mask |= HCR_GPF;
+        }
     }
 
     if (cpu_isar_feature(any_evt, cpu)) {
-- 
2.34.1



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

* [PATCH 05/22] target/arm: SCR_EL3.NS may be RES1
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (3 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 04/22] target/arm: Update SCR and HCR for RME Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 14:39   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 06/22] target/arm: Add RME cpregs Richard Henderson
                   ` (16 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

With RME, SEL2 must also be present to support secure state.
The NS bit is RES1 if SEL2 is not present.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 293f8eda8c..783b675bd1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1853,6 +1853,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
         }
         if (cpu_isar_feature(aa64_sel2, cpu)) {
             valid_mask |= SCR_EEL2;
+        } else if (cpu_isar_feature(aa64_rme, cpu)) {
+            /* With RME and without SEL2, NS is RES1. */
+            value |= SCR_NS;
         }
         if (cpu_isar_feature(aa64_mte, cpu)) {
             valid_mask |= SCR_ATA;
-- 
2.34.1



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

* [PATCH 06/22] target/arm: Add RME cpregs
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (4 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 05/22] target/arm: SCR_EL3.NS may be RES1 Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 14:53   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 07/22] target/arm: Introduce ARMSecuritySpace Richard Henderson
                   ` (15 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

This includes GPCCR, GPTBR, MFAR, the TLB flush insns PAALL,
PAALLOS, RPALOS, RPAOS, and the cache flush insn CIPAPA.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h    | 19 ++++++++++++
 target/arm/helper.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 9d1a6b346d..26bdd6e465 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -529,6 +529,11 @@ typedef struct CPUArchState {
         uint64_t disr_el1;
         uint64_t vdisr_el2;
         uint64_t vsesr_el2;
+
+        /* RME registers */
+        uint64_t gpccr_el3;
+        uint64_t gptbr_el3;
+        uint64_t mfar_el3;
     } cp15;
 
     struct {
@@ -1031,6 +1036,7 @@ struct ArchCPU {
     uint64_t reset_cbar;
     uint32_t reset_auxcr;
     bool reset_hivecs;
+    uint8_t reset_l0gptsz;
 
     /*
      * Intermediate values used during property parsing.
@@ -2324,6 +2330,19 @@ FIELD(MVFR1, SIMDFMAC, 28, 4)
 FIELD(MVFR2, SIMDMISC, 0, 4)
 FIELD(MVFR2, FPMISC, 4, 4)
 
+FIELD(GPCCR, PPS, 0, 3)
+FIELD(GPCCR, IRGN, 8, 2)
+FIELD(GPCCR, ORGN, 10, 2)
+FIELD(GPCCR, SH, 12, 2)
+FIELD(GPCCR, PGS, 14, 2)
+FIELD(GPCCR, GPC, 16, 1)
+FIELD(GPCCR, GPCP, 17, 1)
+FIELD(GPCCR, L0GPTSZ, 20, 4)
+
+FIELD(MFAR, FPA, 12, 40)
+FIELD(MFAR, NSE, 62, 1)
+FIELD(MFAR, NS, 63, 1)
+
 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 783b675bd1..7bd15e9d17 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6848,6 +6848,77 @@ static const ARMCPRegInfo sme_reginfo[] = {
       .access = PL2_RW, .accessfn = access_esm,
       .type = ARM_CP_CONST, .resetvalue = 0 },
 };
+
+static void tlbi_aa64_paall_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                  uint64_t value)
+{
+    CPUState *cs = env_cpu(env);
+
+    tlb_flush(cs);
+}
+
+static void gpccr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                        uint64_t value)
+{
+    /* L0GPTSZ is RO; other bits not mentioned are RES0. */
+    uint64_t rw_mask = R_GPCCR_PPS_MASK | R_GPCCR_IRGN_MASK |
+        R_GPCCR_ORGN_MASK | R_GPCCR_SH_MASK | R_GPCCR_PGS_MASK |
+        R_GPCCR_GPC_MASK | R_GPCCR_GPCP_MASK;
+
+    env->cp15.gpccr_el3 = (value & rw_mask) | (env->cp15.gpccr_el3 & ~rw_mask);
+}
+
+static void gpccr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    env->cp15.gpccr_el3 = FIELD_DP64(0, GPCCR, L0GPTSZ,
+                                     env_archcpu(env)->reset_l0gptsz);
+}
+
+static void tlbi_aa64_paallos_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                    uint64_t value)
+{
+    CPUState *cs = env_cpu(env);
+
+    tlb_flush_all_cpus_synced(cs);
+}
+
+static const ARMCPRegInfo rme_reginfo[] = {
+    { .name = "GPCCR_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 1, .opc2 = 6,
+      .access = PL3_RW, .writefn = gpccr_write, .resetfn = gpccr_reset,
+      .fieldoffset = offsetof(CPUARMState, cp15.gpccr_el3) },
+    { .name = "GPTBR_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 1, .opc2 = 4,
+      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.gptbr_el3) },
+    { .name = "MFAR_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 6, .crn = 6, .crm = 0, .opc2 = 5,
+      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mfar_el3) },
+    { .name = "TLBI_PAALL", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 4,
+      .access = PL3_W, .type = ARM_CP_NO_RAW,
+      .writefn = tlbi_aa64_paall_write },
+    { .name = "TLBI_PAALLOS", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 4,
+      .access = PL3_W, .type = ARM_CP_NO_RAW,
+      .writefn = tlbi_aa64_paallos_write },
+    /*
+     * QEMU does not have a way to invalidate by physical address, thus
+     * invalidating a range of physical addresses is accomplished by
+     * flushing all tlb entries in the outer sharable domain,
+     * just like PAALLOS.
+     */
+    { .name = "TLBI_RPALOS", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 4, .opc2 = 7,
+      .access = PL3_W, .type = ARM_CP_NO_RAW,
+      .writefn = tlbi_aa64_paallos_write },
+    { .name = "TLBI_RPAOS", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 4, .opc2 = 3,
+      .access = PL3_W, .type = ARM_CP_NO_RAW,
+      .writefn = tlbi_aa64_paallos_write },
+    { .name = "DC_CIPAPA", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 14, .opc2 = 1,
+      .access = PL3_W, .type = ARM_CP_NOP },
+};
 #endif /* TARGET_AARCH64 */
 
 static void define_pmu_regs(ARMCPU *cpu)
@@ -8915,6 +8986,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
     if (cpu_isar_feature(aa64_tlbios, cpu)) {
         define_arm_cp_regs(cpu, tlbios_reginfo);
     }
+    if (cpu_isar_feature(aa64_rme, cpu)) {
+        define_arm_cp_regs(cpu, rme_reginfo);
+    }
 #ifndef CONFIG_USER_ONLY
     /* Data Cache clean instructions up to PoP */
     if (cpu_isar_feature(aa64_dcpop, cpu)) {
-- 
2.34.1



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

* [PATCH 07/22] target/arm: Introduce ARMSecuritySpace
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (5 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 06/22] target/arm: Add RME cpregs Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 15:00   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 08/22] include/exec/memattrs: Add two bits of space to MemTxAttrs Richard Henderson
                   ` (14 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Introduce both the enumeration and functions to retrieve
the current state, and state outside of EL3.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h    | 87 +++++++++++++++++++++++++++++++++++----------
 target/arm/helper.c | 46 ++++++++++++++++++++++++
 2 files changed, 115 insertions(+), 18 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 26bdd6e465..cfc62d60b0 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2397,23 +2397,53 @@ static inline int arm_feature(CPUARMState *env, int feature)
 
 void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp);
 
+/*
+ * ARM v9 security states.
+ * The ordering of the enumeration corresponds to the low 2 bits
+ * of the GPI value, and (except for Root) the concat of NSE:NS.
+ */
+
+typedef enum ARMSecuritySpace {
+    ARMSS_Secure     = 0,
+    ARMSS_NonSecure  = 1,
+    ARMSS_Root       = 2,
+    ARMSS_Realm      = 3,
+} ARMSecuritySpace;
+
+/* Return true if @space is secure, in the pre-v9 sense. */
+static inline bool arm_space_is_secure(ARMSecuritySpace space)
+{
+    return space == ARMSS_Secure || space == ARMSS_Root;
+}
+
+/* Return the ARMSecuritySpace for @secure, assuming !RME or EL[0-2]. */
+static inline ARMSecuritySpace arm_secure_to_space(bool secure)
+{
+    return secure ? ARMSS_Secure : ARMSS_NonSecure;
+}
+
 #if !defined(CONFIG_USER_ONLY)
-/* Return true if exception levels below EL3 are in secure state,
- * or would be following an exception return to that level.
- * Unlike arm_is_secure() (which is always a question about the
- * _current_ state of the CPU) this doesn't care about the current
- * EL or mode.
+/**
+ * arm_security_space_below_el3:
+ * @env: cpu context
+ *
+ * Return the security space of exception levels below EL3, following
+ * an exception return to those levels.  Unlike arm_security_space,
+ * this doesn't care about the current EL.
+ */
+ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env);
+
+/**
+ * arm_is_secure_below_el3:
+ * @env: cpu context
+ *
+ * Return true if exception levels below EL3 are in secure state,
+ * or would be following an exception return to those levels.
  */
 static inline bool arm_is_secure_below_el3(CPUARMState *env)
 {
-    if (arm_feature(env, ARM_FEATURE_EL3)) {
-        return !(env->cp15.scr_el3 & SCR_NS);
-    } else {
-        /* If EL3 is not supported then the secure state is implementation
-         * defined, in which case QEMU defaults to non-secure.
-         */
-        return false;
-    }
+    ARMSecuritySpace ss = arm_security_space_below_el3(env);
+    return ss == ARMSS_Secure;
 }
 
 /* Return true if the CPU is AArch64 EL3 or AArch32 Mon */
@@ -2432,13 +2462,24 @@ static inline bool arm_is_el3_or_mon(CPUARMState *env)
     return false;
 }
 
-/* Return true if the processor is in secure state */
+/**
+ * arm_security_space:
+ * @env: cpu context
+ *
+ * Return the current security space of the cpu.
+ */
+ARMSecuritySpace arm_security_space(CPUARMState *env);
+
+/**
+ * arm_is_secure:
+ * @env: cpu context
+ *
+ * Return true if the processor is in secure state.
+ */
 static inline bool arm_is_secure(CPUARMState *env)
 {
-    if (arm_is_el3_or_mon(env)) {
-        return true;
-    }
-    return arm_is_secure_below_el3(env);
+    ARMSecuritySpace ss = arm_security_space(env);
+    return ss == ARMSS_Secure || ss == ARMSS_Root;
 }
 
 /*
@@ -2457,11 +2498,21 @@ static inline bool arm_is_el2_enabled(CPUARMState *env)
 }
 
 #else
+static inline ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env)
+{
+    return ARMSS_NonSecure;
+}
+
 static inline bool arm_is_secure_below_el3(CPUARMState *env)
 {
     return false;
 }
 
+static inline ARMSecuritySpace arm_security_space(CPUARMState *env)
+{
+    return ARMSS_NonSecure;
+}
+
 static inline bool arm_is_secure(CPUARMState *env)
 {
     return false;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7bd15e9d17..bf78a1d74e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -12280,3 +12280,49 @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
     }
 }
 #endif
+
+#ifndef CONFIG_USER_ONLY
+ARMSecuritySpace arm_security_space(CPUARMState *env)
+{
+    if (!arm_feature(env, ARM_FEATURE_EL3)) {
+        return ARMSS_NonSecure;
+    }
+
+    /* Check for AArch64 EL3 or AArch32 Mon. */
+    if (is_a64(env)) {
+        if (extract32(env->pstate, 2, 2) == 3) {
+            if (cpu_isar_feature(aa64_rme, env_archcpu(env))) {
+                return ARMSS_Root;
+            } else {
+                return ARMSS_Secure;
+            }
+        }
+    } else {
+        if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) {
+            return ARMSS_Secure;
+        }
+    }
+
+    return arm_security_space_below_el3(env);
+}
+
+ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env)
+{
+    if (!arm_feature(env, ARM_FEATURE_EL3)) {
+        return ARMSS_NonSecure;
+    }
+
+    /*
+     * Note NSE cannot be set without RME, and NSE & !NS is Reserved.
+     * Ignoring NSE when !NS retains consistency without having to
+     * modify other predicates.
+     */
+    if (!(env->cp15.scr_el3 & SCR_NS)) {
+        return ARMSS_Secure;
+    } else if (env->cp15.scr_el3 & SCR_NSE) {
+        return ARMSS_Realm;
+    } else {
+        return ARMSS_NonSecure;
+    }
+}
+#endif /* !CONFIG_USER_ONLY */
-- 
2.34.1



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

* [PATCH 08/22] include/exec/memattrs: Add two bits of space to MemTxAttrs
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (6 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 07/22] target/arm: Introduce ARMSecuritySpace Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 15:05   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 09/22] target/arm: Adjust the order of Phys and Stage2 ARMMMUIdx Richard Henderson
                   ` (13 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

We will need 2 bits to represent ARMSecurityState.

Do not attempt to replace or widen secure, even though it
logically overlaps the new field -- there are uses within
e.g. hw/block/pflash_cfi01.c, which don't know anything
specific about ARM.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/memattrs.h | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
index 9fb98bc1ef..d04170aa27 100644
--- a/include/exec/memattrs.h
+++ b/include/exec/memattrs.h
@@ -29,10 +29,17 @@ typedef struct MemTxAttrs {
      * "didn't specify" if necessary.
      */
     unsigned int unspecified:1;
-    /* ARM/AMBA: TrustZone Secure access
+    /*
+     * ARM/AMBA: TrustZone Secure access
      * x86: System Management Mode access
      */
     unsigned int secure:1;
+    /*
+     * ARM: ArmSecuritySpace.  This partially overlaps secure, but it is
+     * easier to have both fields to assist code that does not understand
+     * ARMv9 RME, or no specific knowledge of ARM at all (e.g. pflash).
+     */
+    unsigned int space:2;
     /* Memory access is usermode (unprivileged) */
     unsigned int user:1;
     /*
-- 
2.34.1



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

* [PATCH 09/22] target/arm: Adjust the order of Phys and Stage2 ARMMMUIdx
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (7 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 08/22] include/exec/memattrs: Add two bits of space to MemTxAttrs Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 15:07   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 10/22] target/arm: Introduce ARMMMUIdx_Phys_{Realm,Root} Richard Henderson
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

It will be helpful to have ARMMMUIdx_Phys_* to be in the same
relative order as ARMSecuritySpace enumerators. This requires
the adjustment to the nstable check. While there, check for being
in secure state rather than rely on clearing the low bit making
no change to non-secure state.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h | 12 ++++++------
 target/arm/ptw.c | 10 ++++------
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index cfc62d60b0..0114e1ed87 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3057,18 +3057,18 @@ typedef enum ARMMMUIdx {
     ARMMMUIdx_E2        = 6 | ARM_MMU_IDX_A,
     ARMMMUIdx_E3        = 7 | ARM_MMU_IDX_A,
 
-    /* TLBs with 1-1 mapping to the physical address spaces. */
-    ARMMMUIdx_Phys_NS   = 8 | ARM_MMU_IDX_A,
-    ARMMMUIdx_Phys_S    = 9 | ARM_MMU_IDX_A,
-
     /*
      * Used for second stage of an S12 page table walk, or for descriptor
      * loads during first stage of an S1 page table walk.  Note that both
      * are in use simultaneously for SecureEL2: the security state for
      * the S2 ptw is selected by the NS bit from the S1 ptw.
      */
-    ARMMMUIdx_Stage2    = 10 | ARM_MMU_IDX_A,
-    ARMMMUIdx_Stage2_S  = 11 | ARM_MMU_IDX_A,
+    ARMMMUIdx_Stage2_S  = 8 | ARM_MMU_IDX_A,
+    ARMMMUIdx_Stage2    = 9 | ARM_MMU_IDX_A,
+
+    /* TLBs with 1-1 mapping to the physical address spaces. */
+    ARMMMUIdx_Phys_S    = 10 | ARM_MMU_IDX_A,
+    ARMMMUIdx_Phys_NS   = 11 | ARM_MMU_IDX_A,
 
     /*
      * These are not allocated TLBs and are used only for AT system
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 437f6fefa9..59cf64d0a6 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1410,16 +1410,14 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
     descaddr |= (address >> (stride * (4 - level))) & indexmask;
     descaddr &= ~7ULL;
     nstable = extract32(tableattrs, 4, 1);
-    if (nstable) {
+    if (nstable && ptw->in_secure) {
         /*
          * Stage2_S -> Stage2 or Phys_S -> Phys_NS
          * Assert that the non-secure idx are even, and relative order.
          */
-        QEMU_BUILD_BUG_ON((ARMMMUIdx_Phys_NS & 1) != 0);
-        QEMU_BUILD_BUG_ON((ARMMMUIdx_Stage2 & 1) != 0);
-        QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_NS + 1 != ARMMMUIdx_Phys_S);
-        QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2 + 1 != ARMMMUIdx_Stage2_S);
-        ptw->in_ptw_idx &= ~1;
+        QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_S + 1 != ARMMMUIdx_Phys_NS);
+        QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2_S + 1 != ARMMMUIdx_Stage2);
+        ptw->in_ptw_idx += 1;
         ptw->in_secure = false;
     }
     if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
-- 
2.34.1



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

* [PATCH 10/22] target/arm: Introduce ARMMMUIdx_Phys_{Realm,Root}
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (8 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 09/22] target/arm: Adjust the order of Phys and Stage2 ARMMMUIdx Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 15:09   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 11/22] target/arm: Pipe ARMSecuritySpace through ptw.c Richard Henderson
                   ` (11 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

With FEAT_RME, there are four physical address spaces.
For now, just define the symbols, and mention them in
the same spots as the other Phys indexes in ptw.c.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu-param.h |  2 +-
 target/arm/cpu.h       | 17 +++++++++++++++--
 target/arm/ptw.c       | 10 ++++++++--
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
index 53cac9c89b..8dfd7a0bb6 100644
--- a/target/arm/cpu-param.h
+++ b/target/arm/cpu-param.h
@@ -47,6 +47,6 @@
     bool guarded;
 #endif
 
-#define NB_MMU_MODES 12
+#define NB_MMU_MODES 14
 
 #endif
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0114e1ed87..21b9afb773 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3067,8 +3067,10 @@ typedef enum ARMMMUIdx {
     ARMMMUIdx_Stage2    = 9 | ARM_MMU_IDX_A,
 
     /* TLBs with 1-1 mapping to the physical address spaces. */
-    ARMMMUIdx_Phys_S    = 10 | ARM_MMU_IDX_A,
-    ARMMMUIdx_Phys_NS   = 11 | ARM_MMU_IDX_A,
+    ARMMMUIdx_Phys_S     = 10 | ARM_MMU_IDX_A,
+    ARMMMUIdx_Phys_NS    = 11 | ARM_MMU_IDX_A,
+    ARMMMUIdx_Phys_Root  = 12 | ARM_MMU_IDX_A,
+    ARMMMUIdx_Phys_Realm = 13 | ARM_MMU_IDX_A,
 
     /*
      * These are not allocated TLBs and are used only for AT system
@@ -3132,6 +3134,17 @@ typedef enum ARMASIdx {
     ARMASIdx_TagS = 3,
 } ARMASIdx;
 
+static inline ARMMMUIdx arm_space_to_phys(ARMSecuritySpace space)
+{
+    return ARMMMUIdx_Phys_S + space;
+}
+
+static inline ARMSecuritySpace arm_phys_to_space(ARMMMUIdx idx)
+{
+    assert(idx >= ARMMMUIdx_Phys_S && idx <= ARMMMUIdx_Phys_Realm);
+    return idx - ARMMMUIdx_Phys_S;
+}
+
 static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
 {
     /* If all the CLIDR.Ctypem bits are 0 there are no caches, and
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 59cf64d0a6..49b8895a4e 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -182,8 +182,10 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
     case ARMMMUIdx_E3:
         break;
 
-    case ARMMMUIdx_Phys_NS:
     case ARMMMUIdx_Phys_S:
+    case ARMMMUIdx_Phys_NS:
+    case ARMMMUIdx_Phys_Root:
+    case ARMMMUIdx_Phys_Realm:
         /* No translation for physical address spaces. */
         return true;
 
@@ -2632,8 +2634,10 @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
     switch (mmu_idx) {
     case ARMMMUIdx_Stage2:
     case ARMMMUIdx_Stage2_S:
-    case ARMMMUIdx_Phys_NS:
     case ARMMMUIdx_Phys_S:
+    case ARMMMUIdx_Phys_NS:
+    case ARMMMUIdx_Phys_Root:
+    case ARMMMUIdx_Phys_Realm:
         break;
 
     default:
@@ -2830,6 +2834,8 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
     switch (mmu_idx) {
     case ARMMMUIdx_Phys_S:
     case ARMMMUIdx_Phys_NS:
+    case ARMMMUIdx_Phys_Root:
+    case ARMMMUIdx_Phys_Realm:
         /* Checking Phys early avoids special casing later vs regime_el. */
         return get_phys_addr_disabled(env, address, access_type, mmu_idx,
                                       is_secure, result, fi);
-- 
2.34.1



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

* [PATCH 11/22] target/arm: Pipe ARMSecuritySpace through ptw.c
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (9 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 10/22] target/arm: Introduce ARMMMUIdx_Phys_{Realm,Root} Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-07 16:15   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 12/22] target/arm: NSTable is RES0 for the RME EL3 regime Richard Henderson
                   ` (10 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Add input and output space members to S1Translate.
Set and adjust them in S1_ptw_translate, and the
various points at which we drop secure state.
Initialize the space in get_phys_addr; for now
leave get_phys_addr_with_secure considering only
secure vs non-secure spaces.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 95 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 76 insertions(+), 19 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 49b8895a4e..c1b0b8e610 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -19,11 +19,13 @@
 typedef struct S1Translate {
     ARMMMUIdx in_mmu_idx;
     ARMMMUIdx in_ptw_idx;
+    ARMSecuritySpace in_space;
     bool in_secure;
     bool in_debug;
     bool out_secure;
     bool out_rw;
     bool out_be;
+    ARMSecuritySpace out_space;
     hwaddr out_virt;
     hwaddr out_phys;
     void *out_host;
@@ -218,6 +220,7 @@ static bool S2_attrs_are_device(uint64_t hcr, uint8_t attrs)
 static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
                              hwaddr addr, ARMMMUFaultInfo *fi)
 {
+    ARMSecuritySpace space = ptw->in_space;
     bool is_secure = ptw->in_secure;
     ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
     ARMMMUIdx s2_mmu_idx = ptw->in_ptw_idx;
@@ -234,7 +237,8 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
         if (regime_is_stage2(s2_mmu_idx)) {
             S1Translate s2ptw = {
                 .in_mmu_idx = s2_mmu_idx,
-                .in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS,
+                .in_ptw_idx = arm_space_to_phys(space),
+                .in_space = space,
                 .in_secure = is_secure,
                 .in_debug = true,
             };
@@ -292,10 +296,17 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
     }
 
     /* Check if page table walk is to secure or non-secure PA space. */
-    ptw->out_secure = (is_secure
-                       && !(pte_secure
+    if (is_secure) {
+        bool out_secure = !(pte_secure
                             ? env->cp15.vstcr_el2 & VSTCR_SW
-                            : env->cp15.vtcr_el2 & VTCR_NSW));
+                            : env->cp15.vtcr_el2 & VTCR_NSW);
+        if (!out_secure) {
+            is_secure = false;
+            space = ARMSS_NonSecure;
+        }
+    }
+    ptw->out_secure = is_secure;
+    ptw->out_space = space;
     ptw->out_be = regime_translation_big_endian(env, mmu_idx);
     return true;
 
@@ -326,7 +337,10 @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw,
         }
     } else {
         /* Page tables are in MMIO. */
-        MemTxAttrs attrs = { .secure = ptw->out_secure };
+        MemTxAttrs attrs = {
+            .secure = ptw->out_secure,
+            .space = ptw->out_space,
+        };
         AddressSpace *as = arm_addressspace(cs, attrs);
         MemTxResult result = MEMTX_OK;
 
@@ -369,7 +383,10 @@ static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw,
 #endif
     } else {
         /* Page tables are in MMIO. */
-        MemTxAttrs attrs = { .secure = ptw->out_secure };
+        MemTxAttrs attrs = {
+            .secure = ptw->out_secure,
+            .space = ptw->out_space,
+        };
         AddressSpace *as = arm_addressspace(cs, attrs);
         MemTxResult result = MEMTX_OK;
 
@@ -875,6 +892,7 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
          * regime, because the attribute will already be non-secure.
          */
         result->f.attrs.secure = false;
+        result->f.attrs.space = ARMSS_NonSecure;
     }
     result->f.phys_addr = phys_addr;
     return false;
@@ -1579,6 +1597,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
          * regime, because the attribute will already be non-secure.
          */
         result->f.attrs.secure = false;
+        result->f.attrs.space = ARMSS_NonSecure;
     }
 
     /* When in aarch64 mode, and BTI is enabled, remember GP in the TLB.  */
@@ -2363,6 +2382,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
              */
             if (sattrs.ns) {
                 result->f.attrs.secure = false;
+                result->f.attrs.space = ARMSS_NonSecure;
             } else if (!secure) {
                 /*
                  * NS access to S memory must fault.
@@ -2712,6 +2732,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
     bool is_secure = ptw->in_secure;
     bool ret, ipa_secure, s2walk_secure;
     ARMCacheAttrs cacheattrs1;
+    ARMSecuritySpace ipa_space, s2walk_space;
     bool is_el0;
     uint64_t hcr;
 
@@ -2724,20 +2745,24 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
 
     ipa = result->f.phys_addr;
     ipa_secure = result->f.attrs.secure;
+    ipa_space = result->f.attrs.space;
     if (is_secure) {
         /* Select TCR based on the NS bit from the S1 walk. */
         s2walk_secure = !(ipa_secure
                           ? env->cp15.vstcr_el2 & VSTCR_SW
                           : env->cp15.vtcr_el2 & VTCR_NSW);
+        s2walk_space = arm_secure_to_space(s2walk_secure);
     } else {
         assert(!ipa_secure);
         s2walk_secure = false;
+        s2walk_space = ipa_space;
     }
 
     is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
     ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
-    ptw->in_ptw_idx = s2walk_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
+    ptw->in_ptw_idx = arm_space_to_phys(s2walk_space);
     ptw->in_secure = s2walk_secure;
+    ptw->in_space = s2walk_space;
 
     /*
      * S1 is done, now do S2 translation.
@@ -2825,11 +2850,12 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
     ARMMMUIdx s1_mmu_idx;
 
     /*
-     * The page table entries may downgrade secure to non-secure, but
-     * cannot upgrade an non-secure translation regime's attributes
-     * to secure.
+     * The page table entries may downgrade secure to NonSecure, but
+     * cannot upgrade a NonSecure translation regime's attributes
+     * to Secure or Realm.
      */
     result->f.attrs.secure = is_secure;
+    result->f.attrs.space = ptw->in_space;
 
     switch (mmu_idx) {
     case ARMMMUIdx_Phys_S:
@@ -2871,7 +2897,7 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
 
     default:
         /* Single stage and second stage uses physical for ptw. */
-        ptw->in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
+        ptw->in_ptw_idx = arm_space_to_phys(ptw->in_space);
         break;
     }
 
@@ -2946,6 +2972,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
     S1Translate ptw = {
         .in_mmu_idx = mmu_idx,
         .in_secure = is_secure,
+        .in_space = arm_secure_to_space(is_secure),
     };
     return get_phys_addr_with_struct(env, &ptw, address, access_type,
                                      result, fi);
@@ -2955,7 +2982,10 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
                    MMUAccessType access_type, ARMMMUIdx mmu_idx,
                    GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
 {
-    bool is_secure;
+    S1Translate ptw = {
+        .in_mmu_idx = mmu_idx,
+    };
+    ARMSecuritySpace ss;
 
     switch (mmu_idx) {
     case ARMMMUIdx_E10_0:
@@ -2968,30 +2998,55 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
     case ARMMMUIdx_Stage1_E1:
     case ARMMMUIdx_Stage1_E1_PAN:
     case ARMMMUIdx_E2:
-        is_secure = arm_is_secure_below_el3(env);
+        ss = arm_security_space_below_el3(env);
         break;
     case ARMMMUIdx_Stage2:
+        /*
+         * For Secure EL2, we need this index to be NonSecure;
+         * otherwise this will already be NonSecure or Realm.
+         */
+        ss = arm_security_space_below_el3(env);
+        if (ss == ARMSS_Secure) {
+            ss = ARMSS_NonSecure;
+        }
+        break;
     case ARMMMUIdx_Phys_NS:
     case ARMMMUIdx_MPrivNegPri:
     case ARMMMUIdx_MUserNegPri:
     case ARMMMUIdx_MPriv:
     case ARMMMUIdx_MUser:
-        is_secure = false;
+        ss = ARMSS_NonSecure;
         break;
-    case ARMMMUIdx_E3:
     case ARMMMUIdx_Stage2_S:
     case ARMMMUIdx_Phys_S:
     case ARMMMUIdx_MSPrivNegPri:
     case ARMMMUIdx_MSUserNegPri:
     case ARMMMUIdx_MSPriv:
     case ARMMMUIdx_MSUser:
-        is_secure = true;
+        ss = ARMSS_Secure;
+        break;
+    case ARMMMUIdx_E3:
+        if (arm_feature(env, ARM_FEATURE_AARCH64) &&
+            cpu_isar_feature(aa64_rme, env_archcpu(env))) {
+            ss = ARMSS_Root;
+        } else {
+            ss = ARMSS_Secure;
+        }
+        break;
+    case ARMMMUIdx_Phys_Root:
+        ss = ARMSS_Root;
+        break;
+    case ARMMMUIdx_Phys_Realm:
+        ss = ARMSS_Realm;
         break;
     default:
         g_assert_not_reached();
     }
-    return get_phys_addr_with_secure(env, address, access_type, mmu_idx,
-                                     is_secure, result, fi);
+
+    ptw.in_space = ss;
+    ptw.in_secure = arm_space_is_secure(ss);
+    return get_phys_addr_with_struct(env, &ptw, address, access_type,
+                                     result, fi);
 }
 
 hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
@@ -2999,9 +3054,11 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
+    ARMSecuritySpace ss = arm_security_space(env);
     S1Translate ptw = {
         .in_mmu_idx = arm_mmu_idx(env),
-        .in_secure = arm_is_secure(env),
+        .in_space = ss,
+        .in_secure = arm_space_is_secure(ss),
         .in_debug = true,
     };
     GetPhysAddrResult res = {};
-- 
2.34.1



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

* [PATCH 12/22] target/arm: NSTable is RES0 for the RME EL3 regime
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (10 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 11/22] target/arm: Pipe ARMSecuritySpace through ptw.c Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 11:36   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 13/22] target/arm: Handle Block and Page bits for security space Richard Henderson
                   ` (9 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Test in_space instead of in_secure so that we don't switch
out of Root space.  Handle the output space change immediately,
rather than try and combine the NSTable and NS bits later.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 31 ++++++++++++++-----------------
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index c1b0b8e610..ddafb1f329 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1240,7 +1240,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
 {
     ARMCPU *cpu = env_archcpu(env);
     ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
-    bool is_secure = ptw->in_secure;
     int32_t level;
     ARMVAParameters param;
     uint64_t ttbr;
@@ -1256,7 +1255,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
     uint64_t descaddrmask;
     bool aarch64 = arm_el_is_aa64(env, el);
     uint64_t descriptor, new_descriptor;
-    bool nstable;
 
     /* TODO: This code does not support shareability levels. */
     if (aarch64) {
@@ -1417,29 +1415,29 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
         descaddrmask = MAKE_64BIT_MASK(0, 40);
     }
     descaddrmask &= ~indexmask_grainsize;
-
-    /*
-     * Secure accesses start with the page table in secure memory and
-     * can be downgraded to non-secure at any step. Non-secure accesses
-     * remain non-secure. We implement this by just ORing in the NSTable/NS
-     * bits at each step.
-     */
-    tableattrs = is_secure ? 0 : (1 << 4);
+    tableattrs = 0;
 
  next_level:
     descaddr |= (address >> (stride * (4 - level))) & indexmask;
     descaddr &= ~7ULL;
-    nstable = extract32(tableattrs, 4, 1);
-    if (nstable && ptw->in_secure) {
-        /*
-         * Stage2_S -> Stage2 or Phys_S -> Phys_NS
-         * Assert that the non-secure idx are even, and relative order.
-         */
+
+    /*
+     * Process the NSTable bit from the previous level.  This changes
+     * the table address space and the output space from Secure to
+     * NonSecure.  With RME, the EL3 translation regime does not change
+     * from Root to NonSecure.
+     */
+    if (extract32(tableattrs, 4, 1) && ptw->in_space == ARMSS_Secure) {
+        /* Stage2_S -> Stage2 or Phys_S -> Phys_NS */
         QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_S + 1 != ARMMMUIdx_Phys_NS);
         QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2_S + 1 != ARMMMUIdx_Stage2);
         ptw->in_ptw_idx += 1;
         ptw->in_secure = false;
+        ptw->in_space = ARMSS_NonSecure;
+        result->f.attrs.secure = false;
+        result->f.attrs.space = ARMSS_NonSecure;
     }
+
     if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
         goto do_fault;
     }
@@ -1542,7 +1540,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
      */
     attrs = new_descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
     if (!regime_is_stage2(mmu_idx)) {
-        attrs |= nstable << 5; /* NS */
         if (!param.hpd) {
             attrs |= extract64(tableattrs, 0, 2) << 53;     /* XN, PXN */
             /*
-- 
2.34.1



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

* [PATCH 13/22] target/arm: Handle Block and Page bits for security space
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (11 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 12/22] target/arm: NSTable is RES0 for the RME EL3 regime Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 11:53   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 14/22] target/arm: Handle no-execute for Realm and Root regimes Richard Henderson
                   ` (8 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

With Realm security state, bit 55 of a block or page descriptor during
the stage2 walk becomes the NS bit; during the stage1 walk the bit 5
NS bit is RES0.  With Root security state, bit 11 of the block or page
descriptor during the stage1 walk becomes the NSE bit.

Rather than collecting an NS bit and applying it later, compute the
output pa space from the input pa space and unconditionally assign.
This means that we no longer need to adjust the output space earlier
for the NSTable bit.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 74 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 60 insertions(+), 14 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index ddafb1f329..849f5e89ca 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1250,11 +1250,12 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
     int32_t stride;
     int addrsize, inputsize, outputsize;
     uint64_t tcr = regime_tcr(env, mmu_idx);
-    int ap, ns, xn, pxn;
+    int ap, xn, pxn;
     uint32_t el = regime_el(env, mmu_idx);
     uint64_t descaddrmask;
     bool aarch64 = arm_el_is_aa64(env, el);
     uint64_t descriptor, new_descriptor;
+    ARMSecuritySpace out_space;
 
     /* TODO: This code does not support shareability levels. */
     if (aarch64) {
@@ -1434,8 +1435,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
         ptw->in_ptw_idx += 1;
         ptw->in_secure = false;
         ptw->in_space = ARMSS_NonSecure;
-        result->f.attrs.secure = false;
-        result->f.attrs.space = ARMSS_NonSecure;
     }
 
     if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
@@ -1552,12 +1551,66 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
     }
 
     ap = extract32(attrs, 6, 2);
+    out_space = ptw->in_space;
     if (regime_is_stage2(mmu_idx)) {
-        ns = mmu_idx == ARMMMUIdx_Stage2;
+        /*
+         * R_GYNXY: For stage2 in Realm security state, bit 55 is NS.
+         * The bit remains ignored for other security states.
+         */
+        if (out_space == ARMSS_Realm && extract64(attrs, 55, 1)) {
+            out_space = ARMSS_NonSecure;
+        }
         xn = extract64(attrs, 53, 2);
         result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
     } else {
-        ns = extract32(attrs, 5, 1);
+        int ns = extract32(attrs, 5, 1);
+        switch (out_space) {
+        case ARMSS_Root:
+            /*
+             * R_GVZML: Bit 11 becomes the NSE field in the EL3 regime.
+             * R_XTYPW: NSE and NS together select the output pa space.
+             */
+            int nse = extract32(attrs, 11, 1);
+            out_space = (nse << 1) | ns;
+            if (out_space == ARMSS_Secure &&
+                !cpu_isar_feature(aa64_sel2, cpu)) {
+                out_space = ARMSS_NonSecure;
+            }
+            break;
+        case ARMSS_Secure:
+            if (ns) {
+                out_space = ARMSS_NonSecure;
+            }
+            break;
+        case ARMSS_Realm:
+            switch (mmu_idx) {
+            case ARMMMUIdx_Stage1_E0:
+            case ARMMMUIdx_Stage1_E1:
+            case ARMMMUIdx_Stage1_E1_PAN:
+                /* I_CZPRF: For Realm EL1&0 stage1, NS bit is RES0. */
+                break;
+            case ARMMMUIdx_E2:
+            case ARMMMUIdx_E20_0:
+            case ARMMMUIdx_E20_2:
+            case ARMMMUIdx_E20_2_PAN:
+                /*
+                 * R_LYKFZ, R_WGRZN: For Realm EL2 and EL2&1,
+                 * NS changes the output to non-secure space.
+                 */
+                if (ns) {
+                    out_space = ARMSS_NonSecure;
+                }
+                break;
+            default:
+                g_assert_not_reached();
+            }
+            break;
+        case ARMSS_NonSecure:
+            /* R_QRMFF: For NonSecure state, the NS bit is RES0. */
+            break;
+        default:
+            g_assert_not_reached();
+        }
         xn = extract64(attrs, 54, 1);
         pxn = extract64(attrs, 53, 1);
         result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
@@ -1587,15 +1640,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
         }
     }
 
-    if (ns) {
-        /*
-         * The NS bit will (as required by the architecture) have no effect if
-         * the CPU doesn't support TZ or this is a non-secure translation
-         * regime, because the attribute will already be non-secure.
-         */
-        result->f.attrs.secure = false;
-        result->f.attrs.space = ARMSS_NonSecure;
-    }
+    result->f.attrs.space = out_space;
+    result->f.attrs.secure = arm_space_is_secure(out_space);
 
     /* When in aarch64 mode, and BTI is enabled, remember GP in the TLB.  */
     if (aarch64 && cpu_isar_feature(aa64_bti, cpu)) {
-- 
2.34.1



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

* [PATCH 14/22] target/arm: Handle no-execute for Realm and Root regimes
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (12 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 13/22] target/arm: Handle Block and Page bits for security space Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 11:59   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 15/22] target/arm: Use get_phys_addr_with_struct in S1_ptw_translate Richard Henderson
                   ` (7 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

While Root and Realm may read and write data from other spaces,
neither may execute from other pa spaces.

This happens for Stage1 EL3, EL2, EL2&0, but stage2 EL1&0.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 66 ++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 58 insertions(+), 8 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 849f5e89ca..6b6f8195eb 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -909,7 +909,7 @@ do_fault:
  * @xn:      XN (execute-never) bits
  * @s1_is_el0: true if this is S2 of an S1+2 walk for EL0
  */
-static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
+static int get_S2prot_noexecute(int s2ap)
 {
     int prot = 0;
 
@@ -919,6 +919,12 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
     if (s2ap & 2) {
         prot |= PAGE_WRITE;
     }
+    return prot;
+}
+
+static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
+{
+    int prot = get_S2prot_noexecute(s2ap);
 
     if (cpu_isar_feature(any_tts2uxn, env_archcpu(env))) {
         switch (xn) {
@@ -956,12 +962,14 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
  * @mmu_idx: MMU index indicating required translation regime
  * @is_aa64: TRUE if AArch64
  * @ap:      The 2-bit simple AP (AP[2:1])
- * @ns:      NS (non-secure) bit
  * @xn:      XN (execute-never) bit
  * @pxn:     PXN (privileged execute-never) bit
+ * @in_pa:   The original input pa space
+ * @out_pa:  The output pa space, modified by NSTable, NS, and NSE
  */
 static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
-                      int ap, int ns, int xn, int pxn)
+                      int ap, int xn, int pxn,
+                      ARMSecuritySpace in_pa, ARMSecuritySpace out_pa)
 {
     bool is_user = regime_is_user(env, mmu_idx);
     int prot_rw, user_rw;
@@ -982,8 +990,39 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
         }
     }
 
-    if (ns && arm_is_secure(env) && (env->cp15.scr_el3 & SCR_SIF)) {
-        return prot_rw;
+    if (in_pa != out_pa) {
+        switch (in_pa) {
+        case ARMSS_Root:
+            /*
+             * R_ZWRVD: permission fault for insn fetched from non-Root,
+             * I_WWBFB: SIF has no effect in EL3.
+             */
+            return prot_rw;
+        case ARMSS_Realm:
+            /*
+             * R_PKTDS: permission fault for insn fetched from non-Realm,
+             * for Realm EL2 or EL2&0.  The corresponding fault for EL1&0
+             * happens during any stage2 translation.
+             */
+            switch (mmu_idx) {
+            case ARMMMUIdx_E2:
+            case ARMMMUIdx_E20_0:
+            case ARMMMUIdx_E20_2:
+            case ARMMMUIdx_E20_2_PAN:
+                return prot_rw;
+            default:
+                break;
+            }
+            break;
+        case ARMSS_Secure:
+            if (env->cp15.scr_el3 & SCR_SIF) {
+                return prot_rw;
+            }
+            break;
+        default:
+            /* Input NonSecure must have output NonSecure. */
+            g_assert_not_reached();
+        }
     }
 
     /* TODO have_wxn should be replaced with
@@ -1556,12 +1595,16 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
         /*
          * R_GYNXY: For stage2 in Realm security state, bit 55 is NS.
          * The bit remains ignored for other security states.
+         * R_YMCSL: Executing an insn fetched from non-Realm causes
+         * a stage2 permission fault.
          */
         if (out_space == ARMSS_Realm && extract64(attrs, 55, 1)) {
             out_space = ARMSS_NonSecure;
+            result->f.prot = get_S2prot_noexecute(ap);
+        } else {
+            xn = extract64(attrs, 53, 2);
+            result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
         }
-        xn = extract64(attrs, 53, 2);
-        result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
     } else {
         int ns = extract32(attrs, 5, 1);
         switch (out_space) {
@@ -1613,7 +1656,14 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
         }
         xn = extract64(attrs, 54, 1);
         pxn = extract64(attrs, 53, 1);
-        result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
+
+        /*
+         * Note that we modified ptw->in_space earlier for NSTable,
+         * and result->f.attrs was initialized by get_phys_addr, so
+         * that retains a copy of the original security space.
+         */
+        result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, xn, pxn,
+                                    result->f.attrs.space, out_space);
     }
 
     if (!(result->f.prot & (1 << access_type))) {
-- 
2.34.1



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

* [PATCH 15/22] target/arm: Use get_phys_addr_with_struct in S1_ptw_translate
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (13 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 14/22] target/arm: Handle no-execute for Realm and Root regimes Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 13:21   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 16/22] target/arm: Move s1_is_El0 into S1Translate Richard Henderson
                   ` (6 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Do not provide a fast-path for physical addresses,
as those will need to be validated for GPC.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 35 ++++++++++++++---------------------
 1 file changed, 14 insertions(+), 21 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 6b6f8195eb..37f5ff220c 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -234,29 +234,22 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
          * From gdbstub, do not use softmmu so that we don't modify the
          * state of the cpu at all, including softmmu tlb contents.
          */
-        if (regime_is_stage2(s2_mmu_idx)) {
-            S1Translate s2ptw = {
-                .in_mmu_idx = s2_mmu_idx,
-                .in_ptw_idx = arm_space_to_phys(space),
-                .in_space = space,
-                .in_secure = is_secure,
-                .in_debug = true,
-            };
-            GetPhysAddrResult s2 = { };
+        S1Translate s2ptw = {
+            .in_mmu_idx = s2_mmu_idx,
+            .in_ptw_idx = arm_space_to_phys(space),
+            .in_space = space,
+            .in_secure = is_secure,
+            .in_debug = true,
+        };
+        GetPhysAddrResult s2 = { };
 
-            if (get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
-                                   false, &s2, fi)) {
-                goto fail;
-            }
-            ptw->out_phys = s2.f.phys_addr;
-            pte_attrs = s2.cacheattrs.attrs;
-            pte_secure = s2.f.attrs.secure;
-        } else {
-            /* Regime is physical. */
-            ptw->out_phys = addr;
-            pte_attrs = 0;
-            pte_secure = is_secure;
+        if (get_phys_addr_with_struct(env, &s2ptw, addr,
+                                      MMU_DATA_LOAD, &s2, fi)) {
+            goto fail;
         }
+        ptw->out_phys = s2.f.phys_addr;
+        pte_attrs = s2.cacheattrs.attrs;
+        pte_secure = s2.f.attrs.secure;
         ptw->out_host = NULL;
         ptw->out_rw = false;
     } else {
-- 
2.34.1



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

* [PATCH 16/22] target/arm: Move s1_is_El0 into S1Translate
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (14 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 15/22] target/arm: Use get_phys_addr_with_struct in S1_ptw_translate Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 13:23   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 17/22] target/arm: Use get_phys_addr_with_struct for stage2 Richard Henderson
                   ` (5 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Instead of passing this to get_phys_addr_lpae, stash it
in the S1Translate structure.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 21 +++++++--------------
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 37f5ff220c..eaa47f6b62 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -22,6 +22,7 @@ typedef struct S1Translate {
     ARMSecuritySpace in_space;
     bool in_secure;
     bool in_debug;
+    bool in_s1_is_el0;
     bool out_secure;
     bool out_rw;
     bool out_be;
@@ -33,7 +34,7 @@ typedef struct S1Translate {
 
 static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
                                uint64_t address,
-                               MMUAccessType access_type, bool s1_is_el0,
+                               MMUAccessType access_type,
                                GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
     __attribute__((nonnull));
 
@@ -1257,17 +1258,12 @@ static int check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, uint64_t tcr,
  * @ptw: Current and next stage parameters for the walk.
  * @address: virtual address to get physical address for
  * @access_type: MMU_DATA_LOAD, MMU_DATA_STORE or MMU_INST_FETCH
- * @s1_is_el0: if @ptw->in_mmu_idx is ARMMMUIdx_Stage2
- *             (so this is a stage 2 page table walk),
- *             must be true if this is stage 2 of a stage 1+2
- *             walk for an EL0 access. If @mmu_idx is anything else,
- *             @s1_is_el0 is ignored.
  * @result: set on translation success,
  * @fi: set to fault info if the translation fails
  */
 static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
                                uint64_t address,
-                               MMUAccessType access_type, bool s1_is_el0,
+                               MMUAccessType access_type,
                                GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
 {
     ARMCPU *cpu = env_archcpu(env);
@@ -1596,7 +1592,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
             result->f.prot = get_S2prot_noexecute(ap);
         } else {
             xn = extract64(attrs, 53, 2);
-            result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
+            result->f.prot = get_S2prot(env, ap, xn, ptw->in_s1_is_el0);
         }
     } else {
         int ns = extract32(attrs, 5, 1);
@@ -2819,7 +2815,6 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
     bool ret, ipa_secure, s2walk_secure;
     ARMCacheAttrs cacheattrs1;
     ARMSecuritySpace ipa_space, s2walk_space;
-    bool is_el0;
     uint64_t hcr;
 
     ret = get_phys_addr_with_struct(env, ptw, address, access_type, result, fi);
@@ -2844,7 +2839,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
         s2walk_space = ipa_space;
     }
 
-    is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
+    ptw->in_s1_is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
     ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
     ptw->in_ptw_idx = arm_space_to_phys(s2walk_space);
     ptw->in_secure = s2walk_secure;
@@ -2863,8 +2858,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
         ret = get_phys_addr_pmsav8(env, ipa, access_type,
                                    ptw->in_mmu_idx, s2walk_secure, result, fi);
     } else {
-        ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
-                                 is_el0, result, fi);
+        ret = get_phys_addr_lpae(env, ptw, ipa, access_type, result, fi);
     }
     fi->s2addr = ipa;
 
@@ -3040,8 +3034,7 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
     }
 
     if (regime_using_lpae_format(env, mmu_idx)) {
-        return get_phys_addr_lpae(env, ptw, address, access_type, false,
-                                  result, fi);
+        return get_phys_addr_lpae(env, ptw, address, access_type, result, fi);
     } else if (arm_feature(env, ARM_FEATURE_V7) ||
                regime_sctlr(env, mmu_idx) & SCTLR_XP) {
         return get_phys_addr_v6(env, ptw, address, access_type, result, fi);
-- 
2.34.1



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

* [PATCH 17/22] target/arm: Use get_phys_addr_with_struct for stage2
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (15 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 16/22] target/arm: Move s1_is_El0 into S1Translate Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 13:28   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 18/22] target/arm: Add GPC syndrome Richard Henderson
                   ` (4 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

This fixes a bug in which we failed to initialize
the result attributes properly after the memset.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index eaa47f6b62..3205339957 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -32,12 +32,6 @@ typedef struct S1Translate {
     void *out_host;
 } S1Translate;
 
-static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
-                               uint64_t address,
-                               MMUAccessType access_type,
-                               GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
-    __attribute__((nonnull));
-
 static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
                                       target_ulong address,
                                       MMUAccessType access_type,
@@ -2854,12 +2848,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
     cacheattrs1 = result->cacheattrs;
     memset(result, 0, sizeof(*result));
 
-    if (arm_feature(env, ARM_FEATURE_PMSA)) {
-        ret = get_phys_addr_pmsav8(env, ipa, access_type,
-                                   ptw->in_mmu_idx, s2walk_secure, result, fi);
-    } else {
-        ret = get_phys_addr_lpae(env, ptw, ipa, access_type, result, fi);
-    }
+    ret = get_phys_addr_with_struct(env, ptw, ipa, access_type, result, fi);
     fi->s2addr = ipa;
 
     /* Combine the S1 and S2 perms.  */
-- 
2.34.1



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

* [PATCH 18/22] target/arm: Add GPC syndrome
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (16 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 17/22] target/arm: Use get_phys_addr_with_struct for stage2 Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 13:32   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 19/22] target/arm: Implement GPC exceptions Richard Henderson
                   ` (3 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

The function takes the fields as filled in by
the Arm ARM pseudocode for TakeGPCException.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/syndrome.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
index 73df5e3793..3fa926d115 100644
--- a/target/arm/syndrome.h
+++ b/target/arm/syndrome.h
@@ -49,6 +49,7 @@ enum arm_exception_class {
     EC_SYSTEMREGISTERTRAP     = 0x18,
     EC_SVEACCESSTRAP          = 0x19,
     EC_SMETRAP                = 0x1d,
+    EC_GPC                    = 0x1e,
     EC_INSNABORT              = 0x20,
     EC_INSNABORT_SAME_EL      = 0x21,
     EC_PCALIGNMENT            = 0x22,
@@ -237,6 +238,14 @@ static inline uint32_t syn_bxjtrap(int cv, int cond, int rm)
         (cv << 24) | (cond << 20) | rm;
 }
 
+static inline uint32_t syn_gpc(int s2ptw, int ind, int gpcsc,
+                               int cm, int s1ptw, int wnr, int fsc)
+{
+    return (EC_GPC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (s2ptw << 21)
+            | (ind << 20) | (gpcsc << 14) | (cm << 8) | (s1ptw << 7)
+            | (wnr << 6) | fsc;
+}
+
 static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
 {
     return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
-- 
2.34.1



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

* [PATCH 19/22] target/arm: Implement GPC exceptions
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (17 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 18/22] target/arm: Add GPC syndrome Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 13:53   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 20/22] target/arm: Implement the granule protection check Richard Henderson
                   ` (2 subsequent siblings)
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Handle GPC Fault types in arm_deliver_fault, reporting as
either a GPC exception at EL3, or falling through to insn
or data aborts at various exception levels.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h        |  1 +
 target/arm/internals.h  | 27 ++++++++++++
 target/arm/helper.c     |  5 +++
 target/arm/tlb_helper.c | 92 +++++++++++++++++++++++++++++++++++++++--
 4 files changed, 122 insertions(+), 3 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 21b9afb773..7f6f157f54 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -57,6 +57,7 @@
 #define EXCP_UNALIGNED      22   /* v7M UNALIGNED UsageFault */
 #define EXCP_DIVBYZERO      23   /* v7M DIVBYZERO UsageFault */
 #define EXCP_VSERR          24
+#define EXCP_GPC            25   /* v9 Granule Protection Check Fault */
 /* NB: add new EXCP_ defines to the array in arm_log_exception() too */
 
 #define ARMV7M_EXCP_RESET   1
diff --git a/target/arm/internals.h b/target/arm/internals.h
index d9555309df..c9137e814c 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -352,14 +352,27 @@ typedef enum ARMFaultType {
     ARMFault_ICacheMaint,
     ARMFault_QEMU_NSCExec, /* v8M: NS executing in S&NSC memory */
     ARMFault_QEMU_SFault, /* v8M: SecureFault INVTRAN, INVEP or AUVIOL */
+    ARMFault_GPCFOnWalk,
+    ARMFault_GPCFOnOutput,
 } ARMFaultType;
 
+typedef enum ARMGPCF {
+    GPCF_None,
+    GPCF_AddressSize,
+    GPCF_Walk,
+    GPCF_EABT,
+    GPCF_Fail,
+} ARMGPCF;
+
 /**
  * ARMMMUFaultInfo: Information describing an ARM MMU Fault
  * @type: Type of fault
+ * @gpcf: Subtype of ARMFault_GPCFOn{Walk,Output}.
  * @level: Table walk level (for translation, access flag and permission faults)
  * @domain: Domain of the fault address (for non-LPAE CPUs only)
  * @s2addr: Address that caused a fault at stage 2
+ * @paddr: physical address that caused a fault for gpc
+ * @paddr_space: physical address space that caused a fault for gpc
  * @stage2: True if we faulted at stage 2
  * @s1ptw: True if we faulted at stage 2 while doing a stage 1 page-table walk
  * @s1ns: True if we faulted on a non-secure IPA while in secure state
@@ -368,7 +381,10 @@ typedef enum ARMFaultType {
 typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
 struct ARMMMUFaultInfo {
     ARMFaultType type;
+    ARMGPCF gpcf;
     target_ulong s2addr;
+    target_ulong paddr;
+    ARMSecuritySpace paddr_space;
     int level;
     int domain;
     bool stage2;
@@ -542,6 +558,17 @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo *fi)
     case ARMFault_Exclusive:
         fsc = 0x35;
         break;
+    case ARMFault_GPCFOnWalk:
+        assert(fi->level >= -1 && fi->level <= 3);
+        if (fi->level < 0) {
+            fsc = 0b100011;
+        } else {
+            fsc = 0b100100 | fi->level;
+        }
+        break;
+    case ARMFault_GPCFOnOutput:
+        fsc = 0b101000;
+        break;
     default:
         /* Other faults can't occur in a context that requires a
          * long-format status code.
diff --git a/target/arm/helper.c b/target/arm/helper.c
index bf78a1d74e..8d0b9a13c5 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -10014,6 +10014,7 @@ void arm_log_exception(CPUState *cs)
             [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
             [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
             [EXCP_VSERR] = "Virtual SERR",
+            [EXCP_GPC] = "Granule Protection Check",
         };
 
         if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
@@ -10740,6 +10741,10 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
     }
 
     switch (cs->exception_index) {
+    case EXCP_GPC:
+        qemu_log_mask(CPU_LOG_INT, "...with MFAR 0x%" PRIx64 "\n",
+                      env->cp15.mfar_el3);
+        /* fall through */
     case EXCP_PREFETCH_ABORT:
     case EXCP_DATA_ABORT:
         /*
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
index 60abcbebe6..861dc0d566 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tlb_helper.c
@@ -109,17 +109,102 @@ static uint32_t compute_fsr_fsc(CPUARMState *env, ARMMMUFaultInfo *fi,
     return fsr;
 }
 
+static bool report_as_gpc_exception(ARMCPU *cpu, int current_el,
+                                    ARMMMUFaultInfo *fi)
+{
+    bool ret;
+
+    switch (fi->gpcf) {
+    case GPCF_None:
+        return false;
+    case GPCF_AddressSize:
+    case GPCF_Walk:
+    case GPCF_EABT:
+        /* R_PYTGX: GPT faults are reported as GPC. */
+        ret = true;
+        break;
+    case GPCF_Fail:
+        /*
+         * R_BLYPM: A GPF at EL3 is reported as insn or data abort.
+         * R_VBZMW, R_LXHQR: A GPF at EL[0-2] is reported as a GPC
+         * if SCR_EL3.GPF is set, otherwise an insn or data abort.
+         */
+        ret = (cpu->env.cp15.scr_el3 & SCR_GPF) && current_el != 3;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    assert(cpu_isar_feature(aa64_rme, cpu));
+    assert(fi->type == ARMFault_GPCFOnWalk ||
+           fi->type == ARMFault_GPCFOnOutput);
+    assert(fi->level >= 0 && fi->level <= 1);
+
+    return ret;
+}
+
+static unsigned encode_gpcsc(ARMMMUFaultInfo *fi)
+{
+    static uint8_t const gpcsc[] = {
+        [GPCF_AddressSize] = 0b00000,
+        [GPCF_Walk] = 0b00010,
+        [GPCF_Fail] = 0b00110,
+        [GPCF_EABT] = 0b01010,
+    };
+
+    /* Note that we've validated fi->gpcf and fi->level above. */
+    return gpcsc[fi->gpcf] | fi->level;
+}
+
 static G_NORETURN
 void arm_deliver_fault(ARMCPU *cpu, vaddr addr,
                        MMUAccessType access_type,
                        int mmu_idx, ARMMMUFaultInfo *fi)
 {
     CPUARMState *env = &cpu->env;
-    int target_el;
+    int target_el = exception_target_el(env);
+    int current_el = arm_current_el(env);
     bool same_el;
     uint32_t syn, exc, fsr, fsc;
 
-    target_el = exception_target_el(env);
+    if (report_as_gpc_exception(cpu, current_el, fi)) {
+        target_el = 3;
+
+        fsr = compute_fsr_fsc(env, fi, target_el, mmu_idx, &fsc);
+
+        syn = syn_gpc(fi->stage2 && fi->type == ARMFault_GPCFOnWalk,
+                      access_type == MMU_INST_FETCH,
+                      encode_gpcsc(fi), 0, fi->s1ptw,
+                      access_type == MMU_DATA_STORE, fsc);
+
+        env->cp15.mfar_el3 = fi->paddr;
+        switch (fi->paddr_space) {
+        case ARMSS_Secure:
+            break;
+        case ARMSS_NonSecure:
+            env->cp15.mfar_el3 |= R_MFAR_NS_MASK;
+            break;
+        case ARMSS_Root:
+            env->cp15.mfar_el3 |= R_MFAR_NSE_MASK;
+            break;
+        case ARMSS_Realm:
+            env->cp15.mfar_el3 |= R_MFAR_NSE_MASK | R_MFAR_NS_MASK;
+            break;
+        default:
+            g_assert_not_reached();
+        }
+
+        exc = EXCP_GPC;
+        goto do_raise;
+    }
+
+    /* If SCR_EL3.GPF is unset, GPF may still be routed to EL2. */
+    if (fi->gpcf == GPCF_Fail && target_el < 2) {
+        if (arm_hcr_el2_eff(env) & HCR_GPF) {
+            target_el = 2;
+        }
+    }
+
     if (fi->stage2) {
         target_el = 2;
         env->cp15.hpfar_el2 = extract64(fi->s2addr, 12, 47) << 4;
@@ -127,8 +212,8 @@ void arm_deliver_fault(ARMCPU *cpu, vaddr addr,
             env->cp15.hpfar_el2 |= HPFAR_NS;
         }
     }
-    same_el = (arm_current_el(env) == target_el);
 
+    same_el = current_el == target_el;
     fsr = compute_fsr_fsc(env, fi, target_el, mmu_idx, &fsc);
 
     if (access_type == MMU_INST_FETCH) {
@@ -146,6 +231,7 @@ void arm_deliver_fault(ARMCPU *cpu, vaddr addr,
         exc = EXCP_DATA_ABORT;
     }
 
+ do_raise:
     env->exception.vaddress = addr;
     env->exception.fsr = fsr;
     raise_exception(env, exc, syn, target_el);
-- 
2.34.1



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

* [PATCH 20/22] target/arm: Implement the granule protection check
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (18 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 19/22] target/arm: Implement GPC exceptions Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 14:18   ` Peter Maydell
  2023-01-24  0:00 ` [PATCH 21/22] target/arm: Enable RME for -cpu max Richard Henderson
  2023-01-24  0:00 ` [RFC PATCH 22/22] hw/arm/virt: Add some memory for Realm Management Monitor Richard Henderson
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Place the check at the end of get_phys_addr_with_struct,
so that we check all physical results.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/ptw.c | 253 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 234 insertions(+), 19 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 3205339957..8249d93326 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -32,11 +32,18 @@ typedef struct S1Translate {
     void *out_host;
 } S1Translate;
 
-static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
-                                      target_ulong address,
-                                      MMUAccessType access_type,
-                                      GetPhysAddrResult *result,
-                                      ARMMMUFaultInfo *fi)
+static bool get_phys_addr_inner(CPUARMState *env, S1Translate *ptw,
+                                target_ulong address,
+                                MMUAccessType access_type,
+                                GetPhysAddrResult *result,
+                                ARMMMUFaultInfo *fi)
+    __attribute__((nonnull));
+
+static bool get_phys_addr_outer(CPUARMState *env, S1Translate *ptw,
+                                target_ulong address,
+                                MMUAccessType access_type,
+                                GetPhysAddrResult *result,
+                                ARMMMUFaultInfo *fi)
     __attribute__((nonnull));
 
 /* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */
@@ -193,6 +200,197 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
     return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
 }
 
+static bool granule_protection_check(CPUARMState *env, uint64_t paddress,
+                                     ARMSecuritySpace pspace,
+                                     ARMMMUFaultInfo *fi)
+{
+    MemTxAttrs attrs = {
+        .secure = true,
+        .space = ARMSS_Root,
+    };
+    ARMCPU *cpu = env_archcpu(env);
+    uint64_t gpccr = env->cp15.gpccr_el3;
+    unsigned pps, pgs, l0gptsz, level = 0;
+    uint64_t tableaddr, pps_mask, align, entry, index;
+    AddressSpace *as;
+    MemTxResult result;
+    int gpi;
+
+    if (!FIELD_EX64(gpccr, GPCCR, GPC)) {
+        return true;
+    }
+
+    /*
+     * GPC Priority 1 (R_GMGRR):
+     * R_JWCSM: If the configuration of GPCCR_EL3 is invalid,
+     * the access fails as GPT walk fault at level 0.
+     */
+
+    /*
+     * Configuration of PPS to a value exceeding the implemented
+     * physical address size is invalid.
+     */
+    pps = FIELD_EX64(gpccr, GPCCR, PPS);
+    if (pps > FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE)) {
+        goto fault_walk;
+    }
+    pps = pamax_map[pps];
+    pps_mask = MAKE_64BIT_MASK(0, pps);
+
+    switch (FIELD_EX64(gpccr, GPCCR, SH)) {
+    case 0b10: /* outer sharable */
+        break;
+    case 0b00: /* non-sharable */
+    case 0b11: /* inner sharable */
+        /* Inner and Outer non-cacheable requires Outer sharable. */
+        if (FIELD_EX64(gpccr, GPCCR, ORGN) == 0 &&
+            FIELD_EX64(gpccr, GPCCR, IRGN) == 0) {
+            goto fault_walk;
+        }
+        break;
+    default:   /* reserved */
+        goto fault_walk;
+    }
+
+    switch (FIELD_EX64(gpccr, GPCCR, PGS)) {
+    case 0b00: /* 4KB */
+        pgs = 12;
+        break;
+    case 0b01: /* 64KB */
+        pgs = 16;
+        break;
+    case 0b10: /* 16KB */
+        pgs = 14;
+        break;
+    default: /* reserved */
+        goto fault_walk;
+    }
+
+    /* Note this field is read-only and fixed at reset. */
+    l0gptsz = 30 + FIELD_EX64(gpccr, GPCCR, L0GPTSZ);
+
+    /*
+     * GPC Priority 2: Secure, Realm or Root address exceeds PPS.
+     * R_CPDSB: A NonSecure physical address input exceeding PPS
+     * does not experience any fault.
+     */
+    if (paddress & ~pps_mask) {
+        if (pspace == ARMSS_NonSecure) {
+            return true;
+        }
+        goto fault_size;
+    }
+
+    /* GPC Priority 3: the base address of GPTBR_EL3 exceeds PPS. */
+    tableaddr = env->cp15.gptbr_el3 << 12;
+    if (tableaddr & ~pps_mask) {
+        goto fault_size;
+    }
+
+    /*
+     * BADDR is aligned per a function of PPS and L0GPTSZ.
+     * These bits of GPTBR_EL3 are RES0, but are not a configuration error,
+     * unlike the RES0 bits of the GPT entries (R_XNKFZ).
+     */
+    align = MAX(pps - l0gptsz + 3, 12);
+    align = MAKE_64BIT_MASK(0, align);
+    tableaddr &= ~align;
+
+    as = arm_addressspace(env_cpu(env), attrs);
+
+    /* Level 0 lookup. */
+    index = extract64(paddress, l0gptsz, pps - l0gptsz);
+    tableaddr += index * 8;
+    entry = address_space_ldq_le(as, tableaddr, attrs, &result);
+    if (result != MEMTX_OK) {
+        goto fault_eabt;
+    }
+
+    switch (extract32(entry, 0, 4)) {
+    case 1: /* block descriptor */
+        if (entry >> 8) {
+            goto fault_walk; /* RES0 bits not 0 */
+        }
+        gpi = extract32(entry, 4, 4);
+        goto found;
+    case 3: /* table descriptor */
+        tableaddr = entry & ~0xf;
+        align = MAX(l0gptsz - pgs - 1, 12);
+        align = MAKE_64BIT_MASK(0, align);
+        if (tableaddr & (~pps_mask | align)) {
+            goto fault_walk; /* RES0 bits not 0 */
+        }
+        break;
+    default: /* invalid */
+        goto fault_walk;
+    }
+
+    /* Level 1 lookup */
+    level = 1;
+    index = extract64(paddress, pgs + 4, l0gptsz - pgs - 4);
+    tableaddr += index * 8;
+    entry = address_space_ldq_le(as, tableaddr, attrs, &result);
+    if (result != MEMTX_OK) {
+        goto fault_eabt;
+    }
+
+    switch (extract32(entry, 0, 4)) {
+    case 1: /* contiguous descriptor */
+        if (entry >> 10) {
+            goto fault_walk; /* RES0 bits not 0 */
+        }
+        /*
+         * Because the softmmu tlb only works on units of TARGET_PAGE_SIZE,
+         * and because we cannot invalidate by pa, and thus will always
+         * flush entire tlbs, we don't actually care about the range here
+         * and can simply extract the GPI as the result.
+         */
+        if (extract32(entry, 8, 2) == 0) {
+            goto fault_walk; /* reserved contig */
+        }
+        gpi = extract32(entry, 4, 4);
+        break;
+    default:
+        index = extract64(paddress, pgs, 4);
+        gpi = extract64(entry, index * 4, 4);
+        break;
+    }
+
+ found:
+    switch (gpi) {
+    case 0b0000: /* no access */
+        break;
+    case 0b1111: /* all access */
+        return true;
+    case 0b1000:
+    case 0b1001:
+    case 0b1010:
+    case 0b1011:
+        if (pspace == (gpi & 3)) {
+            return true;
+        }
+        break;
+    default:
+        goto fault_walk; /* reserved */
+    }
+
+    fi->gpcf = GPCF_Fail;
+    goto fault_common;
+ fault_eabt:
+    fi->gpcf = GPCF_EABT;
+    goto fault_common;
+ fault_size:
+    fi->gpcf = GPCF_AddressSize;
+    goto fault_common;
+ fault_walk:
+    fi->gpcf = GPCF_Walk;
+ fault_common:
+    fi->level = level;
+    fi->paddr = paddress;
+    fi->paddr_space = pspace;
+    return false;
+}
+
 static bool S2_attrs_are_device(uint64_t hcr, uint8_t attrs)
 {
     /*
@@ -238,8 +436,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
         };
         GetPhysAddrResult s2 = { };
 
-        if (get_phys_addr_with_struct(env, &s2ptw, addr,
-                                      MMU_DATA_LOAD, &s2, fi)) {
+        if (get_phys_addr_outer(env, &s2ptw, addr, MMU_DATA_LOAD, &s2, fi)) {
             goto fail;
         }
         ptw->out_phys = s2.f.phys_addr;
@@ -300,6 +497,9 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
 
  fail:
     assert(fi->type != ARMFault_None);
+    if (fi->type == ARMFault_GPCFOnOutput) {
+        fi->type = ARMFault_GPCFOnWalk;
+    }
     fi->s2addr = addr;
     fi->stage2 = true;
     fi->s1ptw = true;
@@ -2811,7 +3011,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
     ARMSecuritySpace ipa_space, s2walk_space;
     uint64_t hcr;
 
-    ret = get_phys_addr_with_struct(env, ptw, address, access_type, result, fi);
+    ret = get_phys_addr_inner(env, ptw, address, access_type, result, fi);
 
     /* If S1 fails, return early.  */
     if (ret) {
@@ -2848,7 +3048,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
     cacheattrs1 = result->cacheattrs;
     memset(result, 0, sizeof(*result));
 
-    ret = get_phys_addr_with_struct(env, ptw, ipa, access_type, result, fi);
+    ret = get_phys_addr_inner(env, ptw, ipa, access_type, result, fi);
     fi->s2addr = ipa;
 
     /* Combine the S1 and S2 perms.  */
@@ -2908,11 +3108,11 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
     return false;
 }
 
-static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
-                                      target_ulong address,
-                                      MMUAccessType access_type,
-                                      GetPhysAddrResult *result,
-                                      ARMMMUFaultInfo *fi)
+static bool get_phys_addr_inner(CPUARMState *env, S1Translate *ptw,
+                                target_ulong address,
+                                MMUAccessType access_type,
+                                GetPhysAddrResult *result,
+                                ARMMMUFaultInfo *fi)
 {
     ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
     bool is_secure = ptw->in_secure;
@@ -3032,6 +3232,23 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
     }
 }
 
+static bool get_phys_addr_outer(CPUARMState *env, S1Translate *ptw,
+                                target_ulong address,
+                                MMUAccessType access_type,
+                                GetPhysAddrResult *result,
+                                ARMMMUFaultInfo *fi)
+{
+    if (get_phys_addr_inner(env, ptw, address, access_type, result, fi)) {
+        return true;
+    }
+    if (!granule_protection_check(env, result->f.phys_addr,
+                                  result->f.attrs.space, fi)) {
+        fi->type = ARMFault_GPCFOnOutput;
+        return true;
+    }
+    return false;
+}
+
 bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
                                MMUAccessType access_type, ARMMMUIdx mmu_idx,
                                bool is_secure, GetPhysAddrResult *result,
@@ -3042,8 +3259,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
         .in_secure = is_secure,
         .in_space = arm_secure_to_space(is_secure),
     };
-    return get_phys_addr_with_struct(env, &ptw, address, access_type,
-                                     result, fi);
+    return get_phys_addr_outer(env, &ptw, address, access_type, result, fi);
 }
 
 bool get_phys_addr(CPUARMState *env, target_ulong address,
@@ -3113,8 +3329,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
 
     ptw.in_space = ss;
     ptw.in_secure = arm_space_is_secure(ss);
-    return get_phys_addr_with_struct(env, &ptw, address, access_type,
-                                     result, fi);
+    return get_phys_addr_outer(env, &ptw, address, access_type, result, fi);
 }
 
 hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
@@ -3133,7 +3348,7 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
     ARMMMUFaultInfo fi = {};
     bool ret;
 
-    ret = get_phys_addr_with_struct(env, &ptw, addr, MMU_DATA_LOAD, &res, &fi);
+    ret = get_phys_addr_outer(env, &ptw, addr, MMU_DATA_LOAD, &res, &fi);
     *attrs = res.f.attrs;
 
     if (ret) {
-- 
2.34.1



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

* [PATCH 21/22] target/arm: Enable RME for -cpu max
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (19 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 20/22] target/arm: Implement the granule protection check Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 14:20   ` Peter Maydell
  2023-01-24  0:00 ` [RFC PATCH 22/22] hw/arm/virt: Add some memory for Realm Management Monitor Richard Henderson
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

Add a cpu property to set GPCCR_EL3.L0GPTSZ, for testing
various possible configurations.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu64.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 0e021960fb..b9343004fb 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -672,6 +672,40 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp)
     cpu->isar.id_aa64mmfr0 = t;
 }
 
+static void cpu_max_set_l0gptsz(Object *obj, Visitor *v, const char *name,
+                                void *opaque, Error **errp)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    uint32_t value;
+
+    if (!visit_type_uint32(v, name, &value, errp)) {
+        return;
+    }
+
+    /* Encode the value for the GPCCR_EL3 field. */
+    switch (value) {
+    case 30:
+    case 34:
+    case 36:
+    case 39:
+        cpu->reset_l0gptsz = value - 30;
+        break;
+    default:
+        error_setg(errp, "invalid value for l0gptsz");
+        error_append_hint(errp, "valid values are 30, 34, 36, 39\n");
+        break;
+    }
+}
+
+static void cpu_max_get_l0gptsz(Object *obj, Visitor *v, const char *name,
+                                void *opaque, Error **errp)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    uint32_t value = cpu->reset_l0gptsz + 30;
+
+    visit_type_uint32(v, name, &value, errp);
+}
+
 static void aarch64_a57_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
@@ -1200,6 +1234,7 @@ static void aarch64_max_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
     t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1);      /* FEAT_SEL2 */
     t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1);       /* FEAT_DIT */
+    t = FIELD_DP64(t, ID_AA64PFR0, RME, 1);       /* FEAT_RME */
     t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2);      /* FEAT_CSV2_2 */
     t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1);      /* FEAT_CSV3 */
     cpu->isar.id_aa64pfr0 = t;
@@ -1300,6 +1335,8 @@ static void aarch64_max_initfn(Object *obj)
     object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
                         cpu_max_set_sve_max_vq, NULL, NULL);
     qdev_property_add_static(DEVICE(obj), &arm_cpu_lpa2_property);
+    object_property_add(obj, "l0gptsz", "uint32", cpu_max_get_l0gptsz,
+                        cpu_max_set_l0gptsz, NULL, NULL);
 }
 
 static const ARMCPUInfo aarch64_cpus[] = {
-- 
2.34.1



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

* [RFC PATCH 22/22] hw/arm/virt: Add some memory for Realm Management Monitor
  2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
                   ` (20 preceding siblings ...)
  2023-01-24  0:00 ` [PATCH 21/22] target/arm: Enable RME for -cpu max Richard Henderson
@ 2023-01-24  0:00 ` Richard Henderson
  2023-02-10 14:24   ` Peter Maydell
  21 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-01-24  0:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

This is arbitrary, but used by the Huawei TF-A test code.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/hw/arm/virt.h |  2 ++
 hw/arm/virt.c         | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index c7dd59d7f1..bb7ac19358 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -86,6 +86,7 @@ enum {
     VIRT_ACPI_GED,
     VIRT_NVDIMM_ACPI,
     VIRT_PVTIME,
+    VIRT_RMM_MEM,
     VIRT_LOWMEMMAP_LAST,
 };
 
@@ -154,6 +155,7 @@ struct VirtMachineState {
     bool virt;
     bool ras;
     bool mte;
+    bool rmm;
     bool dtb_randomness;
     OnOffAuto acpi;
     VirtGICType gic_version;
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ea2413a0ba..5f1fddd210 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -158,6 +158,7 @@ static const MemMapEntry base_memmap[] = {
     /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
     [VIRT_PLATFORM_BUS] =       { 0x0c000000, 0x02000000 },
     [VIRT_SECURE_MEM] =         { 0x0e000000, 0x01000000 },
+    [VIRT_RMM_MEM] =            { 0x0f000000, 0x00100000 },
     [VIRT_PCIE_MMIO] =          { 0x10000000, 0x2eff0000 },
     [VIRT_PCIE_PIO] =           { 0x3eff0000, 0x00010000 },
     [VIRT_PCIE_ECAM] =          { 0x3f000000, 0x01000000 },
@@ -1601,6 +1602,25 @@ static void create_secure_ram(VirtMachineState *vms,
     g_free(nodename);
 }
 
+static void create_rmm_ram(VirtMachineState *vms,
+                           MemoryRegion *sysmem,
+                           MemoryRegion *tag_sysmem)
+{
+    MemoryRegion *rmm_ram = g_new(MemoryRegion, 1);
+    hwaddr base = vms->memmap[VIRT_RMM_MEM].base;
+    hwaddr size = vms->memmap[VIRT_RMM_MEM].size;
+
+    memory_region_init_ram(rmm_ram, NULL, "virt.rmm-ram", size,
+                           &error_fatal);
+    memory_region_add_subregion(sysmem, base, rmm_ram);
+
+    /* do not fill in fdt to hide rmm from normal world guest */
+
+    if (tag_sysmem) {
+        create_tag_ram(tag_sysmem, base, size, "mach-virt.rmm-tag");
+    }
+}
+
 static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
 {
     const VirtMachineState *board = container_of(binfo, VirtMachineState,
@@ -2273,6 +2293,10 @@ static void machvirt_init(MachineState *machine)
                        machine->ram_size, "mach-virt.tag");
     }
 
+    if (vms->rmm) {
+        create_rmm_ram(vms, sysmem, tag_sysmem);
+    }
+
     vms->highmem_ecam &= (!firmware_loaded || aarch64);
 
     create_rtc(vms);
@@ -2552,6 +2576,20 @@ static void virt_set_mte(Object *obj, bool value, Error **errp)
     vms->mte = value;
 }
 
+static bool virt_get_rmm(Object *obj, Error **errp)
+{
+    VirtMachineState *vms = VIRT_MACHINE(obj);
+
+    return vms->rmm;
+}
+
+static void virt_set_rmm(Object *obj, bool value, Error **errp)
+{
+    VirtMachineState *vms = VIRT_MACHINE(obj);
+
+    vms->rmm = value;
+}
+
 static char *virt_get_gic_version(Object *obj, Error **errp)
 {
     VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -3101,6 +3139,11 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
                                           "guest CPU which implements the ARM "
                                           "Memory Tagging Extension");
 
+    object_class_property_add_bool(oc, "rmm", virt_get_rmm, virt_set_rmm);
+    object_class_property_set_description(oc, "rmm",
+                                          "Set on/off to enable/disable ram "
+                                          "for the Realm Management Monitor");
+
     object_class_property_add_bool(oc, "its", virt_get_its,
                                    virt_set_its);
     object_class_property_set_description(oc, "its",
-- 
2.34.1



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

* Re: [PATCH 01/22] target/arm: Fix pmsav8 stage2 secure parameter
  2023-01-24  0:00 ` [PATCH 01/22] target/arm: Fix pmsav8 stage2 secure parameter Richard Henderson
@ 2023-02-07 14:26   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 14:26 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> We have computed the security state for the stage2 lookup
> into s2walk_secure -- use it.

We've computed *something* into s2walk_secure, but it
doesn't make much sense for PMSAv8 because the VSTCR_EL2
and VTCR_EL2 registers don't exist there. s2walk_secure
also doesn't sound like something we should be using,
because in PMSAv8 there is no "stage 2 walk" being done (there
are no page tables to walk) -- we just use the information in
the EL2 MPU registers.

I think what we want to be passing to get_phys_addr_pmsav8()
is ipa_secure. It's a bit moot, of course, since PMSAv8 doesn't
have TrustZone and for PMSAv8-32 the security state is always
NonSecure. (For PMSAv8-64 it is always Secure, though...)
This means that ipa == address and ipa_secure == is_secure,
since the stage 1 MPU can't change either the address or the
security state. Passing both ipa and ipa_secure to the stage2
call means we're being consistent, I guess.

> Fixes: fca45e3467f ("target/arm: Add PMSAv8r functionality")
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/ptw.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index 57f3615a66..b0f8c59767 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -2727,7 +2727,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
>
>      if (arm_feature(env, ARM_FEATURE_PMSA)) {
>          ret = get_phys_addr_pmsav8(env, ipa, access_type,
> -                                   ptw->in_mmu_idx, is_secure, result, fi);
> +                                   ptw->in_mmu_idx, s2walk_secure, result, fi);
>      } else {
>          ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
>                                   is_el0, result, fi);
> --
> 2.34.1

thanks
-- PMM


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

* Re: [PATCH 03/22] target/arm: Add isar_feature_aa64_rme
  2023-01-24  0:00 ` [PATCH 03/22] target/arm: Add isar_feature_aa64_rme Richard Henderson
@ 2023-02-07 14:31   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 14:31 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Add the missing field for ID_AA64PFR0, and the predicate.
> Disable it if EL3 is forced off by the board or command-line.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 04/22] target/arm: Update SCR and HCR for RME
  2023-01-24  0:00 ` [PATCH 04/22] target/arm: Update SCR and HCR for RME Richard Henderson
@ 2023-02-07 14:34   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 14:34 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Define the missing SCR and HCR bits, allow SCR_NSE and {SCR,HCR}_GPF
> to be set, and invalidate TLBs when NSE changes.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>


Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 05/22] target/arm: SCR_EL3.NS may be RES1
  2023-01-24  0:00 ` [PATCH 05/22] target/arm: SCR_EL3.NS may be RES1 Richard Henderson
@ 2023-02-07 14:39   ` Peter Maydell
  2023-02-07 19:43     ` Richard Henderson
  0 siblings, 1 reply; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 14:39 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:05, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> With RME, SEL2 must also be present to support secure state.
> The NS bit is RES1 if SEL2 is not present.

I couldn't find the bit of the spec that says this --
could you give me a page reference?

thanks
-- PMM


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

* Re: [PATCH 06/22] target/arm: Add RME cpregs
  2023-01-24  0:00 ` [PATCH 06/22] target/arm: Add RME cpregs Richard Henderson
@ 2023-02-07 14:53   ` Peter Maydell
  2023-02-08 21:51     ` Richard Henderson
  0 siblings, 1 reply; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 14:53 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This includes GPCCR, GPTBR, MFAR, the TLB flush insns PAALL,
> PAALLOS, RPALOS, RPAOS, and the cache flush insn CIPAPA.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h    | 19 ++++++++++++
>  target/arm/helper.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 93 insertions(+)
>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

as far as it goes, but don't we also need DC CIGDPAPA when
FEAT_MTE2 is also implemented?

thanks
-- PMM


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

* Re: [PATCH 07/22] target/arm: Introduce ARMSecuritySpace
  2023-01-24  0:00 ` [PATCH 07/22] target/arm: Introduce ARMSecuritySpace Richard Henderson
@ 2023-02-07 15:00   ` Peter Maydell
  2023-02-08 22:00     ` Richard Henderson
  0 siblings, 1 reply; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 15:00 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Introduce both the enumeration and functions to retrieve
> the current state, and state outside of EL3.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h    | 87 +++++++++++++++++++++++++++++++++++----------
>  target/arm/helper.c | 46 ++++++++++++++++++++++++
>  2 files changed, 115 insertions(+), 18 deletions(-)

> +/* Return true if @space is secure, in the pre-v9 sense. */
> +static inline bool arm_space_is_secure(ARMSecuritySpace space)
> +{
> +    return space == ARMSS_Secure || space == ARMSS_Root;
> +}


> +/**
> + * arm_is_secure:
> + * @env: cpu context
> + *
> + * Return true if the processor is in secure state.
> + */
>  static inline bool arm_is_secure(CPUARMState *env)
>  {
> -    if (arm_is_el3_or_mon(env)) {
> -        return true;
> -    }
> -    return arm_is_secure_below_el3(env);
> +    ARMSecuritySpace ss = arm_security_space(env);
> +    return ss == ARMSS_Secure || ss == ARMSS_Root;

maybe
  return arm_space_is_secure(arm_security_space(env));

?

>  }
>
>  /*
> @@ -2457,11 +2498,21 @@ static inline bool arm_is_el2_enabled(CPUARMState *env)
>  }
>
>  #else
> +static inline ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env)
> +{
> +    return ARMSS_NonSecure;
> +}
> +
>  static inline bool arm_is_secure_below_el3(CPUARMState *env)
>  {
>      return false;
>  }
>
> +static inline ARMSecuritySpace arm_security_space(CPUARMState *env)
> +{
> +    return ARMSS_NonSecure;
> +}
> +
>  static inline bool arm_is_secure(CPUARMState *env)
>  {
>      return false;
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 7bd15e9d17..bf78a1d74e 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -12280,3 +12280,49 @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
>      }
>  }
>  #endif
> +
> +#ifndef CONFIG_USER_ONLY
> +ARMSecuritySpace arm_security_space(CPUARMState *env)
> +{
> +    if (!arm_feature(env, ARM_FEATURE_EL3)) {

The old code had a comment
-        /* If EL3 is not supported then the secure state is implementation
-         * defined, in which case QEMU defaults to non-secure.
which should probably go here I guess.

(Though it's not quite so true for R-profile, where you
don't get to make the impdef choice: v8R-32 is always
NS, and v8R-64 always S. If we ever have to implement
the latter this will probably cause some mild pain.)


Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 08/22] include/exec/memattrs: Add two bits of space to MemTxAttrs
  2023-01-24  0:00 ` [PATCH 08/22] include/exec/memattrs: Add two bits of space to MemTxAttrs Richard Henderson
@ 2023-02-07 15:05   ` Peter Maydell
  2023-02-08 22:12     ` Richard Henderson
  0 siblings, 1 reply; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 15:05 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> We will need 2 bits to represent ARMSecurityState.
>
> Do not attempt to replace or widen secure, even though it
> logically overlaps the new field -- there are uses within
> e.g. hw/block/pflash_cfi01.c, which don't know anything
> specific about ARM.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/exec/memattrs.h | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
> index 9fb98bc1ef..d04170aa27 100644
> --- a/include/exec/memattrs.h
> +++ b/include/exec/memattrs.h
> @@ -29,10 +29,17 @@ typedef struct MemTxAttrs {
>       * "didn't specify" if necessary.
>       */
>      unsigned int unspecified:1;
> -    /* ARM/AMBA: TrustZone Secure access
> +    /*
> +     * ARM/AMBA: TrustZone Secure access
>       * x86: System Management Mode access
>       */
>      unsigned int secure:1;
> +    /*
> +     * ARM: ArmSecuritySpace.  This partially overlaps secure, but it is
> +     * easier to have both fields to assist code that does not understand
> +     * ARMv9 RME, or no specific knowledge of ARM at all (e.g. pflash).
> +     */
> +    unsigned int space:2;
>      /* Memory access is usermode (unprivileged) */
>      unsigned int user:1;

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

I guess we aren't so tight on bits in this struct as to
warrant keeping the extra RME info in a single bit (which
should in theory be possible).

thanks
-- PMM


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

* Re: [PATCH 09/22] target/arm: Adjust the order of Phys and Stage2 ARMMMUIdx
  2023-01-24  0:00 ` [PATCH 09/22] target/arm: Adjust the order of Phys and Stage2 ARMMMUIdx Richard Henderson
@ 2023-02-07 15:07   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 15:07 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:02, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> It will be helpful to have ARMMMUIdx_Phys_* to be in the same
> relative order as ARMSecuritySpace enumerators. This requires
> the adjustment to the nstable check. While there, check for being
> in secure state rather than rely on clearing the low bit making
> no change to non-secure state.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h | 12 ++++++------
>  target/arm/ptw.c | 10 ++++------
>  2 files changed, 10 insertions(+), 12 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index cfc62d60b0..0114e1ed87 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -3057,18 +3057,18 @@ typedef enum ARMMMUIdx {
>      ARMMMUIdx_E2        = 6 | ARM_MMU_IDX_A,
>      ARMMMUIdx_E3        = 7 | ARM_MMU_IDX_A,
>
> -    /* TLBs with 1-1 mapping to the physical address spaces. */
> -    ARMMMUIdx_Phys_NS   = 8 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_Phys_S    = 9 | ARM_MMU_IDX_A,
> -
>      /*
>       * Used for second stage of an S12 page table walk, or for descriptor
>       * loads during first stage of an S1 page table walk.  Note that both
>       * are in use simultaneously for SecureEL2: the security state for
>       * the S2 ptw is selected by the NS bit from the S1 ptw.
>       */
> -    ARMMMUIdx_Stage2    = 10 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_Stage2_S  = 11 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_Stage2_S  = 8 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_Stage2    = 9 | ARM_MMU_IDX_A,
> +
> +    /* TLBs with 1-1 mapping to the physical address spaces. */
> +    ARMMMUIdx_Phys_S    = 10 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_Phys_NS   = 11 | ARM_MMU_IDX_A,
>
>      /*
>       * These are not allocated TLBs and are used only for AT system
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index 437f6fefa9..59cf64d0a6 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -1410,16 +1410,14 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>      descaddr |= (address >> (stride * (4 - level))) & indexmask;
>      descaddr &= ~7ULL;
>      nstable = extract32(tableattrs, 4, 1);
> -    if (nstable) {
> +    if (nstable && ptw->in_secure) {
>          /*
>           * Stage2_S -> Stage2 or Phys_S -> Phys_NS
>           * Assert that the non-secure idx are even, and relative order.
>           */

Comment needs updating to match the code change (we're no
longer asserting that the NS indexes are even).

> -        QEMU_BUILD_BUG_ON((ARMMMUIdx_Phys_NS & 1) != 0);
> -        QEMU_BUILD_BUG_ON((ARMMMUIdx_Stage2 & 1) != 0);
> -        QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_NS + 1 != ARMMMUIdx_Phys_S);
> -        QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2 + 1 != ARMMMUIdx_Stage2_S);
> -        ptw->in_ptw_idx &= ~1;
> +        QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_S + 1 != ARMMMUIdx_Phys_NS);
> +        QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2_S + 1 != ARMMMUIdx_Stage2);
> +        ptw->in_ptw_idx += 1;
>          ptw->in_secure = false;
>      }
>      if (!S1_ptw_translate(env, ptw, descaddr, fi)) {

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 10/22] target/arm: Introduce ARMMMUIdx_Phys_{Realm,Root}
  2023-01-24  0:00 ` [PATCH 10/22] target/arm: Introduce ARMMMUIdx_Phys_{Realm,Root} Richard Henderson
@ 2023-02-07 15:09   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 15:09 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> With FEAT_RME, there are four physical address spaces.
> For now, just define the symbols, and mention them in
> the same spots as the other Phys indexes in ptw.c.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu-param.h |  2 +-
>  target/arm/cpu.h       | 17 +++++++++++++++--
>  target/arm/ptw.c       | 10 ++++++++--
>  3 files changed, 24 insertions(+), 5 deletions(-)
>
> diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
> index 53cac9c89b..8dfd7a0bb6 100644
> --- a/target/arm/cpu-param.h
> +++ b/target/arm/cpu-param.h
> @@ -47,6 +47,6 @@
>      bool guarded;
>  #endif
>
> -#define NB_MMU_MODES 12
> +#define NB_MMU_MODES 14
>
>  #endif
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 0114e1ed87..21b9afb773 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -3067,8 +3067,10 @@ typedef enum ARMMMUIdx {
>      ARMMMUIdx_Stage2    = 9 | ARM_MMU_IDX_A,
>
>      /* TLBs with 1-1 mapping to the physical address spaces. */
> -    ARMMMUIdx_Phys_S    = 10 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_Phys_NS   = 11 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_Phys_S     = 10 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_Phys_NS    = 11 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_Phys_Root  = 12 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_Phys_Realm = 13 | ARM_MMU_IDX_A,
>
>      /*
>       * These are not allocated TLBs and are used only for AT system
> @@ -3132,6 +3134,17 @@ typedef enum ARMASIdx {
>      ARMASIdx_TagS = 3,
>  } ARMASIdx;
>
> +static inline ARMMMUIdx arm_space_to_phys(ARMSecuritySpace space)
> +{
> +    return ARMMMUIdx_Phys_S + space;

Compile-time asserts that the mmu idxes are in the same
order as the ARMSecuritySpace enum values, since we're
assuming that here?

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 02/22] target/arm: Rewrite check_s2_mmu_setup
  2023-01-24  0:00 ` [PATCH 02/22] target/arm: Rewrite check_s2_mmu_setup Richard Henderson
@ 2023-02-07 16:00   ` Peter Maydell
  2023-02-07 19:31     ` Richard Henderson
  0 siblings, 1 reply; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 16:00 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Integrate neighboring code from get_phys_addr_lpae which computed
> starting level, as it is easier to validate when doing both at the
> same time.  Mirror the checks at the start of AArch{64,32}.S2Walk,
> especially S2InvalidESL and S2InconsistentSL.
>
> This reverts 49ba115bb74, which was incorrect -- there is nothing
> in the ARM pseudocode that depends on TxSZ, i.e. outputsize; the
> pseudocode is consistent in referencing PAMax.

I'm having difficulty reviewing this one:
 * the latest version of the Arm ARM doesn't have the pseudocode
   functions you refer to, so it's difficult to cross-refer against
   the spec
 * the changes are too large for it to be easy to confirm what's
   just been refactored into the other function and what (if any)
   the behavioural changes are

thanks
-- PMM


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

* Re: [PATCH 11/22] target/arm: Pipe ARMSecuritySpace through ptw.c
  2023-01-24  0:00 ` [PATCH 11/22] target/arm: Pipe ARMSecuritySpace through ptw.c Richard Henderson
@ 2023-02-07 16:15   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-07 16:15 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:06, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Add input and output space members to S1Translate.
> Set and adjust them in S1_ptw_translate, and the
> various points at which we drop secure state.
> Initialize the space in get_phys_addr; for now
> leave get_phys_addr_with_secure considering only
> secure vs non-secure spaces.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---


> @@ -2825,11 +2850,12 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
>      ARMMMUIdx s1_mmu_idx;
>
>      /*
> -     * The page table entries may downgrade secure to non-secure, but
> -     * cannot upgrade an non-secure translation regime's attributes
> -     * to secure.
> +     * The page table entries may downgrade secure to NonSecure, but

"Secure" (just for consistency of capitalization)

> +     * cannot upgrade a NonSecure translation regime's attributes
> +     * to Secure or Realm.
>       */
>      result->f.attrs.secure = is_secure;
> +    result->f.attrs.space = ptw->in_space;
>
>      switch (mmu_idx) {
>      case ARMMMUIdx_Phys_S:

Otherwise

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 02/22] target/arm: Rewrite check_s2_mmu_setup
  2023-02-07 16:00   ` Peter Maydell
@ 2023-02-07 19:31     ` Richard Henderson
  0 siblings, 0 replies; 54+ messages in thread
From: Richard Henderson @ 2023-02-07 19:31 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On 2/7/23 06:00, Peter Maydell wrote:
> On Tue, 24 Jan 2023 at 00:01, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> Integrate neighboring code from get_phys_addr_lpae which computed
>> starting level, as it is easier to validate when doing both at the
>> same time.  Mirror the checks at the start of AArch{64,32}.S2Walk,
>> especially S2InvalidESL and S2InconsistentSL.
>>
>> This reverts 49ba115bb74, which was incorrect -- there is nothing
>> in the ARM pseudocode that depends on TxSZ, i.e. outputsize; the
>> pseudocode is consistent in referencing PAMax.
> 
> I'm having difficulty reviewing this one:
>   * the latest version of the Arm ARM doesn't have the pseudocode
>     functions you refer to, so it's difficult to cross-refer against
>     the spec

DDI 0478 I.a certainly does have them (typo: S2InvalidSL not S2InvalidESL).


r~


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

* Re: [PATCH 05/22] target/arm: SCR_EL3.NS may be RES1
  2023-02-07 14:39   ` Peter Maydell
@ 2023-02-07 19:43     ` Richard Henderson
  0 siblings, 0 replies; 54+ messages in thread
From: Richard Henderson @ 2023-02-07 19:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On 2/7/23 04:39, Peter Maydell wrote:
> On Tue, 24 Jan 2023 at 00:05, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> With RME, SEL2 must also be present to support secure state.
>> The NS bit is RES1 if SEL2 is not present.
> 
> I couldn't find the bit of the spec that says this --
> could you give me a page reference?

DDI0615D.a RME Supplement, R_GSWWH.
and the bit about secure state is I_DJJQJ.


r~



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

* Re: [PATCH 06/22] target/arm: Add RME cpregs
  2023-02-07 14:53   ` Peter Maydell
@ 2023-02-08 21:51     ` Richard Henderson
  0 siblings, 0 replies; 54+ messages in thread
From: Richard Henderson @ 2023-02-08 21:51 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On 2/7/23 04:53, Peter Maydell wrote:
> On Tue, 24 Jan 2023 at 00:01, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> This includes GPCCR, GPTBR, MFAR, the TLB flush insns PAALL,
>> PAALLOS, RPALOS, RPAOS, and the cache flush insn CIPAPA.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   target/arm/cpu.h    | 19 ++++++++++++
>>   target/arm/helper.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 93 insertions(+)
>>
> 
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> 
> as far as it goes, but don't we also need DC CIGDPAPA when
> FEAT_MTE2 is also implemented?

Quite right.


r~



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

* Re: [PATCH 07/22] target/arm: Introduce ARMSecuritySpace
  2023-02-07 15:00   ` Peter Maydell
@ 2023-02-08 22:00     ` Richard Henderson
  0 siblings, 0 replies; 54+ messages in thread
From: Richard Henderson @ 2023-02-08 22:00 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On 2/7/23 05:00, Peter Maydell wrote:
>>   static inline bool arm_is_secure(CPUARMState *env)
>>   {
>> -    if (arm_is_el3_or_mon(env)) {
>> -        return true;
>> -    }
>> -    return arm_is_secure_below_el3(env);
>> +    ARMSecuritySpace ss = arm_security_space(env);
>> +    return ss == ARMSS_Secure || ss == ARMSS_Root;
> 
> maybe
>    return arm_space_is_secure(arm_security_space(env));

Quite right; arm_space_is_secure was something I added later, and failed to propagate 
completely.

>> +#ifndef CONFIG_USER_ONLY
>> +ARMSecuritySpace arm_security_space(CPUARMState *env)
>> +{
>> +    if (!arm_feature(env, ARM_FEATURE_EL3)) {
> 
> The old code had a comment
> -        /* If EL3 is not supported then the secure state is implementation
> -         * defined, in which case QEMU defaults to non-secure.
> which should probably go here I guess.

Ok.


r~


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

* Re: [PATCH 08/22] include/exec/memattrs: Add two bits of space to MemTxAttrs
  2023-02-07 15:05   ` Peter Maydell
@ 2023-02-08 22:12     ` Richard Henderson
  0 siblings, 0 replies; 54+ messages in thread
From: Richard Henderson @ 2023-02-08 22:12 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On 2/7/23 05:05, Peter Maydell wrote:
> On Tue, 24 Jan 2023 at 00:01, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> We will need 2 bits to represent ARMSecurityState.
>>
>> Do not attempt to replace or widen secure, even though it
>> logically overlaps the new field -- there are uses within
>> e.g. hw/block/pflash_cfi01.c, which don't know anything
>> specific about ARM.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   include/exec/memattrs.h | 9 ++++++++-
>>   1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
>> index 9fb98bc1ef..d04170aa27 100644
>> --- a/include/exec/memattrs.h
>> +++ b/include/exec/memattrs.h
>> @@ -29,10 +29,17 @@ typedef struct MemTxAttrs {
>>        * "didn't specify" if necessary.
>>        */
>>       unsigned int unspecified:1;
>> -    /* ARM/AMBA: TrustZone Secure access
>> +    /*
>> +     * ARM/AMBA: TrustZone Secure access
>>        * x86: System Management Mode access
>>        */
>>       unsigned int secure:1;
>> +    /*
>> +     * ARM: ArmSecuritySpace.  This partially overlaps secure, but it is
>> +     * easier to have both fields to assist code that does not understand
>> +     * ARMv9 RME, or no specific knowledge of ARM at all (e.g. pflash).
>> +     */
>> +    unsigned int space:2;
>>       /* Memory access is usermode (unprivileged) */
>>       unsigned int user:1;
> 
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> 
> I guess we aren't so tight on bits in this struct as to
> warrant keeping the extra RME info in a single bit (which
> should in theory be possible).

Indeed not.  And the 3 target_* bits at the end are unused after recent changes.


r~


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

* Re: [PATCH 12/22] target/arm: NSTable is RES0 for the RME EL3 regime
  2023-01-24  0:00 ` [PATCH 12/22] target/arm: NSTable is RES0 for the RME EL3 regime Richard Henderson
@ 2023-02-10 11:36   ` Peter Maydell
  2023-02-10 19:49     ` Richard Henderson
  0 siblings, 1 reply; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 11:36 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Test in_space instead of in_secure so that we don't switch
> out of Root space.  Handle the output space change immediately,
> rather than try and combine the NSTable and NS bits later.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/ptw.c | 31 ++++++++++++++-----------------
>  1 file changed, 14 insertions(+), 17 deletions(-)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index c1b0b8e610..ddafb1f329 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -1240,7 +1240,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>  {
>      ARMCPU *cpu = env_archcpu(env);
>      ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
> -    bool is_secure = ptw->in_secure;
>      int32_t level;
>      ARMVAParameters param;
>      uint64_t ttbr;
> @@ -1256,7 +1255,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>      uint64_t descaddrmask;
>      bool aarch64 = arm_el_is_aa64(env, el);
>      uint64_t descriptor, new_descriptor;
> -    bool nstable;
>
>      /* TODO: This code does not support shareability levels. */
>      if (aarch64) {
> @@ -1417,29 +1415,29 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>          descaddrmask = MAKE_64BIT_MASK(0, 40);
>      }
>      descaddrmask &= ~indexmask_grainsize;
> -
> -    /*
> -     * Secure accesses start with the page table in secure memory and
> -     * can be downgraded to non-secure at any step. Non-secure accesses
> -     * remain non-secure. We implement this by just ORing in the NSTable/NS
> -     * bits at each step.
> -     */
> -    tableattrs = is_secure ? 0 : (1 << 4);
> +    tableattrs = 0;
>
>   next_level:
>      descaddr |= (address >> (stride * (4 - level))) & indexmask;
>      descaddr &= ~7ULL;
> -    nstable = extract32(tableattrs, 4, 1);
> -    if (nstable && ptw->in_secure) {
> -        /*
> -         * Stage2_S -> Stage2 or Phys_S -> Phys_NS
> -         * Assert that the non-secure idx are even, and relative order.
> -         */
> +
> +    /*
> +     * Process the NSTable bit from the previous level.  This changes
> +     * the table address space and the output space from Secure to
> +     * NonSecure.  With RME, the EL3 translation regime does not change
> +     * from Root to NonSecure.
> +     */

To check my understanding, this means that the bit that the spec
describes as FEAT_RME changing the behaviour of NSTable in the EL3
stage 1 translation regime is implemented by us by having the
in_space for EL3 be different for FEAT_RME and not-FEAT_RME ?

> +    if (extract32(tableattrs, 4, 1) && ptw->in_space == ARMSS_Secure) {
> +        /* Stage2_S -> Stage2 or Phys_S -> Phys_NS */
>          QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_S + 1 != ARMMMUIdx_Phys_NS);
>          QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2_S + 1 != ARMMMUIdx_Stage2);
>          ptw->in_ptw_idx += 1;
>          ptw->in_secure = false;
> +        ptw->in_space = ARMSS_NonSecure;
> +        result->f.attrs.secure = false;
> +        result->f.attrs.space = ARMSS_NonSecure;
>      }
> +
>      if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
>          goto do_fault;
>      }
> @@ -1542,7 +1540,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>       */
>      attrs = new_descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
>      if (!regime_is_stage2(mmu_idx)) {
> -        attrs |= nstable << 5; /* NS */

This removes the code where we copy the NSTable bit across to attrs,
but there's still code below here that assumes it can get the combined
NS bit from bit 5 of attrs, isn't there? (It passes it to get_S1prot().)

thanks
-- PMM


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

* Re: [PATCH 13/22] target/arm: Handle Block and Page bits for security space
  2023-01-24  0:00 ` [PATCH 13/22] target/arm: Handle Block and Page bits for security space Richard Henderson
@ 2023-02-10 11:53   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 11:53 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:06, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> With Realm security state, bit 55 of a block or page descriptor during
> the stage2 walk becomes the NS bit; during the stage1 walk the bit 5
> NS bit is RES0.  With Root security state, bit 11 of the block or page
> descriptor during the stage1 walk becomes the NSE bit.
>
> Rather than collecting an NS bit and applying it later, compute the
> output pa space from the input pa space and unconditionally assign.
> This means that we no longer need to adjust the output space earlier
> for the NSTable bit.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/ptw.c | 74 +++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 60 insertions(+), 14 deletions(-)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index ddafb1f329..849f5e89ca 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -1250,11 +1250,12 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>      int32_t stride;
>      int addrsize, inputsize, outputsize;
>      uint64_t tcr = regime_tcr(env, mmu_idx);
> -    int ap, ns, xn, pxn;
> +    int ap, xn, pxn;
>      uint32_t el = regime_el(env, mmu_idx);
>      uint64_t descaddrmask;
>      bool aarch64 = arm_el_is_aa64(env, el);
>      uint64_t descriptor, new_descriptor;
> +    ARMSecuritySpace out_space;
>
>      /* TODO: This code does not support shareability levels. */
>      if (aarch64) {
> @@ -1434,8 +1435,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>          ptw->in_ptw_idx += 1;
>          ptw->in_secure = false;
>          ptw->in_space = ARMSS_NonSecure;
> -        result->f.attrs.secure = false;
> -        result->f.attrs.space = ARMSS_NonSecure;
>      }
>
>      if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
> @@ -1552,12 +1551,66 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>      }
>
>      ap = extract32(attrs, 6, 2);
> +    out_space = ptw->in_space;
>      if (regime_is_stage2(mmu_idx)) {
> -        ns = mmu_idx == ARMMMUIdx_Stage2;
> +        /*
> +         * R_GYNXY: For stage2 in Realm security state, bit 55 is NS.
> +         * The bit remains ignored for other security states.
> +         */
> +        if (out_space == ARMSS_Realm && extract64(attrs, 55, 1)) {
> +            out_space = ARMSS_NonSecure;
> +        }
>          xn = extract64(attrs, 53, 2);
>          result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
>      } else {
> -        ns = extract32(attrs, 5, 1);
> +        int ns = extract32(attrs, 5, 1);
> +        switch (out_space) {
> +        case ARMSS_Root:
> +            /*
> +             * R_GVZML: Bit 11 becomes the NSE field in the EL3 regime.
> +             * R_XTYPW: NSE and NS together select the output pa space.
> +             */
> +            int nse = extract32(attrs, 11, 1);
> +            out_space = (nse << 1) | ns;
> +            if (out_space == ARMSS_Secure &&
> +                !cpu_isar_feature(aa64_sel2, cpu)) {
> +                out_space = ARMSS_NonSecure;
> +            }
> +            break;
> +        case ARMSS_Secure:
> +            if (ns) {
> +                out_space = ARMSS_NonSecure;
> +            }
> +            break;
> +        case ARMSS_Realm:
> +            switch (mmu_idx) {
> +            case ARMMMUIdx_Stage1_E0:
> +            case ARMMMUIdx_Stage1_E1:
> +            case ARMMMUIdx_Stage1_E1_PAN:
> +                /* I_CZPRF: For Realm EL1&0 stage1, NS bit is RES0. */
> +                break;
> +            case ARMMMUIdx_E2:
> +            case ARMMMUIdx_E20_0:
> +            case ARMMMUIdx_E20_2:
> +            case ARMMMUIdx_E20_2_PAN:
> +                /*
> +                 * R_LYKFZ, R_WGRZN: For Realm EL2 and EL2&1,
> +                 * NS changes the output to non-secure space.
> +                 */
> +                if (ns) {
> +                    out_space = ARMSS_NonSecure;
> +                }
> +                break;
> +            default:
> +                g_assert_not_reached();
> +            }
> +            break;
> +        case ARMSS_NonSecure:
> +            /* R_QRMFF: For NonSecure state, the NS bit is RES0. */
> +            break;
> +        default:
> +            g_assert_not_reached();
> +        }
>          xn = extract64(attrs, 54, 1);
>          pxn = extract64(attrs, 53, 1);
>          result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);

Various of these cases say "NS is RES0", but the code is
still extracting it from the attrs bit 5 and passing it
to get_S1prot(), which relies on being passed 1 for any case
where the translation table indicates that the memory is
Non-secure, whether the NS bit in the final block or page descriptor
was 1 or not (it uses it to implement the SCR_EL3.SIF bit).
This used to happen automatically because we set tableattrs to
1 << 4 if the initial access was non-secure, and then that bit
would always end up in attrs bit 5 regardless of what the various
NSTable and NS bits in the descriptors were, but the refactoring
in the previous patch changes that and so we need to do something
else I think.

thanks
-- PMM


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

* Re: [PATCH 14/22] target/arm: Handle no-execute for Realm and Root regimes
  2023-01-24  0:00 ` [PATCH 14/22] target/arm: Handle no-execute for Realm and Root regimes Richard Henderson
@ 2023-02-10 11:59   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 11:59 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:02, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> While Root and Realm may read and write data from other spaces,
> neither may execute from other pa spaces.
>
> This happens for Stage1 EL3, EL2, EL2&0, but stage2 EL1&0.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/ptw.c | 66 ++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 58 insertions(+), 8 deletions(-)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index 849f5e89ca..6b6f8195eb 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -909,7 +909,7 @@ do_fault:
>   * @xn:      XN (execute-never) bits
>   * @s1_is_el0: true if this is S2 of an S1+2 walk for EL0
>   */
> -static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
> +static int get_S2prot_noexecute(int s2ap)
>  {
>      int prot = 0;
>
> @@ -919,6 +919,12 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
>      if (s2ap & 2) {
>          prot |= PAGE_WRITE;
>      }
> +    return prot;
> +}
> +
> +static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
> +{
> +    int prot = get_S2prot_noexecute(s2ap);
>
>      if (cpu_isar_feature(any_tts2uxn, env_archcpu(env))) {
>          switch (xn) {
> @@ -956,12 +962,14 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
>   * @mmu_idx: MMU index indicating required translation regime
>   * @is_aa64: TRUE if AArch64
>   * @ap:      The 2-bit simple AP (AP[2:1])
> - * @ns:      NS (non-secure) bit
>   * @xn:      XN (execute-never) bit
>   * @pxn:     PXN (privileged execute-never) bit
> + * @in_pa:   The original input pa space
> + * @out_pa:  The output pa space, modified by NSTable, NS, and NSE
>   */
>  static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
> -                      int ap, int ns, int xn, int pxn)
> +                      int ap, int xn, int pxn,
> +                      ARMSecuritySpace in_pa, ARMSecuritySpace out_pa)
>  {
>      bool is_user = regime_is_user(env, mmu_idx);
>      int prot_rw, user_rw;
> @@ -982,8 +990,39 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
>          }
>      }
>
> -    if (ns && arm_is_secure(env) && (env->cp15.scr_el3 & SCR_SIF)) {
> -        return prot_rw;

Ah, this looks like it fixes the bug introduced in patch 12;
I guess some of this needs rearranging between patches.

> +    if (in_pa != out_pa) {
> +        switch (in_pa) {
> +        case ARMSS_Root:
> +            /*
> +             * R_ZWRVD: permission fault for insn fetched from non-Root,
> +             * I_WWBFB: SIF has no effect in EL3.
> +             */
> +            return prot_rw;
> +        case ARMSS_Realm:
> +            /*
> +             * R_PKTDS: permission fault for insn fetched from non-Realm,
> +             * for Realm EL2 or EL2&0.  The corresponding fault for EL1&0
> +             * happens during any stage2 translation.
> +             */
> +            switch (mmu_idx) {
> +            case ARMMMUIdx_E2:
> +            case ARMMMUIdx_E20_0:
> +            case ARMMMUIdx_E20_2:
> +            case ARMMMUIdx_E20_2_PAN:
> +                return prot_rw;
> +            default:
> +                break;
> +            }
> +            break;
> +        case ARMSS_Secure:
> +            if (env->cp15.scr_el3 & SCR_SIF) {
> +                return prot_rw;
> +            }
> +            break;
> +        default:
> +            /* Input NonSecure must have output NonSecure. */
> +            g_assert_not_reached();
> +        }
>      }
>
>      /* TODO have_wxn should be replaced with
> @@ -1556,12 +1595,16 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>          /*
>           * R_GYNXY: For stage2 in Realm security state, bit 55 is NS.
>           * The bit remains ignored for other security states.
> +         * R_YMCSL: Executing an insn fetched from non-Realm causes
> +         * a stage2 permission fault.
>           */
>          if (out_space == ARMSS_Realm && extract64(attrs, 55, 1)) {
>              out_space = ARMSS_NonSecure;
> +            result->f.prot = get_S2prot_noexecute(ap);
> +        } else {
> +            xn = extract64(attrs, 53, 2);
> +            result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
>          }
> -        xn = extract64(attrs, 53, 2);
> -        result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
>      } else {
>          int ns = extract32(attrs, 5, 1);
>          switch (out_space) {
> @@ -1613,7 +1656,14 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>          }
>          xn = extract64(attrs, 54, 1);
>          pxn = extract64(attrs, 53, 1);
> -        result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
> +
> +        /*
> +         * Note that we modified ptw->in_space earlier for NSTable,
> +         * and result->f.attrs was initialized by get_phys_addr, so
> +         * that retains a copy of the original security space.
> +         */
> +        result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, xn, pxn,
> +                                    result->f.attrs.space, out_space);
>      }
>
>      if (!(result->f.prot & (1 << access_type))) {
> --
> 2.34.1

thanks
-- PMM


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

* Re: [PATCH 15/22] target/arm: Use get_phys_addr_with_struct in S1_ptw_translate
  2023-01-24  0:00 ` [PATCH 15/22] target/arm: Use get_phys_addr_with_struct in S1_ptw_translate Richard Henderson
@ 2023-02-10 13:21   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 13:21 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Do not provide a fast-path for physical addresses,
> as those will need to be validated for GPC.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/ptw.c | 35 ++++++++++++++---------------------
>  1 file changed, 14 insertions(+), 21 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 16/22] target/arm: Move s1_is_El0 into S1Translate
  2023-01-24  0:00 ` [PATCH 16/22] target/arm: Move s1_is_El0 into S1Translate Richard Henderson
@ 2023-02-10 13:23   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 13:23 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:02, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Instead of passing this to get_phys_addr_lpae, stash it
> in the S1Translate structure.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/ptw.c | 21 +++++++--------------
>  1 file changed, 7 insertions(+), 14 deletions(-)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index 37f5ff220c..eaa47f6b62 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -22,6 +22,7 @@ typedef struct S1Translate {
>      ARMSecuritySpace in_space;
>      bool in_secure;
>      bool in_debug;
> +    bool in_s1_is_el0;
>      bool out_secure;
>      bool out_rw;
>      bool out_be;
> @@ -33,7 +34,7 @@ typedef struct S1Translate {
>
>  static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>                                 uint64_t address,
> -                               MMUAccessType access_type, bool s1_is_el0,
> +                               MMUAccessType access_type,
>                                 GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
>      __attribute__((nonnull));
>
> @@ -1257,17 +1258,12 @@ static int check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, uint64_t tcr,
>   * @ptw: Current and next stage parameters for the walk.
>   * @address: virtual address to get physical address for
>   * @access_type: MMU_DATA_LOAD, MMU_DATA_STORE or MMU_INST_FETCH
> - * @s1_is_el0: if @ptw->in_mmu_idx is ARMMMUIdx_Stage2
> - *             (so this is a stage 2 page table walk),
> - *             must be true if this is stage 2 of a stage 1+2
> - *             walk for an EL0 access. If @mmu_idx is anything else,
> - *             @s1_is_el0 is ignored.

This was a useful comment on a boolean whose semantics aren't
totally clear just from the variable name; can we keep it ?

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 17/22] target/arm: Use get_phys_addr_with_struct for stage2
  2023-01-24  0:00 ` [PATCH 17/22] target/arm: Use get_phys_addr_with_struct for stage2 Richard Henderson
@ 2023-02-10 13:28   ` Peter Maydell
  2023-02-20 22:15     ` Richard Henderson
  0 siblings, 1 reply; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 13:28 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This fixes a bug in which we failed to initialize
> the result attributes properly after the memset.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/ptw.c | 13 +------------
>  1 file changed, 1 insertion(+), 12 deletions(-)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index eaa47f6b62..3205339957 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -32,12 +32,6 @@ typedef struct S1Translate {
>      void *out_host;
>  } S1Translate;
>
> -static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
> -                               uint64_t address,
> -                               MMUAccessType access_type,
> -                               GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
> -    __attribute__((nonnull));

The definition of the function doesn't have the __attribute__,
so if we drop this forward declaration we need to move the attribute.

> -
>  static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
>                                        target_ulong address,
>                                        MMUAccessType access_type,
> @@ -2854,12 +2848,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
>      cacheattrs1 = result->cacheattrs;
>      memset(result, 0, sizeof(*result));
>
> -    if (arm_feature(env, ARM_FEATURE_PMSA)) {
> -        ret = get_phys_addr_pmsav8(env, ipa, access_type,
> -                                   ptw->in_mmu_idx, s2walk_secure, result, fi);
> -    } else {
> -        ret = get_phys_addr_lpae(env, ptw, ipa, access_type, result, fi);
> -    }
> +    ret = get_phys_addr_with_struct(env, ptw, ipa, access_type, result, fi);
>      fi->s2addr = ipa;
>
>      /* Combine the S1 and S2 perms.  */

Does this do the right thing for PMSAv8 ? The code in get_phys_addr_twostage
sets up various things in ptw based on s2walk_secure, which (per previous
patch) is not really well defined for PMSA.

thanks
-- PMM


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

* Re: [PATCH 18/22] target/arm: Add GPC syndrome
  2023-01-24  0:00 ` [PATCH 18/22] target/arm: Add GPC syndrome Richard Henderson
@ 2023-02-10 13:32   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 13:32 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:02, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> The function takes the fields as filled in by
> the Arm ARM pseudocode for TakeGPCException.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/syndrome.h | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
> index 73df5e3793..3fa926d115 100644
> --- a/target/arm/syndrome.h
> +++ b/target/arm/syndrome.h
> @@ -49,6 +49,7 @@ enum arm_exception_class {
>      EC_SYSTEMREGISTERTRAP     = 0x18,
>      EC_SVEACCESSTRAP          = 0x19,
>      EC_SMETRAP                = 0x1d,
> +    EC_GPC                    = 0x1e,
>      EC_INSNABORT              = 0x20,
>      EC_INSNABORT_SAME_EL      = 0x21,
>      EC_PCALIGNMENT            = 0x22,
> @@ -237,6 +238,14 @@ static inline uint32_t syn_bxjtrap(int cv, int cond, int rm)
>          (cv << 24) | (cond << 20) | rm;
>  }
>
> +static inline uint32_t syn_gpc(int s2ptw, int ind, int gpcsc,
> +                               int cm, int s1ptw, int wnr, int fsc)
> +{
> +    return (EC_GPC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (s2ptw << 21)
> +            | (ind << 20) | (gpcsc << 14) | (cm << 8) | (s1ptw << 7)
> +            | (wnr << 6) | fsc;
> +}

I guess we can add VNCR (bit 13) when we implement FEAT_NV2...

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 19/22] target/arm: Implement GPC exceptions
  2023-01-24  0:00 ` [PATCH 19/22] target/arm: Implement GPC exceptions Richard Henderson
@ 2023-02-10 13:53   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 13:53 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:02, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Handle GPC Fault types in arm_deliver_fault, reporting as
> either a GPC exception at EL3, or falling through to insn
> or data aborts at various exception levels.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>




> +static unsigned encode_gpcsc(ARMMMUFaultInfo *fi)
> +{
> +    static uint8_t const gpcsc[] = {
> +        [GPCF_AddressSize] = 0b00000,
> +        [GPCF_Walk] = 0b00010,
> +        [GPCF_Fail] = 0b00110,
> +        [GPCF_EABT] = 0b01010,
> +    };
> +
> +    /* Note that we've validated fi->gpcf and fi->level above. */
> +    return gpcsc[fi->gpcf] | fi->level;

GPCSC is 6 bits, and you've only put the top 5 bits in the
gpcsc[] array here, so you either need to shift that right
by 1, or else have the array entries all have an extra 0
on the least-significant end.

The comment says gpcf and level have been validated, but
the code assumes that GPCF_AddressSize implies level 0,
which isn't validated.

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 20/22] target/arm: Implement the granule protection check
  2023-01-24  0:00 ` [PATCH 20/22] target/arm: Implement the granule protection check Richard Henderson
@ 2023-02-10 14:18   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 14:18 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Place the check at the end of get_phys_addr_with_struct,
> so that we check all physical results.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/ptw.c | 253 +++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 234 insertions(+), 19 deletions(-)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index 3205339957..8249d93326 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -32,11 +32,18 @@ typedef struct S1Translate {
>      void *out_host;
>  } S1Translate;
>
> -static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
> -                                      target_ulong address,
> -                                      MMUAccessType access_type,
> -                                      GetPhysAddrResult *result,
> -                                      ARMMMUFaultInfo *fi)
> +static bool get_phys_addr_inner(CPUARMState *env, S1Translate *ptw,
> +                                target_ulong address,
> +                                MMUAccessType access_type,
> +                                GetPhysAddrResult *result,
> +                                ARMMMUFaultInfo *fi)
> +    __attribute__((nonnull));
> +
> +static bool get_phys_addr_outer(CPUARMState *env, S1Translate *ptw,
> +                                target_ulong address,
> +                                MMUAccessType access_type,
> +                                GetPhysAddrResult *result,
> +                                ARMMMUFaultInfo *fi)
>      __attribute__((nonnull));

I find these function names confusing, and the spec doesn't seem
to use the inner/outer terminology. Maybe there are clearer names?
Failing that, we should have a comment explaining the difference.

>  /* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */
> @@ -193,6 +200,197 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
>      return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
>  }
>
> +static bool granule_protection_check(CPUARMState *env, uint64_t paddress,
> +                                     ARMSecuritySpace pspace,
> +                                     ARMMMUFaultInfo *fi)
> +{
> +    MemTxAttrs attrs = {
> +        .secure = true,
> +        .space = ARMSS_Root,
> +    };
> +    ARMCPU *cpu = env_archcpu(env);
> +    uint64_t gpccr = env->cp15.gpccr_el3;
> +    unsigned pps, pgs, l0gptsz, level = 0;
> +    uint64_t tableaddr, pps_mask, align, entry, index;
> +    AddressSpace *as;
> +    MemTxResult result;
> +    int gpi;
> +
> +    if (!FIELD_EX64(gpccr, GPCCR, GPC)) {
> +        return true;
> +    }
> +
> +    /*
> +     * GPC Priority 1 (R_GMGRR):
> +     * R_JWCSM: If the configuration of GPCCR_EL3 is invalid,
> +     * the access fails as GPT walk fault at level 0.
> +     */
> +
> +    /*
> +     * Configuration of PPS to a value exceeding the implemented
> +     * physical address size is invalid.
> +     */
> +    pps = FIELD_EX64(gpccr, GPCCR, PPS);
> +    if (pps > FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE)) {
> +        goto fault_walk;
> +    }
> +    pps = pamax_map[pps];
> +    pps_mask = MAKE_64BIT_MASK(0, pps);
> +
> +    switch (FIELD_EX64(gpccr, GPCCR, SH)) {
> +    case 0b10: /* outer sharable */
> +        break;
> +    case 0b00: /* non-sharable */
> +    case 0b11: /* inner sharable */
> +        /* Inner and Outer non-cacheable requires Outer sharable. */

"Shareable" with an 'e' in all these comments.

> +        if (FIELD_EX64(gpccr, GPCCR, ORGN) == 0 &&
> +            FIELD_EX64(gpccr, GPCCR, IRGN) == 0) {
> +            goto fault_walk;
> +        }
> +        break;

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 21/22] target/arm: Enable RME for -cpu max
  2023-01-24  0:00 ` [PATCH 21/22] target/arm: Enable RME for -cpu max Richard Henderson
@ 2023-02-10 14:20   ` Peter Maydell
  2023-02-20 23:31     ` Richard Henderson
  0 siblings, 1 reply; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 14:20 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Add a cpu property to set GPCCR_EL3.L0GPTSZ, for testing
> various possible configurations.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Looks OK, but I think we probably shouldn't enable RME by default
until we're happy with what we're planning to do at the
system/board level (eg should it be like MTE where it's only
turned on if the board has support and turns it on?)

thanks
-- PMM


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

* Re: [RFC PATCH 22/22] hw/arm/virt: Add some memory for Realm Management Monitor
  2023-01-24  0:00 ` [RFC PATCH 22/22] hw/arm/virt: Add some memory for Realm Management Monitor Richard Henderson
@ 2023-02-10 14:24   ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-10 14:24 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Tue, 24 Jan 2023 at 00:02, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This is arbitrary, but used by the Huawei TF-A test code.

I guess we should look at how TF-A expects this to work in
real-hardware setups. Presumably the idea is that TF-A
carves out the RAM it wants to use for the RMM and
modifies the device tree / ACPI tables accordingly ?

Also, are we going to want to have more link properties
for the board to be able to pass in MemoryRegions corresponding
to the different physical address spaces, the way we do
today for Secure vs NonSecure ? Or do we think we can
create suitable board models with "just" a lot of MMUs?

thanks
-- PMM


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

* Re: [PATCH 12/22] target/arm: NSTable is RES0 for the RME EL3 regime
  2023-02-10 11:36   ` Peter Maydell
@ 2023-02-10 19:49     ` Richard Henderson
  0 siblings, 0 replies; 54+ messages in thread
From: Richard Henderson @ 2023-02-10 19:49 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On 2/10/23 01:36, Peter Maydell wrote:
> On Tue, 24 Jan 2023 at 00:01, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> Test in_space instead of in_secure so that we don't switch
>> out of Root space.  Handle the output space change immediately,
>> rather than try and combine the NSTable and NS bits later.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   target/arm/ptw.c | 31 ++++++++++++++-----------------
>>   1 file changed, 14 insertions(+), 17 deletions(-)
>>
>> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
>> index c1b0b8e610..ddafb1f329 100644
>> --- a/target/arm/ptw.c
>> +++ b/target/arm/ptw.c
>> @@ -1240,7 +1240,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>>   {
>>       ARMCPU *cpu = env_archcpu(env);
>>       ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
>> -    bool is_secure = ptw->in_secure;
>>       int32_t level;
>>       ARMVAParameters param;
>>       uint64_t ttbr;
>> @@ -1256,7 +1255,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>>       uint64_t descaddrmask;
>>       bool aarch64 = arm_el_is_aa64(env, el);
>>       uint64_t descriptor, new_descriptor;
>> -    bool nstable;
>>
>>       /* TODO: This code does not support shareability levels. */
>>       if (aarch64) {
>> @@ -1417,29 +1415,29 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>>           descaddrmask = MAKE_64BIT_MASK(0, 40);
>>       }
>>       descaddrmask &= ~indexmask_grainsize;
>> -
>> -    /*
>> -     * Secure accesses start with the page table in secure memory and
>> -     * can be downgraded to non-secure at any step. Non-secure accesses
>> -     * remain non-secure. We implement this by just ORing in the NSTable/NS
>> -     * bits at each step.
>> -     */
>> -    tableattrs = is_secure ? 0 : (1 << 4);
>> +    tableattrs = 0;
>>
>>    next_level:
>>       descaddr |= (address >> (stride * (4 - level))) & indexmask;
>>       descaddr &= ~7ULL;
>> -    nstable = extract32(tableattrs, 4, 1);
>> -    if (nstable && ptw->in_secure) {
>> -        /*
>> -         * Stage2_S -> Stage2 or Phys_S -> Phys_NS
>> -         * Assert that the non-secure idx are even, and relative order.
>> -         */
>> +
>> +    /*
>> +     * Process the NSTable bit from the previous level.  This changes
>> +     * the table address space and the output space from Secure to
>> +     * NonSecure.  With RME, the EL3 translation regime does not change
>> +     * from Root to NonSecure.
>> +     */
> 
> To check my understanding, this means that the bit that the spec
> describes as FEAT_RME changing the behaviour of NSTable in the EL3
> stage 1 translation regime is implemented by us by having the
> in_space for EL3 be different for FEAT_RME and not-FEAT_RME ?

Correct -- space is Secure for non-RME EL3, and Root for RME EL3.

>>       attrs = new_descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
>>       if (!regime_is_stage2(mmu_idx)) {
>> -        attrs |= nstable << 5; /* NS */
> 
> This removes the code where we copy the NSTable bit across to attrs,
> but there's still code below here that assumes it can get the combined
> NS bit from bit 5 of attrs, isn't there? (It passes it to get_S1prot().)

Oops.  This gets fixed in patch 14.  Some reordering needed...


r~



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

* Re: [PATCH 17/22] target/arm: Use get_phys_addr_with_struct for stage2
  2023-02-10 13:28   ` Peter Maydell
@ 2023-02-20 22:15     ` Richard Henderson
  2023-02-21 11:11       ` Peter Maydell
  0 siblings, 1 reply; 54+ messages in thread
From: Richard Henderson @ 2023-02-20 22:15 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On 2/10/23 03:28, Peter Maydell wrote:
> On Tue, 24 Jan 2023 at 00:01, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> This fixes a bug in which we failed to initialize
>> the result attributes properly after the memset.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   target/arm/ptw.c | 13 +------------
>>   1 file changed, 1 insertion(+), 12 deletions(-)
>>
>> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
>> index eaa47f6b62..3205339957 100644
>> --- a/target/arm/ptw.c
>> +++ b/target/arm/ptw.c
>> @@ -32,12 +32,6 @@ typedef struct S1Translate {
>>       void *out_host;
>>   } S1Translate;
>>
>> -static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
>> -                               uint64_t address,
>> -                               MMUAccessType access_type,
>> -                               GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
>> -    __attribute__((nonnull));
> 
> The definition of the function doesn't have the __attribute__,
> so if we drop this forward declaration we need to move the attribute.

Eh.  It was useful as an intermediary during one of the ptw reorgs, but now that we've 
eliminated the use case in which NULL had been passed, it can go away.  I assume you'd 
prefer that as a separate patch?

>> @@ -2854,12 +2848,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
>>       cacheattrs1 = result->cacheattrs;
>>       memset(result, 0, sizeof(*result));
>>
>> -    if (arm_feature(env, ARM_FEATURE_PMSA)) {
>> -        ret = get_phys_addr_pmsav8(env, ipa, access_type,
>> -                                   ptw->in_mmu_idx, s2walk_secure, result, fi);
>> -    } else {
>> -        ret = get_phys_addr_lpae(env, ptw, ipa, access_type, result, fi);
>> -    }
>> +    ret = get_phys_addr_with_struct(env, ptw, ipa, access_type, result, fi);
>>       fi->s2addr = ipa;
>>
>>       /* Combine the S1 and S2 perms.  */
> 
> Does this do the right thing for PMSAv8 ? The code in get_phys_addr_twostage
> sets up various things in ptw based on s2walk_secure, which (per previous
> patch) is not really well defined for PMSA.

As far as I can tell, yes, since as you say current PMSAv8 is all NonSecure.


r~



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

* Re: [PATCH 21/22] target/arm: Enable RME for -cpu max
  2023-02-10 14:20   ` Peter Maydell
@ 2023-02-20 23:31     ` Richard Henderson
  0 siblings, 0 replies; 54+ messages in thread
From: Richard Henderson @ 2023-02-20 23:31 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On 2/10/23 04:20, Peter Maydell wrote:
> On Tue, 24 Jan 2023 at 00:01, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> Add a cpu property to set GPCCR_EL3.L0GPTSZ, for testing
>> various possible configurations.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> 
> Looks OK, but I think we probably shouldn't enable RME by default
> until we're happy with what we're planning to do at the
> system/board level (eg should it be like MTE where it's only
> turned on if the board has support and turns it on?)

You're probably right about not enabling by default, and certainly right about figuring 
out what firmware actually expects and needs.


r~


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

* Re: [PATCH 17/22] target/arm: Use get_phys_addr_with_struct for stage2
  2023-02-20 22:15     ` Richard Henderson
@ 2023-02-21 11:11       ` Peter Maydell
  0 siblings, 0 replies; 54+ messages in thread
From: Peter Maydell @ 2023-02-21 11:11 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-arm, yier.jin, jonathan.cameron, leonardo.garcia

On Mon, 20 Feb 2023 at 22:15, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 2/10/23 03:28, Peter Maydell wrote:
> > On Tue, 24 Jan 2023 at 00:01, Richard Henderson
> > <richard.henderson@linaro.org> wrote:
> >>
> >> This fixes a bug in which we failed to initialize
> >> the result attributes properly after the memset.
> >>
> >> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> >> ---
> >>   target/arm/ptw.c | 13 +------------
> >>   1 file changed, 1 insertion(+), 12 deletions(-)
> >>
> >> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> >> index eaa47f6b62..3205339957 100644
> >> --- a/target/arm/ptw.c
> >> +++ b/target/arm/ptw.c
> >> @@ -32,12 +32,6 @@ typedef struct S1Translate {
> >>       void *out_host;
> >>   } S1Translate;
> >>
> >> -static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
> >> -                               uint64_t address,
> >> -                               MMUAccessType access_type,
> >> -                               GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
> >> -    __attribute__((nonnull));
> >
> > The definition of the function doesn't have the __attribute__,
> > so if we drop this forward declaration we need to move the attribute.
>
> Eh.  It was useful as an intermediary during one of the ptw reorgs, but now that we've
> eliminated the use case in which NULL had been passed, it can go away.  I assume you'd
> prefer that as a separate patch?

Yes, if we want to deliberately drop the attribute we should
do that separately with justification for why it's not needed.

thanks
-- PMM


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

end of thread, other threads:[~2023-02-21 11:11 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-24  0:00 [PATCH 00/22] target/arm: Implement FEAT_RME Richard Henderson
2023-01-24  0:00 ` [PATCH 01/22] target/arm: Fix pmsav8 stage2 secure parameter Richard Henderson
2023-02-07 14:26   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 02/22] target/arm: Rewrite check_s2_mmu_setup Richard Henderson
2023-02-07 16:00   ` Peter Maydell
2023-02-07 19:31     ` Richard Henderson
2023-01-24  0:00 ` [PATCH 03/22] target/arm: Add isar_feature_aa64_rme Richard Henderson
2023-02-07 14:31   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 04/22] target/arm: Update SCR and HCR for RME Richard Henderson
2023-02-07 14:34   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 05/22] target/arm: SCR_EL3.NS may be RES1 Richard Henderson
2023-02-07 14:39   ` Peter Maydell
2023-02-07 19:43     ` Richard Henderson
2023-01-24  0:00 ` [PATCH 06/22] target/arm: Add RME cpregs Richard Henderson
2023-02-07 14:53   ` Peter Maydell
2023-02-08 21:51     ` Richard Henderson
2023-01-24  0:00 ` [PATCH 07/22] target/arm: Introduce ARMSecuritySpace Richard Henderson
2023-02-07 15:00   ` Peter Maydell
2023-02-08 22:00     ` Richard Henderson
2023-01-24  0:00 ` [PATCH 08/22] include/exec/memattrs: Add two bits of space to MemTxAttrs Richard Henderson
2023-02-07 15:05   ` Peter Maydell
2023-02-08 22:12     ` Richard Henderson
2023-01-24  0:00 ` [PATCH 09/22] target/arm: Adjust the order of Phys and Stage2 ARMMMUIdx Richard Henderson
2023-02-07 15:07   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 10/22] target/arm: Introduce ARMMMUIdx_Phys_{Realm,Root} Richard Henderson
2023-02-07 15:09   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 11/22] target/arm: Pipe ARMSecuritySpace through ptw.c Richard Henderson
2023-02-07 16:15   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 12/22] target/arm: NSTable is RES0 for the RME EL3 regime Richard Henderson
2023-02-10 11:36   ` Peter Maydell
2023-02-10 19:49     ` Richard Henderson
2023-01-24  0:00 ` [PATCH 13/22] target/arm: Handle Block and Page bits for security space Richard Henderson
2023-02-10 11:53   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 14/22] target/arm: Handle no-execute for Realm and Root regimes Richard Henderson
2023-02-10 11:59   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 15/22] target/arm: Use get_phys_addr_with_struct in S1_ptw_translate Richard Henderson
2023-02-10 13:21   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 16/22] target/arm: Move s1_is_El0 into S1Translate Richard Henderson
2023-02-10 13:23   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 17/22] target/arm: Use get_phys_addr_with_struct for stage2 Richard Henderson
2023-02-10 13:28   ` Peter Maydell
2023-02-20 22:15     ` Richard Henderson
2023-02-21 11:11       ` Peter Maydell
2023-01-24  0:00 ` [PATCH 18/22] target/arm: Add GPC syndrome Richard Henderson
2023-02-10 13:32   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 19/22] target/arm: Implement GPC exceptions Richard Henderson
2023-02-10 13:53   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 20/22] target/arm: Implement the granule protection check Richard Henderson
2023-02-10 14:18   ` Peter Maydell
2023-01-24  0:00 ` [PATCH 21/22] target/arm: Enable RME for -cpu max Richard Henderson
2023-02-10 14:20   ` Peter Maydell
2023-02-20 23:31     ` Richard Henderson
2023-01-24  0:00 ` [RFC PATCH 22/22] hw/arm/virt: Add some memory for Realm Management Monitor Richard Henderson
2023-02-10 14:24   ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.