All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE
@ 2019-07-19 21:03 Richard Henderson
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 01/24] cputlb: Add tlb_set_asid_for_mmuidx Richard Henderson
                   ` (25 more replies)
  0 siblings, 26 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

About half of this patch set is cleanup of the qemu tlb handling
leading up to the actual implementation of VHE, and the biggest
piece of that: The EL2&0 translation regime.

Testing so far has been limited to booting a debian 9 system with
a 4.9 kernel, and a fedora 30 system with a 5.1 kernel.  Both have
KVM enabled, and both report enabling VHE is successful.


r~


Richard Henderson (24):
  cputlb: Add tlb_set_asid_for_mmuidx
  cputlb: Add tlb_flush_asid_by_mmuidx and friends
  target/arm: Install ASIDs for long-form from EL1
  target/arm: Install ASIDs for short-form from EL1
  target/arm: Install ASIDs for EL2
  target/arm: Define isar_feature_aa64_vh
  target/arm: Enable HCR_E2H for VHE
  target/arm: Add CONTEXTIDR_EL2
  target/arm: Add TTBR1_EL2
  target/arm: Update CNTVCT_EL0 for VHE
  target/arm: Add the hypervisor virtual counter
  target/arm: Add VHE system register redirection and aliasing
  target/arm: Split out vae1_tlbmask, vmalle1_tlbmask
  target/arm: Simplify tlb_force_broadcast alternatives
  target/arm: Reorganize ARMMMUIdx
  target/arm: Add regime_has_2_ranges
  target/arm: Update arm_mmu_idx for VHE
  target/arm: Update arm_sctlr for VHE
  target/arm: Install asids for E2&0 translation regime
  target/arm: Flush tlbs for E2&0 translation regime
  target/arm: Update arm_phys_excp_target_el for TGE
  target/arm: Update regime_is_user for EL2&0
  target/arm: Update {fp,sve}_exception_el for VHE
  target/arm: Enable ARMv8.1-VHE in -cpu max

 include/exec/cpu-all.h     |  11 +
 include/exec/cpu-defs.h    |   2 +
 include/exec/exec-all.h    |  35 ++
 include/qom/cpu.h          |   1 +
 target/arm/cpu-qom.h       |   1 +
 target/arm/cpu.h           | 259 +++++-----
 target/arm/internals.h     |  62 ++-
 target/arm/translate.h     |   2 +-
 accel/tcg/cputlb.c         |  77 +++
 target/arm/arch_dump.c     |   2 +-
 target/arm/cpu.c           |   2 +
 target/arm/cpu64.c         |   1 +
 target/arm/debug_helper.c  |  50 +-
 target/arm/helper-a64.c    |   2 +-
 target/arm/helper.c        | 985 ++++++++++++++++++++++++++-----------
 target/arm/m_helper.c      |   6 +-
 target/arm/pauth_helper.c  |   9 +-
 target/arm/translate-a64.c |  14 +-
 target/arm/translate.c     |  17 +-
 19 files changed, 1058 insertions(+), 480 deletions(-)

-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 01/24] cputlb: Add tlb_set_asid_for_mmuidx
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-22  9:53   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 02/24] cputlb: Add tlb_flush_asid_by_mmuidx and friends Richard Henderson
                   ` (24 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

Although we can't do much with ASIDs except remember them, this
will allow cleanups within target/ that should make things clearer.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
v2: Assert cpu_is_self; only flush idx w/ asid mismatch.
---
 include/exec/cpu-all.h  | 11 +++++++++++
 include/exec/cpu-defs.h |  2 ++
 include/exec/exec-all.h | 19 +++++++++++++++++++
 accel/tcg/cputlb.c      | 26 ++++++++++++++++++++++++++
 4 files changed, 58 insertions(+)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 536ea58f81..40b140cbba 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -439,4 +439,15 @@ static inline CPUTLB *env_tlb(CPUArchState *env)
     return &env_neg(env)->tlb;
 }
 
+/**
+ * cpu_tlb(env)
+ * @cpu: The generic CPUState
+ *
+ * Return the CPUTLB state associated with the cpu.
+ */
+static inline CPUTLB *cpu_tlb(CPUState *cpu)
+{
+    return &cpu_neg(cpu)->tlb;
+}
+
 #endif /* CPU_ALL_H */
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 9bc713a70b..73584841c0 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -169,6 +169,8 @@ typedef struct CPUTLBDesc {
     size_t n_used_entries;
     /* The next index to use in the tlb victim table.  */
     size_t vindex;
+    /* The current ASID for this tlb.  */
+    uint32_t asid;
     /* The tlb victim table, in two parts.  */
     CPUTLBEntry vtable[CPU_VTLB_SIZE];
     CPUIOTLBEntry viotlb[CPU_VTLB_SIZE];
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 16034ee651..9c77aa5bf9 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -225,6 +225,21 @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
  * depend on when the guests translation ends the TB.
  */
 void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
+/**
+ * tlb_set_asid_for_mmuidx:
+ * @cpu: Originating cpu
+ * @asid: Address Space Identifier
+ * @idxmap: bitmap of MMU indexes to set to @asid
+ * @depmap: bitmap of dependent MMU indexes
+ *
+ * Set an ASID for all of @idxmap.  If any previous ASID was different,
+ * then we will flush the mmu idx.  If a flush is required, then also flush
+ * all dependent mmu indicies in @depmap.  This latter is typically used
+ * for secondary page resolution, for implementing virtualization within
+ * the guest.
+ */
+void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid,
+                             uint16_t idxmap, uint16_t dep_idxmap);
 /**
  * tlb_set_page_with_attrs:
  * @cpu: CPU to add this TLB entry for
@@ -310,6 +325,10 @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
                                                        uint16_t idxmap)
 {
 }
+static inline void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid,
+                                           uint16_t idxmap, uint16_t depmap)
+{
+}
 #endif
 
 #define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index bb9897b25a..c68f57755b 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -540,6 +540,32 @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
     tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
 }
 
+void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid, uint16_t idxmap,
+                             uint16_t depmap)
+{
+    CPUTLB *tlb = cpu_tlb(cpu);
+    uint16_t work, to_flush = 0;
+
+    /* It doesn't make sense to set context across cpus.  */
+    assert_cpu_is_self(cpu);
+
+    /*
+     * We don't support ASIDs except for trivially.
+     * If there is any change, then we must flush the TLB.
+     */
+    for (work = idxmap; work != 0; work &= work - 1) {
+        int mmu_idx = ctz32(work);
+        if (tlb->d[mmu_idx].asid != asid) {
+            tlb->d[mmu_idx].asid = asid;
+            to_flush |= 1 << mmu_idx;
+        }
+    }
+    if (to_flush) {
+        to_flush |= depmap;
+        tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(to_flush));
+    }
+}
+
 /* update the TLBs so that writes to code in the virtual page 'addr'
    can be detected */
 void tlb_protect_code(ram_addr_t ram_addr)
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 02/24] cputlb: Add tlb_flush_asid_by_mmuidx and friends
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 01/24] cputlb: Add tlb_set_asid_for_mmuidx Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-22 10:04   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 03/24] target/arm: Install ASIDs for long-form from EL1 Richard Henderson
                   ` (23 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

Since we have remembered ASIDs, we can further minimize flushing
by comparing against the one we want to flush.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/exec-all.h | 16 +++++++++++++
 include/qom/cpu.h       |  1 +
 accel/tcg/cputlb.c      | 51 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+)

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 9c77aa5bf9..0d890e1e60 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -240,6 +240,22 @@ void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
  */
 void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid,
                              uint16_t idxmap, uint16_t dep_idxmap);
+/**
+ * tlb_flush_asid_by_mmuidx:
+ * @cpu: Originating CPU of the flush
+ * @asid: Address Space Identifier
+ * @idxmap: bitmap of MMU indexes to flush if asid matches
+ *
+ * For each mmu index, if @asid matches the value previously saved via
+ * tlb_set_asid_for_mmuidx, flush the index.
+ */
+void tlb_flush_asid_by_mmuidx(CPUState *cpu, uint32_t asid, uint16_t idxmap);
+/* Similarly, broadcasting to all cpus. */
+void tlb_flush_asid_by_mmuidx_all_cpus(CPUState *cpu, uint32_t asid,
+                                       uint16_t idxmap);
+/* Similarly, waiting for the broadcast to complete.  */
+void tlb_flush_asid_by_mmuidx_all_cpus_synced(CPUState *cpu, uint32_t asid,
+                                              uint16_t idxmap);
 /**
  * tlb_set_page_with_attrs:
  * @cpu: CPU to add this TLB entry for
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 5ee0046b62..4ae6ea3e1d 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -283,6 +283,7 @@ struct hax_vcpu_state;
 typedef union {
     int           host_int;
     unsigned long host_ulong;
+    uint64_t      host_uint64;
     void         *host_ptr;
     vaddr         target_ptr;
 } run_on_cpu_data;
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index c68f57755b..3ef68a11bf 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -540,6 +540,57 @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
     tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
 }
 
+static void tlb_flush_asid_by_mmuidx_async_work(CPUState *cpu,
+                                                run_on_cpu_data data)
+{
+    CPUTLB *tlb = cpu_tlb(cpu);
+    uint32_t asid = data.host_uint64;
+    uint16_t idxmap = data.host_uint64 >> 32;
+    uint16_t to_flush = 0, work;
+
+    assert_cpu_is_self(cpu);
+
+    for (work = idxmap; work != 0; work &= work - 1) {
+        int mmu_idx = ctz32(work);
+        if (tlb->d[mmu_idx].asid == asid) {
+            to_flush |= 1 << mmu_idx;
+        }
+    }
+
+    if (to_flush) {
+        tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(to_flush));
+    }
+}
+
+void tlb_flush_asid_by_mmuidx(CPUState *cpu, uint32_t asid, uint16_t idxmap)
+{
+    run_on_cpu_data data = { .host_uint64 = deposit64(asid, 32, 32, idxmap) };
+
+    if (cpu->created && !qemu_cpu_is_self(cpu)) {
+        async_run_on_cpu(cpu, tlb_flush_asid_by_mmuidx_async_work, data);
+    } else {
+        tlb_flush_asid_by_mmuidx_async_work(cpu, data);
+    }
+}
+
+void tlb_flush_asid_by_mmuidx_all_cpus(CPUState *src_cpu,
+                                       uint32_t asid, uint16_t idxmap)
+{
+    run_on_cpu_data data = { .host_uint64 = deposit64(asid, 32, 32, idxmap) };
+
+    flush_all_helper(src_cpu, tlb_flush_asid_by_mmuidx_async_work, data);
+    tlb_flush_asid_by_mmuidx_async_work(src_cpu, data);
+}
+
+void tlb_flush_asid_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
+                                              uint32_t asid, uint16_t idxmap)
+{
+    run_on_cpu_data data = { .host_uint64 = deposit64(asid, 32, 32, idxmap) };
+
+    flush_all_helper(src_cpu, tlb_flush_asid_by_mmuidx_async_work, data);
+    async_safe_run_on_cpu(src_cpu, tlb_flush_asid_by_mmuidx_async_work, data);
+}
+
 void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid, uint16_t idxmap,
                              uint16_t depmap)
 {
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 03/24] target/arm: Install ASIDs for long-form from EL1
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 01/24] cputlb: Add tlb_set_asid_for_mmuidx Richard Henderson
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 02/24] cputlb: Add tlb_flush_asid_by_mmuidx and friends Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-22 15:28   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 04/24] target/arm: Install ASIDs for short-form " Richard Henderson
                   ` (22 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

In addition to providing the core with the current ASID, this minimizes
both the number of flushes due to non-changing ASID as well as the set
of mmu_idx that are affected by each flush.

In particular, updates to the secure mode registers flushes only the
relevant secure mode mmu_idx's, and similarly non-secure updates only
affect non-secure mmu_idx's.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 20f8728be1..0f21a077de 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3327,6 +3327,36 @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
     REGINFO_SENTINEL
 };
 
+/* Called after a change to any of TTBR*_EL1 or TTBCR_EL1.  */
+static void update_lpae_el1_asid(CPUARMState *env, int secure)
+{
+    CPUState *cs = env_cpu(env);
+    uint64_t ttbr0, ttbr1, ttcr;
+    int asid, idxmask;
+
+    switch (secure) {
+    case ARM_CP_SECSTATE_S:
+        ttbr0 = env->cp15.ttbr0_s;
+        ttbr1 = env->cp15.ttbr1_s;
+        ttcr = env->cp15.tcr_el[3].raw_tcr;
+        /* Note that cp15.ttbr0_s == cp15.ttbr0_el[3], so S1E3 is affected.  */
+        /* ??? Secure EL3 really using the ASID field?  Doesn't make sense.  */
+        idxmask = ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0 | ARMMMUIdxBit_S1E3;
+        break;
+    case ARM_CP_SECSTATE_NS:
+        ttbr0 = env->cp15.ttbr0_ns;
+        ttbr1 = env->cp15.ttbr1_ns;
+        ttcr = env->cp15.tcr_el[1].raw_tcr;
+        idxmask = ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    asid = extract64(ttcr & TTBCR_A1 ? ttbr1 : ttbr0, 48, 16);
+
+    tlb_set_asid_for_mmuidx(cs, asid, idxmask, 0);
+}
+
 static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                  uint64_t value)
 {
@@ -3363,18 +3393,16 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
                              uint64_t value)
 {
-    ARMCPU *cpu = env_archcpu(env);
     TCR *tcr = raw_ptr(env, ri);
 
-    if (arm_feature(env, ARM_FEATURE_LPAE)) {
-        /* With LPAE the TTBCR could result in a change of ASID
-         * via the TTBCR.A1 bit, so do a TLB flush.
-         */
-        tlb_flush(CPU(cpu));
-    }
     /* Preserve the high half of TCR_EL1, set via TTBCR2.  */
     value = deposit64(tcr->raw_tcr, 0, 32, value);
     vmsa_ttbcr_raw_write(env, ri, value);
+
+    if (arm_feature(env, ARM_FEATURE_LPAE)) {
+        /* The A1 bit controls which ASID is active.  */
+        update_lpae_el1_asid(env, ri->secure);
+    }
 }
 
 static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -3392,24 +3420,19 @@ static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
 static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                uint64_t value)
 {
-    ARMCPU *cpu = env_archcpu(env);
-    TCR *tcr = raw_ptr(env, ri);
-
-    /* For AArch64 the A1 bit could result in a change of ASID, so TLB flush. */
-    tlb_flush(CPU(cpu));
-    tcr->raw_tcr = value;
+    raw_write(env, ri, value);
+    /* The A1 bit controls which ASID is active.  */
+    update_lpae_el1_asid(env, ri->secure);
 }
 
-static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                            uint64_t value)
+static void vmsa_ttbr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                uint64_t value)
 {
-    /* If the ASID changes (with a 64-bit write), we must flush the TLB.  */
-    if (cpreg_field_is_64bit(ri) &&
-        extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
-        ARMCPU *cpu = env_archcpu(env);
-        tlb_flush(CPU(cpu));
-    }
     raw_write(env, ri, value);
+    if (cpreg_field_is_64bit(ri)) {
+        /* The LPAE format (64-bit write) contains an ASID field.  */
+        update_lpae_el1_asid(env, ri->secure);
+    }
 }
 
 static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -3455,12 +3478,12 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
       .fieldoffset = offsetof(CPUARMState, cp15.esr_el[1]), .resetvalue = 0, },
     { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 0,
-      .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
+      .access = PL1_RW, .writefn = vmsa_ttbr_el1_write, .resetvalue = 0,
       .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
                              offsetof(CPUARMState, cp15.ttbr0_ns) } },
     { .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 1,
-      .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
+      .access = PL1_RW, .writefn = vmsa_ttbr_el1_write, .resetvalue = 0,
       .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
                              offsetof(CPUARMState, cp15.ttbr1_ns) } },
     { .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
@@ -3715,12 +3738,12 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
       .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
       .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
                              offsetof(CPUARMState, cp15.ttbr0_ns) },
-      .writefn = vmsa_ttbr_write, },
+      .writefn = vmsa_ttbr_el1_write, },
     { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
       .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
       .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
                              offsetof(CPUARMState, cp15.ttbr1_ns) },
-      .writefn = vmsa_ttbr_write, },
+      .writefn = vmsa_ttbr_el1_write, },
     REGINFO_SENTINEL
 };
 
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 04/24] target/arm: Install ASIDs for short-form from EL1
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (2 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 03/24] target/arm: Install ASIDs for long-form from EL1 Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-24 11:47   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 05/24] target/arm: Install ASIDs for EL2 Richard Henderson
                   ` (21 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

This is less complex than the LPAE case, but still we now avoid the
flush in case it is only the PROCID field that is changing.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0f21a077de..1ed7c06313 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -551,17 +551,31 @@ static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
                              uint64_t value)
 {
-    ARMCPU *cpu = env_archcpu(env);
-
-    if (raw_read(env, ri) != value && !arm_feature(env, ARM_FEATURE_PMSA)
-        && !extended_addresses_enabled(env)) {
-        /* For VMSA (when not using the LPAE long descriptor page table
-         * format) this register includes the ASID, so do a TLB flush.
-         * For PMSA it is purely a process ID and no action is needed.
-         */
-        tlb_flush(CPU(cpu));
-    }
     raw_write(env, ri, value);
+
+    /*
+     * For VMSA (when not using the LPAE long descriptor page table format)
+     * this register includes the ASID.  For PMSA it is purely a process ID
+     * and no action is needed.
+     */
+    if (!arm_feature(env, ARM_FEATURE_PMSA) &&
+        !extended_addresses_enabled(env)) {
+        CPUState *cs = env_cpu(env);
+        int asid = extract32(value, 0, 8);
+        int idxmask;
+
+        switch (ri->secure) {
+        case ARM_CP_SECSTATE_S:
+            idxmask = ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
+            break;
+        case ARM_CP_SECSTATE_NS:
+            idxmask = ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
+            break;
+        default:
+            g_assert_not_reached();
+        }
+        tlb_set_asid_for_mmuidx(cs, asid, idxmask, 0);
+    }
 }
 
 /* IS variants of TLB operations must affect all cores */
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 05/24] target/arm: Install ASIDs for EL2
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (3 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 04/24] target/arm: Install ASIDs for short-form " Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-24 11:49   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 06/24] target/arm: Define isar_feature_aa64_vh Richard Henderson
                   ` (20 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

The VMID is the ASID for the 2nd stage page lookup.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 1ed7c06313..3a9f35bf4b 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3452,17 +3452,23 @@ static void vmsa_ttbr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
                         uint64_t value)
 {
-    ARMCPU *cpu = env_archcpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUState *cs = env_cpu(env);
+    int vmid;
 
-    /* Accesses to VTTBR may change the VMID so we must flush the TLB.  */
-    if (raw_read(env, ri) != value) {
-        tlb_flush_by_mmuidx(cs,
-                            ARMMMUIdxBit_S12NSE1 |
-                            ARMMMUIdxBit_S12NSE0 |
-                            ARMMMUIdxBit_S2NS);
-        raw_write(env, ri, value);
-    }
+    raw_write(env, ri, value);
+
+    /*
+     * TODO: with ARMv8.1-VMID16, aarch64 must examine VTCR.VS
+     * (re-evaluating with changes to VTCR) then use bits [63:48].
+     */
+    vmid = extract64(value, 48, 8);
+
+    /*
+     * A change in VMID to the stage2 page table (S2NS) invalidates
+     * the combined stage 1&2 tlbs (S12NSE1 and S12NSE0).
+     */
+    tlb_set_asid_for_mmuidx(cs, vmid, ARMMMUIdxBit_S2NS,
+                            ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0);
 }
 
 static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 06/24] target/arm: Define isar_feature_aa64_vh
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (4 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 05/24] target/arm: Install ASIDs for EL2 Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-24 12:59   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 07/24] target/arm: Enable HCR_E2H for VHE Richard Henderson
                   ` (19 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

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

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 94c990cddb..e6a76d14c6 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3573,6 +3573,11 @@ static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
     return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
 }
 
+static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
+}
+
 static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
 {
     return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 07/24] target/arm: Enable HCR_E2H for VHE
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (5 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 06/24] target/arm: Define isar_feature_aa64_vh Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-24 13:01   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 08/24] target/arm: Add CONTEXTIDR_EL2 Richard Henderson
                   ` (18 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

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

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index e6a76d14c6..e37008a4f7 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1366,13 +1366,6 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
 #define HCR_ATA       (1ULL << 56)
 #define HCR_DCT       (1ULL << 57)
 
-/*
- * When we actually implement ARMv8.1-VHE we should add HCR_E2H to
- * HCR_MASK and then clear it again if the feature bit is not set in
- * hcr_write().
- */
-#define HCR_MASK      ((1ULL << 34) - 1)
-
 #define SCR_NS                (1U << 0)
 #define SCR_IRQ               (1U << 1)
 #define SCR_FIQ               (1U << 2)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 3a9f35bf4b..0a55096770 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4623,7 +4623,8 @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
 static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 {
     ARMCPU *cpu = env_archcpu(env);
-    uint64_t valid_mask = HCR_MASK;
+    /* Begin with bits defined in base ARMv8.0.  */
+    uint64_t valid_mask = MAKE_64BIT_MASK(0, 34);
 
     if (arm_feature(env, ARM_FEATURE_EL3)) {
         valid_mask &= ~HCR_HCD;
@@ -4637,6 +4638,9 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
          */
         valid_mask &= ~HCR_TSC;
     }
+    if (cpu_isar_feature(aa64_vh, cpu)) {
+        valid_mask |= HCR_E2H;
+    }
     if (cpu_isar_feature(aa64_lor, cpu)) {
         valid_mask |= HCR_TLOR;
     }
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 08/24] target/arm: Add CONTEXTIDR_EL2
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (6 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 07/24] target/arm: Enable HCR_E2H for VHE Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-24 13:57   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 09/24] target/arm: Add TTBR1_EL2 Richard Henderson
                   ` (17 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

Not all of the breakpoint types are supported, but those that
only examine contextidr are extended to support the new register.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/debug_helper.c | 50 +++++++++++++++++++++++++++++----------
 target/arm/helper.c       | 11 +++++++++
 2 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index dde80273ff..2e3e90c6a5 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -20,6 +20,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
     int ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
     int bt;
     uint32_t contextidr;
+    uint64_t hcr_el2;
 
     /*
      * Links to unimplemented or non-context aware breakpoints are
@@ -40,24 +41,44 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
     }
 
     bt = extract64(bcr, 20, 4);
-
-    /*
-     * We match the whole register even if this is AArch32 using the
-     * short descriptor format (in which case it holds both PROCID and ASID),
-     * since we don't implement the optional v7 context ID masking.
-     */
-    contextidr = extract64(env->cp15.contextidr_el[1], 0, 32);
+    hcr_el2 = arm_hcr_el2_eff(env);
 
     switch (bt) {
     case 3: /* linked context ID match */
-        if (arm_current_el(env) > 1) {
-            /* Context matches never fire in EL2 or (AArch64) EL3 */
+        switch (arm_current_el(env)) {
+        default:
+            /* Context matches never fire in AArch64 EL3 */
             return false;
+        case 2:
+            if (!(hcr_el2 & HCR_E2H)) {
+                /* Context matches never fire in EL2 without E2H enabled. */
+                return false;
+            }
+            contextidr = env->cp15.contextidr_el[2];
+            break;
+        case 1:
+            contextidr = env->cp15.contextidr_el[1];
+            break;
+        case 0:
+            if ((hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
+                contextidr = env->cp15.contextidr_el[2];
+            } else {
+                contextidr = env->cp15.contextidr_el[1];
+            }
+            break;
         }
-        return (contextidr == extract64(env->cp15.dbgbvr[lbn], 0, 32));
-    case 5: /* linked address mismatch (reserved in AArch64) */
+        break;
+
+    case 7:  /* linked contextidr_el1 match */
+        contextidr = env->cp15.contextidr_el[1];
+        break;
+    case 13: /* linked contextidr_el2 match */
+        contextidr = env->cp15.contextidr_el[2];
+        break;
+
     case 9: /* linked VMID match (reserved if no EL2) */
     case 11: /* linked context ID and VMID match (reserved if no EL2) */
+    case 15: /* linked full context ID match */
     default:
         /*
          * Links to Unlinked context breakpoints must generate no
@@ -66,7 +87,12 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
         return false;
     }
 
-    return false;
+    /*
+     * We match the whole register even if this is AArch32 using the
+     * short descriptor format (in which case it holds both PROCID and ASID),
+     * since we don't implement the optional v7 context ID masking.
+     */
+    return contextidr == (uint32_t)env->cp15.dbgbvr[lbn];
 }
 
 static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0a55096770..d1bf31ab74 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6801,6 +6801,17 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         define_arm_cp_regs(cpu, lor_reginfo);
     }
 
+    if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
+        static const ARMCPRegInfo vhe_reginfo[] = {
+            { .name = "CONTEXTIDR_EL2", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 1,
+              .access = PL2_RW,
+              .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[2]) },
+            REGINFO_SENTINEL
+        };
+        define_arm_cp_regs(cpu, vhe_reginfo);
+    }
+
     if (cpu_isar_feature(aa64_sve, cpu)) {
         define_one_arm_cp_reg(cpu, &zcr_el1_reginfo);
         if (arm_feature(env, ARM_FEATURE_EL2)) {
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 09/24] target/arm: Add TTBR1_EL2
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (7 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 08/24] target/arm: Add CONTEXTIDR_EL2 Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-24 14:12   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 10/24] target/arm: Update CNTVCT_EL0 for VHE Richard Henderson
                   ` (16 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

At the same time, add writefn to TTBR0_EL2 and TCR_EL2.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index d1bf31ab74..da2e0627b2 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3449,6 +3449,15 @@ static void vmsa_ttbr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
     }
 }
 
+static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                    uint64_t value)
+{
+    raw_write(env, ri, value);
+    if (arm_hcr_el2_eff(env) & HCR_E2H) {
+        /* The ASID field is active.  */
+    }
+}
+
 static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
                         uint64_t value)
 {
@@ -4844,10 +4853,8 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
       .resetvalue = 0 },
     { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
-      .access = PL2_RW,
-      /* no .writefn needed as this can't cause an ASID change;
-       * no .raw_writefn or .resetfn needed as we never use mask/base_mask
-       */
+      .access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
+      /* no .raw_writefn or .resetfn needed as we never use mask/base_mask */
       .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) },
     { .name = "VTCR", .state = ARM_CP_STATE_AA32,
       .cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
@@ -4881,7 +4888,7 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
       .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[2]) },
     { .name = "TTBR0_EL2", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
-      .access = PL2_RW, .resetvalue = 0,
+      .access = PL2_RW, .resetvalue = 0, .writefn = vmsa_tcr_ttbr_el2_write,
       .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
     { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
       .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
@@ -6807,6 +6814,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 1,
               .access = PL2_RW,
               .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[2]) },
+            { .name = "TTBR1_EL2", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 1,
+              .access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
+              .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el[2]) },
             REGINFO_SENTINEL
         };
         define_arm_cp_regs(cpu, vhe_reginfo);
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 10/24] target/arm: Update CNTVCT_EL0 for VHE
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (8 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 09/24] target/arm: Add TTBR1_EL2 Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-24 14:47   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 11/24] target/arm: Add the hypervisor virtual counter Richard Henderson
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

The virtual offset may be 0 depending on EL, E2H and TGE.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index da2e0627b2..3124d682a2 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2484,9 +2484,31 @@ static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
     return gt_get_countervalue(env);
 }
 
+static uint64_t gt_virt_cnt_offset(CPUARMState *env)
+{
+    uint64_t hcr;
+
+    switch (arm_current_el(env)) {
+    case 2:
+        hcr = arm_hcr_el2_eff(env);
+        if (hcr & HCR_E2H) {
+            return 0;
+        }
+        break;
+    case 0:
+        hcr = arm_hcr_el2_eff(env);
+        if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
+            return 0;
+        }
+        break;
+    }
+
+    return env->cp15.cntvoff_el2;
+}
+
 static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
-    return gt_get_countervalue(env) - env->cp15.cntvoff_el2;
+    return gt_get_countervalue(env) - gt_virt_cnt_offset(env);
 }
 
 static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -2501,7 +2523,13 @@ static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
                              int timeridx)
 {
-    uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
+    uint64_t offset = 0;
+
+    switch (timeridx) {
+    case GTIMER_VIRT:
+        offset = gt_virt_cnt_offset(env);
+        break;
+    }
 
     return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
                       (gt_get_countervalue(env) - offset));
@@ -2511,7 +2539,13 @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
                           int timeridx,
                           uint64_t value)
 {
-    uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
+    uint64_t offset = 0;
+
+    switch (timeridx) {
+    case GTIMER_VIRT:
+        offset = gt_virt_cnt_offset(env);
+        break;
+    }
 
     trace_arm_gt_tval_write(timeridx, value);
     env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 11/24] target/arm: Add the hypervisor virtual counter
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (9 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 10/24] target/arm: Update CNTVCT_EL0 for VHE Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-24 20:05   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 12/24] target/arm: Add VHE system register redirection and aliasing Richard Henderson
                   ` (14 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

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

diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
index 2049fa9612..43fc8296db 100644
--- a/target/arm/cpu-qom.h
+++ b/target/arm/cpu-qom.h
@@ -76,6 +76,7 @@ void arm_gt_ptimer_cb(void *opaque);
 void arm_gt_vtimer_cb(void *opaque);
 void arm_gt_htimer_cb(void *opaque);
 void arm_gt_stimer_cb(void *opaque);
+void arm_gt_hvtimer_cb(void *opaque);
 
 #define ARM_AFF0_SHIFT 0
 #define ARM_AFF0_MASK  (0xFFULL << ARM_AFF0_SHIFT)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index e37008a4f7..bba4e1f984 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -144,11 +144,12 @@ typedef struct ARMGenericTimer {
     uint64_t ctl; /* Timer Control register */
 } ARMGenericTimer;
 
-#define GTIMER_PHYS 0
-#define GTIMER_VIRT 1
-#define GTIMER_HYP  2
-#define GTIMER_SEC  3
-#define NUM_GTIMERS 4
+#define GTIMER_PHYS     0
+#define GTIMER_VIRT     1
+#define GTIMER_HYP      2
+#define GTIMER_SEC      3
+#define GTIMER_HYPVIRT  4
+#define NUM_GTIMERS     5
 
 typedef struct {
     uint64_t raw_tcr;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 1959467fdc..90352decc5 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1218,6 +1218,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
                                           arm_gt_htimer_cb, cpu);
     cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
                                           arm_gt_stimer_cb, cpu);
+    cpu->gt_timer[GTIMER_HYPVIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
+                                              arm_gt_hvtimer_cb, cpu);
 #endif
 
     cpu_exec_realizefn(cs, &local_err);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 3124d682a2..329548e45d 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2527,6 +2527,7 @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
 
     switch (timeridx) {
     case GTIMER_VIRT:
+    case GTIMER_HYPVIRT:
         offset = gt_virt_cnt_offset(env);
         break;
     }
@@ -2543,6 +2544,7 @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
     switch (timeridx) {
     case GTIMER_VIRT:
+    case GTIMER_HYPVIRT:
         offset = gt_virt_cnt_offset(env);
         break;
     }
@@ -2698,6 +2700,34 @@ static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
     gt_ctl_write(env, ri, GTIMER_SEC, value);
 }
 
+static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    gt_timer_reset(env, ri, GTIMER_HYPVIRT);
+}
+
+static void gt_hv_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                             uint64_t value)
+{
+    gt_cval_write(env, ri, GTIMER_HYPVIRT, value);
+}
+
+static uint64_t gt_hv_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    return gt_tval_read(env, ri, GTIMER_HYPVIRT);
+}
+
+static void gt_hv_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                             uint64_t value)
+{
+    gt_tval_write(env, ri, GTIMER_HYPVIRT, value);
+}
+
+static void gt_hv_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                            uint64_t value)
+{
+    gt_ctl_write(env, ri, GTIMER_HYPVIRT, value);
+}
+
 void arm_gt_ptimer_cb(void *opaque)
 {
     ARMCPU *cpu = opaque;
@@ -2726,6 +2756,13 @@ void arm_gt_stimer_cb(void *opaque)
     gt_recalc_timer(cpu, GTIMER_SEC);
 }
 
+void arm_gt_hvtimer_cb(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+
+    gt_recalc_timer(cpu, GTIMER_HYPVIRT);
+}
+
 static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
     /* Note that CNTFRQ is purely reads-as-written for the benefit
      * of software; writing it doesn't actually change the timer frequency.
@@ -6852,6 +6889,26 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 1,
               .access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
               .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el[2]) },
+#ifndef CONFIG_USER_ONLY
+            { .name = "CNTHV_CVAL_EL2", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 2,
+              .fieldoffset =
+                offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].cval),
+              .type = ARM_CP_IO, .access = PL2_RW,
+              .writefn = gt_hv_cval_write, .raw_writefn = raw_write },
+            { .name = "CNTHV_TVAL_EL2", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 0,
+              .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
+              .resetfn = gt_hv_timer_reset,
+              .readfn = gt_hv_tval_read, .writefn = gt_hv_tval_write },
+            { .name = "CNTHV_CTL_EL2", .state = ARM_CP_STATE_BOTH,
+              .type = ARM_CP_IO,
+              .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 1,
+              .access = PL2_RW,
+              .fieldoffset =
+                offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].ctl),
+              .writefn = gt_hv_ctl_write, .raw_writefn = raw_write },
+#endif
             REGINFO_SENTINEL
         };
         define_arm_cp_regs(cpu, vhe_reginfo);
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 12/24] target/arm: Add VHE system register redirection and aliasing
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (10 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 11/24] target/arm: Add the hypervisor virtual counter Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-25 14:01   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 13/24] target/arm: Split out vae1_tlbmask, vmalle1_tlbmask Richard Henderson
                   ` (13 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

Several of the EL1/0 registers are redirected to the EL2 version when in
EL2 and HCR_EL2.E2H is set.  Many of these registers have side effects.
Link together the two ARMCPRegInfo structures after they have been
properly instantiated.  Install common dispatch routines to all of the
relevant registers.

The same set of registers that are redirected also have additional
EL12/EL02 aliases created to access the original register that was
redirected.

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

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index bba4e1f984..a0f10b60eb 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2455,19 +2455,6 @@ struct ARMCPRegInfo {
      */
     ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
 
-    /* Offsets of the secure and non-secure fields in CPUARMState for the
-     * register if it is banked.  These fields are only used during the static
-     * registration of a register.  During hashing the bank associated
-     * with a given security state is copied to fieldoffset which is used from
-     * there on out.
-     *
-     * It is expected that register definitions use either fieldoffset or
-     * bank_fieldoffsets in the definition but not both.  It is also expected
-     * that both bank offsets are set when defining a banked register.  This
-     * use indicates that a register is banked.
-     */
-    ptrdiff_t bank_fieldoffsets[2];
-
     /* Function for making any access checks for this register in addition to
      * those specified by the 'access' permissions bits. If NULL, no extra
      * checks required. The access check is performed at runtime, not at
@@ -2502,6 +2489,37 @@ struct ARMCPRegInfo {
      * fieldoffset is 0 then no reset will be done.
      */
     CPResetFn *resetfn;
+
+    union {
+        /*
+         * Offsets of the secure and non-secure fields in CPUARMState for
+         * the register if it is banked.  These fields are only used during
+         * the static registration of a register.  During hashing the bank
+         * associated with a given security state is copied to fieldoffset
+         * which is used from there on out.
+         *
+         * It is expected that register definitions use either fieldoffset
+         * or bank_fieldoffsets in the definition but not both.  It is also
+         * expected that both bank offsets are set when defining a banked
+         * register.  This use indicates that a register is banked.
+         */
+        ptrdiff_t bank_fieldoffsets[2];
+
+        /*
+         * "Original" writefn and readfn.
+         * For ARMv8.1-VHE register aliases, we overwrite the read/write
+         * accessor functions of various EL1/EL0 to perform the runtime
+         * check for which sysreg should actually be modified, and then
+         * forwards the operation.  Before overwriting the accessors,
+         * the original function is copied here, so that accesses that
+         * really do go to the EL1/EL0 version proceed normally.
+         * (The corresponding EL2 register is linked via opaque.)
+         */
+        struct {
+            CPReadFn *orig_readfn;
+            CPWriteFn *orig_writefn;
+        };
+    };
 };
 
 /* Macros which are lvalues for the field in CPUARMState for the
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 329548e45d..9a9809ff4f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5228,6 +5228,169 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
     REGINFO_SENTINEL
 };
 
+/* Test if system register redirection is to occur in the current state.  */
+static bool redirect_for_e2h(CPUARMState *env)
+{
+    return arm_current_el(env) == 2 && (arm_hcr_el2_eff(env) & HCR_E2H);
+}
+
+static uint64_t el2_e2h_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    CPReadFn *readfn;
+
+    if (redirect_for_e2h(env)) {
+        /* Switch to the saved EL2 version of the register.  */
+        ri = ri->opaque;
+        readfn = ri->readfn;
+    } else {
+        readfn = ri->orig_readfn;
+    }
+    if (readfn == NULL) {
+        readfn = raw_read;
+    }
+    return readfn(env, ri);
+}
+
+static void el2_e2h_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                          uint64_t value)
+{
+    CPWriteFn *writefn;
+
+    if (redirect_for_e2h(env)) {
+        /* Switch to the saved EL2 version of the register.  */
+        ri = ri->opaque;
+        writefn = ri->writefn;
+    } else {
+        writefn = ri->orig_writefn;
+    }
+    if (writefn == NULL) {
+        writefn = raw_write;
+    }
+    writefn(env, ri, value);
+}
+
+static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
+{
+    struct E2HAlias {
+        uint32_t src_key, dst_key, new_key;
+        const char *src_name, *dst_name, *new_name;
+        bool (*feature)(const ARMISARegisters *id);
+    };
+
+#define K(op0, op1, crn, crm, op2) \
+    ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
+
+    static const struct E2HAlias aliases[] = {
+        { K(3, 0,  1, 0, 0), K(3, 4,  1, 0, 0), K(3, 5, 1, 0, 0),
+          "SCTLR", "SCTLR_EL2", "SCTLR_EL12" },
+        { K(3, 0,  1, 0, 2), K(3, 4,  1, 1, 2), K(3, 5, 1, 0, 2),
+          "CPACR", "CPTR_EL2", "CPACR_EL12" },
+        { K(3, 0,  2, 0, 0), K(3, 4,  2, 0, 0), K(3, 5, 2, 0, 0),
+          "TTBR0_EL1", "TTBR0_EL2", "TTBR0_EL12" },
+        { K(3, 0,  2, 0, 1), K(3, 4,  2, 0, 1), K(3, 5, 2, 0, 1),
+          "TTBR1_EL1", "TTBR1_EL2", "TTBR1_EL12" },
+        { K(3, 0,  2, 0, 2), K(3, 4,  2, 0, 2), K(3, 5, 2, 0, 2),
+          "TCR_EL1", "TCR_EL2", "TCR_EL12" },
+        { K(3, 0,  4, 0, 0), K(3, 4,  4, 0, 0), K(3, 5, 4, 0, 0),
+          "SPSR_EL1", "SPSR_EL2", "SPSR_EL12" },
+        { K(3, 0,  4, 0, 1), K(3, 4,  4, 0, 1), K(3, 5, 4, 0, 1),
+          "ELR_EL1", "ELR_EL2", "ELR_EL12" },
+        { K(3, 0,  5, 1, 0), K(3, 4,  5, 1, 0), K(3, 5, 5, 1, 0),
+          "AFSR0_EL1", "AFSR0_EL2", "AFSR0_EL12" },
+        { K(3, 0,  5, 1, 1), K(3, 4,  5, 1, 1), K(3, 5, 5, 1, 1),
+          "AFSR1_EL1", "AFSR1_EL2", "AFSR1_EL12" },
+        { K(3, 0,  5, 2, 0), K(3, 4,  5, 2, 0), K(3, 5, 5, 2, 0),
+          "ESR_EL1", "ESR_EL2", "ESR_EL12" },
+        { K(3, 0,  6, 0, 0), K(3, 4,  6, 0, 0), K(3, 5, 6, 0, 0),
+          "FAR_EL1", "FAR_EL2", "FAR_EL12" },
+        { K(3, 0, 10, 2, 0), K(3, 4, 10, 2, 0), K(3, 5, 10, 2, 0),
+          "MAIR_EL1", "MAIR_EL2", "MAIR_EL12" },
+        { K(3, 0, 10, 3, 0), K(3, 4, 10, 3, 0), K(3, 5, 10, 3, 0),
+          "AMAIR0", "AMAIR_EL2", "AMAIR_EL12" },
+        { K(3, 0, 12, 0, 0), K(3, 4, 12, 0, 0), K(3, 5, 12, 0, 0),
+          "VBAR", "VBAR_EL2", "VBAR_EL12" },
+        { K(3, 0, 13, 0, 1), K(3, 4, 13, 0, 1), K(3, 5, 13, 0, 1),
+          "CONTEXTIDR_EL1", "CONTEXTIDR_EL2", "CONTEXTIDR_EL12" },
+        { K(3, 0, 14, 1, 0), K(3, 4, 14, 1, 0), K(3, 5, 14, 1, 0),
+          "CNTKCTL", "CNTHCTL_EL2", "CNTKCTL_EL12" },
+        { K(3, 3, 14, 2, 0), K(3, 4, 14, 2, 0), K(3, 5, 14, 2, 0),
+          "CNTP_TVAL_EL0", "CNTHP_TVAL_EL2", "CNTP_TVAL_EL02" },
+        { K(3, 3, 14, 2, 1), K(3, 4, 14, 2, 1), K(3, 5, 14, 2, 1),
+          "CNTP_CTL_EL0", "CNTHP_CTL_EL2", "CNTP_CTL_EL02" },
+        { K(3, 3, 14, 2, 2), K(3, 4, 14, 2, 2), K(3, 5, 14, 2, 2),
+          "CNTP_CVAL_EL0", "CNTHP_CVAL_EL2", "CNTP_CVAL_EL02" },
+        { K(3, 3, 14, 3, 0), K(3, 4, 14, 3, 0), K(3, 5, 14, 3, 0),
+          "CNTV_TVAL_EL0", "CNTHV_TVAL_EL2", "CNTV_TVAL_EL02" },
+        { K(3, 3, 14, 3, 1), K(3, 4, 14, 3, 1), K(3, 5, 14, 3, 1),
+          "CNTV_CTL_EL0", "CNTHV_CTL_EL2", "CNTV_CTL_EL02" },
+        { K(3, 3, 14, 3, 2), K(3, 4, 14, 3, 2), K(3, 5, 14, 3, 2),
+          "CNTV_CVAL_EL0", "CNTHV_CVAL_EL2", "CNTV_CVAL_EL02" },
+        /*
+         * CNTHV_CVAL is a special case because there is no separate
+         * AArch32 EL2 register to which CNTV_CVAL may be directed.
+         * The effect can be achieved via CNTHV_CVAL_EL2.
+         */
+        { ENCODE_CP_REG(15, 1, 1, 0, 14, 3, 0), K(3, 4, 14, 3, 2), 0,
+          "CNTV_CVAL", "CNTHV_CVAL_EL2", NULL },
+
+        /*
+         * Note that redirection of ZCR is mentioned in the description
+         * of ZCR_EL2, and aliasing in the description of ZCR_EL1, but
+         * not in the summary table.
+         */
+        { K(3, 0,  1, 2, 0), K(3, 4,  1, 2, 0), K(3, 5, 1, 2, 0),
+          "ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve },
+
+        /* TODO: ARMv8.2-SPE -- PMSCR_EL2 */
+        /* TODO: ARMv8.4-Trace -- TRFCR_EL2 */
+    };
+#undef K
+
+    size_t i;
+
+    for (i = 0; i < ARRAY_SIZE(aliases); i++) {
+        const struct E2HAlias *a = &aliases[i];
+        ARMCPRegInfo *src_reg, *dst_reg;
+
+        if (a->feature && !a->feature(&cpu->isar)) {
+            continue;
+        }
+
+        src_reg = g_hash_table_lookup(cpu->cp_regs, &a->src_key);
+        dst_reg = g_hash_table_lookup(cpu->cp_regs, &a->dst_key);
+        g_assert(src_reg != NULL);
+        g_assert(dst_reg != NULL);
+
+        /* Cross-compare names to detect typos in the keys.  */
+        g_assert(strcmp(src_reg->name, a->src_name) == 0);
+        g_assert(strcmp(dst_reg->name, a->dst_name) == 0);
+
+        /* None of the core system registers use opaque; we will.  */
+        g_assert(src_reg->opaque == NULL);
+
+        /* Create alias before redirection so we dup the right data. */
+        if (a->new_key) {
+            ARMCPRegInfo *new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
+            uint32_t *new_key = g_memdup(&a->new_key, sizeof(uint32_t));
+            bool ok;
+
+            new_reg->name = a->new_name;
+            new_reg->type |= ARM_CP_ALIAS;
+            /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place.  */
+            new_reg->access &= 0xf0;
+
+            ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
+            g_assert(ok);
+        }
+
+        src_reg->opaque = dst_reg;
+        src_reg->orig_readfn = src_reg->readfn;
+        src_reg->orig_writefn = src_reg->writefn;
+        src_reg->readfn = el2_e2h_read;
+        src_reg->writefn = el2_e2h_write;
+    }
+}
+
 static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
                                      bool isread)
 {
@@ -6945,6 +7108,14 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         : cpu_isar_feature(aa32_predinv, cpu)) {
         define_arm_cp_regs(cpu, predinv_reginfo);
     }
+
+    /*
+     * Register redirections and aliases must be done last,
+     * after the registers from the other extensions have been defined.
+     */
+    if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
+        define_arm_vh_e2h_redirects_aliases(cpu);
+    }
 }
 
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 13/24] target/arm: Split out vae1_tlbmask, vmalle1_tlbmask
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (11 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 12/24] target/arm: Add VHE system register redirection and aliasing Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-25 14:02   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 14/24] target/arm: Simplify tlb_force_broadcast alternatives Richard Henderson
                   ` (12 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

No functional change, but unify code sequences.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 9a9809ff4f..7adbf51479 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3901,70 +3901,61 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
  * Page D4-1736 (DDI0487A.b)
  */
 
+static int vae1_tlbmask(CPUARMState *env)
+{
+    if (arm_is_secure_below_el3(env)) {
+        return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
+    } else {
+        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
+    }
+}
+
 static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                       uint64_t value)
 {
     CPUState *cs = env_cpu(env);
-    bool sec = arm_is_secure_below_el3(env);
+    int mask = vae1_tlbmask(env);
 
-    if (sec) {
-        tlb_flush_by_mmuidx_all_cpus_synced(cs,
-                                            ARMMMUIdxBit_S1SE1 |
-                                            ARMMMUIdxBit_S1SE0);
-    } else {
-        tlb_flush_by_mmuidx_all_cpus_synced(cs,
-                                            ARMMMUIdxBit_S12NSE1 |
-                                            ARMMMUIdxBit_S12NSE0);
-    }
+    tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
 }
 
 static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                     uint64_t value)
 {
     CPUState *cs = env_cpu(env);
+    int mask = vae1_tlbmask(env);
 
     if (tlb_force_broadcast(env)) {
         tlbi_aa64_vmalle1is_write(env, NULL, value);
         return;
     }
 
+    tlb_flush_by_mmuidx(cs, mask);
+}
+
+static int vmalle1_tlbmask(CPUARMState *env)
+{
+    /*
+     * Note that the 'ALL' scope must invalidate both stage 1 and
+     * stage 2 translations, whereas most other scopes only invalidate
+     * stage 1 translations.
+     */
     if (arm_is_secure_below_el3(env)) {
-        tlb_flush_by_mmuidx(cs,
-                            ARMMMUIdxBit_S1SE1 |
-                            ARMMMUIdxBit_S1SE0);
+        return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
+    } else if (arm_feature(env, ARM_FEATURE_EL2)) {
+        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0 | ARMMMUIdxBit_S2NS;
     } else {
-        tlb_flush_by_mmuidx(cs,
-                            ARMMMUIdxBit_S12NSE1 |
-                            ARMMMUIdxBit_S12NSE0);
+        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
     }
 }
 
 static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                   uint64_t value)
 {
-    /* Note that the 'ALL' scope must invalidate both stage 1 and
-     * stage 2 translations, whereas most other scopes only invalidate
-     * stage 1 translations.
-     */
-    ARMCPU *cpu = env_archcpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUState *cs = env_cpu(env);
+    int mask = vmalle1_tlbmask(env);
 
-    if (arm_is_secure_below_el3(env)) {
-        tlb_flush_by_mmuidx(cs,
-                            ARMMMUIdxBit_S1SE1 |
-                            ARMMMUIdxBit_S1SE0);
-    } else {
-        if (arm_feature(env, ARM_FEATURE_EL2)) {
-            tlb_flush_by_mmuidx(cs,
-                                ARMMMUIdxBit_S12NSE1 |
-                                ARMMMUIdxBit_S12NSE0 |
-                                ARMMMUIdxBit_S2NS);
-        } else {
-            tlb_flush_by_mmuidx(cs,
-                                ARMMMUIdxBit_S12NSE1 |
-                                ARMMMUIdxBit_S12NSE0);
-        }
-    }
+    tlb_flush_by_mmuidx(cs, mask);
 }
 
 static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -3988,28 +3979,10 @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                     uint64_t value)
 {
-    /* Note that the 'ALL' scope must invalidate both stage 1 and
-     * stage 2 translations, whereas most other scopes only invalidate
-     * stage 1 translations.
-     */
     CPUState *cs = env_cpu(env);
-    bool sec = arm_is_secure_below_el3(env);
-    bool has_el2 = arm_feature(env, ARM_FEATURE_EL2);
+    int mask = vmalle1_tlbmask(env);
 
-    if (sec) {
-        tlb_flush_by_mmuidx_all_cpus_synced(cs,
-                                            ARMMMUIdxBit_S1SE1 |
-                                            ARMMMUIdxBit_S1SE0);
-    } else if (has_el2) {
-        tlb_flush_by_mmuidx_all_cpus_synced(cs,
-                                            ARMMMUIdxBit_S12NSE1 |
-                                            ARMMMUIdxBit_S12NSE0 |
-                                            ARMMMUIdxBit_S2NS);
-    } else {
-          tlb_flush_by_mmuidx_all_cpus_synced(cs,
-                                              ARMMMUIdxBit_S12NSE1 |
-                                              ARMMMUIdxBit_S12NSE0);
-    }
+    tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
 }
 
 static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4059,20 +4032,11 @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                    uint64_t value)
 {
-    ARMCPU *cpu = env_archcpu(env);
-    CPUState *cs = CPU(cpu);
-    bool sec = arm_is_secure_below_el3(env);
+    CPUState *cs = env_cpu(env);
+    int mask = vae1_tlbmask(env);
     uint64_t pageaddr = sextract64(value << 12, 0, 56);
 
-    if (sec) {
-        tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
-                                                 ARMMMUIdxBit_S1SE1 |
-                                                 ARMMMUIdxBit_S1SE0);
-    } else {
-        tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
-                                                 ARMMMUIdxBit_S12NSE1 |
-                                                 ARMMMUIdxBit_S12NSE0);
-    }
+    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
 }
 
 static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4083,8 +4047,8 @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
      * since we don't support flush-for-specific-ASID-only or
      * flush-last-level-only.
      */
-    ARMCPU *cpu = env_archcpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUState *cs = env_cpu(env);
+    int mask = vae1_tlbmask(env);
     uint64_t pageaddr = sextract64(value << 12, 0, 56);
 
     if (tlb_force_broadcast(env)) {
@@ -4092,15 +4056,7 @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
         return;
     }
 
-    if (arm_is_secure_below_el3(env)) {
-        tlb_flush_page_by_mmuidx(cs, pageaddr,
-                                 ARMMMUIdxBit_S1SE1 |
-                                 ARMMMUIdxBit_S1SE0);
-    } else {
-        tlb_flush_page_by_mmuidx(cs, pageaddr,
-                                 ARMMMUIdxBit_S12NSE1 |
-                                 ARMMMUIdxBit_S12NSE0);
-    }
+    tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
 }
 
 static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 14/24] target/arm: Simplify tlb_force_broadcast alternatives
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (12 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 13/24] target/arm: Split out vae1_tlbmask, vmalle1_tlbmask Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-25 14:08   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 15/24] target/arm: Reorganize ARMMMUIdx Richard Henderson
                   ` (11 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

Rather than call to a separate function and re-compute any
parameters for the flush, simply use the correct flush
function directly.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7adbf51479..2b95fc763f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -626,56 +626,54 @@ static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
                           uint64_t value)
 {
     /* Invalidate all (TLBIALL) */
-    ARMCPU *cpu = env_archcpu(env);
+    CPUState *cs = env_cpu(env);
 
     if (tlb_force_broadcast(env)) {
-        tlbiall_is_write(env, NULL, value);
-        return;
+        tlb_flush_all_cpus_synced(cs);
+    } else {
+        tlb_flush(cs);
     }
-
-    tlb_flush(CPU(cpu));
 }
 
 static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri,
                           uint64_t value)
 {
     /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */
-    ARMCPU *cpu = env_archcpu(env);
+    CPUState *cs = env_cpu(env);
 
+    value &= TARGET_PAGE_MASK;
     if (tlb_force_broadcast(env)) {
-        tlbimva_is_write(env, NULL, value);
-        return;
+        tlb_flush_page_all_cpus_synced(cs, value);
+    } else {
+        tlb_flush_page(cs, value);
     }
-
-    tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
 }
 
 static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri,
                            uint64_t value)
 {
     /* Invalidate by ASID (TLBIASID) */
-    ARMCPU *cpu = env_archcpu(env);
+    CPUState *cs = env_cpu(env);
 
     if (tlb_force_broadcast(env)) {
-        tlbiasid_is_write(env, NULL, value);
-        return;
+        tlb_flush_all_cpus_synced(cs);
+    } else {
+        tlb_flush(cs);
     }
-
-    tlb_flush(CPU(cpu));
 }
 
 static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
                            uint64_t value)
 {
     /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */
-    ARMCPU *cpu = env_archcpu(env);
+    CPUState *cs = env_cpu(env);
 
+    value &= TARGET_PAGE_MASK;
     if (tlb_force_broadcast(env)) {
-        tlbimvaa_is_write(env, NULL, value);
-        return;
+        tlb_flush_page_all_cpus_synced(cs, value);
+    } else {
+        tlb_flush_page(cs, value);
     }
-
-    tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
 }
 
 static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -3926,11 +3924,10 @@ static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
     int mask = vae1_tlbmask(env);
 
     if (tlb_force_broadcast(env)) {
-        tlbi_aa64_vmalle1is_write(env, NULL, value);
-        return;
+        tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
+    } else {
+        tlb_flush_by_mmuidx(cs, mask);
     }
-
-    tlb_flush_by_mmuidx(cs, mask);
 }
 
 static int vmalle1_tlbmask(CPUARMState *env)
@@ -4052,11 +4049,10 @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
     uint64_t pageaddr = sextract64(value << 12, 0, 56);
 
     if (tlb_force_broadcast(env)) {
-        tlbi_aa64_vae1is_write(env, NULL, value);
-        return;
+        tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
+    } else {
+        tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
     }
-
-    tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
 }
 
 static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 15/24] target/arm: Reorganize ARMMMUIdx
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (13 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 14/24] target/arm: Simplify tlb_force_broadcast alternatives Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-25 15:57   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 16/24] target/arm: Add regime_has_2_ranges Richard Henderson
                   ` (10 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

Prepare for, but do not yet implement, the EL2&0 regime and the
Secure EL2 regime.  Rename all of the a-profile symbols to make
the distictions clearer.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h           | 180 ++++++++++++++--------------
 target/arm/internals.h     |  46 ++++---
 target/arm/translate.h     |   2 +-
 target/arm/helper.c        | 237 ++++++++++++++++++++++---------------
 target/arm/m_helper.c      |   6 +-
 target/arm/translate-a64.c |  11 +-
 target/arm/translate.c     |  17 ++-
 7 files changed, 273 insertions(+), 226 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index a0f10b60eb..4b537c4613 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2764,7 +2764,10 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
  *  + NonSecure EL1 & 0 stage 1
  *  + NonSecure EL1 & 0 stage 2
  *  + NonSecure EL2
- *  + Secure EL1 & EL0
+ *  + NonSecure EL2 & 0   (ARMv8.1-VHE)
+ *  + Secure EL0
+ *  + Secure EL1
+ *  + Secure EL2          (ARMv8.4-SecEL2)
  *  + Secure EL3
  * If EL3 is 32-bit:
  *  + NonSecure PL1 & 0 stage 1
@@ -2774,8 +2777,9 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
  * (reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.)
  *
  * For QEMU, an mmu_idx is not quite the same as a translation regime because:
- *  1. we need to split the "EL1 & 0" regimes into two mmu_idxes, because they
- *     may differ in access permissions even if the VA->PA map is the same
+ *  1. we need to split the "EL1 & 0" and "EL2 & 0" regimes into two mmu_idxes,
+ *     because they may differ in access permissions even if the VA->PA map is
+ *     the same
  *  2. we want to cache in our TLB the full VA->IPA->PA lookup for a stage 1+2
  *     translation, which means that we have one mmu_idx that deals with two
  *     concatenated translation regimes [this sort of combined s1+2 TLB is
@@ -2787,19 +2791,26 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
  *  4. we can also safely fold together the "32 bit EL3" and "64 bit EL3"
  *     translation regimes, because they map reasonably well to each other
  *     and they can't both be active at the same time.
- * This gives us the following list of mmu_idx values:
+ *  5. we want to be able to use the TLB for accesses done as part of a
+ *     stage1 page table walk, rather than having to walk the stage2 page
+ *     table over and over.
  *
- * NS EL0 (aka NS PL0) stage 1+2
- * NS EL1 (aka NS PL1) stage 1+2
+ * This gives us the following list of cases:
+ *
+ * NS EL0 (aka NS PL0) EL1&0 stage 1+2
+ * NS EL1 (aka NS PL1) EL1&0 stage 1+2
+ * NS EL0 (aka NS PL0) EL2&0
+ * NS EL2 (aka NS PL2) EL2&0
  * NS EL2 (aka NS PL2)
- * S EL3 (aka S PL1)
  * S EL0 (aka S PL0)
  * S EL1 (not used if EL3 is 32 bit)
- * NS EL0+1 stage 2
+ * S EL2 (not used if EL3 is 32 bit)
+ * S EL3 (aka S PL1)
+ * NS EL0&1 stage 2
  *
- * (The last of these is an mmu_idx because we want to be able to use the TLB
- * for the accesses done as part of a stage 1 page table walk, rather than
- * having to walk the stage 2 page table over and over.)
+ * We then merge the two NS EL0 cases, and two NS EL2 cases to produce
+ * 8 different mmu_idx.  We retain separate symbols for these four cases
+ * in order to simplify distinguishing them in the code.
  *
  * R profile CPUs have an MPU, but can use the same set of MMU indexes
  * as A profile. They only need to distinguish NS EL0 and NS EL1 (and
@@ -2837,62 +2848,93 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
  * For M profile we arrange them to have a bit for priv, a bit for negpri
  * and a bit for secure.
  */
-#define ARM_MMU_IDX_A 0x10 /* A profile */
-#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
-#define ARM_MMU_IDX_M 0x40 /* M profile */
+#define ARM_MMU_IDX_S     0x04  /* Secure */
+#define ARM_MMU_IDX_A     0x10  /* A profile */
+#define ARM_MMU_IDX_M     0x20  /* M profile */
+#define ARM_MMU_IDX_NOTLB 0x100 /* does not have a TLB */
 
-/* meanings of the bits for M profile mmu idx values */
-#define ARM_MMU_IDX_M_PRIV 0x1
+/* Meanings of the bits for A profile mmu idx values */
+#define ARM_MMU_IDX_A_PRIV   0x3
+#define ARM_MMU_IDX_A_EL10   0x40
+#define ARM_MMU_IDX_A_EL20   0x80
+
+/* Meanings of the bits for M profile mmu idx values */
+#define ARM_MMU_IDX_M_PRIV   0x1
 #define ARM_MMU_IDX_M_NEGPRI 0x2
-#define ARM_MMU_IDX_M_S 0x4
 
-#define ARM_MMU_IDX_TYPE_MASK (~0x7)
+#define ARM_MMU_IDX_TYPE_MASK    (ARM_MMU_IDX_A | ARM_MMU_IDX_M)
 #define ARM_MMU_IDX_COREIDX_MASK 0x7
 
 typedef enum ARMMMUIdx {
-    ARMMMUIdx_S12NSE0 = 0 | ARM_MMU_IDX_A,
-    ARMMMUIdx_S12NSE1 = 1 | ARM_MMU_IDX_A,
-    ARMMMUIdx_S1E2 = 2 | ARM_MMU_IDX_A,
-    ARMMMUIdx_S1E3 = 3 | ARM_MMU_IDX_A,
-    ARMMMUIdx_S1SE0 = 4 | ARM_MMU_IDX_A,
-    ARMMMUIdx_S1SE1 = 5 | ARM_MMU_IDX_A,
-    ARMMMUIdx_S2NS = 6 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E0 = 0 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E1 = 1 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E2 = 2 | ARM_MMU_IDX_A,
+
+    /*
+     * While Stage2 is used by A profile, and uses a TLB, it is only
+     * used for page table walks and is not a valid as an arm_mmu_idx().
+     * Overlap it on the non-existant non-secure el3 slot.
+     */
+    ARMMMUIdx_Stage2 = 3,
+
+    ARMMMUIdx_SE0 = 0 | ARM_MMU_IDX_S | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE1 = 1 | ARM_MMU_IDX_S | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE2 = 2 | ARM_MMU_IDX_S | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE3 = 3 | ARM_MMU_IDX_S | ARM_MMU_IDX_A,
+
     ARMMMUIdx_MUser = 0 | ARM_MMU_IDX_M,
     ARMMMUIdx_MPriv = 1 | ARM_MMU_IDX_M,
     ARMMMUIdx_MUserNegPri = 2 | ARM_MMU_IDX_M,
     ARMMMUIdx_MPrivNegPri = 3 | ARM_MMU_IDX_M,
-    ARMMMUIdx_MSUser = 4 | ARM_MMU_IDX_M,
-    ARMMMUIdx_MSPriv = 5 | ARM_MMU_IDX_M,
-    ARMMMUIdx_MSUserNegPri = 6 | ARM_MMU_IDX_M,
-    ARMMMUIdx_MSPrivNegPri = 7 | ARM_MMU_IDX_M,
-    /* Indexes below here don't have TLBs and are used only for AT system
-     * instructions or for the first stage of an S12 page table walk.
-     */
-    ARMMMUIdx_S1NSE0 = 0 | ARM_MMU_IDX_NOTLB,
-    ARMMMUIdx_S1NSE1 = 1 | ARM_MMU_IDX_NOTLB,
+    ARMMMUIdx_MSUser = 0 | ARM_MMU_IDX_S | ARM_MMU_IDX_M,
+    ARMMMUIdx_MSPriv = 1 | ARM_MMU_IDX_S | ARM_MMU_IDX_M,
+    ARMMMUIdx_MSUserNegPri = 2 | ARM_MMU_IDX_S | ARM_MMU_IDX_M,
+    ARMMMUIdx_MSPrivNegPri = 3 | ARM_MMU_IDX_S | ARM_MMU_IDX_M,
+
+    /* Indicies that map onto the same core mmu_idx.  */
+    ARMMMUIdx_EL10_0 = ARMMMUIdx_E0 | ARM_MMU_IDX_A_EL10,
+    ARMMMUIdx_EL10_1 = ARMMMUIdx_E1 | ARM_MMU_IDX_A_EL10,
+    ARMMMUIdx_EL20_0 = ARMMMUIdx_E0 | ARM_MMU_IDX_A_EL20,
+    ARMMMUIdx_EL20_2 = ARMMMUIdx_E2 | ARM_MMU_IDX_A_EL20,
+
+    /* Indicies that are only used only for AT system or Stage1 walk.  */
+    ARMMMUIdx_Stage1_E0 = ARMMMUIdx_E0 | ARM_MMU_IDX_NOTLB,
+    ARMMMUIdx_Stage1_E1 = ARMMMUIdx_E1 | ARM_MMU_IDX_NOTLB,
 } ARMMMUIdx;
 
-/* Bit macros for the core-mmu-index values for each index,
+/*
+ * Bit macros for the core-mmu-index values for each index,
  * for use when calling tlb_flush_by_mmuidx() and friends.
  */
+#define TO_CORE_BIT(NAME) \
+    ARMMMUIdxBit_##NAME = 1 << (ARMMMUIdx_##NAME & ARM_MMU_IDX_COREIDX_MASK)
+
 typedef enum ARMMMUIdxBit {
-    ARMMMUIdxBit_S12NSE0 = 1 << 0,
-    ARMMMUIdxBit_S12NSE1 = 1 << 1,
-    ARMMMUIdxBit_S1E2 = 1 << 2,
-    ARMMMUIdxBit_S1E3 = 1 << 3,
-    ARMMMUIdxBit_S1SE0 = 1 << 4,
-    ARMMMUIdxBit_S1SE1 = 1 << 5,
-    ARMMMUIdxBit_S2NS = 1 << 6,
-    ARMMMUIdxBit_MUser = 1 << 0,
-    ARMMMUIdxBit_MPriv = 1 << 1,
-    ARMMMUIdxBit_MUserNegPri = 1 << 2,
-    ARMMMUIdxBit_MPrivNegPri = 1 << 3,
-    ARMMMUIdxBit_MSUser = 1 << 4,
-    ARMMMUIdxBit_MSPriv = 1 << 5,
-    ARMMMUIdxBit_MSUserNegPri = 1 << 6,
-    ARMMMUIdxBit_MSPrivNegPri = 1 << 7,
+    TO_CORE_BIT(E0),
+    TO_CORE_BIT(E1),
+    TO_CORE_BIT(E2),
+    TO_CORE_BIT(Stage2),
+    TO_CORE_BIT(SE0),
+    TO_CORE_BIT(SE1),
+    TO_CORE_BIT(SE2),
+    TO_CORE_BIT(SE3),
+    TO_CORE_BIT(EL10_0),
+    TO_CORE_BIT(EL10_1),
+    TO_CORE_BIT(EL20_0),
+    TO_CORE_BIT(EL20_2),
+
+    TO_CORE_BIT(MUser),
+    TO_CORE_BIT(MPriv),
+    TO_CORE_BIT(MUserNegPri),
+    TO_CORE_BIT(MPrivNegPri),
+    TO_CORE_BIT(MSUser),
+    TO_CORE_BIT(MSPriv),
+    TO_CORE_BIT(MSUserNegPri),
+    TO_CORE_BIT(MSPrivNegPri),
 } ARMMMUIdxBit;
 
+#undef TO_CORE_BIT
+
 #define MMU_USER_IDX 0
 
 static inline int arm_to_core_mmu_idx(ARMMMUIdx mmu_idx)
@@ -2900,44 +2942,6 @@ static inline int arm_to_core_mmu_idx(ARMMMUIdx mmu_idx)
     return mmu_idx & ARM_MMU_IDX_COREIDX_MASK;
 }
 
-static inline ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
-{
-    if (arm_feature(env, ARM_FEATURE_M)) {
-        return mmu_idx | ARM_MMU_IDX_M;
-    } else {
-        return mmu_idx | ARM_MMU_IDX_A;
-    }
-}
-
-/* Return the exception level we're running at if this is our mmu_idx */
-static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
-{
-    switch (mmu_idx & ARM_MMU_IDX_TYPE_MASK) {
-    case ARM_MMU_IDX_A:
-        return mmu_idx & 3;
-    case ARM_MMU_IDX_M:
-        return mmu_idx & ARM_MMU_IDX_M_PRIV;
-    default:
-        g_assert_not_reached();
-    }
-}
-
-/*
- * Return the MMU index for a v7M CPU with all relevant information
- * manually specified.
- */
-ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
-                              bool secstate, bool priv, bool negpri);
-
-/* Return the MMU index for a v7M CPU in the specified security and
- * privilege state.
- */
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
-                                                bool secstate, bool priv);
-
-/* Return the MMU index for a v7M CPU in the specified security state */
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
-
 /**
  * cpu_mmu_index:
  * @env: The cpu environment
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 232d963875..047cbfd1d7 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -769,6 +769,26 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
                       MMUAccessType access_type, int mmu_idx,
                       bool probe, uintptr_t retaddr);
 
+ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx);
+int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx);
+
+/*
+ * Return the MMU index for a v7M CPU with all relevant information
+ * manually specified.
+ */
+ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
+                              bool secstate, bool priv, bool negpri);
+
+/*
+ * Return the MMU index for a v7M CPU in the specified security and
+ * privilege state.
+ */
+ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
+                                                bool secstate, bool priv);
+
+/* Return the MMU index for a v7M CPU in the specified security state */
+ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
+
 /* Return true if the stage 1 translation regime is using LPAE format page
  * tables */
 bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx);
@@ -807,29 +827,7 @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
 /* Return true if this address translation regime is secure */
 static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
-    switch (mmu_idx) {
-    case ARMMMUIdx_S12NSE0:
-    case ARMMMUIdx_S12NSE1:
-    case ARMMMUIdx_S1NSE0:
-    case ARMMMUIdx_S1NSE1:
-    case ARMMMUIdx_S1E2:
-    case ARMMMUIdx_S2NS:
-    case ARMMMUIdx_MPrivNegPri:
-    case ARMMMUIdx_MUserNegPri:
-    case ARMMMUIdx_MPriv:
-    case ARMMMUIdx_MUser:
-        return false;
-    case ARMMMUIdx_S1E3:
-    case ARMMMUIdx_S1SE0:
-    case ARMMMUIdx_S1SE1:
-    case ARMMMUIdx_MSPrivNegPri:
-    case ARMMMUIdx_MSUserNegPri:
-    case ARMMMUIdx_MSPriv:
-    case ARMMMUIdx_MSUser:
-        return true;
-    default:
-        g_assert_not_reached();
-    }
+    return (mmu_idx & ARM_MMU_IDX_S) != 0;
 }
 
 /* Return the FSR value for a debug exception (watchpoint, hardware
@@ -966,7 +964,7 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env);
 #ifdef CONFIG_USER_ONLY
 static inline ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
 {
-    return ARMMMUIdx_S1NSE0;
+    return ARMMMUIdx_EL10_0;
 }
 #else
 ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
diff --git a/target/arm/translate.h b/target/arm/translate.h
index a20f6e2056..715fa08e3b 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -122,7 +122,7 @@ static inline int default_exception_el(DisasContext *s)
      * exceptions can only be routed to ELs above 1, so we target the higher of
      * 1 or the current EL.
      */
-    return (s->mmu_idx == ARMMMUIdx_S1SE0 && s->secure_routed_to_el3)
+    return (s->mmu_idx == ARMMMUIdx_SE0 && s->secure_routed_to_el3)
             ? 3 : MAX(1, s->current_el);
 }
 
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2b95fc763f..240a6ed168 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -566,10 +566,10 @@ static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
         switch (ri->secure) {
         case ARM_CP_SECSTATE_S:
-            idxmask = ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
+            idxmask = ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0;
             break;
         case ARM_CP_SECSTATE_NS:
-            idxmask = ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
+            idxmask = ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
             break;
         default:
             g_assert_not_reached();
@@ -682,9 +682,9 @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
     CPUState *cs = env_cpu(env);
 
     tlb_flush_by_mmuidx(cs,
-                        ARMMMUIdxBit_S12NSE1 |
-                        ARMMMUIdxBit_S12NSE0 |
-                        ARMMMUIdxBit_S2NS);
+                        ARMMMUIdxBit_E1 |
+                        ARMMMUIdxBit_E0 |
+                        ARMMMUIdxBit_Stage2);
 }
 
 static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -693,9 +693,9 @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     CPUState *cs = env_cpu(env);
 
     tlb_flush_by_mmuidx_all_cpus_synced(cs,
-                                        ARMMMUIdxBit_S12NSE1 |
-                                        ARMMMUIdxBit_S12NSE0 |
-                                        ARMMMUIdxBit_S2NS);
+                                        ARMMMUIdxBit_E1 |
+                                        ARMMMUIdxBit_E0 |
+                                        ARMMMUIdxBit_Stage2);
 }
 
 static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -716,7 +716,7 @@ static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
     pageaddr = sextract64(value << 12, 0, 40);
 
-    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S2NS);
+    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
 }
 
 static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -731,8 +731,7 @@ static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
     pageaddr = sextract64(value << 12, 0, 40);
 
-    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
-                                             ARMMMUIdxBit_S2NS);
+    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2);
 }
 
 static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -740,7 +739,7 @@ static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     CPUState *cs = env_cpu(env);
 
-    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_S1E2);
+    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
 }
 
 static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -748,7 +747,7 @@ static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     CPUState *cs = env_cpu(env);
 
-    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E2);
+    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
 }
 
 static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -757,7 +756,7 @@ static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
     CPUState *cs = env_cpu(env);
     uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
 
-    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S1E2);
+    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
 }
 
 static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -766,8 +765,7 @@ static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     CPUState *cs = env_cpu(env);
     uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
 
-    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
-                                             ARMMMUIdxBit_S1E2);
+    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_E2);
 }
 
 static const ARMCPRegInfo cp_reginfo[] = {
@@ -3047,7 +3045,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
         format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
 
         if (arm_feature(env, ARM_FEATURE_EL2)) {
-            if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
+            if (mmu_idx == ARMMMUIdx_EL10_0 || mmu_idx == ARMMMUIdx_EL10_1) {
                 format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
             } else {
                 format64 |= arm_current_el(env) == 2;
@@ -3116,13 +3114,13 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
         /* stage 1 current state PL1: ATS1CPR, ATS1CPW */
         switch (el) {
         case 3:
-            mmu_idx = ARMMMUIdx_S1E3;
+            mmu_idx = ARMMMUIdx_SE3;
             break;
         case 2:
-            mmu_idx = ARMMMUIdx_S1NSE1;
+            mmu_idx = ARMMMUIdx_Stage1_E1;
             break;
         case 1:
-            mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S1NSE1;
+            mmu_idx = secure ? ARMMMUIdx_SE1 : ARMMMUIdx_Stage1_E1;
             break;
         default:
             g_assert_not_reached();
@@ -3132,13 +3130,13 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
         /* stage 1 current state PL0: ATS1CUR, ATS1CUW */
         switch (el) {
         case 3:
-            mmu_idx = ARMMMUIdx_S1SE0;
+            mmu_idx = ARMMMUIdx_SE0;
             break;
         case 2:
-            mmu_idx = ARMMMUIdx_S1NSE0;
+            mmu_idx = ARMMMUIdx_Stage1_E0;
             break;
         case 1:
-            mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0;
+            mmu_idx = secure ? ARMMMUIdx_SE0 : ARMMMUIdx_Stage1_E0;
             break;
         default:
             g_assert_not_reached();
@@ -3146,11 +3144,11 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
         break;
     case 4:
         /* stage 1+2 NonSecure PL1: ATS12NSOPR, ATS12NSOPW */
-        mmu_idx = ARMMMUIdx_S12NSE1;
+        mmu_idx = ARMMMUIdx_EL10_1;
         break;
     case 6:
         /* stage 1+2 NonSecure PL0: ATS12NSOUR, ATS12NSOUW */
-        mmu_idx = ARMMMUIdx_S12NSE0;
+        mmu_idx = ARMMMUIdx_EL10_0;
         break;
     default:
         g_assert_not_reached();
@@ -3167,7 +3165,7 @@ static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
     MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
     uint64_t par64;
 
-    par64 = do_ats_write(env, value, access_type, ARMMMUIdx_S1E2);
+    par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2);
 
     A32_BANKED_CURRENT_REG_SET(env, par, par64);
 }
@@ -3192,26 +3190,26 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
     case 0:
         switch (ri->opc1) {
         case 0: /* AT S1E1R, AT S1E1W */
-            mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S1NSE1;
+            mmu_idx = secure ? ARMMMUIdx_SE1 : ARMMMUIdx_Stage1_E1;
             break;
         case 4: /* AT S1E2R, AT S1E2W */
-            mmu_idx = ARMMMUIdx_S1E2;
+            mmu_idx = ARMMMUIdx_E2;
             break;
         case 6: /* AT S1E3R, AT S1E3W */
-            mmu_idx = ARMMMUIdx_S1E3;
+            mmu_idx = ARMMMUIdx_SE3;
             break;
         default:
             g_assert_not_reached();
         }
         break;
     case 2: /* AT S1E0R, AT S1E0W */
-        mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0;
+        mmu_idx = secure ? ARMMMUIdx_SE0 : ARMMMUIdx_Stage1_E0;
         break;
     case 4: /* AT S12E1R, AT S12E1W */
-        mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S12NSE1;
+        mmu_idx = secure ? ARMMMUIdx_SE1 : ARMMMUIdx_EL10_1;
         break;
     case 6: /* AT S12E0R, AT S12E0W */
-        mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S12NSE0;
+        mmu_idx = secure ? ARMMMUIdx_SE0 : ARMMMUIdx_EL10_0;
         break;
     default:
         g_assert_not_reached();
@@ -3422,15 +3420,15 @@ static void update_lpae_el1_asid(CPUARMState *env, int secure)
         ttbr0 = env->cp15.ttbr0_s;
         ttbr1 = env->cp15.ttbr1_s;
         ttcr = env->cp15.tcr_el[3].raw_tcr;
-        /* Note that cp15.ttbr0_s == cp15.ttbr0_el[3], so S1E3 is affected.  */
+        /* Note that cp15.ttbr0_s == cp15.ttbr0_el[3], so SE3 is affected.  */
         /* ??? Secure EL3 really using the ASID field?  Doesn't make sense.  */
-        idxmask = ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0 | ARMMMUIdxBit_S1E3;
+        idxmask = ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0 | ARMMMUIdxBit_SE3;
         break;
     case ARM_CP_SECSTATE_NS:
         ttbr0 = env->cp15.ttbr0_ns;
         ttbr1 = env->cp15.ttbr1_ns;
         ttcr = env->cp15.tcr_el[1].raw_tcr;
-        idxmask = ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
+        idxmask = ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
         break;
     default:
         g_assert_not_reached();
@@ -3542,11 +3540,11 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
     vmid = extract64(value, 48, 8);
 
     /*
-     * A change in VMID to the stage2 page table (S2NS) invalidates
-     * the combined stage 1&2 tlbs (S12NSE1 and S12NSE0).
+     * A change in VMID to the stage2 page table (Stage2) invalidates
+     * the combined stage 1&2 tlbs (EL10_1 and EL10_0).
      */
-    tlb_set_asid_for_mmuidx(cs, vmid, ARMMMUIdxBit_S2NS,
-                            ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0);
+    tlb_set_asid_for_mmuidx(cs, vmid, ARMMMUIdxBit_Stage2,
+                            ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0);
 }
 
 static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
@@ -3902,9 +3900,9 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
 static int vae1_tlbmask(CPUARMState *env)
 {
     if (arm_is_secure_below_el3(env)) {
-        return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
+        return ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0;
     } else {
-        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
+        return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
     }
 }
 
@@ -3938,11 +3936,11 @@ static int vmalle1_tlbmask(CPUARMState *env)
      * stage 1 translations.
      */
     if (arm_is_secure_below_el3(env)) {
-        return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
+        return ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0;
     } else if (arm_feature(env, ARM_FEATURE_EL2)) {
-        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0 | ARMMMUIdxBit_S2NS;
+        return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0 | ARMMMUIdxBit_Stage2;
     } else {
-        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
+        return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
     }
 }
 
@@ -3961,7 +3959,7 @@ static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
     ARMCPU *cpu = env_archcpu(env);
     CPUState *cs = CPU(cpu);
 
-    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_S1E2);
+    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
 }
 
 static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -3970,7 +3968,7 @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
     ARMCPU *cpu = env_archcpu(env);
     CPUState *cs = CPU(cpu);
 
-    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_S1E3);
+    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_SE3);
 }
 
 static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -3987,7 +3985,7 @@ static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     CPUState *cs = env_cpu(env);
 
-    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E2);
+    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
 }
 
 static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -3995,7 +3993,7 @@ static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     CPUState *cs = env_cpu(env);
 
-    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E3);
+    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_SE3);
 }
 
 static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4009,7 +4007,7 @@ static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
     CPUState *cs = CPU(cpu);
     uint64_t pageaddr = sextract64(value << 12, 0, 56);
 
-    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S1E2);
+    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
 }
 
 static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4023,7 +4021,7 @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
     CPUState *cs = CPU(cpu);
     uint64_t pageaddr = sextract64(value << 12, 0, 56);
 
-    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S1E3);
+    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_SE3);
 }
 
 static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4061,8 +4059,7 @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     CPUState *cs = env_cpu(env);
     uint64_t pageaddr = sextract64(value << 12, 0, 56);
 
-    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
-                                             ARMMMUIdxBit_S1E2);
+    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_E2);
 }
 
 static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4071,8 +4068,7 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     CPUState *cs = env_cpu(env);
     uint64_t pageaddr = sextract64(value << 12, 0, 56);
 
-    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
-                                             ARMMMUIdxBit_S1E3);
+    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_SE3);
 }
 
 static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4094,7 +4090,7 @@ static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
     pageaddr = sextract64(value << 12, 0, 48);
 
-    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S2NS);
+    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
 }
 
 static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4109,8 +4105,7 @@ static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
     pageaddr = sextract64(value << 12, 0, 48);
 
-    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
-                                             ARMMMUIdxBit_S2NS);
+    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2);
 }
 
 static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4378,7 +4373,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
     { .name = "AT_S12E0W", .state = ARM_CP_STATE_AA64,
       .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 7,
       .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
-    /* AT S1E2* are elsewhere as they UNDEF from EL3 if EL2 is not present */
+    /* AT E2* are elsewhere as they UNDEF from EL3 if EL2 is not present */
     { .name = "AT_S1E3R", .state = ARM_CP_STATE_AA64,
       .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 0,
       .access = PL3_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
@@ -8685,19 +8680,23 @@ void arm_cpu_do_interrupt(CPUState *cs)
 #endif /* !CONFIG_USER_ONLY */
 
 /* Return the exception level which controls this address translation regime */
-static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
+static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
     switch (mmu_idx) {
-    case ARMMMUIdx_S2NS:
-    case ARMMMUIdx_S1E2:
+    case ARMMMUIdx_EL20_0:
+    case ARMMMUIdx_EL20_2:
+    case ARMMMUIdx_Stage2:
+    case ARMMMUIdx_E2:
         return 2;
-    case ARMMMUIdx_S1E3:
+    case ARMMMUIdx_SE3:
         return 3;
-    case ARMMMUIdx_S1SE0:
+    case ARMMMUIdx_SE0:
         return arm_el_is_aa64(env, 3) ? 1 : 3;
-    case ARMMMUIdx_S1SE1:
-    case ARMMMUIdx_S1NSE0:
-    case ARMMMUIdx_S1NSE1:
+    case ARMMMUIdx_SE1:
+    case ARMMMUIdx_Stage1_E0:
+    case ARMMMUIdx_Stage1_E1:
+    case ARMMMUIdx_EL10_0:
+    case ARMMMUIdx_EL10_1:
     case ARMMMUIdx_MPrivNegPri:
     case ARMMMUIdx_MUserNegPri:
     case ARMMMUIdx_MPriv:
@@ -8742,7 +8741,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
         }
     }
 
-    if (mmu_idx == ARMMMUIdx_S2NS) {
+    if (mmu_idx == ARMMMUIdx_Stage2) {
         /* HCR.DC means HCR.VM behaves as 1 */
         return (env->cp15.hcr_el2 & (HCR_DC | HCR_VM)) == 0;
     }
@@ -8755,7 +8754,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
     }
 
     if ((env->cp15.hcr_el2 & HCR_DC) &&
-        (mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1)) {
+        (mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1)) {
         /* HCR.DC means SCTLR_EL1.M behaves as 0 */
         return true;
     }
@@ -8773,7 +8772,7 @@ static inline bool regime_translation_big_endian(CPUARMState *env,
 static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
                                    int ttbrn)
 {
-    if (mmu_idx == ARMMMUIdx_S2NS) {
+    if (mmu_idx == ARMMMUIdx_Stage2) {
         return env->cp15.vttbr_el2;
     }
     if (ttbrn == 0) {
@@ -8788,7 +8787,7 @@ static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
 /* Return the TCR controlling this translation regime */
 static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
-    if (mmu_idx == ARMMMUIdx_S2NS) {
+    if (mmu_idx == ARMMMUIdx_Stage2) {
         return &env->cp15.vtcr_el2;
     }
     return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
@@ -8799,8 +8798,8 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
  */
 static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
 {
-    if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
-        mmu_idx += (ARMMMUIdx_S1NSE0 - ARMMMUIdx_S12NSE0);
+    if (mmu_idx == ARMMMUIdx_EL10_0 || mmu_idx == ARMMMUIdx_EL10_1) {
+        mmu_idx += (ARMMMUIdx_Stage1_E0 - ARMMMUIdx_EL10_0);
     }
     return mmu_idx;
 }
@@ -8834,8 +8833,8 @@ bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
 static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
     switch (mmu_idx) {
-    case ARMMMUIdx_S1SE0:
-    case ARMMMUIdx_S1NSE0:
+    case ARMMMUIdx_SE0:
+    case ARMMMUIdx_Stage1_E0:
     case ARMMMUIdx_MUser:
     case ARMMMUIdx_MSUser:
     case ARMMMUIdx_MUserNegPri:
@@ -8843,8 +8842,8 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
         return true;
     default:
         return false;
-    case ARMMMUIdx_S12NSE0:
-    case ARMMMUIdx_S12NSE1:
+    case ARMMMUIdx_EL10_0:
+    case ARMMMUIdx_EL10_1:
         g_assert_not_reached();
     }
 }
@@ -8975,7 +8974,7 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
     bool have_wxn;
     int wxn = 0;
 
-    assert(mmu_idx != ARMMMUIdx_S2NS);
+    assert(mmu_idx != ARMMMUIdx_Stage2);
 
     user_rw = simple_ap_to_rw_prot_is_user(ap, true);
     if (is_user) {
@@ -9066,8 +9065,8 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
                                hwaddr addr, MemTxAttrs txattrs,
                                ARMMMUFaultInfo *fi)
 {
-    if ((mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1) &&
-        !regime_translation_disabled(env, ARMMMUIdx_S2NS)) {
+    if ((mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1) &&
+        !regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
         target_ulong s2size;
         hwaddr s2pa;
         int s2prot;
@@ -9084,7 +9083,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
             pcacheattrs = &cacheattrs;
         }
 
-        ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
+        ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_Stage2, &s2pa,
                                  &txattrs, &s2prot, &s2size, fi, pcacheattrs);
         if (ret) {
             assert(fi->type != ARMFault_None);
@@ -9556,7 +9555,7 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
         tsz = extract32(tcr, 0, 6);
         using64k = extract32(tcr, 14, 1);
         using16k = extract32(tcr, 15, 1);
-        if (mmu_idx == ARMMMUIdx_S2NS) {
+        if (mmu_idx == ARMMMUIdx_Stage2) {
             /* VTCR_EL2 */
             tbi = tbid = hpd = false;
         } else {
@@ -9617,7 +9616,7 @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
     int select, tsz;
     bool epd, hpd;
 
-    if (mmu_idx == ARMMMUIdx_S2NS) {
+    if (mmu_idx == ARMMMUIdx_Stage2) {
         /* VTCR */
         bool sext = extract32(tcr, 4, 1);
         bool sign = extract32(tcr, 3, 1);
@@ -9719,7 +9718,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
         level = 1;
         /* There is no TTBR1 for EL2 */
         ttbr1_valid = (el != 2);
-        addrsize = (mmu_idx == ARMMMUIdx_S2NS ? 40 : 32);
+        addrsize = (mmu_idx == ARMMMUIdx_Stage2 ? 40 : 32);
         inputsize = addrsize - param.tsz;
     }
 
@@ -9770,7 +9769,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
         goto do_fault;
     }
 
-    if (mmu_idx != ARMMMUIdx_S2NS) {
+    if (mmu_idx != ARMMMUIdx_Stage2) {
         /* The starting level depends on the virtual address size (which can
          * be up to 48 bits) and the translation granule size. It indicates
          * the number of strides (stride bits at a time) needed to
@@ -9870,7 +9869,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
         attrs = extract64(descriptor, 2, 10)
             | (extract64(descriptor, 52, 12) << 10);
 
-        if (mmu_idx == ARMMMUIdx_S2NS) {
+        if (mmu_idx == ARMMMUIdx_Stage2) {
             /* Stage 2 table descriptors do not include any attribute fields */
             break;
         }
@@ -9901,7 +9900,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
     ap = extract32(attrs, 4, 2);
     xn = extract32(attrs, 12, 1);
 
-    if (mmu_idx == ARMMMUIdx_S2NS) {
+    if (mmu_idx == ARMMMUIdx_Stage2) {
         ns = true;
         *prot = get_S2prot(env, ap, xn);
     } else {
@@ -9928,7 +9927,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
     }
 
     if (cacheattrs != NULL) {
-        if (mmu_idx == ARMMMUIdx_S2NS) {
+        if (mmu_idx == ARMMMUIdx_Stage2) {
             cacheattrs->attrs = convert_stage2_attrs(env,
                                                      extract32(attrs, 0, 4));
         } else {
@@ -9949,7 +9948,7 @@ do_fault:
     fi->type = fault_type;
     fi->level = level;
     /* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2.  */
-    fi->stage2 = fi->s1ptw || (mmu_idx == ARMMMUIdx_S2NS);
+    fi->stage2 = fi->s1ptw || (mmu_idx == ARMMMUIdx_Stage2);
     return true;
 }
 
@@ -10748,7 +10747,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
                    target_ulong *page_size,
                    ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
 {
-    if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
+    if (mmu_idx == ARMMMUIdx_EL10_0 || mmu_idx == ARMMMUIdx_EL10_1) {
         /* Call ourselves recursively to do the stage 1 and then stage 2
          * translations.
          */
@@ -10763,13 +10762,13 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
                                 prot, page_size, fi, cacheattrs);
 
             /* If S1 fails or S2 is disabled, return early.  */
-            if (ret || regime_translation_disabled(env, ARMMMUIdx_S2NS)) {
+            if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
                 *phys_ptr = ipa;
                 return ret;
             }
 
             /* S1 is done. Now do S2 translation.  */
-            ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_S2NS,
+            ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_Stage2,
                                      phys_ptr, attrs, &s2_prot,
                                      page_size, fi,
                                      cacheattrs != NULL ? &cacheattrs2 : NULL);
@@ -10811,7 +10810,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
     /* Fast Context Switch Extension. This doesn't exist at all in v8.
      * In v7 and earlier it affects all stage 1 translations.
      */
-    if (address < 0x02000000 && mmu_idx != ARMMMUIdx_S2NS
+    if (address < 0x02000000 && mmu_idx != ARMMMUIdx_Stage2
         && !arm_feature(env, ARM_FEATURE_V8)) {
         if (regime_el(env, mmu_idx) == 3) {
             address += env->cp15.fcseidr_s;
@@ -11260,6 +11259,41 @@ int fp_exception_el(CPUARMState *env, int cur_el)
     return 0;
 }
 
+ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
+{
+    if (arm_feature(env, ARM_FEATURE_M)) {
+        return mmu_idx | ARM_MMU_IDX_M;
+    }
+
+    mmu_idx |= ARM_MMU_IDX_A;
+    switch (mmu_idx) {
+    case ARMMMUIdx_E0:
+        return ARMMMUIdx_EL10_0;
+    case ARMMMUIdx_E1:
+        return ARMMMUIdx_EL10_1;
+    case ARMMMUIdx_E2:
+    case ARMMMUIdx_SE0:
+    case ARMMMUIdx_SE1:
+    case ARMMMUIdx_SE3:
+        return mmu_idx;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+/* Return the exception level we're running at if this is our mmu_idx */
+int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
+{
+    switch (mmu_idx & ARM_MMU_IDX_TYPE_MASK) {
+    case ARM_MMU_IDX_A:
+        return mmu_idx & ARM_MMU_IDX_A_PRIV;
+    case ARM_MMU_IDX_M:
+        return mmu_idx & ARM_MMU_IDX_M_PRIV;
+    default:
+        g_assert_not_reached();
+    }
+}
+
 #ifndef CONFIG_TCG
 ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
 {
@@ -11276,10 +11310,21 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env)
     }
 
     el = arm_current_el(env);
-    if (el < 2 && arm_is_secure_below_el3(env)) {
-        return ARMMMUIdx_S1SE0 + el;
-    } else {
-        return ARMMMUIdx_S12NSE0 + el;
+    switch (el) {
+    case 0:
+        /* TODO: ARMv8.1-VHE */
+    case 1:
+        return (arm_is_secure_below_el3(env)
+                ? ARMMMUIdx_SE0 + el
+                : ARMMMUIdx_EL10_0 + el);
+    case 2:
+        /* TODO: ARMv8.1-VHE */
+        /* TODO: ARMv8.4-SecEL2 */
+        return ARMMMUIdx_E2;
+    case 3:
+        return ARMMMUIdx_SE3;
+    default:
+        g_assert_not_reached();
     }
 }
 
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 84609f446e..f745c0d067 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -126,7 +126,7 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
     hwaddr physaddr;
     int prot;
     ARMMMUFaultInfo fi = {};
-    bool secure = mmu_idx & ARM_MMU_IDX_M_S;
+    bool secure = mmu_idx & ARM_MMU_IDX_S;
     int exc;
     bool exc_secure;
 
@@ -218,7 +218,7 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr,
     hwaddr physaddr;
     int prot;
     ARMMMUFaultInfo fi = {};
-    bool secure = mmu_idx & ARM_MMU_IDX_M_S;
+    bool secure = mmu_idx & ARM_MMU_IDX_S;
     int exc;
     bool exc_secure;
     uint32_t value;
@@ -2669,7 +2669,7 @@ ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
     }
 
     if (secstate) {
-        mmu_idx |= ARM_MMU_IDX_M_S;
+        mmu_idx |= ARM_MMU_IDX_S;
     }
 
     return mmu_idx;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d3231477a2..a9e65fe347 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -113,13 +113,14 @@ static inline int get_a64_user_mem_index(DisasContext *s)
     ARMMMUIdx useridx;
 
     switch (s->mmu_idx) {
-    case ARMMMUIdx_S12NSE1:
-        useridx = ARMMMUIdx_S12NSE0;
+    case ARMMMUIdx_EL10_1:
+        /* FIXME: ARMv8.1-VHE */
+        useridx = ARMMMUIdx_EL10_0;
         break;
-    case ARMMMUIdx_S1SE1:
-        useridx = ARMMMUIdx_S1SE0;
+    case ARMMMUIdx_SE1:
+        useridx = ARMMMUIdx_SE0;
         break;
-    case ARMMMUIdx_S2NS:
+    case ARMMMUIdx_Stage2:
         g_assert_not_reached();
     default:
         useridx = s->mmu_idx;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 7853462b21..0346088e75 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -152,14 +152,14 @@ static inline int get_a32_user_mem_index(DisasContext *s)
      *  otherwise, access as if at PL0.
      */
     switch (s->mmu_idx) {
-    case ARMMMUIdx_S1E2:        /* this one is UNPREDICTABLE */
-    case ARMMMUIdx_S12NSE0:
-    case ARMMMUIdx_S12NSE1:
-        return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
-    case ARMMMUIdx_S1E3:
-    case ARMMMUIdx_S1SE0:
-    case ARMMMUIdx_S1SE1:
-        return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
+    case ARMMMUIdx_E2:        /* this one is UNPREDICTABLE */
+    case ARMMMUIdx_EL10_1:
+    case ARMMMUIdx_EL10_0:
+        return arm_to_core_mmu_idx(ARMMMUIdx_EL10_0);
+    case ARMMMUIdx_SE3:
+    case ARMMMUIdx_SE1:
+    case ARMMMUIdx_SE0:
+        return arm_to_core_mmu_idx(ARMMMUIdx_SE0);
     case ARMMMUIdx_MUser:
     case ARMMMUIdx_MPriv:
         return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
@@ -172,7 +172,6 @@ static inline int get_a32_user_mem_index(DisasContext *s)
     case ARMMMUIdx_MSUserNegPri:
     case ARMMMUIdx_MSPrivNegPri:
         return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
-    case ARMMMUIdx_S2NS:
     default:
         g_assert_not_reached();
     }
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 16/24] target/arm: Add regime_has_2_ranges
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (14 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 15/24] target/arm: Reorganize ARMMMUIdx Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-25 15:59   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 17/24] target/arm: Update arm_mmu_idx for VHE Richard Henderson
                   ` (9 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/internals.h     | 16 ++++++++++++++++
 target/arm/helper.c        | 22 +++++-----------------
 target/arm/translate-a64.c |  3 +--
 3 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 047cbfd1d7..f653e0e7f5 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -824,6 +824,22 @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
     }
 }
 
+/* Return true if this address translation regime has two ranges.  */
+static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
+{
+    switch (mmu_idx) {
+    case ARMMMUIdx_Stage1_E0:
+    case ARMMMUIdx_Stage1_E1:
+    case ARMMMUIdx_EL10_0:
+    case ARMMMUIdx_EL10_1:
+    case ARMMMUIdx_EL20_0:
+    case ARMMMUIdx_EL20_2:
+        return true;
+    default:
+        return false;
+    }
+}
+
 /* Return true if this address translation regime is secure */
 static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 240a6ed168..2d5658f9e3 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8999,15 +8999,8 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
     }
 
     if (is_aa64) {
-        switch (regime_el(env, mmu_idx)) {
-        case 1:
-            if (!is_user) {
-                xn = pxn || (user_rw & PAGE_WRITE);
-            }
-            break;
-        case 2:
-        case 3:
-            break;
+        if (regime_has_2_ranges(mmu_idx) && !is_user) {
+            xn = pxn || (user_rw & PAGE_WRITE);
         }
     } else if (arm_feature(env, ARM_FEATURE_V7)) {
         switch (regime_el(env, mmu_idx)) {
@@ -9541,7 +9534,6 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
                                         ARMMMUIdx mmu_idx)
 {
     uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
-    uint32_t el = regime_el(env, mmu_idx);
     bool tbi, tbid, epd, hpd, using16k, using64k;
     int select, tsz;
 
@@ -9551,7 +9543,7 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
      */
     select = extract64(va, 55, 1);
 
-    if (el > 1) {
+    if (!regime_has_2_ranges(mmu_idx)) {
         tsz = extract32(tcr, 0, 6);
         using64k = extract32(tcr, 14, 1);
         using16k = extract32(tcr, 15, 1);
@@ -9707,10 +9699,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
         param = aa64_va_parameters(env, address, mmu_idx,
                                    access_type != MMU_INST_FETCH);
         level = 0;
-        /* If we are in 64-bit EL2 or EL3 then there is no TTBR1, so mark it
-         * invalid.
-         */
-        ttbr1_valid = (el < 2);
+        ttbr1_valid = regime_has_2_ranges(mmu_idx);
         addrsize = 64 - 8 * param.tbi;
         inputsize = 64 - param.tsz;
     } else {
@@ -11361,8 +11350,7 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
             ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
             int tbii, tbid;
 
-            /* FIXME: ARMv8.1-VHE S2 translation regime.  */
-            if (regime_el(env, stage1) < 2) {
+            if (regime_has_2_ranges(mmu_idx)) {
                 ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
                 tbid = (p1.tbi << 1) | p0.tbi;
                 tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index a9e65fe347..5679349310 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -176,8 +176,7 @@ static void gen_top_byte_ignore(DisasContext *s, TCGv_i64 dst,
     if (tbi == 0) {
         /* Load unmodified address */
         tcg_gen_mov_i64(dst, src);
-    } else if (s->current_el >= 2) {
-        /* FIXME: ARMv8.1-VHE S2 translation regime.  */
+    } else if (!regime_has_2_ranges(s->mmu_idx)) {
         /* Force tag byte to all zero */
         tcg_gen_extract_i64(dst, src, 0, 56);
     } else {
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 17/24] target/arm: Update arm_mmu_idx for VHE
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (15 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 16/24] target/arm: Add regime_has_2_ranges Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-25 16:01   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 18/24] target/arm: Update arm_sctlr " Richard Henderson
                   ` (8 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

This covers initial generation in arm_mmu_idx, and reconstruction
in core_to_arm_mmu_idx.  As a conseqeuence, we also need a bit in
TBFLAGS in order to make the latter reliable.

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

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 4b537c4613..7310adfd9b 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3158,6 +3158,8 @@ FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1)
 /* Target EL if we take a floating-point-disabled exception */
 FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2)
 FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
+/* For A profile only, if EL2 is AA64 and HCR_EL2.E2H is set.  */
+FIELD(TBFLAG_ANY, E2H, 22, 1)
 
 /* Bit usage when in AArch32 state: */
 FIELD(TBFLAG_A32, THUMB, 0, 1)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2d5658f9e3..54c328b844 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11250,21 +11250,29 @@ int fp_exception_el(CPUARMState *env, int cur_el)
 
 ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
 {
+    bool e2h;
+
     if (arm_feature(env, ARM_FEATURE_M)) {
         return mmu_idx | ARM_MMU_IDX_M;
     }
 
     mmu_idx |= ARM_MMU_IDX_A;
+    if (mmu_idx & ARM_MMU_IDX_S) {
+        return mmu_idx;
+    }
+
+    e2h = (env->cp15.hcr_el2 & HCR_E2H) != 0;
+    if (!arm_el_is_aa64(env, 2)) {
+        e2h = false;
+    }
+
     switch (mmu_idx) {
     case ARMMMUIdx_E0:
-        return ARMMMUIdx_EL10_0;
+        return e2h ? ARMMMUIdx_EL20_0 : ARMMMUIdx_EL10_0;
     case ARMMMUIdx_E1:
         return ARMMMUIdx_EL10_1;
     case ARMMMUIdx_E2:
-    case ARMMMUIdx_SE0:
-    case ARMMMUIdx_SE1:
-    case ARMMMUIdx_SE3:
-        return mmu_idx;
+        return e2h ? ARMMMUIdx_EL20_2 : ARMMMUIdx_E2;
     default:
         g_assert_not_reached();
     }
@@ -11292,24 +11300,28 @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
 
 ARMMMUIdx arm_mmu_idx(CPUARMState *env)
 {
+    bool e2h, sec;
     int el;
 
     if (arm_feature(env, ARM_FEATURE_M)) {
         return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
     }
 
+    sec = arm_is_secure_below_el3(env);
+    e2h = (env->cp15.hcr_el2 & HCR_E2H) != 0;
+    if (!arm_el_is_aa64(env, 2)) {
+        e2h = false;
+    }
+
     el = arm_current_el(env);
     switch (el) {
     case 0:
-        /* TODO: ARMv8.1-VHE */
+        return sec ? ARMMMUIdx_SE0 : e2h ? ARMMMUIdx_EL20_0 : ARMMMUIdx_EL10_0;
     case 1:
-        return (arm_is_secure_below_el3(env)
-                ? ARMMMUIdx_SE0 + el
-                : ARMMMUIdx_EL10_0 + el);
+        return sec ? ARMMMUIdx_SE1 : ARMMMUIdx_EL10_1;
     case 2:
-        /* TODO: ARMv8.1-VHE */
         /* TODO: ARMv8.4-SecEL2 */
-        return ARMMMUIdx_E2;
+        return e2h ? ARMMMUIdx_EL20_2 : ARMMMUIdx_E2;
     case 3:
         return ARMMMUIdx_SE3;
     default:
@@ -11421,6 +11433,14 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 
     flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
 
+    /*
+     * Include E2H in TBFLAGS so that core_to_arm_mmu_idx can
+     * reliably determine E1&0 vs E2&0 regimes.
+     */
+    if (arm_el_is_aa64(env, 2) && (env->cp15.hcr_el2 & HCR_E2H)) {
+        flags = FIELD_DP32(flags, TBFLAG_ANY, E2H, 1);
+    }
+
     /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
      * states defined in the ARM ARM for software singlestep:
      *  SS_ACTIVE   PSTATE.SS   State
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 18/24] target/arm: Update arm_sctlr for VHE
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (16 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 17/24] target/arm: Update arm_mmu_idx for VHE Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-25 16:02   ` Alex Bennée
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 19/24] target/arm: Install asids for E2&0 translation regime Richard Henderson
                   ` (7 subsequent siblings)
  25 siblings, 1 reply; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

Use this function in many more places in order to select
the correct control.

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

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 7310adfd9b..7efbb488d9 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3104,11 +3104,13 @@ static inline bool arm_sctlr_b(CPUARMState *env)
 static inline uint64_t arm_sctlr(CPUARMState *env, int el)
 {
     if (el == 0) {
-        /* FIXME: ARMv8.1-VHE S2 translation regime.  */
-        return env->cp15.sctlr_el[1];
-    } else {
-        return env->cp15.sctlr_el[el];
+        if (arm_el_is_aa64(env, 2) && (arm_hcr_el2_eff(env) & HCR_E2H)) {
+            el = 2;
+        } else {
+            el = 1;
+        }
     }
+    return env->cp15.sctlr_el[el];
 }
 
 
diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
index 26a2c09868..5fbd008d8c 100644
--- a/target/arm/arch_dump.c
+++ b/target/arm/arch_dump.c
@@ -320,7 +320,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
      * dump a hypervisor that happens to be running an opposite-endian
      * kernel.
      */
-    info->d_endian = (env->cp15.sctlr_el[1] & SCTLR_EE) != 0
+    info->d_endian = (arm_sctlr(env, 1) & SCTLR_EE) != 0
                      ? ELFDATA2MSB : ELFDATA2LSB;
 
     return 0;
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 060699b901..3bf1b731e7 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -70,7 +70,7 @@ static void daif_check(CPUARMState *env, uint32_t op,
                        uint32_t imm, uintptr_t ra)
 {
     /* DAIF update to PSTATE. This is OK from EL0 only if UMA is set.  */
-    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
+    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) {
         raise_exception_ra(env, EXCP_UDEF,
                            syn_aa64_sysregtrap(0, extract32(op, 0, 3),
                                                extract32(op, 3, 3), 4,
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 54c328b844..db13a8f9c0 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3868,7 +3868,7 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri,
                                        bool isread)
 {
-    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
+    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -3887,7 +3887,7 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
     /* Cache invalidate/clean: NOP, but EL0 must UNDEF unless
      * SCTLR_EL1.UCI is set.
      */
-    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCI)) {
+    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UCI)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -4114,7 +4114,7 @@ static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
     /* We don't implement EL2, so the only control on DC ZVA is the
      * bit in the SCTLR which can prohibit access for EL0.
      */
-    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_DZE)) {
+    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_DZE)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -5344,7 +5344,7 @@ static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
     /* Only accessible in EL0 if SCTLR.UCT is set (and only in AArch64,
      * but the AArch32 CTR has its own reginfo struct)
      */
-    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
+    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UCT)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -8161,7 +8161,7 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
     env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
     /* Set new mode endianness */
     env->uncached_cpsr &= ~CPSR_E;
-    if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
+    if (arm_sctlr(env, arm_current_el(env)) & SCTLR_EE) {
         env->uncached_cpsr |= CPSR_E;
     }
     /* J and IL must always be cleared for exception entry */
diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c
index d3194f2043..42c9141bb7 100644
--- a/target/arm/pauth_helper.c
+++ b/target/arm/pauth_helper.c
@@ -386,14 +386,7 @@ static void pauth_check_trap(CPUARMState *env, int el, uintptr_t ra)
 
 static bool pauth_key_enabled(CPUARMState *env, int el, uint32_t bit)
 {
-    uint32_t sctlr;
-    if (el == 0) {
-        /* FIXME: ARMv8.1-VHE S2 translation regime.  */
-        sctlr = env->cp15.sctlr_el[1];
-    } else {
-        sctlr = env->cp15.sctlr_el[el];
-    }
-    return (sctlr & bit) != 0;
+    return (arm_sctlr(env, el) & bit) != 0;
 }
 
 uint64_t HELPER(pacia)(CPUARMState *env, uint64_t x, uint64_t y)
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 19/24] target/arm: Install asids for E2&0 translation regime
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (17 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 18/24] target/arm: Update arm_sctlr " Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 20/24] target/arm: Flush tlbs " Richard Henderson
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

When clearing HCR_E2H, this involves re-installing the E1&0 asid.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index db13a8f9c0..22eb056b27 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3516,12 +3516,28 @@ static void vmsa_ttbr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
     }
 }
 
+static void update_el2_asid(CPUARMState *env)
+{
+    CPUState *cs = env_cpu(env);
+    uint64_t ttbr0, ttbr1, ttcr;
+    int asid, idxmask;
+
+    ttbr0 = env->cp15.ttbr0_el[2];
+    ttbr1 = env->cp15.ttbr1_el[2];
+    ttcr = env->cp15.tcr_el[2].raw_tcr;
+    idxmask = ARMMMUIdxBit_E2 | ARMMMUIdxBit_E0;
+    asid = extract64(ttcr & TTBCR_A1 ? ttbr1 : ttbr0, 48, 16);
+
+    tlb_set_asid_for_mmuidx(cs, asid, idxmask, 0);
+}
+
 static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                     uint64_t value)
 {
     raw_write(env, ri, value);
     if (arm_hcr_el2_eff(env) & HCR_E2H) {
-        /* The ASID field is active.  */
+        /* We are running with EL2&0 regime and the ASID is active.  */
+        update_el2_asid(env);
     }
 }
 
@@ -4652,6 +4668,7 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
     ARMCPU *cpu = env_archcpu(env);
     /* Begin with bits defined in base ARMv8.0.  */
     uint64_t valid_mask = MAKE_64BIT_MASK(0, 34);
+    uint64_t old_value;
 
     if (arm_feature(env, ARM_FEATURE_EL3)) {
         valid_mask &= ~HCR_HCD;
@@ -4678,15 +4695,25 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
     /* Clear RES0 bits.  */
     value &= valid_mask;
 
-    /* These bits change the MMU setup:
+    old_value = env->cp15.hcr_el2;
+    env->cp15.hcr_el2 = value;
+
+    /*
+     * These bits change the MMU setup:
      * HCR_VM enables stage 2 translation
      * HCR_PTW forbids certain page-table setups
-     * HCR_DC Disables stage1 and enables stage2 translation
+     * HCR_DC disables stage1 and enables stage2 translation
+     * HCR_E2H enables E2&0 translation regime.
      */
-    if ((env->cp15.hcr_el2 ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) {
+    if ((old_value ^ value) & (HCR_VM | HCR_PTW | HCR_DC | HCR_E2H)) {
         tlb_flush(CPU(cpu));
+        /* Also install the correct ASID for the regime.  */
+        if (value & HCR_E2H) {
+            update_el2_asid(env);
+        } else {
+            update_lpae_el1_asid(env, false);
+        }
     }
-    env->cp15.hcr_el2 = value;
 
     /*
      * Updates to VI and VF require us to update the status of
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 20/24] target/arm: Flush tlbs for E2&0 translation regime
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (18 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 19/24] target/arm: Install asids for E2&0 translation regime Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 21/24] target/arm: Update arm_phys_excp_target_el for TGE Richard Henderson
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 22eb056b27..fe022f51d6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3915,8 +3915,11 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
 
 static int vae1_tlbmask(CPUARMState *env)
 {
+    /* Since we exclude secure first, we may read HCR_EL2 directly. */
     if (arm_is_secure_below_el3(env)) {
         return ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0;
+    } else if (env->cp15.hcr_el2 & HCR_E2H) {
+        return ARMMMUIdxBit_E2 | ARMMMUIdxBit_E0;
     } else {
         return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
     }
@@ -3954,7 +3957,12 @@ static int vmalle1_tlbmask(CPUARMState *env)
     if (arm_is_secure_below_el3(env)) {
         return ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0;
     } else if (arm_feature(env, ARM_FEATURE_EL2)) {
-        return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0 | ARMMMUIdxBit_Stage2;
+        /* Since we exclude secure first, we may read HCR_EL2 directly. */
+        if (env->cp15.hcr_el2 & HCR_E2H) {
+            return ARMMMUIdxBit_E2 | ARMMMUIdxBit_E0;
+        } else {
+            return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0 | ARMMMUIdxBit_Stage2;
+        }
     } else {
         return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
     }
@@ -3969,13 +3977,22 @@ static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
     tlb_flush_by_mmuidx(cs, mask);
 }
 
+static int vae2_tlbmask(CPUARMState *env)
+{
+    if (arm_hcr_el2_eff(env) & HCR_E2H) {
+        return ARMMMUIdxBit_E0 | ARMMMUIdxBit_E2;
+    } else {
+        return ARMMMUIdxBit_E2;
+    }
+}
+
 static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                   uint64_t value)
 {
-    ARMCPU *cpu = env_archcpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUState *cs = env_cpu(env);
+    int mask = vae2_tlbmask(env);
 
-    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
+    tlb_flush_by_mmuidx(cs, mask);
 }
 
 static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4000,8 +4017,9 @@ static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                     uint64_t value)
 {
     CPUState *cs = env_cpu(env);
+    int mask = vae2_tlbmask(env);
 
-    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
+    tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
 }
 
 static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4019,11 +4037,11 @@ static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
      * Currently handles both VAE2 and VALE2, since we don't support
      * flush-last-level-only.
      */
-    ARMCPU *cpu = env_archcpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUState *cs = env_cpu(env);
+    int mask = vae2_tlbmask(env);
     uint64_t pageaddr = sextract64(value << 12, 0, 56);
 
-    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
+    tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
 }
 
 static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 21/24] target/arm: Update arm_phys_excp_target_el for TGE
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (19 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 20/24] target/arm: Flush tlbs " Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 22/24] target/arm: Update regime_is_user for EL2&0 Richard Henderson
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

The TGE bit routes all asynchronous exceptions to EL2.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index fe022f51d6..f06e7bcd77 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7928,6 +7928,12 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
         break;
     };
 
+    /*
+     * For these purposes, TGE and AMO/IMO/FMO both force the
+     * interrupt to EL2.  Fold TGE into the bit extracted above.
+     */
+    hcr |= (hcr_el2 & HCR_TGE) != 0;
+
     /* Perform a table-lookup for the target EL given the current state */
     target_el = target_el_table[is64][scr][rw][hcr][secure][cur_el];
 
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 22/24] target/arm: Update regime_is_user for EL2&0
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (20 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 21/24] target/arm: Update arm_phys_excp_target_el for TGE Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 23/24] target/arm: Update {fp, sve}_exception_el for VHE Richard Henderson
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index f06e7bcd77..ae3ec9ea67 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8885,6 +8885,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
     switch (mmu_idx) {
     case ARMMMUIdx_SE0:
+    case ARMMMUIdx_EL20_0:
     case ARMMMUIdx_Stage1_E0:
     case ARMMMUIdx_MUser:
     case ARMMMUIdx_MSUser:
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 23/24] target/arm: Update {fp, sve}_exception_el for VHE
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (21 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 22/24] target/arm: Update regime_is_user for EL2&0 Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 24/24] target/arm: Enable ARMv8.1-VHE in -cpu max Richard Henderson
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

When TGE+E2H are both set, CPACR_EL1 is ignored.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index ae3ec9ea67..bbe36eb3a9 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5501,7 +5501,9 @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
 int sve_exception_el(CPUARMState *env, int el)
 {
 #ifndef CONFIG_USER_ONLY
-    if (el <= 1) {
+    uint64_t hcr_el2 = arm_hcr_el2_eff(env);
+
+    if (el <= 1 && (hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
         bool disabled = false;
 
         /* The CPACR.ZEN controls traps to EL1:
@@ -5516,8 +5518,7 @@ int sve_exception_el(CPUARMState *env, int el)
         }
         if (disabled) {
             /* route_to_el2 */
-            return (arm_feature(env, ARM_FEATURE_EL2)
-                    && (arm_hcr_el2_eff(env) & HCR_TGE) ? 2 : 1);
+            return hcr_el2 & HCR_TGE ? 2 : 1;
         }
 
         /* Check CPACR.FPEN.  */
@@ -11212,8 +11213,6 @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
 int fp_exception_el(CPUARMState *env, int cur_el)
 {
 #ifndef CONFIG_USER_ONLY
-    int fpen;
-
     /* CPACR and the CPTR registers don't exist before v6, so FP is
      * always accessible
      */
@@ -11241,30 +11240,34 @@ int fp_exception_el(CPUARMState *env, int cur_el)
      * 0, 2 : trap EL0 and EL1/PL1 accesses
      * 1    : trap only EL0 accesses
      * 3    : trap no accesses
+     * This register is ignored if E2H+TGE are both set.
      */
-    fpen = extract32(env->cp15.cpacr_el1, 20, 2);
-    switch (fpen) {
-    case 0:
-    case 2:
-        if (cur_el == 0 || cur_el == 1) {
-            /* Trap to PL1, which might be EL1 or EL3 */
-            if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
+    if ((arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
+        int fpen = extract32(env->cp15.cpacr_el1, 20, 2);
+
+        switch (fpen) {
+        case 0:
+        case 2:
+            if (cur_el == 0 || cur_el == 1) {
+                /* Trap to PL1, which might be EL1 or EL3 */
+                if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
+                    return 3;
+                }
+                return 1;
+            }
+            if (cur_el == 3 && !is_a64(env)) {
+                /* Secure PL1 running at EL3 */
                 return 3;
             }
-            return 1;
+            break;
+        case 1:
+            if (cur_el == 0) {
+                return 1;
+            }
+            break;
+        case 3:
+            break;
         }
-        if (cur_el == 3 && !is_a64(env)) {
-            /* Secure PL1 running at EL3 */
-            return 3;
-        }
-        break;
-    case 1:
-        if (cur_el == 0) {
-            return 1;
-        }
-        break;
-    case 3:
-        break;
     }
 
     /*
-- 
2.17.1



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

* [Qemu-devel] [PATCH for-4.2 24/24] target/arm: Enable ARMv8.1-VHE in -cpu max
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (22 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 23/24] target/arm: Update {fp, sve}_exception_el for VHE Richard Henderson
@ 2019-07-19 21:03 ` Richard Henderson
  2019-07-22  7:31 ` [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Alex Bennée
  2019-07-25 16:15 ` Alex Bennée
  25 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-19 21:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska

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

diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 1901997a06..b1bb394c6d 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -337,6 +337,7 @@ static void aarch64_max_initfn(Object *obj)
         t = cpu->isar.id_aa64mmfr1;
         t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
         t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
+        t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
         cpu->isar.id_aa64mmfr1 = t;
 
         /* Replicate the same data to the 32-bit id registers.  */
-- 
2.17.1



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

* Re: [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (23 preceding siblings ...)
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 24/24] target/arm: Enable ARMv8.1-VHE in -cpu max Richard Henderson
@ 2019-07-22  7:31 ` Alex Bennée
  2019-07-22  9:37   ` Alex Bennée
  2019-07-25 16:15 ` Alex Bennée
  25 siblings, 1 reply; 51+ messages in thread
From: Alex Bennée @ 2019-07-22  7:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> About half of this patch set is cleanup of the qemu tlb handling
> leading up to the actual implementation of VHE, and the biggest
> piece of that: The EL2&0 translation regime.
>
> Testing so far has been limited to booting a debian 9 system with
> a 4.9 kernel, and a fedora 30 system with a 5.1 kernel.  Both have
> KVM enabled, and both report enabling VHE is successful.

check-tcg is throwing up errors for ARM:

ERROR:/home/alex/lsrc/qemu.git/target/arm/helper.c:5353:define_arm_vh_e2h_redirects_aliases:assertion failed: (src_reg != NULL)

>
>
> r~
>
>
> Richard Henderson (24):
>   cputlb: Add tlb_set_asid_for_mmuidx
>   cputlb: Add tlb_flush_asid_by_mmuidx and friends
>   target/arm: Install ASIDs for long-form from EL1
>   target/arm: Install ASIDs for short-form from EL1
>   target/arm: Install ASIDs for EL2
>   target/arm: Define isar_feature_aa64_vh
>   target/arm: Enable HCR_E2H for VHE
>   target/arm: Add CONTEXTIDR_EL2
>   target/arm: Add TTBR1_EL2
>   target/arm: Update CNTVCT_EL0 for VHE
>   target/arm: Add the hypervisor virtual counter
>   target/arm: Add VHE system register redirection and aliasing
>   target/arm: Split out vae1_tlbmask, vmalle1_tlbmask
>   target/arm: Simplify tlb_force_broadcast alternatives
>   target/arm: Reorganize ARMMMUIdx
>   target/arm: Add regime_has_2_ranges
>   target/arm: Update arm_mmu_idx for VHE
>   target/arm: Update arm_sctlr for VHE
>   target/arm: Install asids for E2&0 translation regime
>   target/arm: Flush tlbs for E2&0 translation regime
>   target/arm: Update arm_phys_excp_target_el for TGE
>   target/arm: Update regime_is_user for EL2&0
>   target/arm: Update {fp,sve}_exception_el for VHE
>   target/arm: Enable ARMv8.1-VHE in -cpu max
>
>  include/exec/cpu-all.h     |  11 +
>  include/exec/cpu-defs.h    |   2 +
>  include/exec/exec-all.h    |  35 ++
>  include/qom/cpu.h          |   1 +
>  target/arm/cpu-qom.h       |   1 +
>  target/arm/cpu.h           | 259 +++++-----
>  target/arm/internals.h     |  62 ++-
>  target/arm/translate.h     |   2 +-
>  accel/tcg/cputlb.c         |  77 +++
>  target/arm/arch_dump.c     |   2 +-
>  target/arm/cpu.c           |   2 +
>  target/arm/cpu64.c         |   1 +
>  target/arm/debug_helper.c  |  50 +-
>  target/arm/helper-a64.c    |   2 +-
>  target/arm/helper.c        | 985 ++++++++++++++++++++++++++-----------
>  target/arm/m_helper.c      |   6 +-
>  target/arm/pauth_helper.c  |   9 +-
>  target/arm/translate-a64.c |  14 +-
>  target/arm/translate.c     |  17 +-
>  19 files changed, 1058 insertions(+), 480 deletions(-)


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE
  2019-07-22  7:31 ` [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Alex Bennée
@ 2019-07-22  9:37   ` Alex Bennée
  2019-07-22 15:10     ` Richard Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Alex Bennée @ 2019-07-22  9:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Alex Bennée <alex.bennee@linaro.org> writes:

> Richard Henderson <richard.henderson@linaro.org> writes:
>
>> About half of this patch set is cleanup of the qemu tlb handling
>> leading up to the actual implementation of VHE, and the biggest
>> piece of that: The EL2&0 translation regime.
>>
>> Testing so far has been limited to booting a debian 9 system with
>> a 4.9 kernel, and a fedora 30 system with a 5.1 kernel.  Both have
>> KVM enabled, and both report enabling VHE is successful.
>
> check-tcg is throwing up errors for ARM:
>
> ERROR:/home/alex/lsrc/qemu.git/target/arm/helper.c:5353:define_arm_vh_e2h_redirects_aliases:assertion
> failed: (src_reg != NULL)

I'm going to go out on a limb and say this is because the aliases
registers are SoftMMU only. Do we even want to handle any re-directs for
linux-user?

>
>>
>>
>> r~
>>
>>
>> Richard Henderson (24):
>>   cputlb: Add tlb_set_asid_for_mmuidx
>>   cputlb: Add tlb_flush_asid_by_mmuidx and friends
>>   target/arm: Install ASIDs for long-form from EL1
>>   target/arm: Install ASIDs for short-form from EL1
>>   target/arm: Install ASIDs for EL2
>>   target/arm: Define isar_feature_aa64_vh
>>   target/arm: Enable HCR_E2H for VHE
>>   target/arm: Add CONTEXTIDR_EL2
>>   target/arm: Add TTBR1_EL2
>>   target/arm: Update CNTVCT_EL0 for VHE
>>   target/arm: Add the hypervisor virtual counter
>>   target/arm: Add VHE system register redirection and aliasing
>>   target/arm: Split out vae1_tlbmask, vmalle1_tlbmask
>>   target/arm: Simplify tlb_force_broadcast alternatives
>>   target/arm: Reorganize ARMMMUIdx
>>   target/arm: Add regime_has_2_ranges
>>   target/arm: Update arm_mmu_idx for VHE
>>   target/arm: Update arm_sctlr for VHE
>>   target/arm: Install asids for E2&0 translation regime
>>   target/arm: Flush tlbs for E2&0 translation regime
>>   target/arm: Update arm_phys_excp_target_el for TGE
>>   target/arm: Update regime_is_user for EL2&0
>>   target/arm: Update {fp,sve}_exception_el for VHE
>>   target/arm: Enable ARMv8.1-VHE in -cpu max
>>
>>  include/exec/cpu-all.h     |  11 +
>>  include/exec/cpu-defs.h    |   2 +
>>  include/exec/exec-all.h    |  35 ++
>>  include/qom/cpu.h          |   1 +
>>  target/arm/cpu-qom.h       |   1 +
>>  target/arm/cpu.h           | 259 +++++-----
>>  target/arm/internals.h     |  62 ++-
>>  target/arm/translate.h     |   2 +-
>>  accel/tcg/cputlb.c         |  77 +++
>>  target/arm/arch_dump.c     |   2 +-
>>  target/arm/cpu.c           |   2 +
>>  target/arm/cpu64.c         |   1 +
>>  target/arm/debug_helper.c  |  50 +-
>>  target/arm/helper-a64.c    |   2 +-
>>  target/arm/helper.c        | 985 ++++++++++++++++++++++++++-----------
>>  target/arm/m_helper.c      |   6 +-
>>  target/arm/pauth_helper.c  |   9 +-
>>  target/arm/translate-a64.c |  14 +-
>>  target/arm/translate.c     |  17 +-
>>  19 files changed, 1058 insertions(+), 480 deletions(-)


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 01/24] cputlb: Add tlb_set_asid_for_mmuidx
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 01/24] cputlb: Add tlb_set_asid_for_mmuidx Richard Henderson
@ 2019-07-22  9:53   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-22  9:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Although we can't do much with ASIDs except remember them, this
> will allow cleanups within target/ that should make things clearer.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>
> ---
> v2: Assert cpu_is_self; only flush idx w/ asid mismatch.
> ---
>  include/exec/cpu-all.h  | 11 +++++++++++
>  include/exec/cpu-defs.h |  2 ++
>  include/exec/exec-all.h | 19 +++++++++++++++++++
>  accel/tcg/cputlb.c      | 26 ++++++++++++++++++++++++++
>  4 files changed, 58 insertions(+)
>
> diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
> index 536ea58f81..40b140cbba 100644
> --- a/include/exec/cpu-all.h
> +++ b/include/exec/cpu-all.h
> @@ -439,4 +439,15 @@ static inline CPUTLB *env_tlb(CPUArchState *env)
>      return &env_neg(env)->tlb;
>  }
>
> +/**
> + * cpu_tlb(env)
> + * @cpu: The generic CPUState
> + *
> + * Return the CPUTLB state associated with the cpu.
> + */
> +static inline CPUTLB *cpu_tlb(CPUState *cpu)
> +{
> +    return &cpu_neg(cpu)->tlb;
> +}
> +
>  #endif /* CPU_ALL_H */
> diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
> index 9bc713a70b..73584841c0 100644
> --- a/include/exec/cpu-defs.h
> +++ b/include/exec/cpu-defs.h
> @@ -169,6 +169,8 @@ typedef struct CPUTLBDesc {
>      size_t n_used_entries;
>      /* The next index to use in the tlb victim table.  */
>      size_t vindex;
> +    /* The current ASID for this tlb.  */
> +    uint32_t asid;

is it worth adding a "if used" to the comment. I assume there are arches
that will never set and therefore care about ASID.

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

>      /* The tlb victim table, in two parts.  */
>      CPUTLBEntry vtable[CPU_VTLB_SIZE];
>      CPUIOTLBEntry viotlb[CPU_VTLB_SIZE];
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index 16034ee651..9c77aa5bf9 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -225,6 +225,21 @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
>   * depend on when the guests translation ends the TB.
>   */
>  void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
> +/**
> + * tlb_set_asid_for_mmuidx:
> + * @cpu: Originating cpu
> + * @asid: Address Space Identifier
> + * @idxmap: bitmap of MMU indexes to set to @asid
> + * @depmap: bitmap of dependent MMU indexes
> + *
> + * Set an ASID for all of @idxmap.  If any previous ASID was different,
> + * then we will flush the mmu idx.  If a flush is required, then also flush
> + * all dependent mmu indicies in @depmap.  This latter is typically used
> + * for secondary page resolution, for implementing virtualization within
> + * the guest.
> + */
> +void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid,
> +                             uint16_t idxmap, uint16_t dep_idxmap);
>  /**
>   * tlb_set_page_with_attrs:
>   * @cpu: CPU to add this TLB entry for
> @@ -310,6 +325,10 @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
>                                                         uint16_t idxmap)
>  {
>  }
> +static inline void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid,
> +                                           uint16_t idxmap, uint16_t depmap)
> +{
> +}
>  #endif
>
>  #define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
> diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
> index bb9897b25a..c68f57755b 100644
> --- a/accel/tcg/cputlb.c
> +++ b/accel/tcg/cputlb.c
> @@ -540,6 +540,32 @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
>      tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
>  }
>
> +void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid, uint16_t idxmap,
> +                             uint16_t depmap)
> +{
> +    CPUTLB *tlb = cpu_tlb(cpu);
> +    uint16_t work, to_flush = 0;
> +
> +    /* It doesn't make sense to set context across cpus.  */
> +    assert_cpu_is_self(cpu);
> +
> +    /*
> +     * We don't support ASIDs except for trivially.
> +     * If there is any change, then we must flush the TLB.
> +     */
> +    for (work = idxmap; work != 0; work &= work - 1) {
> +        int mmu_idx = ctz32(work);
> +        if (tlb->d[mmu_idx].asid != asid) {
> +            tlb->d[mmu_idx].asid = asid;
> +            to_flush |= 1 << mmu_idx;
> +        }
> +    }
> +    if (to_flush) {
> +        to_flush |= depmap;
> +        tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(to_flush));
> +    }
> +}
> +
>  /* update the TLBs so that writes to code in the virtual page 'addr'
>     can be detected */
>  void tlb_protect_code(ram_addr_t ram_addr)


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 02/24] cputlb: Add tlb_flush_asid_by_mmuidx and friends
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 02/24] cputlb: Add tlb_flush_asid_by_mmuidx and friends Richard Henderson
@ 2019-07-22 10:04   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-22 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Since we have remembered ASIDs, we can further minimize flushing
> by comparing against the one we want to flush.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/exec/exec-all.h | 16 +++++++++++++
>  include/qom/cpu.h       |  1 +
>  accel/tcg/cputlb.c      | 51 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 68 insertions(+)
>
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index 9c77aa5bf9..0d890e1e60 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -240,6 +240,22 @@ void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
>   */
>  void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid,
>                               uint16_t idxmap, uint16_t dep_idxmap);
> +/**
> + * tlb_flush_asid_by_mmuidx:
> + * @cpu: Originating CPU of the flush
> + * @asid: Address Space Identifier
> + * @idxmap: bitmap of MMU indexes to flush if asid matches
> + *
> + * For each mmu index, if @asid matches the value previously saved via
> + * tlb_set_asid_for_mmuidx, flush the index.
> + */
> +void tlb_flush_asid_by_mmuidx(CPUState *cpu, uint32_t asid, uint16_t idxmap);
> +/* Similarly, broadcasting to all cpus. */
> +void tlb_flush_asid_by_mmuidx_all_cpus(CPUState *cpu, uint32_t asid,
> +                                       uint16_t idxmap);
> +/* Similarly, waiting for the broadcast to complete.  */
> +void tlb_flush_asid_by_mmuidx_all_cpus_synced(CPUState *cpu, uint32_t asid,
> +                                              uint16_t idxmap);
>  /**
>   * tlb_set_page_with_attrs:
>   * @cpu: CPU to add this TLB entry for
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index 5ee0046b62..4ae6ea3e1d 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -283,6 +283,7 @@ struct hax_vcpu_state;
>  typedef union {
>      int           host_int;
>      unsigned long host_ulong;
> +    uint64_t      host_uint64;

Missing an access helper, although host_uint64 doesn't make sense, 64 is
64 always:

  #define RUN_ON_CPU_UINT64(i)    ((run_on_cpu_data){.uint64 = (i)})

>      void         *host_ptr;
>      vaddr         target_ptr;
>  } run_on_cpu_data;
> diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
> index c68f57755b..3ef68a11bf 100644
> --- a/accel/tcg/cputlb.c
> +++ b/accel/tcg/cputlb.c
> @@ -540,6 +540,57 @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
>      tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
>  }
>
> +static void tlb_flush_asid_by_mmuidx_async_work(CPUState *cpu,
> +                                                run_on_cpu_data data)
> +{
> +    CPUTLB *tlb = cpu_tlb(cpu);
> +    uint32_t asid = data.host_uint64;
> +    uint16_t idxmap = data.host_uint64 >> 32;
> +    uint16_t to_flush = 0, work;
> +
> +    assert_cpu_is_self(cpu);
> +
> +    for (work = idxmap; work != 0; work &= work - 1) {
> +        int mmu_idx = ctz32(work);
> +        if (tlb->d[mmu_idx].asid == asid) {
> +            to_flush |= 1 << mmu_idx;
> +        }
> +    }
> +
> +    if (to_flush) {
> +        tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(to_flush));
> +    }
> +}
> +
> +void tlb_flush_asid_by_mmuidx(CPUState *cpu, uint32_t asid, uint16_t idxmap)
> +{
> +    run_on_cpu_data data = { .host_uint64 = deposit64(asid, 32, 32,
> idxmap) };

Then this would be:
     uint64_t asid_idx_map = deposit64(asid, 32, 32, idxmap);
     ...
     async_run_on_cpu(cpu, tlb_flush_asid_by_mmuidx_async_work, RUN_ON_CPU_UINT64(data))

Not a massive win but consistent with the other *_run_on calls and
easier to grep.

> +
> +    if (cpu->created && !qemu_cpu_is_self(cpu)) {
> +        async_run_on_cpu(cpu, tlb_flush_asid_by_mmuidx_async_work, data);
> +    } else {
> +        tlb_flush_asid_by_mmuidx_async_work(cpu, data);
> +    }
> +}
> +
> +void tlb_flush_asid_by_mmuidx_all_cpus(CPUState *src_cpu,
> +                                       uint32_t asid, uint16_t idxmap)
> +{
> +    run_on_cpu_data data = { .host_uint64 = deposit64(asid, 32, 32, idxmap) };
> +
> +    flush_all_helper(src_cpu, tlb_flush_asid_by_mmuidx_async_work, data);
> +    tlb_flush_asid_by_mmuidx_async_work(src_cpu, data);
> +}
> +
> +void tlb_flush_asid_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
> +                                              uint32_t asid, uint16_t idxmap)
> +{
> +    run_on_cpu_data data = { .host_uint64 = deposit64(asid, 32, 32, idxmap) };
> +
> +    flush_all_helper(src_cpu, tlb_flush_asid_by_mmuidx_async_work, data);
> +    async_safe_run_on_cpu(src_cpu, tlb_flush_asid_by_mmuidx_async_work, data);
> +}
> +
>  void tlb_set_asid_for_mmuidx(CPUState *cpu, uint32_t asid, uint16_t idxmap,
>                               uint16_t depmap)
>  {

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE
  2019-07-22  9:37   ` Alex Bennée
@ 2019-07-22 15:10     ` Richard Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-22 15:10 UTC (permalink / raw)
  To: Alex Bennée, qemu-devel; +Cc: peter.maydell, beata.michalska

On 7/22/19 2:37 AM, Alex Bennée wrote:
>>> Testing so far has been limited to booting a debian 9 system with
>>> a 4.9 kernel, and a fedora 30 system with a 5.1 kernel.  Both have
>>> KVM enabled, and both report enabling VHE is successful.
>>
>> check-tcg is throwing up errors for ARM:
>>
>> ERROR:/home/alex/lsrc/qemu.git/target/arm/helper.c:5353:define_arm_vh_e2h_redirects_aliases:assertion
>> failed: (src_reg != NULL)
> 
> I'm going to go out on a limb and say this is because the aliases
> registers are SoftMMU only. Do we even want to handle any re-directs for
> linux-user?

Ah, no.  Thanks for the inspection.


r~


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

* Re: [Qemu-devel] [PATCH for-4.2 03/24] target/arm: Install ASIDs for long-form from EL1
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 03/24] target/arm: Install ASIDs for long-form from EL1 Richard Henderson
@ 2019-07-22 15:28   ` Alex Bennée
  2019-07-22 15:48     ` Richard Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Alex Bennée @ 2019-07-22 15:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> In addition to providing the core with the current ASID, this minimizes
> both the number of flushes due to non-changing ASID as well as the set
> of mmu_idx that are affected by each flush.
>
> In particular, updates to the secure mode registers flushes only the
> relevant secure mode mmu_idx's, and similarly non-secure updates only
> affect non-secure mmu_idx's.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/helper.c | 73 +++++++++++++++++++++++++++++----------------
>  1 file changed, 48 insertions(+), 25 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 20f8728be1..0f21a077de 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3327,6 +3327,36 @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
>      REGINFO_SENTINEL
>  };
>
> +/* Called after a change to any of TTBR*_EL1 or TTBCR_EL1.  */
> +static void update_lpae_el1_asid(CPUARMState *env, int secure)
> +{
> +    CPUState *cs = env_cpu(env);
> +    uint64_t ttbr0, ttbr1, ttcr;
> +    int asid, idxmask;
> +
> +    switch (secure) {
> +    case ARM_CP_SECSTATE_S:
> +        ttbr0 = env->cp15.ttbr0_s;
> +        ttbr1 = env->cp15.ttbr1_s;
> +        ttcr = env->cp15.tcr_el[3].raw_tcr;
> +        /* Note that cp15.ttbr0_s == cp15.ttbr0_el[3], so S1E3 is affected.  */
> +        /* ??? Secure EL3 really using the ASID field?  Doesn't make sense.  */
> +        idxmask = ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0 | ARMMMUIdxBit_S1E3;
> +        break;
> +    case ARM_CP_SECSTATE_NS:
> +        ttbr0 = env->cp15.ttbr0_ns;
> +        ttbr1 = env->cp15.ttbr1_ns;
> +        ttcr = env->cp15.tcr_el[1].raw_tcr;
> +        idxmask = ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
> +        break;
> +    default:
> +        g_assert_not_reached();
> +    }
> +    asid = extract64(ttcr & TTBCR_A1 ? ttbr1 : ttbr0, 48, 16);
> +
> +    tlb_set_asid_for_mmuidx(cs, asid, idxmask, 0);
> +}
> +
>  static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                                   uint64_t value)
>  {
> @@ -3363,18 +3393,16 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                               uint64_t value)
>  {
> -    ARMCPU *cpu = env_archcpu(env);
>      TCR *tcr = raw_ptr(env, ri);
>
> -    if (arm_feature(env, ARM_FEATURE_LPAE)) {
> -        /* With LPAE the TTBCR could result in a change of ASID
> -         * via the TTBCR.A1 bit, so do a TLB flush.
> -         */
> -        tlb_flush(CPU(cpu));
> -    }
>      /* Preserve the high half of TCR_EL1, set via TTBCR2.  */
>      value = deposit64(tcr->raw_tcr, 0, 32, value);
>      vmsa_ttbcr_raw_write(env, ri, value);
> +
> +    if (arm_feature(env, ARM_FEATURE_LPAE)) {
> +        /* The A1 bit controls which ASID is active.  */
> +        update_lpae_el1_asid(env, ri->secure);
> +    }
>  }
>
>  static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
> @@ -3392,24 +3420,19 @@ static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
>  static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                                 uint64_t value)
>  {
> -    ARMCPU *cpu = env_archcpu(env);
> -    TCR *tcr = raw_ptr(env, ri);
> -
> -    /* For AArch64 the A1 bit could result in a change of ASID, so TLB flush. */
> -    tlb_flush(CPU(cpu));
> -    tcr->raw_tcr = value;
> +    raw_write(env, ri, value);
> +    /* The A1 bit controls which ASID is active.  */
> +    update_lpae_el1_asid(env, ri->secure);
>  }
>
> -static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> -                            uint64_t value)
> +static void vmsa_ttbr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                                uint64_t value)

Why the rename here? It would make sense if it was only EL1 writes but
the lpae_cp_reginfo doesn't seem to use that nomclature (unless we
should fix .name for those as well?).

>  {
> -    /* If the ASID changes (with a 64-bit write), we must flush the TLB.  */
> -    if (cpreg_field_is_64bit(ri) &&
> -        extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
> -        ARMCPU *cpu = env_archcpu(env);
> -        tlb_flush(CPU(cpu));
> -    }
>      raw_write(env, ri, value);
> +    if (cpreg_field_is_64bit(ri)) {
> +        /* The LPAE format (64-bit write) contains an ASID field.  */
> +        update_lpae_el1_asid(env, ri->secure);
> +    }
>  }
>
>  static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -3455,12 +3478,12 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
>        .fieldoffset = offsetof(CPUARMState, cp15.esr_el[1]), .resetvalue = 0, },
>      { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
>        .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 0,
> -      .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
> +      .access = PL1_RW, .writefn = vmsa_ttbr_el1_write, .resetvalue = 0,
>        .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
>                               offsetof(CPUARMState, cp15.ttbr0_ns) } },
>      { .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH,
>        .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 1,
> -      .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
> +      .access = PL1_RW, .writefn = vmsa_ttbr_el1_write, .resetvalue = 0,
>        .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
>                               offsetof(CPUARMState, cp15.ttbr1_ns) } },
>      { .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
> @@ -3715,12 +3738,12 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
>        .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
>        .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
>                               offsetof(CPUARMState, cp15.ttbr0_ns) },
> -      .writefn = vmsa_ttbr_write, },
> +      .writefn = vmsa_ttbr_el1_write, },
>      { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
>        .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
>        .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
>                               offsetof(CPUARMState, cp15.ttbr1_ns) },
> -      .writefn = vmsa_ttbr_write, },
> +      .writefn = vmsa_ttbr_el1_write, },
>      REGINFO_SENTINEL
>  };

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 03/24] target/arm: Install ASIDs for long-form from EL1
  2019-07-22 15:28   ` Alex Bennée
@ 2019-07-22 15:48     ` Richard Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-22 15:48 UTC (permalink / raw)
  To: Alex Bennée, qemu-devel; +Cc: peter.maydell, beata.michalska

On 7/22/19 8:28 AM, Alex Bennée wrote:
>> -static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>> -                            uint64_t value)
>> +static void vmsa_ttbr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>> +                                uint64_t value)
> 
> Why the rename here? It would make sense if it was only EL1 writes but
> the lpae_cp_reginfo doesn't seem to use that nomclature (unless we
> should fix .name for those as well?).

Because in a later patch we'll add vmsa_ttbr_el2_write.

The lpae_cp_reginfo naming is tied to the old aa32 naming,
which isn't as helpful as it might be for aa64.  But the
naming affects migration, iirc, so it can't be changed.


r~


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

* Re: [Qemu-devel] [PATCH for-4.2 04/24] target/arm: Install ASIDs for short-form from EL1
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 04/24] target/arm: Install ASIDs for short-form " Richard Henderson
@ 2019-07-24 11:47   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-24 11:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> This is less complex than the LPAE case, but still we now avoid the
> flush in case it is only the PROCID field that is changing.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/helper.c | 34 ++++++++++++++++++++++++----------
>  1 file changed, 24 insertions(+), 10 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 0f21a077de..1ed7c06313 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -551,17 +551,31 @@ static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
>  static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                               uint64_t value)
>  {
> -    ARMCPU *cpu = env_archcpu(env);
> -
> -    if (raw_read(env, ri) != value && !arm_feature(env, ARM_FEATURE_PMSA)
> -        && !extended_addresses_enabled(env)) {
> -        /* For VMSA (when not using the LPAE long descriptor page table
> -         * format) this register includes the ASID, so do a TLB flush.
> -         * For PMSA it is purely a process ID and no action is needed.
> -         */
> -        tlb_flush(CPU(cpu));
> -    }
>      raw_write(env, ri, value);
> +
> +    /*
> +     * For VMSA (when not using the LPAE long descriptor page table format)
> +     * this register includes the ASID.  For PMSA it is purely a process ID
> +     * and no action is needed.
> +     */
> +    if (!arm_feature(env, ARM_FEATURE_PMSA) &&
> +        !extended_addresses_enabled(env)) {
> +        CPUState *cs = env_cpu(env);
> +        int asid = extract32(value, 0, 8);
> +        int idxmask;
> +
> +        switch (ri->secure) {
> +        case ARM_CP_SECSTATE_S:
> +            idxmask = ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
> +            break;
> +        case ARM_CP_SECSTATE_NS:
> +            idxmask = ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
> +            break;
> +        default:
> +            g_assert_not_reached();
> +        }
> +        tlb_set_asid_for_mmuidx(cs, asid, idxmask, 0);
> +    }
>  }
>
>  /* IS variants of TLB operations must affect all cores */


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 05/24] target/arm: Install ASIDs for EL2
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 05/24] target/arm: Install ASIDs for EL2 Richard Henderson
@ 2019-07-24 11:49   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-24 11:49 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> The VMID is the ASID for the 2nd stage page lookup.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/helper.c | 26 ++++++++++++++++----------
>  1 file changed, 16 insertions(+), 10 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 1ed7c06313..3a9f35bf4b 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3452,17 +3452,23 @@ static void vmsa_ttbr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                          uint64_t value)
>  {
> -    ARMCPU *cpu = env_archcpu(env);
> -    CPUState *cs = CPU(cpu);
> +    CPUState *cs = env_cpu(env);
> +    int vmid;
>
> -    /* Accesses to VTTBR may change the VMID so we must flush the TLB.  */
> -    if (raw_read(env, ri) != value) {
> -        tlb_flush_by_mmuidx(cs,
> -                            ARMMMUIdxBit_S12NSE1 |
> -                            ARMMMUIdxBit_S12NSE0 |
> -                            ARMMMUIdxBit_S2NS);
> -        raw_write(env, ri, value);
> -    }
> +    raw_write(env, ri, value);
> +
> +    /*
> +     * TODO: with ARMv8.1-VMID16, aarch64 must examine VTCR.VS
> +     * (re-evaluating with changes to VTCR) then use bits [63:48].
> +     */
> +    vmid = extract64(value, 48, 8);
> +
> +    /*
> +     * A change in VMID to the stage2 page table (S2NS) invalidates
> +     * the combined stage 1&2 tlbs (S12NSE1 and S12NSE0).
> +     */
> +    tlb_set_asid_for_mmuidx(cs, vmid, ARMMMUIdxBit_S2NS,
> +                            ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0);
>  }
>
>  static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 06/24] target/arm: Define isar_feature_aa64_vh
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 06/24] target/arm: Define isar_feature_aa64_vh Richard Henderson
@ 2019-07-24 12:59   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-24 12:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/cpu.h | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 94c990cddb..e6a76d14c6 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -3573,6 +3573,11 @@ static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
>      return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
>  }
>
> +static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
> +{
> +    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
> +}
> +
>  static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
>  {
>      return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 07/24] target/arm: Enable HCR_E2H for VHE
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 07/24] target/arm: Enable HCR_E2H for VHE Richard Henderson
@ 2019-07-24 13:01   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-24 13:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/cpu.h    | 7 -------
>  target/arm/helper.c | 6 +++++-
>  2 files changed, 5 insertions(+), 8 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index e6a76d14c6..e37008a4f7 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1366,13 +1366,6 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
>  #define HCR_ATA       (1ULL << 56)
>  #define HCR_DCT       (1ULL << 57)
>
> -/*
> - * When we actually implement ARMv8.1-VHE we should add HCR_E2H to
> - * HCR_MASK and then clear it again if the feature bit is not set in
> - * hcr_write().
> - */
> -#define HCR_MASK      ((1ULL << 34) - 1)
> -
>  #define SCR_NS                (1U << 0)
>  #define SCR_IRQ               (1U << 1)
>  #define SCR_FIQ               (1U << 2)
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 3a9f35bf4b..0a55096770 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -4623,7 +4623,8 @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
>  static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
>  {
>      ARMCPU *cpu = env_archcpu(env);
> -    uint64_t valid_mask = HCR_MASK;
> +    /* Begin with bits defined in base ARMv8.0.  */
> +    uint64_t valid_mask = MAKE_64BIT_MASK(0, 34);
>
>      if (arm_feature(env, ARM_FEATURE_EL3)) {
>          valid_mask &= ~HCR_HCD;
> @@ -4637,6 +4638,9 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
>           */
>          valid_mask &= ~HCR_TSC;
>      }
> +    if (cpu_isar_feature(aa64_vh, cpu)) {
> +        valid_mask |= HCR_E2H;
> +    }
>      if (cpu_isar_feature(aa64_lor, cpu)) {
>          valid_mask |= HCR_TLOR;
>      }


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 08/24] target/arm: Add CONTEXTIDR_EL2
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 08/24] target/arm: Add CONTEXTIDR_EL2 Richard Henderson
@ 2019-07-24 13:57   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-24 13:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Not all of the breakpoint types are supported, but those that
> only examine contextidr are extended to support the new register.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/debug_helper.c | 50 +++++++++++++++++++++++++++++----------
>  target/arm/helper.c       | 11 +++++++++
>  2 files changed, 49 insertions(+), 12 deletions(-)
>
> diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
> index dde80273ff..2e3e90c6a5 100644
> --- a/target/arm/debug_helper.c
> +++ b/target/arm/debug_helper.c
> @@ -20,6 +20,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
>      int ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
>      int bt;
>      uint32_t contextidr;
> +    uint64_t hcr_el2;
>
>      /*
>       * Links to unimplemented or non-context aware breakpoints are
> @@ -40,24 +41,44 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
>      }
>
>      bt = extract64(bcr, 20, 4);
> -
> -    /*
> -     * We match the whole register even if this is AArch32 using the
> -     * short descriptor format (in which case it holds both PROCID and ASID),
> -     * since we don't implement the optional v7 context ID masking.
> -     */
> -    contextidr = extract64(env->cp15.contextidr_el[1], 0, 32);
> +    hcr_el2 = arm_hcr_el2_eff(env);
>
>      switch (bt) {
>      case 3: /* linked context ID match */
> -        if (arm_current_el(env) > 1) {
> -            /* Context matches never fire in EL2 or (AArch64) EL3 */
> +        switch (arm_current_el(env)) {
> +        default:
> +            /* Context matches never fire in AArch64 EL3 */
>              return false;
> +        case 2:
> +            if (!(hcr_el2 & HCR_E2H)) {
> +                /* Context matches never fire in EL2 without E2H enabled. */
> +                return false;
> +            }
> +            contextidr = env->cp15.contextidr_el[2];
> +            break;
> +        case 1:
> +            contextidr = env->cp15.contextidr_el[1];
> +            break;
> +        case 0:
> +            if ((hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
> +                contextidr = env->cp15.contextidr_el[2];
> +            } else {
> +                contextidr = env->cp15.contextidr_el[1];
> +            }
> +            break;
>          }
> -        return (contextidr == extract64(env->cp15.dbgbvr[lbn], 0, 32));
> -    case 5: /* linked address mismatch (reserved in AArch64) */
> +        break;
> +
> +    case 7:  /* linked contextidr_el1 match */
> +        contextidr = env->cp15.contextidr_el[1];
> +        break;
> +    case 13: /* linked contextidr_el2 match */
> +        contextidr = env->cp15.contextidr_el[2];
> +        break;
> +
>      case 9: /* linked VMID match (reserved if no EL2) */
>      case 11: /* linked context ID and VMID match (reserved if no EL2) */
> +    case 15: /* linked full context ID match */
>      default:

I'm wondering if a qemu_log(UNIMP) here? I guess not as we check the
value a lot....

>          /*
>           * Links to Unlinked context breakpoints must generate no
> @@ -66,7 +87,12 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
>          return false;
>      }
>
> -    return false;
> +    /*
> +     * We match the whole register even if this is AArch32 using the
> +     * short descriptor format (in which case it holds both PROCID and ASID),
> +     * since we don't implement the optional v7 context ID masking.
> +     */
> +    return contextidr == (uint32_t)env->cp15.dbgbvr[lbn];
>  }
>
>  static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 0a55096770..d1bf31ab74 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -6801,6 +6801,17 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>          define_arm_cp_regs(cpu, lor_reginfo);
>      }
>
> +    if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
> +        static const ARMCPRegInfo vhe_reginfo[] = {
> +            { .name = "CONTEXTIDR_EL2", .state = ARM_CP_STATE_AA64,
> +              .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 1,
> +              .access = PL2_RW,
> +              .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[2]) },
> +            REGINFO_SENTINEL
> +        };
> +        define_arm_cp_regs(cpu, vhe_reginfo);
> +    }
> +
>      if (cpu_isar_feature(aa64_sve, cpu)) {
>          define_one_arm_cp_reg(cpu, &zcr_el1_reginfo);
>          if (arm_feature(env, ARM_FEATURE_EL2)) {

Anyway:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 09/24] target/arm: Add TTBR1_EL2
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 09/24] target/arm: Add TTBR1_EL2 Richard Henderson
@ 2019-07-24 14:12   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-24 14:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> At the same time, add writefn to TTBR0_EL2 and TCR_EL2.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/helper.c | 21 ++++++++++++++++-----
>  1 file changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index d1bf31ab74..da2e0627b2 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3449,6 +3449,15 @@ static void vmsa_ttbr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      }
>  }
>
> +static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                                    uint64_t value)
> +{
> +    raw_write(env, ri, value);

I wonder if the bellow would be better merged with:

  target/arm: Install asids for E2&0 translation regime

And the commit message amended to say something like:

  "later patches will potentially update the asid"

> +    if (arm_hcr_el2_eff(env) & HCR_E2H) {
> +        /* The ASID field is active.  */
> +    }
> +}
> +
>  static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                          uint64_t value)
>  {
> @@ -4844,10 +4853,8 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
>        .resetvalue = 0 },
>      { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
>        .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
> -      .access = PL2_RW,
> -      /* no .writefn needed as this can't cause an ASID change;
> -       * no .raw_writefn or .resetfn needed as we never use mask/base_mask
> -       */
> +      .access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
> +      /* no .raw_writefn or .resetfn needed as we never use mask/base_mask */
>        .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) },
>      { .name = "VTCR", .state = ARM_CP_STATE_AA32,
>        .cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
> @@ -4881,7 +4888,7 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
>        .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[2]) },
>      { .name = "TTBR0_EL2", .state = ARM_CP_STATE_AA64,
>        .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
> -      .access = PL2_RW, .resetvalue = 0,
> +      .access = PL2_RW, .resetvalue = 0, .writefn = vmsa_tcr_ttbr_el2_write,
>        .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
>      { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
>        .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
> @@ -6807,6 +6814,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>                .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 1,
>                .access = PL2_RW,
>                .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[2]) },
> +            { .name = "TTBR1_EL2", .state = ARM_CP_STATE_AA64,
> +              .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 1,
> +              .access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
> +              .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el[2]) },
>              REGINFO_SENTINEL
>          };
>          define_arm_cp_regs(cpu, vhe_reginfo);

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 10/24] target/arm: Update CNTVCT_EL0 for VHE
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 10/24] target/arm: Update CNTVCT_EL0 for VHE Richard Henderson
@ 2019-07-24 14:47   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-24 14:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> The virtual offset may be 0 depending on EL, E2H and TGE.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/helper.c | 40 +++++++++++++++++++++++++++++++++++++---
>  1 file changed, 37 insertions(+), 3 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index da2e0627b2..3124d682a2 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -2484,9 +2484,31 @@ static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
>      return gt_get_countervalue(env);
>  }
>
> +static uint64_t gt_virt_cnt_offset(CPUARMState *env)
> +{
> +    uint64_t hcr;
> +
> +    switch (arm_current_el(env)) {
> +    case 2:
> +        hcr = arm_hcr_el2_eff(env);
> +        if (hcr & HCR_E2H) {
> +            return 0;
> +        }
> +        break;
> +    case 0:
> +        hcr = arm_hcr_el2_eff(env);
> +        if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
> +            return 0;
> +        }
> +        break;
> +    }
> +
> +    return env->cp15.cntvoff_el2;
> +}
> +
>  static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
>  {
> -    return gt_get_countervalue(env) - env->cp15.cntvoff_el2;
> +    return gt_get_countervalue(env) - gt_virt_cnt_offset(env);
>  }
>
>  static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -2501,7 +2523,13 @@ static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
>                               int timeridx)
>  {
> -    uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
> +    uint64_t offset = 0;
> +
> +    switch (timeridx) {
> +    case GTIMER_VIRT:
> +        offset = gt_virt_cnt_offset(env);
> +        break;
> +    }
>
>      return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
>                        (gt_get_countervalue(env) - offset));
> @@ -2511,7 +2539,13 @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                            int timeridx,
>                            uint64_t value)
>  {
> -    uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
> +    uint64_t offset = 0;
> +
> +    switch (timeridx) {
> +    case GTIMER_VIRT:
> +        offset = gt_virt_cnt_offset(env);
> +        break;
> +    }
>
>      trace_arm_gt_tval_write(timeridx, value);
>      env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 11/24] target/arm: Add the hypervisor virtual counter
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 11/24] target/arm: Add the hypervisor virtual counter Richard Henderson
@ 2019-07-24 20:05   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-24 20:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/cpu-qom.h |  1 +
>  target/arm/cpu.h     | 11 +++++----
>  target/arm/cpu.c     |  2 ++
>  target/arm/helper.c  | 57 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 66 insertions(+), 5 deletions(-)
>
> diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
> index 2049fa9612..43fc8296db 100644
> --- a/target/arm/cpu-qom.h
> +++ b/target/arm/cpu-qom.h
> @@ -76,6 +76,7 @@ void arm_gt_ptimer_cb(void *opaque);
>  void arm_gt_vtimer_cb(void *opaque);
>  void arm_gt_htimer_cb(void *opaque);
>  void arm_gt_stimer_cb(void *opaque);
> +void arm_gt_hvtimer_cb(void *opaque);
>
>  #define ARM_AFF0_SHIFT 0
>  #define ARM_AFF0_MASK  (0xFFULL << ARM_AFF0_SHIFT)
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index e37008a4f7..bba4e1f984 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -144,11 +144,12 @@ typedef struct ARMGenericTimer {
>      uint64_t ctl; /* Timer Control register */
>  } ARMGenericTimer;
>
> -#define GTIMER_PHYS 0
> -#define GTIMER_VIRT 1
> -#define GTIMER_HYP  2
> -#define GTIMER_SEC  3
> -#define NUM_GTIMERS 4
> +#define GTIMER_PHYS     0
> +#define GTIMER_VIRT     1
> +#define GTIMER_HYP      2
> +#define GTIMER_SEC      3
> +#define GTIMER_HYPVIRT  4
> +#define NUM_GTIMERS     5
>
>  typedef struct {
>      uint64_t raw_tcr;
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index 1959467fdc..90352decc5 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -1218,6 +1218,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
>                                            arm_gt_htimer_cb, cpu);
>      cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
>                                            arm_gt_stimer_cb, cpu);
> +    cpu->gt_timer[GTIMER_HYPVIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
> +                                              arm_gt_hvtimer_cb, cpu);
>  #endif
>
>      cpu_exec_realizefn(cs, &local_err);
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 3124d682a2..329548e45d 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -2527,6 +2527,7 @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
>
>      switch (timeridx) {
>      case GTIMER_VIRT:
> +    case GTIMER_HYPVIRT:
>          offset = gt_virt_cnt_offset(env);
>          break;
>      }
> @@ -2543,6 +2544,7 @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
>      switch (timeridx) {
>      case GTIMER_VIRT:
> +    case GTIMER_HYPVIRT:
>          offset = gt_virt_cnt_offset(env);
>          break;
>      }
> @@ -2698,6 +2700,34 @@ static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      gt_ctl_write(env, ri, GTIMER_SEC, value);
>  }
>
> +static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> +    gt_timer_reset(env, ri, GTIMER_HYPVIRT);
> +}
> +
> +static void gt_hv_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                             uint64_t value)
> +{
> +    gt_cval_write(env, ri, GTIMER_HYPVIRT, value);
> +}
> +
> +static uint64_t gt_hv_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> +    return gt_tval_read(env, ri, GTIMER_HYPVIRT);
> +}
> +
> +static void gt_hv_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                             uint64_t value)
> +{
> +    gt_tval_write(env, ri, GTIMER_HYPVIRT, value);
> +}
> +
> +static void gt_hv_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                            uint64_t value)
> +{
> +    gt_ctl_write(env, ri, GTIMER_HYPVIRT, value);
> +}
> +
>  void arm_gt_ptimer_cb(void *opaque)
>  {
>      ARMCPU *cpu = opaque;
> @@ -2726,6 +2756,13 @@ void arm_gt_stimer_cb(void *opaque)
>      gt_recalc_timer(cpu, GTIMER_SEC);
>  }
>
> +void arm_gt_hvtimer_cb(void *opaque)
> +{
> +    ARMCPU *cpu = opaque;
> +
> +    gt_recalc_timer(cpu, GTIMER_HYPVIRT);
> +}
> +
>  static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
>      /* Note that CNTFRQ is purely reads-as-written for the benefit
>       * of software; writing it doesn't actually change the timer frequency.
> @@ -6852,6 +6889,26 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>                .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 1,
>                .access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
>                .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el[2]) },
> +#ifndef CONFIG_USER_ONLY
> +            { .name = "CNTHV_CVAL_EL2", .state = ARM_CP_STATE_AA64,
> +              .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 2,
> +              .fieldoffset =
> +                offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].cval),
> +              .type = ARM_CP_IO, .access = PL2_RW,
> +              .writefn = gt_hv_cval_write, .raw_writefn = raw_write },
> +            { .name = "CNTHV_TVAL_EL2", .state = ARM_CP_STATE_BOTH,
> +              .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 0,
> +              .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
> +              .resetfn = gt_hv_timer_reset,
> +              .readfn = gt_hv_tval_read, .writefn = gt_hv_tval_write },
> +            { .name = "CNTHV_CTL_EL2", .state = ARM_CP_STATE_BOTH,
> +              .type = ARM_CP_IO,
> +              .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 1,
> +              .access = PL2_RW,
> +              .fieldoffset =
> +                offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].ctl),
> +              .writefn = gt_hv_ctl_write, .raw_writefn = raw_write },
> +#endif
>              REGINFO_SENTINEL
>          };
>          define_arm_cp_regs(cpu, vhe_reginfo);


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 12/24] target/arm: Add VHE system register redirection and aliasing
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 12/24] target/arm: Add VHE system register redirection and aliasing Richard Henderson
@ 2019-07-25 14:01   ` Alex Bennée
  2019-07-25 14:24     ` Richard Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Alex Bennée @ 2019-07-25 14:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Several of the EL1/0 registers are redirected to the EL2 version when in
> EL2 and HCR_EL2.E2H is set.  Many of these registers have side effects.
> Link together the two ARMCPRegInfo structures after they have been
> properly instantiated.  Install common dispatch routines to all of the
> relevant registers.
>
> The same set of registers that are redirected also have additional
> EL12/EL02 aliases created to access the original register that was
> redirected.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h    |  44 ++++++++----
>  target/arm/helper.c | 171 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 202 insertions(+), 13 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index bba4e1f984..a0f10b60eb 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2455,19 +2455,6 @@ struct ARMCPRegInfo {
>       */
>      ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
>
> -    /* Offsets of the secure and non-secure fields in CPUARMState for the
> -     * register if it is banked.  These fields are only used during the static
> -     * registration of a register.  During hashing the bank associated
> -     * with a given security state is copied to fieldoffset which is used from
> -     * there on out.
> -     *
> -     * It is expected that register definitions use either fieldoffset or
> -     * bank_fieldoffsets in the definition but not both.  It is also expected
> -     * that both bank offsets are set when defining a banked register.  This
> -     * use indicates that a register is banked.
> -     */
> -    ptrdiff_t bank_fieldoffsets[2];
> -
>      /* Function for making any access checks for this register in addition to
>       * those specified by the 'access' permissions bits. If NULL, no extra
>       * checks required. The access check is performed at runtime, not at
> @@ -2502,6 +2489,37 @@ struct ARMCPRegInfo {
>       * fieldoffset is 0 then no reset will be done.
>       */
>      CPResetFn *resetfn;
> +
> +    union {
> +        /*
> +         * Offsets of the secure and non-secure fields in CPUARMState for
> +         * the register if it is banked.  These fields are only used during
> +         * the static registration of a register.  During hashing the bank
> +         * associated with a given security state is copied to fieldoffset
> +         * which is used from there on out.
> +         *
> +         * It is expected that register definitions use either fieldoffset
> +         * or bank_fieldoffsets in the definition but not both.  It is also
> +         * expected that both bank offsets are set when defining a banked
> +         * register.  This use indicates that a register is banked.
> +         */
> +        ptrdiff_t bank_fieldoffsets[2];

It seems a bit off that we are compressing this structure into a union
when we didn't bother with the above fieldoffset despite the statement
that only one or the other is used.

> +
> +        /*
> +         * "Original" writefn and readfn.
> +         * For ARMv8.1-VHE register aliases, we overwrite the read/write
> +         * accessor functions of various EL1/EL0 to perform the runtime
> +         * check for which sysreg should actually be modified, and then
> +         * forwards the operation.  Before overwriting the accessors,
> +         * the original function is copied here, so that accesses that
> +         * really do go to the EL1/EL0 version proceed normally.
> +         * (The corresponding EL2 register is linked via opaque.)
> +         */
> +        struct {
> +            CPReadFn *orig_readfn;
> +            CPWriteFn *orig_writefn;
> +        };

Is 2 pointers enough saving? Will we never see a re-directed register
that was using the banked fieldoffsets? Can we protect against that?

> +    };
>  };
>
>  /* Macros which are lvalues for the field in CPUARMState for the
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 329548e45d..9a9809ff4f 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -5228,6 +5228,169 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
>      REGINFO_SENTINEL
>  };
>

You already know about the ifndef CONFIG_USER_ONLY needed here:

> +/* Test if system register redirection is to occur in the current state.  */
> +static bool redirect_for_e2h(CPUARMState *env)
> +{
> +    return arm_current_el(env) == 2 && (arm_hcr_el2_eff(env) & HCR_E2H);
> +}
> +
> +static uint64_t el2_e2h_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> +    CPReadFn *readfn;
> +
> +    if (redirect_for_e2h(env)) {
> +        /* Switch to the saved EL2 version of the register.  */
> +        ri = ri->opaque;
> +        readfn = ri->readfn;
> +    } else {
> +        readfn = ri->orig_readfn;
> +    }
> +    if (readfn == NULL) {
> +        readfn = raw_read;
> +    }
> +    return readfn(env, ri);
> +}
> +
> +static void el2_e2h_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                          uint64_t value)
> +{
> +    CPWriteFn *writefn;
> +
> +    if (redirect_for_e2h(env)) {
> +        /* Switch to the saved EL2 version of the register.  */
> +        ri = ri->opaque;
> +        writefn = ri->writefn;
> +    } else {
> +        writefn = ri->orig_writefn;
> +    }
> +    if (writefn == NULL) {
> +        writefn = raw_write;
> +    }
> +    writefn(env, ri, value);
> +}
> +
> +static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
> +{
> +    struct E2HAlias {
> +        uint32_t src_key, dst_key, new_key;
> +        const char *src_name, *dst_name, *new_name;

  /* some redirects are only enabled on feature detection */ ?

> +        bool (*feature)(const ARMISARegisters *id);
> +    };
> +
> +#define K(op0, op1, crn, crm, op2) \
> +    ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
> +
> +    static const struct E2HAlias aliases[] = {
> +        { K(3, 0,  1, 0, 0), K(3, 4,  1, 0, 0), K(3, 5, 1, 0, 0),
> +          "SCTLR", "SCTLR_EL2", "SCTLR_EL12" },
> +        { K(3, 0,  1, 0, 2), K(3, 4,  1, 1, 2), K(3, 5, 1, 0, 2),
> +          "CPACR", "CPTR_EL2", "CPACR_EL12" },
> +        { K(3, 0,  2, 0, 0), K(3, 4,  2, 0, 0), K(3, 5, 2, 0, 0),
> +          "TTBR0_EL1", "TTBR0_EL2", "TTBR0_EL12" },
> +        { K(3, 0,  2, 0, 1), K(3, 4,  2, 0, 1), K(3, 5, 2, 0, 1),
> +          "TTBR1_EL1", "TTBR1_EL2", "TTBR1_EL12" },
> +        { K(3, 0,  2, 0, 2), K(3, 4,  2, 0, 2), K(3, 5, 2, 0, 2),
> +          "TCR_EL1", "TCR_EL2", "TCR_EL12" },
> +        { K(3, 0,  4, 0, 0), K(3, 4,  4, 0, 0), K(3, 5, 4, 0, 0),
> +          "SPSR_EL1", "SPSR_EL2", "SPSR_EL12" },
> +        { K(3, 0,  4, 0, 1), K(3, 4,  4, 0, 1), K(3, 5, 4, 0, 1),
> +          "ELR_EL1", "ELR_EL2", "ELR_EL12" },
> +        { K(3, 0,  5, 1, 0), K(3, 4,  5, 1, 0), K(3, 5, 5, 1, 0),
> +          "AFSR0_EL1", "AFSR0_EL2", "AFSR0_EL12" },
> +        { K(3, 0,  5, 1, 1), K(3, 4,  5, 1, 1), K(3, 5, 5, 1, 1),
> +          "AFSR1_EL1", "AFSR1_EL2", "AFSR1_EL12" },
> +        { K(3, 0,  5, 2, 0), K(3, 4,  5, 2, 0), K(3, 5, 5, 2, 0),
> +          "ESR_EL1", "ESR_EL2", "ESR_EL12" },
> +        { K(3, 0,  6, 0, 0), K(3, 4,  6, 0, 0), K(3, 5, 6, 0, 0),
> +          "FAR_EL1", "FAR_EL2", "FAR_EL12" },
> +        { K(3, 0, 10, 2, 0), K(3, 4, 10, 2, 0), K(3, 5, 10, 2, 0),
> +          "MAIR_EL1", "MAIR_EL2", "MAIR_EL12" },
> +        { K(3, 0, 10, 3, 0), K(3, 4, 10, 3, 0), K(3, 5, 10, 3, 0),
> +          "AMAIR0", "AMAIR_EL2", "AMAIR_EL12" },
> +        { K(3, 0, 12, 0, 0), K(3, 4, 12, 0, 0), K(3, 5, 12, 0, 0),
> +          "VBAR", "VBAR_EL2", "VBAR_EL12" },
> +        { K(3, 0, 13, 0, 1), K(3, 4, 13, 0, 1), K(3, 5, 13, 0, 1),
> +          "CONTEXTIDR_EL1", "CONTEXTIDR_EL2", "CONTEXTIDR_EL12" },
> +        { K(3, 0, 14, 1, 0), K(3, 4, 14, 1, 0), K(3, 5, 14, 1, 0),
> +          "CNTKCTL", "CNTHCTL_EL2", "CNTKCTL_EL12" },
> +        { K(3, 3, 14, 2, 0), K(3, 4, 14, 2, 0), K(3, 5, 14, 2, 0),
> +          "CNTP_TVAL_EL0", "CNTHP_TVAL_EL2", "CNTP_TVAL_EL02" },
> +        { K(3, 3, 14, 2, 1), K(3, 4, 14, 2, 1), K(3, 5, 14, 2, 1),
> +          "CNTP_CTL_EL0", "CNTHP_CTL_EL2", "CNTP_CTL_EL02" },
> +        { K(3, 3, 14, 2, 2), K(3, 4, 14, 2, 2), K(3, 5, 14, 2, 2),
> +          "CNTP_CVAL_EL0", "CNTHP_CVAL_EL2", "CNTP_CVAL_EL02" },
> +        { K(3, 3, 14, 3, 0), K(3, 4, 14, 3, 0), K(3, 5, 14, 3, 0),
> +          "CNTV_TVAL_EL0", "CNTHV_TVAL_EL2", "CNTV_TVAL_EL02" },
> +        { K(3, 3, 14, 3, 1), K(3, 4, 14, 3, 1), K(3, 5, 14, 3, 1),
> +          "CNTV_CTL_EL0", "CNTHV_CTL_EL2", "CNTV_CTL_EL02" },
> +        { K(3, 3, 14, 3, 2), K(3, 4, 14, 3, 2), K(3, 5, 14, 3, 2),
> +          "CNTV_CVAL_EL0", "CNTHV_CVAL_EL2", "CNTV_CVAL_EL02" },
> +        /*
> +         * CNTHV_CVAL is a special case because there is no separate
> +         * AArch32 EL2 register to which CNTV_CVAL may be directed.
> +         * The effect can be achieved via CNTHV_CVAL_EL2.
> +         */
> +        { ENCODE_CP_REG(15, 1, 1, 0, 14, 3, 0), K(3, 4, 14, 3, 2), 0,
> +          "CNTV_CVAL", "CNTHV_CVAL_EL2", NULL },
> +
> +        /*
> +         * Note that redirection of ZCR is mentioned in the description
> +         * of ZCR_EL2, and aliasing in the description of ZCR_EL1, but
> +         * not in the summary table.
> +         */
> +        { K(3, 0,  1, 2, 0), K(3, 4,  1, 2, 0), K(3, 5, 1, 2, 0),
> +          "ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve },
> +
> +        /* TODO: ARMv8.2-SPE -- PMSCR_EL2 */
> +        /* TODO: ARMv8.4-Trace -- TRFCR_EL2 */
> +    };
> +#undef K
> +
> +    size_t i;
> +
> +    for (i = 0; i < ARRAY_SIZE(aliases); i++) {
> +        const struct E2HAlias *a = &aliases[i];
> +        ARMCPRegInfo *src_reg, *dst_reg;
> +
> +        if (a->feature && !a->feature(&cpu->isar)) {
> +            continue;
> +        }
> +
> +        src_reg = g_hash_table_lookup(cpu->cp_regs, &a->src_key);
> +        dst_reg = g_hash_table_lookup(cpu->cp_regs, &a->dst_key);
> +        g_assert(src_reg != NULL);
> +        g_assert(dst_reg != NULL);
> +
> +        /* Cross-compare names to detect typos in the keys.  */
> +        g_assert(strcmp(src_reg->name, a->src_name) == 0);
> +        g_assert(strcmp(dst_reg->name, a->dst_name) == 0);
> +
> +        /* None of the core system registers use opaque; we will.  */
> +        g_assert(src_reg->opaque == NULL);

re above: assert bank_fieldoffsets not used?

> +
> +        /* Create alias before redirection so we dup the right data. */
> +        if (a->new_key) {
> +            ARMCPRegInfo *new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
> +            uint32_t *new_key = g_memdup(&a->new_key, sizeof(uint32_t));
> +            bool ok;
> +
> +            new_reg->name = a->new_name;
> +            new_reg->type |= ARM_CP_ALIAS;
> +            /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place.  */
> +            new_reg->access &= 0xf0;
> +
> +            ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
> +            g_assert(ok);
> +        }
> +
> +        src_reg->opaque = dst_reg;
> +        src_reg->orig_readfn = src_reg->readfn;
> +        src_reg->orig_writefn = src_reg->writefn;
> +        src_reg->readfn = el2_e2h_read;
> +        src_reg->writefn = el2_e2h_write;
> +    }
> +}
> +
>  static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
>                                       bool isread)
>  {
> @@ -6945,6 +7108,14 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>          : cpu_isar_feature(aa32_predinv, cpu)) {
>          define_arm_cp_regs(cpu, predinv_reginfo);
>      }
> +
> +    /*
> +     * Register redirections and aliases must be done last,
> +     * after the registers from the other extensions have been defined.
> +     */
> +    if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
> +        define_arm_vh_e2h_redirects_aliases(cpu);
> +    }
>  }
>
>  void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 13/24] target/arm: Split out vae1_tlbmask, vmalle1_tlbmask
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 13/24] target/arm: Split out vae1_tlbmask, vmalle1_tlbmask Richard Henderson
@ 2019-07-25 14:02   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> No functional change, but unify code sequences.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/helper.c | 118 ++++++++++++++------------------------------
>  1 file changed, 37 insertions(+), 81 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 9a9809ff4f..7adbf51479 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3901,70 +3901,61 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
>   * Page D4-1736 (DDI0487A.b)
>   */
>
> +static int vae1_tlbmask(CPUARMState *env)
> +{
> +    if (arm_is_secure_below_el3(env)) {
> +        return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
> +    } else {
> +        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
> +    }
> +}
> +
>  static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                                        uint64_t value)
>  {
>      CPUState *cs = env_cpu(env);
> -    bool sec = arm_is_secure_below_el3(env);
> +    int mask = vae1_tlbmask(env);
>
> -    if (sec) {
> -        tlb_flush_by_mmuidx_all_cpus_synced(cs,
> -                                            ARMMMUIdxBit_S1SE1 |
> -                                            ARMMMUIdxBit_S1SE0);
> -    } else {
> -        tlb_flush_by_mmuidx_all_cpus_synced(cs,
> -                                            ARMMMUIdxBit_S12NSE1 |
> -                                            ARMMMUIdxBit_S12NSE0);
> -    }
> +    tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
>  }
>
>  static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                                      uint64_t value)
>  {
>      CPUState *cs = env_cpu(env);
> +    int mask = vae1_tlbmask(env);
>
>      if (tlb_force_broadcast(env)) {
>          tlbi_aa64_vmalle1is_write(env, NULL, value);
>          return;
>      }
>
> +    tlb_flush_by_mmuidx(cs, mask);
> +}
> +
> +static int vmalle1_tlbmask(CPUARMState *env)
> +{
> +    /*
> +     * Note that the 'ALL' scope must invalidate both stage 1 and
> +     * stage 2 translations, whereas most other scopes only invalidate
> +     * stage 1 translations.
> +     */
>      if (arm_is_secure_below_el3(env)) {
> -        tlb_flush_by_mmuidx(cs,
> -                            ARMMMUIdxBit_S1SE1 |
> -                            ARMMMUIdxBit_S1SE0);
> +        return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
> +    } else if (arm_feature(env, ARM_FEATURE_EL2)) {
> +        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0 | ARMMMUIdxBit_S2NS;
>      } else {
> -        tlb_flush_by_mmuidx(cs,
> -                            ARMMMUIdxBit_S12NSE1 |
> -                            ARMMMUIdxBit_S12NSE0);
> +        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
>      }
>  }
>
>  static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                                    uint64_t value)
>  {
> -    /* Note that the 'ALL' scope must invalidate both stage 1 and
> -     * stage 2 translations, whereas most other scopes only invalidate
> -     * stage 1 translations.
> -     */
> -    ARMCPU *cpu = env_archcpu(env);
> -    CPUState *cs = CPU(cpu);
> +    CPUState *cs = env_cpu(env);
> +    int mask = vmalle1_tlbmask(env);
>
> -    if (arm_is_secure_below_el3(env)) {
> -        tlb_flush_by_mmuidx(cs,
> -                            ARMMMUIdxBit_S1SE1 |
> -                            ARMMMUIdxBit_S1SE0);
> -    } else {
> -        if (arm_feature(env, ARM_FEATURE_EL2)) {
> -            tlb_flush_by_mmuidx(cs,
> -                                ARMMMUIdxBit_S12NSE1 |
> -                                ARMMMUIdxBit_S12NSE0 |
> -                                ARMMMUIdxBit_S2NS);
> -        } else {
> -            tlb_flush_by_mmuidx(cs,
> -                                ARMMMUIdxBit_S12NSE1 |
> -                                ARMMMUIdxBit_S12NSE0);
> -        }
> -    }
> +    tlb_flush_by_mmuidx(cs, mask);
>  }
>
>  static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -3988,28 +3979,10 @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                                      uint64_t value)
>  {
> -    /* Note that the 'ALL' scope must invalidate both stage 1 and
> -     * stage 2 translations, whereas most other scopes only invalidate
> -     * stage 1 translations.
> -     */
>      CPUState *cs = env_cpu(env);
> -    bool sec = arm_is_secure_below_el3(env);
> -    bool has_el2 = arm_feature(env, ARM_FEATURE_EL2);
> +    int mask = vmalle1_tlbmask(env);
>
> -    if (sec) {
> -        tlb_flush_by_mmuidx_all_cpus_synced(cs,
> -                                            ARMMMUIdxBit_S1SE1 |
> -                                            ARMMMUIdxBit_S1SE0);
> -    } else if (has_el2) {
> -        tlb_flush_by_mmuidx_all_cpus_synced(cs,
> -                                            ARMMMUIdxBit_S12NSE1 |
> -                                            ARMMMUIdxBit_S12NSE0 |
> -                                            ARMMMUIdxBit_S2NS);
> -    } else {
> -          tlb_flush_by_mmuidx_all_cpus_synced(cs,
> -                                              ARMMMUIdxBit_S12NSE1 |
> -                                              ARMMMUIdxBit_S12NSE0);
> -    }
> +    tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
>  }
>
>  static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4059,20 +4032,11 @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                                     uint64_t value)
>  {
> -    ARMCPU *cpu = env_archcpu(env);
> -    CPUState *cs = CPU(cpu);
> -    bool sec = arm_is_secure_below_el3(env);
> +    CPUState *cs = env_cpu(env);
> +    int mask = vae1_tlbmask(env);
>      uint64_t pageaddr = sextract64(value << 12, 0, 56);
>
> -    if (sec) {
> -        tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
> -                                                 ARMMMUIdxBit_S1SE1 |
> -                                                 ARMMMUIdxBit_S1SE0);
> -    } else {
> -        tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
> -                                                 ARMMMUIdxBit_S12NSE1 |
> -                                                 ARMMMUIdxBit_S12NSE0);
> -    }
> +    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
>  }
>
>  static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4083,8 +4047,8 @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>       * since we don't support flush-for-specific-ASID-only or
>       * flush-last-level-only.
>       */
> -    ARMCPU *cpu = env_archcpu(env);
> -    CPUState *cs = CPU(cpu);
> +    CPUState *cs = env_cpu(env);
> +    int mask = vae1_tlbmask(env);
>      uint64_t pageaddr = sextract64(value << 12, 0, 56);
>
>      if (tlb_force_broadcast(env)) {
> @@ -4092,15 +4056,7 @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>          return;
>      }
>
> -    if (arm_is_secure_below_el3(env)) {
> -        tlb_flush_page_by_mmuidx(cs, pageaddr,
> -                                 ARMMMUIdxBit_S1SE1 |
> -                                 ARMMMUIdxBit_S1SE0);
> -    } else {
> -        tlb_flush_page_by_mmuidx(cs, pageaddr,
> -                                 ARMMMUIdxBit_S12NSE1 |
> -                                 ARMMMUIdxBit_S12NSE0);
> -    }
> +    tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
>  }
>
>  static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 14/24] target/arm: Simplify tlb_force_broadcast alternatives
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 14/24] target/arm: Simplify tlb_force_broadcast alternatives Richard Henderson
@ 2019-07-25 14:08   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-25 14:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Rather than call to a separate function and re-compute any
> parameters for the flush, simply use the correct flush
> function directly.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/helper.c | 52 +++++++++++++++++++++------------------------
>  1 file changed, 24 insertions(+), 28 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 7adbf51479..2b95fc763f 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -626,56 +626,54 @@ static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                            uint64_t value)
>  {
>      /* Invalidate all (TLBIALL) */
> -    ARMCPU *cpu = env_archcpu(env);
> +    CPUState *cs = env_cpu(env);
>
>      if (tlb_force_broadcast(env)) {
> -        tlbiall_is_write(env, NULL, value);
> -        return;
> +        tlb_flush_all_cpus_synced(cs);
> +    } else {
> +        tlb_flush(cs);
>      }
> -
> -    tlb_flush(CPU(cpu));
>  }
>
>  static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                            uint64_t value)
>  {
>      /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */
> -    ARMCPU *cpu = env_archcpu(env);
> +    CPUState *cs = env_cpu(env);
>
> +    value &= TARGET_PAGE_MASK;

I'm fairly sure this is superfluous (we certainly mask pages in the
cputlb code, don't know if we do at the translation end).

>      if (tlb_force_broadcast(env)) {
> -        tlbimva_is_write(env, NULL, value);
> -        return;
> +        tlb_flush_page_all_cpus_synced(cs, value);
> +    } else {
> +        tlb_flush_page(cs, value);
>      }
> -
> -    tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
>  }
>
>  static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                             uint64_t value)
>  {
>      /* Invalidate by ASID (TLBIASID) */
> -    ARMCPU *cpu = env_archcpu(env);
> +    CPUState *cs = env_cpu(env);
>
>      if (tlb_force_broadcast(env)) {
> -        tlbiasid_is_write(env, NULL, value);
> -        return;
> +        tlb_flush_all_cpus_synced(cs);
> +    } else {
> +        tlb_flush(cs);
>      }
> -
> -    tlb_flush(CPU(cpu));
>  }
>
>  static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                             uint64_t value)
>  {
>      /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */
> -    ARMCPU *cpu = env_archcpu(env);
> +    CPUState *cs = env_cpu(env);
>
> +    value &= TARGET_PAGE_MASK;
>      if (tlb_force_broadcast(env)) {
> -        tlbimvaa_is_write(env, NULL, value);
> -        return;
> +        tlb_flush_page_all_cpus_synced(cs, value);
> +    } else {
> +        tlb_flush_page(cs, value);
>      }
> -
> -    tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
>  }
>
>  static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -3926,11 +3924,10 @@ static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      int mask = vae1_tlbmask(env);
>
>      if (tlb_force_broadcast(env)) {
> -        tlbi_aa64_vmalle1is_write(env, NULL, value);
> -        return;
> +        tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
> +    } else {
> +        tlb_flush_by_mmuidx(cs, mask);
>      }
> -
> -    tlb_flush_by_mmuidx(cs, mask);
>  }
>
>  static int vmalle1_tlbmask(CPUARMState *env)
> @@ -4052,11 +4049,10 @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      uint64_t pageaddr = sextract64(value << 12, 0, 56);
>
>      if (tlb_force_broadcast(env)) {
> -        tlbi_aa64_vae1is_write(env, NULL, value);
> -        return;
> +        tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
> +    } else {
> +        tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
>      }
> -
> -    tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
>  }
>
>  static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,

Anyway:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 12/24] target/arm: Add VHE system register redirection and aliasing
  2019-07-25 14:01   ` Alex Bennée
@ 2019-07-25 14:24     ` Richard Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-25 14:24 UTC (permalink / raw)
  To: Alex Bennée, qemu-devel; +Cc: peter.maydell, beata.michalska

On 7/25/19 7:01 AM, Alex Bennée wrote:
>> +    union {
>> +        /*
>> +         * Offsets of the secure and non-secure fields in CPUARMState for
>> +         * the register if it is banked.  These fields are only used during
>> +         * the static registration of a register.  During hashing the bank
>> +         * associated with a given security state is copied to fieldoffset
>> +         * which is used from there on out.
>> +         *
>> +         * It is expected that register definitions use either fieldoffset
>> +         * or bank_fieldoffsets in the definition but not both.  It is also
>> +         * expected that both bank offsets are set when defining a banked
>> +         * register.  This use indicates that a register is banked.
>> +         */
>> +        ptrdiff_t bank_fieldoffsets[2];
> 
> It seems a bit off that we are compressing this structure into a union
> when we didn't bother with the above fieldoffset despite the statement
> that only one or the other is used.
...
> Is 2 pointers enough saving? Will we never see a re-directed register
> that was using the banked fieldoffsets? Can we protect against that?

It's because bank_fieldoffsets[] is only used before instantiation.

Before the structure is given to add_cpreg_to_hashtable, we have copied the
structure, copied bank_fieldoffsets into fieldoffset, and adjusted the secure
state flag.

After instantiation, those two pointers are unused, and I thought I could
reclaim it.  However, you may have a point re total memory savings not making
the complication worthwhile.


r~


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

* Re: [Qemu-devel] [PATCH for-4.2 15/24] target/arm: Reorganize ARMMMUIdx
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 15/24] target/arm: Reorganize ARMMMUIdx Richard Henderson
@ 2019-07-25 15:57   ` Alex Bennée
  2019-07-25 18:18     ` Richard Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Alex Bennée @ 2019-07-25 15:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Prepare for, but do not yet implement, the EL2&0 regime and the
> Secure EL2 regime.  Rename all of the a-profile symbols to make
> the distictions clearer.

Perhaps a summary of the renames would be useful here? My head is
spinning a little given the number that we have and not being familiar
with the naming convention.

  ARMMMUIdx[_StageN]_[M][S]Enn[_nn]

  _StageN - stage N only, otherwise assumed 1+2 lookup?
  M - M profile (interleaved with A profile)
  S - Secure
  Enn - visible exception level, so E02 is shared EL0 and EL2?
  _nn - not sure?

The cpu.h comment is very detailed but doesn't actually give me enough
information to decode an ARMMMUIdx when I come across it in the code.

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h           | 180 ++++++++++++++--------------
>  target/arm/internals.h     |  46 ++++---
>  target/arm/translate.h     |   2 +-
>  target/arm/helper.c        | 237 ++++++++++++++++++++++---------------
>  target/arm/m_helper.c      |   6 +-
>  target/arm/translate-a64.c |  11 +-
>  target/arm/translate.c     |  17 ++-
>  7 files changed, 273 insertions(+), 226 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index a0f10b60eb..4b537c4613 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2764,7 +2764,10 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
>   *  + NonSecure EL1 & 0 stage 1
>   *  + NonSecure EL1 & 0 stage 2
>   *  + NonSecure EL2
> - *  + Secure EL1 & EL0
> + *  + NonSecure EL2 & 0   (ARMv8.1-VHE)
> + *  + Secure EL0
> + *  + Secure EL1
> + *  + Secure EL2          (ARMv8.4-SecEL2)
>   *  + Secure EL3
>   * If EL3 is 32-bit:
>   *  + NonSecure PL1 & 0 stage 1
> @@ -2774,8 +2777,9 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
>   * (reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.)
>   *
>   * For QEMU, an mmu_idx is not quite the same as a translation regime because:
> - *  1. we need to split the "EL1 & 0" regimes into two mmu_idxes, because they
> - *     may differ in access permissions even if the VA->PA map is the same
> + *  1. we need to split the "EL1 & 0" and "EL2 & 0" regimes into two mmu_idxes,
> + *     because they may differ in access permissions even if the VA->PA map is
> + *     the same
>   *  2. we want to cache in our TLB the full VA->IPA->PA lookup for a stage 1+2
>   *     translation, which means that we have one mmu_idx that deals with two
>   *     concatenated translation regimes [this sort of combined s1+2 TLB is
> @@ -2787,19 +2791,26 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
>   *  4. we can also safely fold together the "32 bit EL3" and "64 bit EL3"
>   *     translation regimes, because they map reasonably well to each other
>   *     and they can't both be active at the same time.
> - * This gives us the following list of mmu_idx values:
> + *  5. we want to be able to use the TLB for accesses done as part of a
> + *     stage1 page table walk, rather than having to walk the stage2 page
> + *     table over and over.
>   *
> - * NS EL0 (aka NS PL0) stage 1+2
> - * NS EL1 (aka NS PL1) stage 1+2
> + * This gives us the following list of cases:
> + *
> + * NS EL0 (aka NS PL0) EL1&0 stage 1+2
> + * NS EL1 (aka NS PL1) EL1&0 stage 1+2
> + * NS EL0 (aka NS PL0) EL2&0
> + * NS EL2 (aka NS PL2) EL2&0
>   * NS EL2 (aka NS PL2)
> - * S EL3 (aka S PL1)
>   * S EL0 (aka S PL0)
>   * S EL1 (not used if EL3 is 32 bit)
> - * NS EL0+1 stage 2
> + * S EL2 (not used if EL3 is 32 bit)
> + * S EL3 (aka S PL1)
> + * NS EL0&1 stage 2
>   *
> - * (The last of these is an mmu_idx because we want to be able to use the TLB
> - * for the accesses done as part of a stage 1 page table walk, rather than
> - * having to walk the stage 2 page table over and over.)
> + * We then merge the two NS EL0 cases, and two NS EL2 cases to produce
> + * 8 different mmu_idx.  We retain separate symbols for these four cases
> + * in order to simplify distinguishing them in the code.
>   *
>   * R profile CPUs have an MPU, but can use the same set of MMU indexes
>   * as A profile. They only need to distinguish NS EL0 and NS EL1 (and
> @@ -2837,62 +2848,93 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
>   * For M profile we arrange them to have a bit for priv, a bit for negpri
>   * and a bit for secure.
>   */
> -#define ARM_MMU_IDX_A 0x10 /* A profile */
> -#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
> -#define ARM_MMU_IDX_M 0x40 /* M profile */
> +#define ARM_MMU_IDX_S     0x04  /* Secure */
> +#define ARM_MMU_IDX_A     0x10  /* A profile */
> +#define ARM_MMU_IDX_M     0x20  /* M profile */
> +#define ARM_MMU_IDX_NOTLB 0x100 /* does not have a TLB */
>
> -/* meanings of the bits for M profile mmu idx values */
> -#define ARM_MMU_IDX_M_PRIV 0x1
> +/* Meanings of the bits for A profile mmu idx values */
> +#define ARM_MMU_IDX_A_PRIV   0x3
> +#define ARM_MMU_IDX_A_EL10   0x40
> +#define ARM_MMU_IDX_A_EL20   0x80
> +
> +/* Meanings of the bits for M profile mmu idx values */
> +#define ARM_MMU_IDX_M_PRIV   0x1
>  #define ARM_MMU_IDX_M_NEGPRI 0x2
> -#define ARM_MMU_IDX_M_S 0x4
>
> -#define ARM_MMU_IDX_TYPE_MASK (~0x7)
> +#define ARM_MMU_IDX_TYPE_MASK    (ARM_MMU_IDX_A | ARM_MMU_IDX_M)
>  #define ARM_MMU_IDX_COREIDX_MASK 0x7
>
>  typedef enum ARMMMUIdx {
> -    ARMMMUIdx_S12NSE0 = 0 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_S12NSE1 = 1 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_S1E2 = 2 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_S1E3 = 3 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_S1SE0 = 4 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_S1SE1 = 5 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_S2NS = 6 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E0 = 0 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E1 = 1 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E2 = 2 | ARM_MMU_IDX_A,
> +
> +    /*
> +     * While Stage2 is used by A profile, and uses a TLB, it is only
> +     * used for page table walks and is not a valid as an arm_mmu_idx().
> +     * Overlap it on the non-existant non-secure el3 slot.
> +     */
> +    ARMMMUIdx_Stage2 = 3,
> +
> +    ARMMMUIdx_SE0 = 0 | ARM_MMU_IDX_S | ARM_MMU_IDX_A,
> +    ARMMMUIdx_SE1 = 1 | ARM_MMU_IDX_S | ARM_MMU_IDX_A,
> +    ARMMMUIdx_SE2 = 2 | ARM_MMU_IDX_S | ARM_MMU_IDX_A,
> +    ARMMMUIdx_SE3 = 3 | ARM_MMU_IDX_S | ARM_MMU_IDX_A,
> +
>      ARMMMUIdx_MUser = 0 | ARM_MMU_IDX_M,
>      ARMMMUIdx_MPriv = 1 | ARM_MMU_IDX_M,
>      ARMMMUIdx_MUserNegPri = 2 | ARM_MMU_IDX_M,
>      ARMMMUIdx_MPrivNegPri = 3 | ARM_MMU_IDX_M,
> -    ARMMMUIdx_MSUser = 4 | ARM_MMU_IDX_M,
> -    ARMMMUIdx_MSPriv = 5 | ARM_MMU_IDX_M,
> -    ARMMMUIdx_MSUserNegPri = 6 | ARM_MMU_IDX_M,
> -    ARMMMUIdx_MSPrivNegPri = 7 | ARM_MMU_IDX_M,
> -    /* Indexes below here don't have TLBs and are used only for AT system
> -     * instructions or for the first stage of an S12 page table walk.
> -     */
> -    ARMMMUIdx_S1NSE0 = 0 | ARM_MMU_IDX_NOTLB,
> -    ARMMMUIdx_S1NSE1 = 1 | ARM_MMU_IDX_NOTLB,
> +    ARMMMUIdx_MSUser = 0 | ARM_MMU_IDX_S | ARM_MMU_IDX_M,
> +    ARMMMUIdx_MSPriv = 1 | ARM_MMU_IDX_S | ARM_MMU_IDX_M,
> +    ARMMMUIdx_MSUserNegPri = 2 | ARM_MMU_IDX_S | ARM_MMU_IDX_M,
> +    ARMMMUIdx_MSPrivNegPri = 3 | ARM_MMU_IDX_S | ARM_MMU_IDX_M,
> +
> +    /* Indicies that map onto the same core mmu_idx.  */
> +    ARMMMUIdx_EL10_0 = ARMMMUIdx_E0 | ARM_MMU_IDX_A_EL10,
> +    ARMMMUIdx_EL10_1 = ARMMMUIdx_E1 | ARM_MMU_IDX_A_EL10,
> +    ARMMMUIdx_EL20_0 = ARMMMUIdx_E0 | ARM_MMU_IDX_A_EL20,
> +    ARMMMUIdx_EL20_2 = ARMMMUIdx_E2 | ARM_MMU_IDX_A_EL20,
> +
> +    /* Indicies that are only used only for AT system or Stage1 walk.  */
> +    ARMMMUIdx_Stage1_E0 = ARMMMUIdx_E0 | ARM_MMU_IDX_NOTLB,
> +    ARMMMUIdx_Stage1_E1 = ARMMMUIdx_E1 | ARM_MMU_IDX_NOTLB,
>  } ARMMMUIdx;
>
> -/* Bit macros for the core-mmu-index values for each index,
> +/*
> + * Bit macros for the core-mmu-index values for each index,
>   * for use when calling tlb_flush_by_mmuidx() and friends.
>   */
> +#define TO_CORE_BIT(NAME) \
> +    ARMMMUIdxBit_##NAME = 1 << (ARMMMUIdx_##NAME & ARM_MMU_IDX_COREIDX_MASK)
> +
>  typedef enum ARMMMUIdxBit {
> -    ARMMMUIdxBit_S12NSE0 = 1 << 0,
> -    ARMMMUIdxBit_S12NSE1 = 1 << 1,
> -    ARMMMUIdxBit_S1E2 = 1 << 2,
> -    ARMMMUIdxBit_S1E3 = 1 << 3,
> -    ARMMMUIdxBit_S1SE0 = 1 << 4,
> -    ARMMMUIdxBit_S1SE1 = 1 << 5,
> -    ARMMMUIdxBit_S2NS = 1 << 6,
> -    ARMMMUIdxBit_MUser = 1 << 0,
> -    ARMMMUIdxBit_MPriv = 1 << 1,
> -    ARMMMUIdxBit_MUserNegPri = 1 << 2,
> -    ARMMMUIdxBit_MPrivNegPri = 1 << 3,
> -    ARMMMUIdxBit_MSUser = 1 << 4,
> -    ARMMMUIdxBit_MSPriv = 1 << 5,
> -    ARMMMUIdxBit_MSUserNegPri = 1 << 6,
> -    ARMMMUIdxBit_MSPrivNegPri = 1 << 7,
> +    TO_CORE_BIT(E0),
> +    TO_CORE_BIT(E1),
> +    TO_CORE_BIT(E2),
> +    TO_CORE_BIT(Stage2),
> +    TO_CORE_BIT(SE0),
> +    TO_CORE_BIT(SE1),
> +    TO_CORE_BIT(SE2),
> +    TO_CORE_BIT(SE3),
> +    TO_CORE_BIT(EL10_0),
> +    TO_CORE_BIT(EL10_1),
> +    TO_CORE_BIT(EL20_0),
> +    TO_CORE_BIT(EL20_2),
> +
> +    TO_CORE_BIT(MUser),
> +    TO_CORE_BIT(MPriv),
> +    TO_CORE_BIT(MUserNegPri),
> +    TO_CORE_BIT(MPrivNegPri),
> +    TO_CORE_BIT(MSUser),
> +    TO_CORE_BIT(MSPriv),
> +    TO_CORE_BIT(MSUserNegPri),
> +    TO_CORE_BIT(MSPrivNegPri),
>  } ARMMMUIdxBit;
>
> +#undef TO_CORE_BIT
> +
>  #define MMU_USER_IDX 0
>
>  static inline int arm_to_core_mmu_idx(ARMMMUIdx mmu_idx)
> @@ -2900,44 +2942,6 @@ static inline int arm_to_core_mmu_idx(ARMMMUIdx mmu_idx)
>      return mmu_idx & ARM_MMU_IDX_COREIDX_MASK;
>  }
>
> -static inline ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
> -{
> -    if (arm_feature(env, ARM_FEATURE_M)) {
> -        return mmu_idx | ARM_MMU_IDX_M;
> -    } else {
> -        return mmu_idx | ARM_MMU_IDX_A;
> -    }
> -}
> -
> -/* Return the exception level we're running at if this is our mmu_idx */
> -static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
> -{
> -    switch (mmu_idx & ARM_MMU_IDX_TYPE_MASK) {
> -    case ARM_MMU_IDX_A:
> -        return mmu_idx & 3;
> -    case ARM_MMU_IDX_M:
> -        return mmu_idx & ARM_MMU_IDX_M_PRIV;
> -    default:
> -        g_assert_not_reached();
> -    }
> -}
> -
> -/*
> - * Return the MMU index for a v7M CPU with all relevant information
> - * manually specified.
> - */
> -ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
> -                              bool secstate, bool priv, bool negpri);
> -
> -/* Return the MMU index for a v7M CPU in the specified security and
> - * privilege state.
> - */
> -ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
> -                                                bool secstate, bool priv);
> -
> -/* Return the MMU index for a v7M CPU in the specified security state */
> -ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
> -
>  /**
>   * cpu_mmu_index:
>   * @env: The cpu environment
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 232d963875..047cbfd1d7 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -769,6 +769,26 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>                        MMUAccessType access_type, int mmu_idx,
>                        bool probe, uintptr_t retaddr);
>
> +ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx);
> +int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx);
> +
> +/*
> + * Return the MMU index for a v7M CPU with all relevant information
> + * manually specified.
> + */
> +ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
> +                              bool secstate, bool priv, bool negpri);
> +
> +/*
> + * Return the MMU index for a v7M CPU in the specified security and
> + * privilege state.
> + */
> +ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
> +                                                bool secstate, bool priv);
> +
> +/* Return the MMU index for a v7M CPU in the specified security state */
> +ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
> +
>  /* Return true if the stage 1 translation regime is using LPAE format page
>   * tables */
>  bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx);
> @@ -807,29 +827,7 @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
>  /* Return true if this address translation regime is secure */
>  static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
>  {
> -    switch (mmu_idx) {
> -    case ARMMMUIdx_S12NSE0:
> -    case ARMMMUIdx_S12NSE1:
> -    case ARMMMUIdx_S1NSE0:
> -    case ARMMMUIdx_S1NSE1:
> -    case ARMMMUIdx_S1E2:
> -    case ARMMMUIdx_S2NS:
> -    case ARMMMUIdx_MPrivNegPri:
> -    case ARMMMUIdx_MUserNegPri:
> -    case ARMMMUIdx_MPriv:
> -    case ARMMMUIdx_MUser:
> -        return false;
> -    case ARMMMUIdx_S1E3:
> -    case ARMMMUIdx_S1SE0:
> -    case ARMMMUIdx_S1SE1:
> -    case ARMMMUIdx_MSPrivNegPri:
> -    case ARMMMUIdx_MSUserNegPri:
> -    case ARMMMUIdx_MSPriv:
> -    case ARMMMUIdx_MSUser:
> -        return true;
> -    default:
> -        g_assert_not_reached();
> -    }
> +    return (mmu_idx & ARM_MMU_IDX_S) != 0;
>  }
>
>  /* Return the FSR value for a debug exception (watchpoint, hardware
> @@ -966,7 +964,7 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env);
>  #ifdef CONFIG_USER_ONLY
>  static inline ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
>  {
> -    return ARMMMUIdx_S1NSE0;
> +    return ARMMMUIdx_EL10_0;
>  }
>  #else
>  ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
> diff --git a/target/arm/translate.h b/target/arm/translate.h
> index a20f6e2056..715fa08e3b 100644
> --- a/target/arm/translate.h
> +++ b/target/arm/translate.h
> @@ -122,7 +122,7 @@ static inline int default_exception_el(DisasContext *s)
>       * exceptions can only be routed to ELs above 1, so we target the higher of
>       * 1 or the current EL.
>       */
> -    return (s->mmu_idx == ARMMMUIdx_S1SE0 && s->secure_routed_to_el3)
> +    return (s->mmu_idx == ARMMMUIdx_SE0 && s->secure_routed_to_el3)
>              ? 3 : MAX(1, s->current_el);
>  }
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 2b95fc763f..240a6ed168 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -566,10 +566,10 @@ static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
>          switch (ri->secure) {
>          case ARM_CP_SECSTATE_S:
> -            idxmask = ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
> +            idxmask = ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0;
>              break;
>          case ARM_CP_SECSTATE_NS:
> -            idxmask = ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
> +            idxmask = ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
>              break;
>          default:
>              g_assert_not_reached();
> @@ -682,9 +682,9 @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      CPUState *cs = env_cpu(env);
>
>      tlb_flush_by_mmuidx(cs,
> -                        ARMMMUIdxBit_S12NSE1 |
> -                        ARMMMUIdxBit_S12NSE0 |
> -                        ARMMMUIdxBit_S2NS);
> +                        ARMMMUIdxBit_E1 |
> +                        ARMMMUIdxBit_E0 |
> +                        ARMMMUIdxBit_Stage2);
>  }
>
>  static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -693,9 +693,9 @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      CPUState *cs = env_cpu(env);
>
>      tlb_flush_by_mmuidx_all_cpus_synced(cs,
> -                                        ARMMMUIdxBit_S12NSE1 |
> -                                        ARMMMUIdxBit_S12NSE0 |
> -                                        ARMMMUIdxBit_S2NS);
> +                                        ARMMMUIdxBit_E1 |
> +                                        ARMMMUIdxBit_E0 |
> +                                        ARMMMUIdxBit_Stage2);
>  }
>
>  static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -716,7 +716,7 @@ static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
>      pageaddr = sextract64(value << 12, 0, 40);
>
> -    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S2NS);
> +    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
>  }
>
>  static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -731,8 +731,7 @@ static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
>      pageaddr = sextract64(value << 12, 0, 40);
>
> -    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
> -                                             ARMMMUIdxBit_S2NS);
> +    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2);
>  }
>
>  static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -740,7 +739,7 @@ static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  {
>      CPUState *cs = env_cpu(env);
>
> -    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_S1E2);
> +    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
>  }
>
>  static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -748,7 +747,7 @@ static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  {
>      CPUState *cs = env_cpu(env);
>
> -    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E2);
> +    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
>  }
>
>  static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -757,7 +756,7 @@ static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      CPUState *cs = env_cpu(env);
>      uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
>
> -    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S1E2);
> +    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
>  }
>
>  static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -766,8 +765,7 @@ static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      CPUState *cs = env_cpu(env);
>      uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
>
> -    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
> -                                             ARMMMUIdxBit_S1E2);
> +    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_E2);
>  }
>
>  static const ARMCPRegInfo cp_reginfo[] = {
> @@ -3047,7 +3045,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
>          format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
>
>          if (arm_feature(env, ARM_FEATURE_EL2)) {
> -            if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
> +            if (mmu_idx == ARMMMUIdx_EL10_0 || mmu_idx == ARMMMUIdx_EL10_1) {
>                  format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
>              } else {
>                  format64 |= arm_current_el(env) == 2;
> @@ -3116,13 +3114,13 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
>          /* stage 1 current state PL1: ATS1CPR, ATS1CPW */
>          switch (el) {
>          case 3:
> -            mmu_idx = ARMMMUIdx_S1E3;
> +            mmu_idx = ARMMMUIdx_SE3;
>              break;
>          case 2:
> -            mmu_idx = ARMMMUIdx_S1NSE1;
> +            mmu_idx = ARMMMUIdx_Stage1_E1;
>              break;
>          case 1:
> -            mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S1NSE1;
> +            mmu_idx = secure ? ARMMMUIdx_SE1 : ARMMMUIdx_Stage1_E1;
>              break;
>          default:
>              g_assert_not_reached();
> @@ -3132,13 +3130,13 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
>          /* stage 1 current state PL0: ATS1CUR, ATS1CUW */
>          switch (el) {
>          case 3:
> -            mmu_idx = ARMMMUIdx_S1SE0;
> +            mmu_idx = ARMMMUIdx_SE0;
>              break;
>          case 2:
> -            mmu_idx = ARMMMUIdx_S1NSE0;
> +            mmu_idx = ARMMMUIdx_Stage1_E0;
>              break;
>          case 1:
> -            mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0;
> +            mmu_idx = secure ? ARMMMUIdx_SE0 : ARMMMUIdx_Stage1_E0;
>              break;
>          default:
>              g_assert_not_reached();
> @@ -3146,11 +3144,11 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
>          break;
>      case 4:
>          /* stage 1+2 NonSecure PL1: ATS12NSOPR, ATS12NSOPW */
> -        mmu_idx = ARMMMUIdx_S12NSE1;
> +        mmu_idx = ARMMMUIdx_EL10_1;
>          break;
>      case 6:
>          /* stage 1+2 NonSecure PL0: ATS12NSOUR, ATS12NSOUW */
> -        mmu_idx = ARMMMUIdx_S12NSE0;
> +        mmu_idx = ARMMMUIdx_EL10_0;
>          break;
>      default:
>          g_assert_not_reached();
> @@ -3167,7 +3165,7 @@ static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
>      uint64_t par64;
>
> -    par64 = do_ats_write(env, value, access_type, ARMMMUIdx_S1E2);
> +    par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2);
>
>      A32_BANKED_CURRENT_REG_SET(env, par, par64);
>  }
> @@ -3192,26 +3190,26 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
>      case 0:
>          switch (ri->opc1) {
>          case 0: /* AT S1E1R, AT S1E1W */
> -            mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S1NSE1;
> +            mmu_idx = secure ? ARMMMUIdx_SE1 : ARMMMUIdx_Stage1_E1;
>              break;
>          case 4: /* AT S1E2R, AT S1E2W */
> -            mmu_idx = ARMMMUIdx_S1E2;
> +            mmu_idx = ARMMMUIdx_E2;
>              break;
>          case 6: /* AT S1E3R, AT S1E3W */
> -            mmu_idx = ARMMMUIdx_S1E3;
> +            mmu_idx = ARMMMUIdx_SE3;
>              break;
>          default:
>              g_assert_not_reached();
>          }
>          break;
>      case 2: /* AT S1E0R, AT S1E0W */
> -        mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0;
> +        mmu_idx = secure ? ARMMMUIdx_SE0 : ARMMMUIdx_Stage1_E0;
>          break;
>      case 4: /* AT S12E1R, AT S12E1W */
> -        mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S12NSE1;
> +        mmu_idx = secure ? ARMMMUIdx_SE1 : ARMMMUIdx_EL10_1;
>          break;
>      case 6: /* AT S12E0R, AT S12E0W */
> -        mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S12NSE0;
> +        mmu_idx = secure ? ARMMMUIdx_SE0 : ARMMMUIdx_EL10_0;
>          break;
>      default:
>          g_assert_not_reached();
> @@ -3422,15 +3420,15 @@ static void update_lpae_el1_asid(CPUARMState *env, int secure)
>          ttbr0 = env->cp15.ttbr0_s;
>          ttbr1 = env->cp15.ttbr1_s;
>          ttcr = env->cp15.tcr_el[3].raw_tcr;
> -        /* Note that cp15.ttbr0_s == cp15.ttbr0_el[3], so S1E3 is affected.  */
> +        /* Note that cp15.ttbr0_s == cp15.ttbr0_el[3], so SE3 is affected.  */
>          /* ??? Secure EL3 really using the ASID field?  Doesn't make sense.  */
> -        idxmask = ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0 | ARMMMUIdxBit_S1E3;
> +        idxmask = ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0 | ARMMMUIdxBit_SE3;
>          break;
>      case ARM_CP_SECSTATE_NS:
>          ttbr0 = env->cp15.ttbr0_ns;
>          ttbr1 = env->cp15.ttbr1_ns;
>          ttcr = env->cp15.tcr_el[1].raw_tcr;
> -        idxmask = ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
> +        idxmask = ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
>          break;
>      default:
>          g_assert_not_reached();
> @@ -3542,11 +3540,11 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      vmid = extract64(value, 48, 8);
>
>      /*
> -     * A change in VMID to the stage2 page table (S2NS) invalidates
> -     * the combined stage 1&2 tlbs (S12NSE1 and S12NSE0).
> +     * A change in VMID to the stage2 page table (Stage2) invalidates
> +     * the combined stage 1&2 tlbs (EL10_1 and EL10_0).
>       */
> -    tlb_set_asid_for_mmuidx(cs, vmid, ARMMMUIdxBit_S2NS,
> -                            ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0);
> +    tlb_set_asid_for_mmuidx(cs, vmid, ARMMMUIdxBit_Stage2,
> +                            ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0);
>  }
>
>  static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
> @@ -3902,9 +3900,9 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
>  static int vae1_tlbmask(CPUARMState *env)
>  {
>      if (arm_is_secure_below_el3(env)) {
> -        return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
> +        return ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0;
>      } else {
> -        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
> +        return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
>      }
>  }
>
> @@ -3938,11 +3936,11 @@ static int vmalle1_tlbmask(CPUARMState *env)
>       * stage 1 translations.
>       */
>      if (arm_is_secure_below_el3(env)) {
> -        return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
> +        return ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0;
>      } else if (arm_feature(env, ARM_FEATURE_EL2)) {
> -        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0 | ARMMMUIdxBit_S2NS;
> +        return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0 | ARMMMUIdxBit_Stage2;
>      } else {
> -        return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
> +        return ARMMMUIdxBit_E1 | ARMMMUIdxBit_E0;
>      }
>  }
>
> @@ -3961,7 +3959,7 @@ static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      ARMCPU *cpu = env_archcpu(env);
>      CPUState *cs = CPU(cpu);
>
> -    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_S1E2);
> +    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
>  }
>
>  static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -3970,7 +3968,7 @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      ARMCPU *cpu = env_archcpu(env);
>      CPUState *cs = CPU(cpu);
>
> -    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_S1E3);
> +    tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_SE3);
>  }
>
>  static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -3987,7 +3985,7 @@ static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  {
>      CPUState *cs = env_cpu(env);
>
> -    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E2);
> +    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
>  }
>
>  static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -3995,7 +3993,7 @@ static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  {
>      CPUState *cs = env_cpu(env);
>
> -    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E3);
> +    tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_SE3);
>  }
>
>  static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4009,7 +4007,7 @@ static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      CPUState *cs = CPU(cpu);
>      uint64_t pageaddr = sextract64(value << 12, 0, 56);
>
> -    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S1E2);
> +    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
>  }
>
>  static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4023,7 +4021,7 @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      CPUState *cs = CPU(cpu);
>      uint64_t pageaddr = sextract64(value << 12, 0, 56);
>
> -    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S1E3);
> +    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_SE3);
>  }
>
>  static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4061,8 +4059,7 @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      CPUState *cs = env_cpu(env);
>      uint64_t pageaddr = sextract64(value << 12, 0, 56);
>
> -    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
> -                                             ARMMMUIdxBit_S1E2);
> +    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_E2);
>  }
>
>  static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4071,8 +4068,7 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      CPUState *cs = env_cpu(env);
>      uint64_t pageaddr = sextract64(value << 12, 0, 56);
>
> -    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
> -                                             ARMMMUIdxBit_S1E3);
> +    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_SE3);
>  }
>
>  static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4094,7 +4090,7 @@ static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
>      pageaddr = sextract64(value << 12, 0, 48);
>
> -    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S2NS);
> +    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
>  }
>
>  static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4109,8 +4105,7 @@ static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
>      pageaddr = sextract64(value << 12, 0, 48);
>
> -    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
> -                                             ARMMMUIdxBit_S2NS);
> +    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2);
>  }
>
>  static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4378,7 +4373,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
>      { .name = "AT_S12E0W", .state = ARM_CP_STATE_AA64,
>        .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 7,
>        .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
> -    /* AT S1E2* are elsewhere as they UNDEF from EL3 if EL2 is not present */
> +    /* AT E2* are elsewhere as they UNDEF from EL3 if EL2 is not present */
>      { .name = "AT_S1E3R", .state = ARM_CP_STATE_AA64,
>        .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 0,
>        .access = PL3_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
> @@ -8685,19 +8680,23 @@ void arm_cpu_do_interrupt(CPUState *cs)
>  #endif /* !CONFIG_USER_ONLY */
>
>  /* Return the exception level which controls this address translation regime */
> -static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
> +static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
>  {
>      switch (mmu_idx) {
> -    case ARMMMUIdx_S2NS:
> -    case ARMMMUIdx_S1E2:
> +    case ARMMMUIdx_EL20_0:
> +    case ARMMMUIdx_EL20_2:
> +    case ARMMMUIdx_Stage2:
> +    case ARMMMUIdx_E2:
>          return 2;
> -    case ARMMMUIdx_S1E3:
> +    case ARMMMUIdx_SE3:
>          return 3;
> -    case ARMMMUIdx_S1SE0:
> +    case ARMMMUIdx_SE0:
>          return arm_el_is_aa64(env, 3) ? 1 : 3;
> -    case ARMMMUIdx_S1SE1:
> -    case ARMMMUIdx_S1NSE0:
> -    case ARMMMUIdx_S1NSE1:
> +    case ARMMMUIdx_SE1:
> +    case ARMMMUIdx_Stage1_E0:
> +    case ARMMMUIdx_Stage1_E1:
> +    case ARMMMUIdx_EL10_0:
> +    case ARMMMUIdx_EL10_1:
>      case ARMMMUIdx_MPrivNegPri:
>      case ARMMMUIdx_MUserNegPri:
>      case ARMMMUIdx_MPriv:
> @@ -8742,7 +8741,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
>          }
>      }
>
> -    if (mmu_idx == ARMMMUIdx_S2NS) {
> +    if (mmu_idx == ARMMMUIdx_Stage2) {
>          /* HCR.DC means HCR.VM behaves as 1 */
>          return (env->cp15.hcr_el2 & (HCR_DC | HCR_VM)) == 0;
>      }
> @@ -8755,7 +8754,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
>      }
>
>      if ((env->cp15.hcr_el2 & HCR_DC) &&
> -        (mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1)) {
> +        (mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1)) {
>          /* HCR.DC means SCTLR_EL1.M behaves as 0 */
>          return true;
>      }
> @@ -8773,7 +8772,7 @@ static inline bool regime_translation_big_endian(CPUARMState *env,
>  static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
>                                     int ttbrn)
>  {
> -    if (mmu_idx == ARMMMUIdx_S2NS) {
> +    if (mmu_idx == ARMMMUIdx_Stage2) {
>          return env->cp15.vttbr_el2;
>      }
>      if (ttbrn == 0) {
> @@ -8788,7 +8787,7 @@ static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
>  /* Return the TCR controlling this translation regime */
>  static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
>  {
> -    if (mmu_idx == ARMMMUIdx_S2NS) {
> +    if (mmu_idx == ARMMMUIdx_Stage2) {
>          return &env->cp15.vtcr_el2;
>      }
>      return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
> @@ -8799,8 +8798,8 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
>   */
>  static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
>  {
> -    if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
> -        mmu_idx += (ARMMMUIdx_S1NSE0 - ARMMMUIdx_S12NSE0);
> +    if (mmu_idx == ARMMMUIdx_EL10_0 || mmu_idx == ARMMMUIdx_EL10_1) {
> +        mmu_idx += (ARMMMUIdx_Stage1_E0 - ARMMMUIdx_EL10_0);
>      }
>      return mmu_idx;
>  }
> @@ -8834,8 +8833,8 @@ bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
>  static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
>  {
>      switch (mmu_idx) {
> -    case ARMMMUIdx_S1SE0:
> -    case ARMMMUIdx_S1NSE0:
> +    case ARMMMUIdx_SE0:
> +    case ARMMMUIdx_Stage1_E0:
>      case ARMMMUIdx_MUser:
>      case ARMMMUIdx_MSUser:
>      case ARMMMUIdx_MUserNegPri:
> @@ -8843,8 +8842,8 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
>          return true;
>      default:
>          return false;
> -    case ARMMMUIdx_S12NSE0:
> -    case ARMMMUIdx_S12NSE1:
> +    case ARMMMUIdx_EL10_0:
> +    case ARMMMUIdx_EL10_1:
>          g_assert_not_reached();
>      }
>  }
> @@ -8975,7 +8974,7 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
>      bool have_wxn;
>      int wxn = 0;
>
> -    assert(mmu_idx != ARMMMUIdx_S2NS);
> +    assert(mmu_idx != ARMMMUIdx_Stage2);
>
>      user_rw = simple_ap_to_rw_prot_is_user(ap, true);
>      if (is_user) {
> @@ -9066,8 +9065,8 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
>                                 hwaddr addr, MemTxAttrs txattrs,
>                                 ARMMMUFaultInfo *fi)
>  {
> -    if ((mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1) &&
> -        !regime_translation_disabled(env, ARMMMUIdx_S2NS)) {
> +    if ((mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1) &&
> +        !regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
>          target_ulong s2size;
>          hwaddr s2pa;
>          int s2prot;
> @@ -9084,7 +9083,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
>              pcacheattrs = &cacheattrs;
>          }
>
> -        ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
> +        ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_Stage2, &s2pa,
>                                   &txattrs, &s2prot, &s2size, fi, pcacheattrs);
>          if (ret) {
>              assert(fi->type != ARMFault_None);
> @@ -9556,7 +9555,7 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
>          tsz = extract32(tcr, 0, 6);
>          using64k = extract32(tcr, 14, 1);
>          using16k = extract32(tcr, 15, 1);
> -        if (mmu_idx == ARMMMUIdx_S2NS) {
> +        if (mmu_idx == ARMMMUIdx_Stage2) {
>              /* VTCR_EL2 */
>              tbi = tbid = hpd = false;
>          } else {
> @@ -9617,7 +9616,7 @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
>      int select, tsz;
>      bool epd, hpd;
>
> -    if (mmu_idx == ARMMMUIdx_S2NS) {
> +    if (mmu_idx == ARMMMUIdx_Stage2) {
>          /* VTCR */
>          bool sext = extract32(tcr, 4, 1);
>          bool sign = extract32(tcr, 3, 1);
> @@ -9719,7 +9718,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>          level = 1;
>          /* There is no TTBR1 for EL2 */
>          ttbr1_valid = (el != 2);
> -        addrsize = (mmu_idx == ARMMMUIdx_S2NS ? 40 : 32);
> +        addrsize = (mmu_idx == ARMMMUIdx_Stage2 ? 40 : 32);
>          inputsize = addrsize - param.tsz;
>      }
>
> @@ -9770,7 +9769,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>          goto do_fault;
>      }
>
> -    if (mmu_idx != ARMMMUIdx_S2NS) {
> +    if (mmu_idx != ARMMMUIdx_Stage2) {
>          /* The starting level depends on the virtual address size (which can
>           * be up to 48 bits) and the translation granule size. It indicates
>           * the number of strides (stride bits at a time) needed to
> @@ -9870,7 +9869,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>          attrs = extract64(descriptor, 2, 10)
>              | (extract64(descriptor, 52, 12) << 10);
>
> -        if (mmu_idx == ARMMMUIdx_S2NS) {
> +        if (mmu_idx == ARMMMUIdx_Stage2) {
>              /* Stage 2 table descriptors do not include any attribute fields */
>              break;
>          }
> @@ -9901,7 +9900,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>      ap = extract32(attrs, 4, 2);
>      xn = extract32(attrs, 12, 1);
>
> -    if (mmu_idx == ARMMMUIdx_S2NS) {
> +    if (mmu_idx == ARMMMUIdx_Stage2) {
>          ns = true;
>          *prot = get_S2prot(env, ap, xn);
>      } else {
> @@ -9928,7 +9927,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>      }
>
>      if (cacheattrs != NULL) {
> -        if (mmu_idx == ARMMMUIdx_S2NS) {
> +        if (mmu_idx == ARMMMUIdx_Stage2) {
>              cacheattrs->attrs = convert_stage2_attrs(env,
>                                                       extract32(attrs, 0, 4));
>          } else {
> @@ -9949,7 +9948,7 @@ do_fault:
>      fi->type = fault_type;
>      fi->level = level;
>      /* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2.  */
> -    fi->stage2 = fi->s1ptw || (mmu_idx == ARMMMUIdx_S2NS);
> +    fi->stage2 = fi->s1ptw || (mmu_idx == ARMMMUIdx_Stage2);
>      return true;
>  }
>
> @@ -10748,7 +10747,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
>                     target_ulong *page_size,
>                     ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
>  {
> -    if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
> +    if (mmu_idx == ARMMMUIdx_EL10_0 || mmu_idx == ARMMMUIdx_EL10_1) {
>          /* Call ourselves recursively to do the stage 1 and then stage 2
>           * translations.
>           */
> @@ -10763,13 +10762,13 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
>                                  prot, page_size, fi, cacheattrs);
>
>              /* If S1 fails or S2 is disabled, return early.  */
> -            if (ret || regime_translation_disabled(env, ARMMMUIdx_S2NS)) {
> +            if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
>                  *phys_ptr = ipa;
>                  return ret;
>              }
>
>              /* S1 is done. Now do S2 translation.  */
> -            ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_S2NS,
> +            ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_Stage2,
>                                       phys_ptr, attrs, &s2_prot,
>                                       page_size, fi,
>                                       cacheattrs != NULL ? &cacheattrs2 : NULL);
> @@ -10811,7 +10810,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
>      /* Fast Context Switch Extension. This doesn't exist at all in v8.
>       * In v7 and earlier it affects all stage 1 translations.
>       */
> -    if (address < 0x02000000 && mmu_idx != ARMMMUIdx_S2NS
> +    if (address < 0x02000000 && mmu_idx != ARMMMUIdx_Stage2
>          && !arm_feature(env, ARM_FEATURE_V8)) {
>          if (regime_el(env, mmu_idx) == 3) {
>              address += env->cp15.fcseidr_s;
> @@ -11260,6 +11259,41 @@ int fp_exception_el(CPUARMState *env, int cur_el)
>      return 0;
>  }
>
> +ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
> +{
> +    if (arm_feature(env, ARM_FEATURE_M)) {
> +        return mmu_idx | ARM_MMU_IDX_M;
> +    }
> +
> +    mmu_idx |= ARM_MMU_IDX_A;
> +    switch (mmu_idx) {
> +    case ARMMMUIdx_E0:
> +        return ARMMMUIdx_EL10_0;
> +    case ARMMMUIdx_E1:
> +        return ARMMMUIdx_EL10_1;
> +    case ARMMMUIdx_E2:
> +    case ARMMMUIdx_SE0:
> +    case ARMMMUIdx_SE1:
> +    case ARMMMUIdx_SE3:
> +        return mmu_idx;
> +    default:
> +        g_assert_not_reached();
> +    }
> +}
> +
> +/* Return the exception level we're running at if this is our mmu_idx */
> +int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
> +{
> +    switch (mmu_idx & ARM_MMU_IDX_TYPE_MASK) {
> +    case ARM_MMU_IDX_A:
> +        return mmu_idx & ARM_MMU_IDX_A_PRIV;
> +    case ARM_MMU_IDX_M:
> +        return mmu_idx & ARM_MMU_IDX_M_PRIV;
> +    default:
> +        g_assert_not_reached();
> +    }
> +}
> +
>  #ifndef CONFIG_TCG
>  ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
>  {
> @@ -11276,10 +11310,21 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env)
>      }
>
>      el = arm_current_el(env);
> -    if (el < 2 && arm_is_secure_below_el3(env)) {
> -        return ARMMMUIdx_S1SE0 + el;
> -    } else {
> -        return ARMMMUIdx_S12NSE0 + el;
> +    switch (el) {
> +    case 0:
> +        /* TODO: ARMv8.1-VHE */
> +    case 1:
> +        return (arm_is_secure_below_el3(env)
> +                ? ARMMMUIdx_SE0 + el
> +                : ARMMMUIdx_EL10_0 + el);
> +    case 2:
> +        /* TODO: ARMv8.1-VHE */
> +        /* TODO: ARMv8.4-SecEL2 */
> +        return ARMMMUIdx_E2;
> +    case 3:
> +        return ARMMMUIdx_SE3;
> +    default:
> +        g_assert_not_reached();
>      }
>  }
>
> diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
> index 84609f446e..f745c0d067 100644
> --- a/target/arm/m_helper.c
> +++ b/target/arm/m_helper.c
> @@ -126,7 +126,7 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
>      hwaddr physaddr;
>      int prot;
>      ARMMMUFaultInfo fi = {};
> -    bool secure = mmu_idx & ARM_MMU_IDX_M_S;
> +    bool secure = mmu_idx & ARM_MMU_IDX_S;
>      int exc;
>      bool exc_secure;
>
> @@ -218,7 +218,7 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr,
>      hwaddr physaddr;
>      int prot;
>      ARMMMUFaultInfo fi = {};
> -    bool secure = mmu_idx & ARM_MMU_IDX_M_S;
> +    bool secure = mmu_idx & ARM_MMU_IDX_S;
>      int exc;
>      bool exc_secure;
>      uint32_t value;
> @@ -2669,7 +2669,7 @@ ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
>      }
>
>      if (secstate) {
> -        mmu_idx |= ARM_MMU_IDX_M_S;
> +        mmu_idx |= ARM_MMU_IDX_S;
>      }
>
>      return mmu_idx;
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index d3231477a2..a9e65fe347 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -113,13 +113,14 @@ static inline int get_a64_user_mem_index(DisasContext *s)
>      ARMMMUIdx useridx;
>
>      switch (s->mmu_idx) {
> -    case ARMMMUIdx_S12NSE1:
> -        useridx = ARMMMUIdx_S12NSE0;
> +    case ARMMMUIdx_EL10_1:
> +        /* FIXME: ARMv8.1-VHE */
> +        useridx = ARMMMUIdx_EL10_0;
>          break;
> -    case ARMMMUIdx_S1SE1:
> -        useridx = ARMMMUIdx_S1SE0;
> +    case ARMMMUIdx_SE1:
> +        useridx = ARMMMUIdx_SE0;
>          break;
> -    case ARMMMUIdx_S2NS:
> +    case ARMMMUIdx_Stage2:
>          g_assert_not_reached();
>      default:
>          useridx = s->mmu_idx;
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 7853462b21..0346088e75 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -152,14 +152,14 @@ static inline int get_a32_user_mem_index(DisasContext *s)
>       *  otherwise, access as if at PL0.
>       */
>      switch (s->mmu_idx) {
> -    case ARMMMUIdx_S1E2:        /* this one is UNPREDICTABLE */
> -    case ARMMMUIdx_S12NSE0:
> -    case ARMMMUIdx_S12NSE1:
> -        return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
> -    case ARMMMUIdx_S1E3:
> -    case ARMMMUIdx_S1SE0:
> -    case ARMMMUIdx_S1SE1:
> -        return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
> +    case ARMMMUIdx_E2:        /* this one is UNPREDICTABLE */
> +    case ARMMMUIdx_EL10_1:
> +    case ARMMMUIdx_EL10_0:
> +        return arm_to_core_mmu_idx(ARMMMUIdx_EL10_0);
> +    case ARMMMUIdx_SE3:
> +    case ARMMMUIdx_SE1:
> +    case ARMMMUIdx_SE0:
> +        return arm_to_core_mmu_idx(ARMMMUIdx_SE0);
>      case ARMMMUIdx_MUser:
>      case ARMMMUIdx_MPriv:
>          return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
> @@ -172,7 +172,6 @@ static inline int get_a32_user_mem_index(DisasContext *s)
>      case ARMMMUIdx_MSUserNegPri:
>      case ARMMMUIdx_MSPrivNegPri:
>          return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
> -    case ARMMMUIdx_S2NS:
>      default:
>          g_assert_not_reached();
>      }


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 16/24] target/arm: Add regime_has_2_ranges
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 16/24] target/arm: Add regime_has_2_ranges Richard Henderson
@ 2019-07-25 15:59   ` Alex Bennée
  2019-07-25 18:28     ` Richard Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Alex Bennée @ 2019-07-25 15:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

Can you elucidate what we mean by having 2 ranges?


> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/internals.h     | 16 ++++++++++++++++
>  target/arm/helper.c        | 22 +++++-----------------
>  target/arm/translate-a64.c |  3 +--
>  3 files changed, 22 insertions(+), 19 deletions(-)
>
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 047cbfd1d7..f653e0e7f5 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -824,6 +824,22 @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
>      }
>  }
>
> +/* Return true if this address translation regime has two ranges.  */
> +static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
> +{
> +    switch (mmu_idx) {
> +    case ARMMMUIdx_Stage1_E0:
> +    case ARMMMUIdx_Stage1_E1:
> +    case ARMMMUIdx_EL10_0:
> +    case ARMMMUIdx_EL10_1:
> +    case ARMMMUIdx_EL20_0:
> +    case ARMMMUIdx_EL20_2:
> +        return true;
> +    default:
> +        return false;
> +    }
> +}
> +
>  /* Return true if this address translation regime is secure */
>  static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
>  {
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 240a6ed168..2d5658f9e3 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -8999,15 +8999,8 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
>      }
>
>      if (is_aa64) {
> -        switch (regime_el(env, mmu_idx)) {
> -        case 1:
> -            if (!is_user) {
> -                xn = pxn || (user_rw & PAGE_WRITE);
> -            }
> -            break;
> -        case 2:
> -        case 3:
> -            break;
> +        if (regime_has_2_ranges(mmu_idx) && !is_user) {
> +            xn = pxn || (user_rw & PAGE_WRITE);
>          }
>      } else if (arm_feature(env, ARM_FEATURE_V7)) {
>          switch (regime_el(env, mmu_idx)) {
> @@ -9541,7 +9534,6 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
>                                          ARMMMUIdx mmu_idx)
>  {
>      uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
> -    uint32_t el = regime_el(env, mmu_idx);
>      bool tbi, tbid, epd, hpd, using16k, using64k;
>      int select, tsz;
>
> @@ -9551,7 +9543,7 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
>       */
>      select = extract64(va, 55, 1);
>
> -    if (el > 1) {
> +    if (!regime_has_2_ranges(mmu_idx)) {
>          tsz = extract32(tcr, 0, 6);
>          using64k = extract32(tcr, 14, 1);
>          using16k = extract32(tcr, 15, 1);
> @@ -9707,10 +9699,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>          param = aa64_va_parameters(env, address, mmu_idx,
>                                     access_type != MMU_INST_FETCH);
>          level = 0;
> -        /* If we are in 64-bit EL2 or EL3 then there is no TTBR1, so mark it
> -         * invalid.
> -         */
> -        ttbr1_valid = (el < 2);
> +        ttbr1_valid = regime_has_2_ranges(mmu_idx);
>          addrsize = 64 - 8 * param.tbi;
>          inputsize = 64 - param.tsz;
>      } else {
> @@ -11361,8 +11350,7 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>              ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
>              int tbii, tbid;
>
> -            /* FIXME: ARMv8.1-VHE S2 translation regime.  */
> -            if (regime_el(env, stage1) < 2) {
> +            if (regime_has_2_ranges(mmu_idx)) {
>                  ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
>                  tbid = (p1.tbi << 1) | p0.tbi;
>                  tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index a9e65fe347..5679349310 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -176,8 +176,7 @@ static void gen_top_byte_ignore(DisasContext *s, TCGv_i64 dst,
>      if (tbi == 0) {
>          /* Load unmodified address */
>          tcg_gen_mov_i64(dst, src);
> -    } else if (s->current_el >= 2) {
> -        /* FIXME: ARMv8.1-VHE S2 translation regime.  */
> +    } else if (!regime_has_2_ranges(s->mmu_idx)) {
>          /* Force tag byte to all zero */
>          tcg_gen_extract_i64(dst, src, 0, 56);
>      } else {


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 17/24] target/arm: Update arm_mmu_idx for VHE
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 17/24] target/arm: Update arm_mmu_idx for VHE Richard Henderson
@ 2019-07-25 16:01   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-25 16:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> This covers initial generation in arm_mmu_idx, and reconstruction
> in core_to_arm_mmu_idx.  As a conseqeuence, we also need a bit in
> TBFLAGS in order to make the latter reliable.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/cpu.h    |  2 ++
>  target/arm/helper.c | 42 +++++++++++++++++++++++++++++++-----------
>  2 files changed, 33 insertions(+), 11 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 4b537c4613..7310adfd9b 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -3158,6 +3158,8 @@ FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1)
>  /* Target EL if we take a floating-point-disabled exception */
>  FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2)
>  FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
> +/* For A profile only, if EL2 is AA64 and HCR_EL2.E2H is set.  */
> +FIELD(TBFLAG_ANY, E2H, 22, 1)
>
>  /* Bit usage when in AArch32 state: */
>  FIELD(TBFLAG_A32, THUMB, 0, 1)
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 2d5658f9e3..54c328b844 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -11250,21 +11250,29 @@ int fp_exception_el(CPUARMState *env, int cur_el)
>
>  ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
>  {
> +    bool e2h;
> +
>      if (arm_feature(env, ARM_FEATURE_M)) {
>          return mmu_idx | ARM_MMU_IDX_M;
>      }
>
>      mmu_idx |= ARM_MMU_IDX_A;
> +    if (mmu_idx & ARM_MMU_IDX_S) {
> +        return mmu_idx;
> +    }
> +
> +    e2h = (env->cp15.hcr_el2 & HCR_E2H) != 0;
> +    if (!arm_el_is_aa64(env, 2)) {
> +        e2h = false;
> +    }
> +
>      switch (mmu_idx) {
>      case ARMMMUIdx_E0:
> -        return ARMMMUIdx_EL10_0;
> +        return e2h ? ARMMMUIdx_EL20_0 : ARMMMUIdx_EL10_0;
>      case ARMMMUIdx_E1:
>          return ARMMMUIdx_EL10_1;
>      case ARMMMUIdx_E2:
> -    case ARMMMUIdx_SE0:
> -    case ARMMMUIdx_SE1:
> -    case ARMMMUIdx_SE3:
> -        return mmu_idx;
> +        return e2h ? ARMMMUIdx_EL20_2 : ARMMMUIdx_E2;
>      default:
>          g_assert_not_reached();
>      }
> @@ -11292,24 +11300,28 @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
>
>  ARMMMUIdx arm_mmu_idx(CPUARMState *env)
>  {
> +    bool e2h, sec;
>      int el;
>
>      if (arm_feature(env, ARM_FEATURE_M)) {
>          return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
>      }
>
> +    sec = arm_is_secure_below_el3(env);
> +    e2h = (env->cp15.hcr_el2 & HCR_E2H) != 0;
> +    if (!arm_el_is_aa64(env, 2)) {
> +        e2h = false;
> +    }
> +
>      el = arm_current_el(env);
>      switch (el) {
>      case 0:
> -        /* TODO: ARMv8.1-VHE */
> +        return sec ? ARMMMUIdx_SE0 : e2h ? ARMMMUIdx_EL20_0 : ARMMMUIdx_EL10_0;
>      case 1:
> -        return (arm_is_secure_below_el3(env)
> -                ? ARMMMUIdx_SE0 + el
> -                : ARMMMUIdx_EL10_0 + el);
> +        return sec ? ARMMMUIdx_SE1 : ARMMMUIdx_EL10_1;
>      case 2:
> -        /* TODO: ARMv8.1-VHE */
>          /* TODO: ARMv8.4-SecEL2 */
> -        return ARMMMUIdx_E2;
> +        return e2h ? ARMMMUIdx_EL20_2 : ARMMMUIdx_E2;
>      case 3:
>          return ARMMMUIdx_SE3;
>      default:
> @@ -11421,6 +11433,14 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>
>      flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
>
> +    /*
> +     * Include E2H in TBFLAGS so that core_to_arm_mmu_idx can
> +     * reliably determine E1&0 vs E2&0 regimes.
> +     */
> +    if (arm_el_is_aa64(env, 2) && (env->cp15.hcr_el2 & HCR_E2H)) {
> +        flags = FIELD_DP32(flags, TBFLAG_ANY, E2H, 1);
> +    }
> +
>      /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
>       * states defined in the ARM ARM for software singlestep:
>       *  SS_ACTIVE   PSTATE.SS   State


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 18/24] target/arm: Update arm_sctlr for VHE
  2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 18/24] target/arm: Update arm_sctlr " Richard Henderson
@ 2019-07-25 16:02   ` Alex Bennée
  0 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-25 16:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> Use this function in many more places in order to select
> the correct control.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/cpu.h          | 10 ++++++----
>  target/arm/arch_dump.c    |  2 +-
>  target/arm/helper-a64.c   |  2 +-
>  target/arm/helper.c       | 10 +++++-----
>  target/arm/pauth_helper.c |  9 +--------
>  5 files changed, 14 insertions(+), 19 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 7310adfd9b..7efbb488d9 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -3104,11 +3104,13 @@ static inline bool arm_sctlr_b(CPUARMState *env)
>  static inline uint64_t arm_sctlr(CPUARMState *env, int el)
>  {
>      if (el == 0) {
> -        /* FIXME: ARMv8.1-VHE S2 translation regime.  */
> -        return env->cp15.sctlr_el[1];
> -    } else {
> -        return env->cp15.sctlr_el[el];
> +        if (arm_el_is_aa64(env, 2) && (arm_hcr_el2_eff(env) & HCR_E2H)) {
> +            el = 2;
> +        } else {
> +            el = 1;
> +        }
>      }
> +    return env->cp15.sctlr_el[el];
>  }
>
>
> diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
> index 26a2c09868..5fbd008d8c 100644
> --- a/target/arm/arch_dump.c
> +++ b/target/arm/arch_dump.c
> @@ -320,7 +320,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
>       * dump a hypervisor that happens to be running an opposite-endian
>       * kernel.
>       */
> -    info->d_endian = (env->cp15.sctlr_el[1] & SCTLR_EE) != 0
> +    info->d_endian = (arm_sctlr(env, 1) & SCTLR_EE) != 0
>                       ? ELFDATA2MSB : ELFDATA2LSB;
>
>      return 0;
> diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
> index 060699b901..3bf1b731e7 100644
> --- a/target/arm/helper-a64.c
> +++ b/target/arm/helper-a64.c
> @@ -70,7 +70,7 @@ static void daif_check(CPUARMState *env, uint32_t op,
>                         uint32_t imm, uintptr_t ra)
>  {
>      /* DAIF update to PSTATE. This is OK from EL0 only if UMA is set.  */
> -    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
> +    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) {
>          raise_exception_ra(env, EXCP_UDEF,
>                             syn_aa64_sysregtrap(0, extract32(op, 0, 3),
>                                                 extract32(op, 3, 3), 4,
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 54c328b844..db13a8f9c0 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3868,7 +3868,7 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri,
>                                         bool isread)
>  {
> -    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
> +    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) {
>          return CP_ACCESS_TRAP;
>      }
>      return CP_ACCESS_OK;
> @@ -3887,7 +3887,7 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
>      /* Cache invalidate/clean: NOP, but EL0 must UNDEF unless
>       * SCTLR_EL1.UCI is set.
>       */
> -    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCI)) {
> +    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UCI)) {
>          return CP_ACCESS_TRAP;
>      }
>      return CP_ACCESS_OK;
> @@ -4114,7 +4114,7 @@ static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
>      /* We don't implement EL2, so the only control on DC ZVA is the
>       * bit in the SCTLR which can prohibit access for EL0.
>       */
> -    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_DZE)) {
> +    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_DZE)) {
>          return CP_ACCESS_TRAP;
>      }
>      return CP_ACCESS_OK;
> @@ -5344,7 +5344,7 @@ static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
>      /* Only accessible in EL0 if SCTLR.UCT is set (and only in AArch64,
>       * but the AArch32 CTR has its own reginfo struct)
>       */
> -    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
> +    if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UCT)) {
>          return CP_ACCESS_TRAP;
>      }
>      return CP_ACCESS_OK;
> @@ -8161,7 +8161,7 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
>      env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
>      /* Set new mode endianness */
>      env->uncached_cpsr &= ~CPSR_E;
> -    if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
> +    if (arm_sctlr(env, arm_current_el(env)) & SCTLR_EE) {
>          env->uncached_cpsr |= CPSR_E;
>      }
>      /* J and IL must always be cleared for exception entry */
> diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c
> index d3194f2043..42c9141bb7 100644
> --- a/target/arm/pauth_helper.c
> +++ b/target/arm/pauth_helper.c
> @@ -386,14 +386,7 @@ static void pauth_check_trap(CPUARMState *env, int el, uintptr_t ra)
>
>  static bool pauth_key_enabled(CPUARMState *env, int el, uint32_t bit)
>  {
> -    uint32_t sctlr;
> -    if (el == 0) {
> -        /* FIXME: ARMv8.1-VHE S2 translation regime.  */
> -        sctlr = env->cp15.sctlr_el[1];
> -    } else {
> -        sctlr = env->cp15.sctlr_el[el];
> -    }
> -    return (sctlr & bit) != 0;
> +    return (arm_sctlr(env, el) & bit) != 0;
>  }
>
>  uint64_t HELPER(pacia)(CPUARMState *env, uint64_t x, uint64_t y)


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE
  2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
                   ` (24 preceding siblings ...)
  2019-07-22  7:31 ` [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Alex Bennée
@ 2019-07-25 16:15 ` Alex Bennée
  25 siblings, 0 replies; 51+ messages in thread
From: Alex Bennée @ 2019-07-25 16:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, beata.michalska


Richard Henderson <richard.henderson@linaro.org> writes:

> About half of this patch set is cleanup of the qemu tlb handling
> leading up to the actual implementation of VHE, and the biggest
> piece of that: The EL2&0 translation regime.
>
> Testing so far has been limited to booting a debian 9 system with
> a 4.9 kernel, and a fedora 30 system with a 5.1 kernel.  Both have
> KVM enabled, and both report enabling VHE is successful.

So you haven't booted a kernel via KVM inside the emulation yet? That
might explain why I was struggling to do so. For example single-stepping
through the guest kernel gets stuck. I suspect that means some state
machine doesn't quite work (or possibly that is an existing bug, I need
to check without VHE as well).

Anyway I've done my pass for now. I'll come back to the later patches
when more stuff is working.

>
>
> r~
>
>
> Richard Henderson (24):
>   cputlb: Add tlb_set_asid_for_mmuidx
>   cputlb: Add tlb_flush_asid_by_mmuidx and friends
>   target/arm: Install ASIDs for long-form from EL1
>   target/arm: Install ASIDs for short-form from EL1
>   target/arm: Install ASIDs for EL2
>   target/arm: Define isar_feature_aa64_vh
>   target/arm: Enable HCR_E2H for VHE
>   target/arm: Add CONTEXTIDR_EL2
>   target/arm: Add TTBR1_EL2
>   target/arm: Update CNTVCT_EL0 for VHE
>   target/arm: Add the hypervisor virtual counter
>   target/arm: Add VHE system register redirection and aliasing
>   target/arm: Split out vae1_tlbmask, vmalle1_tlbmask
>   target/arm: Simplify tlb_force_broadcast alternatives
>   target/arm: Reorganize ARMMMUIdx
>   target/arm: Add regime_has_2_ranges
>   target/arm: Update arm_mmu_idx for VHE
>   target/arm: Update arm_sctlr for VHE
>   target/arm: Install asids for E2&0 translation regime
>   target/arm: Flush tlbs for E2&0 translation regime
>   target/arm: Update arm_phys_excp_target_el for TGE
>   target/arm: Update regime_is_user for EL2&0
>   target/arm: Update {fp,sve}_exception_el for VHE
>   target/arm: Enable ARMv8.1-VHE in -cpu max
>
>  include/exec/cpu-all.h     |  11 +
>  include/exec/cpu-defs.h    |   2 +
>  include/exec/exec-all.h    |  35 ++
>  include/qom/cpu.h          |   1 +
>  target/arm/cpu-qom.h       |   1 +
>  target/arm/cpu.h           | 259 +++++-----
>  target/arm/internals.h     |  62 ++-
>  target/arm/translate.h     |   2 +-
>  accel/tcg/cputlb.c         |  77 +++
>  target/arm/arch_dump.c     |   2 +-
>  target/arm/cpu.c           |   2 +
>  target/arm/cpu64.c         |   1 +
>  target/arm/debug_helper.c  |  50 +-
>  target/arm/helper-a64.c    |   2 +-
>  target/arm/helper.c        | 985 ++++++++++++++++++++++++++-----------
>  target/arm/m_helper.c      |   6 +-
>  target/arm/pauth_helper.c  |   9 +-
>  target/arm/translate-a64.c |  14 +-
>  target/arm/translate.c     |  17 +-
>  19 files changed, 1058 insertions(+), 480 deletions(-)


--
Alex Bennée


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

* Re: [Qemu-devel] [PATCH for-4.2 15/24] target/arm: Reorganize ARMMMUIdx
  2019-07-25 15:57   ` Alex Bennée
@ 2019-07-25 18:18     ` Richard Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-25 18:18 UTC (permalink / raw)
  To: Alex Bennée, qemu-devel; +Cc: peter.maydell, beata.michalska

On 7/25/19 8:57 AM, Alex Bennée wrote:
> 
> Richard Henderson <richard.henderson@linaro.org> writes:
> 
>> Prepare for, but do not yet implement, the EL2&0 regime and the
>> Secure EL2 regime.  Rename all of the a-profile symbols to make
>> the distictions clearer.
> 
> Perhaps a summary of the renames would be useful here? My head is
> spinning a little given the number that we have and not being familiar
> with the naming convention.
> 
>   ARMMMUIdx[_StageN]_[M][S]Enn[_nn]
> 
>   _StageN - stage N only, otherwise assumed 1+2 lookup?

How about "full", since most of the indicies only have a single stage lookup.

>   M - M profile (interleaved with A profile)
>   S - Secure
>   Enn - visible exception level, so E02 is shared EL0 and EL2?
>   _nn - not sure?
> 
> The cpu.h comment is very detailed but doesn't actually give me enough
> information to decode an ARMMMUIdx when I come across it in the code.

I have wondered if it was worth going back and splitting this patch so that we
do exactly one rename at at time.  It would mean 9 of these patches...


r~


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

* Re: [Qemu-devel] [PATCH for-4.2 16/24] target/arm: Add regime_has_2_ranges
  2019-07-25 15:59   ` Alex Bennée
@ 2019-07-25 18:28     ` Richard Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Richard Henderson @ 2019-07-25 18:28 UTC (permalink / raw)
  To: Alex Bennée, qemu-devel; +Cc: peter.maydell, beata.michalska

On 7/25/19 8:59 AM, Alex Bennée wrote:
> Can you elucidate what we mean by having 2 ranges?

Both positive and negative virtual addresses, with the hole in the middle,
controlled by two translation tables.

In the current (E.a) manual, see D.5.2.1 page D5-2516, in the (sub-)section
titled "About address translation and supported input address ranges".  It is
summarized in table D5-1.


r~


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

end of thread, other threads:[~2019-07-25 18:28 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-19 21:03 [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 01/24] cputlb: Add tlb_set_asid_for_mmuidx Richard Henderson
2019-07-22  9:53   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 02/24] cputlb: Add tlb_flush_asid_by_mmuidx and friends Richard Henderson
2019-07-22 10:04   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 03/24] target/arm: Install ASIDs for long-form from EL1 Richard Henderson
2019-07-22 15:28   ` Alex Bennée
2019-07-22 15:48     ` Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 04/24] target/arm: Install ASIDs for short-form " Richard Henderson
2019-07-24 11:47   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 05/24] target/arm: Install ASIDs for EL2 Richard Henderson
2019-07-24 11:49   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 06/24] target/arm: Define isar_feature_aa64_vh Richard Henderson
2019-07-24 12:59   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 07/24] target/arm: Enable HCR_E2H for VHE Richard Henderson
2019-07-24 13:01   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 08/24] target/arm: Add CONTEXTIDR_EL2 Richard Henderson
2019-07-24 13:57   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 09/24] target/arm: Add TTBR1_EL2 Richard Henderson
2019-07-24 14:12   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 10/24] target/arm: Update CNTVCT_EL0 for VHE Richard Henderson
2019-07-24 14:47   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 11/24] target/arm: Add the hypervisor virtual counter Richard Henderson
2019-07-24 20:05   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 12/24] target/arm: Add VHE system register redirection and aliasing Richard Henderson
2019-07-25 14:01   ` Alex Bennée
2019-07-25 14:24     ` Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 13/24] target/arm: Split out vae1_tlbmask, vmalle1_tlbmask Richard Henderson
2019-07-25 14:02   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 14/24] target/arm: Simplify tlb_force_broadcast alternatives Richard Henderson
2019-07-25 14:08   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 15/24] target/arm: Reorganize ARMMMUIdx Richard Henderson
2019-07-25 15:57   ` Alex Bennée
2019-07-25 18:18     ` Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 16/24] target/arm: Add regime_has_2_ranges Richard Henderson
2019-07-25 15:59   ` Alex Bennée
2019-07-25 18:28     ` Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 17/24] target/arm: Update arm_mmu_idx for VHE Richard Henderson
2019-07-25 16:01   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 18/24] target/arm: Update arm_sctlr " Richard Henderson
2019-07-25 16:02   ` Alex Bennée
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 19/24] target/arm: Install asids for E2&0 translation regime Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 20/24] target/arm: Flush tlbs " Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 21/24] target/arm: Update arm_phys_excp_target_el for TGE Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 22/24] target/arm: Update regime_is_user for EL2&0 Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 23/24] target/arm: Update {fp, sve}_exception_el for VHE Richard Henderson
2019-07-19 21:03 ` [Qemu-devel] [PATCH for-4.2 24/24] target/arm: Enable ARMv8.1-VHE in -cpu max Richard Henderson
2019-07-22  7:31 ` [Qemu-devel] [PATCH for-4.2 00/24] target/arm: Implement ARMv8.1-VHE Alex Bennée
2019-07-22  9:37   ` Alex Bennée
2019-07-22 15:10     ` Richard Henderson
2019-07-25 16:15 ` Alex Bennée

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.