qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN
@ 2020-03-30 21:03 Peter Maydell
  2020-03-30 21:03 ` [PATCH 1/4] target/arm: Don't use a TLB for ARMMMUIdx_Stage2 Peter Maydell
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Peter Maydell @ 2020-03-30 21:03 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Richard Henderson

This is obviously not 5.0 material, but I figured it would be better
to push it out for review now rather than hang on to it and forget...

TTS2UXN is an ARMv8.2 extension which changes the 'XN' field in stage
2 translation table descriptors from just bit [54] to bits [54:53],
allowing stage 2 to control execution permissions separately for EL0
and EL1.

For QEMU this had the potential to be awkward, because it means that
the stage 2 translation now depends on whether it's being used
for an EL0 or an EL1 stage 1 access (the address doesn't change
but the access permissions do). Fortunately, although we allocated
a QEMU TLB/MMU index for Stage 2, we never actually look anything
up in the TLB. So patch 1 turns ARMMMUIdx_Stage2 into a 'NOTLB'
index (ie one without a QEMU TLB), thus avoiding the complication
of splitting it into separate Stage2-for-EL0 and Stage2-for-EL1
indexes. Once we've done that the actual implementation is pretty
trivial -- we just need to plumb an extra 's1_is_el0' argument
into get_phys_addr_lpae(), and then use it to decide what to do.

Peter Maydell (4):
  target/arm: Don't use a TLB for ARMMMUIdx_Stage2
  target/arm: Use enum constant in get_phys_addr_lpae() call
  target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae()
  target/arm: Implement ARMv8.2-TTS2UXN

 target/arm/cpu-param.h |   2 +-
 target/arm/cpu.h       |  36 ++++++--
 target/arm/cpu.c       |   1 +
 target/arm/cpu64.c     |   2 +
 target/arm/helper.c    | 183 ++++++++++++++++-------------------------
 5 files changed, 107 insertions(+), 117 deletions(-)

-- 
2.20.1



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

* [PATCH 1/4] target/arm: Don't use a TLB for ARMMMUIdx_Stage2
  2020-03-30 21:03 [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN Peter Maydell
@ 2020-03-30 21:03 ` Peter Maydell
  2020-04-29 18:39   ` Richard Henderson
  2020-03-30 21:03 ` [PATCH 2/4] target/arm: Use enum constant in get_phys_addr_lpae() call Peter Maydell
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Peter Maydell @ 2020-03-30 21:03 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Richard Henderson

We define ARMMMUIdx_Stage2 as being an MMU index which uses a QEMU
TLB.  However we never actually use the TLB -- all stage 2 lookups
are done by direct calls to get_phys_addr_lpae() followed by a
physical address load via address_space_ld*().

Remove Stage2 from the list of ARM MMU indexes which correspond to
real core MMU indexes, and instead put it in the set of "NOTLB" ARM
MMU indexes.

This allows us to drop NB_MMU_MODES to 11.  It also means we can
safely add support for the ARMv8.3-TTS2UXN extension, which adds
permission bits to the stage 2 descriptors which define execute
permission separatel for EL0 and EL1; supporting that while keeping
Stage2 in a QEMU TLB would require us to use separate TLBs for
"Stage2 for an EL0 access" and "Stage2 for an EL1 access", which is a
lot of extra complication given we aren't even using the QEMU TLB.

In the process of updating the comment on our MMU index use,
fix a couple of other minor errors:
 * NS EL2 EL2&0 was missing from the list in the comment
 * some text hadn't been updated from when we bumped NB_MMU_MODES
   above 8

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu-param.h |   2 +-
 target/arm/cpu.h       |  21 +++++---
 target/arm/helper.c    | 112 ++++-------------------------------------
 3 files changed, 27 insertions(+), 108 deletions(-)

diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
index d593b60b28d..6321385b469 100644
--- a/target/arm/cpu-param.h
+++ b/target/arm/cpu-param.h
@@ -29,6 +29,6 @@
 # define TARGET_PAGE_BITS_MIN  10
 #endif
 
-#define NB_MMU_MODES 12
+#define NB_MMU_MODES 11
 
 #endif
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 8b9f2961ba0..fe03a74bf08 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2801,6 +2801,9 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
  *     handling via the TLB. The only way to do a stage 1 translation without
  *     the immediate stage 2 translation is via the ATS or AT system insns,
  *     which can be slow-pathed and always do a page table walk.
+ *     The only use of stage 2 translations is either as part of an s1+2
+ *     lookup or when loading the descriptors during a stage 1 page table walk,
+ *     and in both those cases we don't use the TLB.
  *  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.
@@ -2816,15 +2819,15 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
  * NS EL1 EL1&0 stage 1+2 (aka NS PL1)
  * NS EL1 EL1&0 stage 1+2 +PAN
  * NS EL0 EL2&0
+ * NS EL2 EL2&0
  * NS EL2 EL2&0 +PAN
  * NS EL2 (aka NS PL2)
  * S EL0 EL1&0 (aka S PL0)
  * S EL1 EL1&0 (not used if EL3 is 32 bit)
  * S EL1 EL1&0 +PAN
  * S EL3 (aka S PL1)
- * NS EL1&0 stage 2
  *
- * for a total of 12 different mmu_idx.
+ * for a total of 11 different mmu_idx.
  *
  * 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
@@ -2846,7 +2849,8 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
  * are not quite the same -- different CPU types (most notably M profile
  * vs A/R profile) would like to use MMU indexes with different semantics,
  * but since we don't ever need to use all of those in a single CPU we
- * can avoid setting NB_MMU_MODES to more than 8. The lower bits of
+ * can avoid having to set NB_MMU_MODES to "total number of A profile MMU
+ * modes + total number of M profile MMU modes". The lower bits of
  * ARMMMUIdx are the core TLB mmu index, and the higher bits are always
  * the same for any particular CPU.
  * Variables of type ARMMUIdx are always full values, and the core
@@ -2894,8 +2898,6 @@ typedef enum ARMMMUIdx {
     ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A,
     ARMMMUIdx_SE3        = 10 | ARM_MMU_IDX_A,
 
-    ARMMMUIdx_Stage2     = 11 | ARM_MMU_IDX_A,
-
     /*
      * These are not allocated TLBs and are used only for AT system
      * instructions or for the first stage of an S12 page table walk.
@@ -2903,6 +2905,14 @@ typedef enum ARMMMUIdx {
     ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
     ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
     ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
+    /*
+     * Not allocated a TLB: used only for second stage of an S12 page
+     * table walk, or for descriptor loads during first stage of an S1
+     * page table walk. Note that if we ever want to have a TLB for this
+     * then various TLB flush insns which currently are no-ops or flush
+     * only stage 1 MMU indexes will need to change to flush stage 2.
+     */
+    ARMMMUIdx_Stage2     = 3 | ARM_MMU_IDX_NOTLB,
 
     /*
      * M-profile.
@@ -2936,7 +2946,6 @@ typedef enum ARMMMUIdxBit {
     TO_CORE_BIT(SE10_1),
     TO_CORE_BIT(SE10_1_PAN),
     TO_CORE_BIT(SE3),
-    TO_CORE_BIT(Stage2),
 
     TO_CORE_BIT(MUser),
     TO_CORE_BIT(MPriv),
diff --git a/target/arm/helper.c b/target/arm/helper.c
index ed7eb8ab54e..a0b3082aad9 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -814,8 +814,7 @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
     tlb_flush_by_mmuidx(cs,
                         ARMMMUIdxBit_E10_1 |
                         ARMMMUIdxBit_E10_1_PAN |
-                        ARMMMUIdxBit_E10_0 |
-                        ARMMMUIdxBit_Stage2);
+                        ARMMMUIdxBit_E10_0);
 }
 
 static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -826,46 +825,9 @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     tlb_flush_by_mmuidx_all_cpus_synced(cs,
                                         ARMMMUIdxBit_E10_1 |
                                         ARMMMUIdxBit_E10_1_PAN |
-                                        ARMMMUIdxBit_E10_0 |
-                                        ARMMMUIdxBit_Stage2);
+                                        ARMMMUIdxBit_E10_0);
 }
 
-static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                            uint64_t value)
-{
-    /* Invalidate by IPA. This has to invalidate any structures that
-     * contain only stage 2 translation information, but does not need
-     * to apply to structures that contain combined stage 1 and stage 2
-     * translation information.
-     * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero.
-     */
-    CPUState *cs = env_cpu(env);
-    uint64_t pageaddr;
-
-    if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
-        return;
-    }
-
-    pageaddr = sextract64(value << 12, 0, 40);
-
-    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
-}
-
-static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                               uint64_t value)
-{
-    CPUState *cs = env_cpu(env);
-    uint64_t pageaddr;
-
-    if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
-        return;
-    }
-
-    pageaddr = sextract64(value << 12, 0, 40);
-
-    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
-                                             ARMMMUIdxBit_Stage2);
-}
 
 static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
                               uint64_t value)
@@ -4038,8 +4000,7 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
         tlb_flush_by_mmuidx(cs,
                             ARMMMUIdxBit_E10_1 |
                             ARMMMUIdxBit_E10_1_PAN |
-                            ARMMMUIdxBit_E10_0 |
-                            ARMMMUIdxBit_Stage2);
+                            ARMMMUIdxBit_E10_0);
         raw_write(env, ri, value);
     }
 }
@@ -4521,11 +4482,6 @@ static int alle1_tlbmask(CPUARMState *env)
         return ARMMMUIdxBit_SE10_1 |
                ARMMMUIdxBit_SE10_1_PAN |
                ARMMMUIdxBit_SE10_0;
-    } else if (arm_feature(env, ARM_FEATURE_EL2)) {
-        return ARMMMUIdxBit_E10_1 |
-               ARMMMUIdxBit_E10_1_PAN |
-               ARMMMUIdxBit_E10_0 |
-               ARMMMUIdxBit_Stage2;
     } else {
         return ARMMMUIdxBit_E10_1 |
                ARMMMUIdxBit_E10_1_PAN |
@@ -4672,44 +4628,6 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                              ARMMMUIdxBit_SE3);
 }
 
-static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                                    uint64_t value)
-{
-    /* Invalidate by IPA. This has to invalidate any structures that
-     * contain only stage 2 translation information, but does not need
-     * to apply to structures that contain combined stage 1 and stage 2
-     * translation information.
-     * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero.
-     */
-    ARMCPU *cpu = env_archcpu(env);
-    CPUState *cs = CPU(cpu);
-    uint64_t pageaddr;
-
-    if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
-        return;
-    }
-
-    pageaddr = sextract64(value << 12, 0, 48);
-
-    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
-}
-
-static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                                      uint64_t value)
-{
-    CPUState *cs = env_cpu(env);
-    uint64_t pageaddr;
-
-    if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
-        return;
-    }
-
-    pageaddr = sextract64(value << 12, 0, 48);
-
-    tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
-                                             ARMMMUIdxBit_Stage2);
-}
-
 static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
                                       bool isread)
 {
@@ -4948,12 +4866,10 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
       .writefn = tlbi_aa64_vae1_write },
     { .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64,
       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
-      .access = PL2_W, .type = ARM_CP_NO_RAW,
-      .writefn = tlbi_aa64_ipas2e1is_write },
+      .access = PL2_W, .type = ARM_CP_NOP },
     { .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64,
       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
-      .access = PL2_W, .type = ARM_CP_NO_RAW,
-      .writefn = tlbi_aa64_ipas2e1is_write },
+      .access = PL2_W, .type = ARM_CP_NOP },
     { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64,
       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
       .access = PL2_W, .type = ARM_CP_NO_RAW,
@@ -4964,12 +4880,10 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
       .writefn = tlbi_aa64_alle1is_write },
     { .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64,
       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
-      .access = PL2_W, .type = ARM_CP_NO_RAW,
-      .writefn = tlbi_aa64_ipas2e1_write },
+      .access = PL2_W, .type = ARM_CP_NOP },
     { .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64,
       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
-      .access = PL2_W, .type = ARM_CP_NO_RAW,
-      .writefn = tlbi_aa64_ipas2e1_write },
+      .access = PL2_W, .type = ARM_CP_NOP },
     { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64,
       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
       .access = PL2_W, .type = ARM_CP_NO_RAW,
@@ -5050,20 +4964,16 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
       .writefn = tlbimva_hyp_is_write },
     { .name = "TLBIIPAS2",
       .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
-      .type = ARM_CP_NO_RAW, .access = PL2_W,
-      .writefn = tlbiipas2_write },
+      .type = ARM_CP_NOP, .access = PL2_W },
     { .name = "TLBIIPAS2IS",
       .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
-      .type = ARM_CP_NO_RAW, .access = PL2_W,
-      .writefn = tlbiipas2_is_write },
+      .type = ARM_CP_NOP, .access = PL2_W },
     { .name = "TLBIIPAS2L",
       .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
-      .type = ARM_CP_NO_RAW, .access = PL2_W,
-      .writefn = tlbiipas2_write },
+      .type = ARM_CP_NOP, .access = PL2_W },
     { .name = "TLBIIPAS2LIS",
       .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
-      .type = ARM_CP_NO_RAW, .access = PL2_W,
-      .writefn = tlbiipas2_is_write },
+      .type = ARM_CP_NOP, .access = PL2_W },
     /* 32 bit cache operations */
     { .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
       .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access },
-- 
2.20.1



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

* [PATCH 2/4] target/arm: Use enum constant in get_phys_addr_lpae() call
  2020-03-30 21:03 [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN Peter Maydell
  2020-03-30 21:03 ` [PATCH 1/4] target/arm: Don't use a TLB for ARMMMUIdx_Stage2 Peter Maydell
@ 2020-03-30 21:03 ` Peter Maydell
  2020-04-29 18:39   ` Richard Henderson
  2020-03-30 21:03 ` [PATCH 3/4] target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae() Peter Maydell
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Peter Maydell @ 2020-03-30 21:03 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Richard Henderson

The access_type argument to get_phys_addr_lpae() is an MMUAccessType;
use the enum constant MMU_DATA_LOAD rather than a literal 0 when we
call it in S1_ptw_translate().

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index a0b3082aad9..25439bf6fd9 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -10035,8 +10035,9 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
             pcacheattrs = &cacheattrs;
         }
 
-        ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_Stage2, &s2pa,
-                                 &txattrs, &s2prot, &s2size, fi, pcacheattrs);
+        ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, ARMMMUIdx_Stage2,
+                                 &s2pa, &txattrs, &s2prot, &s2size, fi,
+                                 pcacheattrs);
         if (ret) {
             assert(fi->type != ARMFault_None);
             fi->s2addr = addr;
-- 
2.20.1



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

* [PATCH 3/4] target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae()
  2020-03-30 21:03 [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN Peter Maydell
  2020-03-30 21:03 ` [PATCH 1/4] target/arm: Don't use a TLB for ARMMMUIdx_Stage2 Peter Maydell
  2020-03-30 21:03 ` [PATCH 2/4] target/arm: Use enum constant in get_phys_addr_lpae() call Peter Maydell
@ 2020-03-30 21:03 ` Peter Maydell
  2020-04-29 18:41   ` Richard Henderson
  2020-03-30 21:04 ` [PATCH 4/4] target/arm: Implement ARMv8.2-TTS2UXN Peter Maydell
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Peter Maydell @ 2020-03-30 21:03 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Richard Henderson

For ARMv8.2-TTS2UXN, the stage 2 page table walk wants to know
whether the stage 1 access is for EL0 or not, because whether
exec permission is given can depend on whether this is an EL0
or EL1 access. Add a new argument to get_phys_addr_lpae() so
the call sites can pass this information in.

Since get_phys_addr_lpae() doesn't already have a doc comment,
add one so we have a place to put the documentation of the
semantics of the new s1_is_el0 argument.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 25439bf6fd9..47a175b8e9d 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -41,6 +41,7 @@
 
 static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
                                MMUAccessType access_type, ARMMMUIdx mmu_idx,
+                               bool s1_is_el0,
                                hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
                                target_ulong *page_size_ptr,
                                ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs);
@@ -10036,6 +10037,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
         }
 
         ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, ARMMMUIdx_Stage2,
+                                 false,
                                  &s2pa, &txattrs, &s2prot, &s2size, fi,
                                  pcacheattrs);
         if (ret) {
@@ -10638,8 +10640,32 @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
     };
 }
 
+/**
+ * get_phys_addr_lpae: perform one stage of page table walk, LPAE format
+ *
+ * Returns false if the translation was successful. Otherwise, phys_ptr, attrs,
+ * prot and page_size may not be filled in, and the populated fsr value provides
+ * information on why the translation aborted, in the format of a long-format
+ * DFSR/IFSR fault register, with the following caveats:
+ *  * the WnR bit is never set (the caller must do this).
+ *
+ * @env: CPUARMState
+ * @address: virtual address to get physical address for
+ * @access_type: MMU_DATA_LOAD, MMU_DATA_STORE or MMU_INST_FETCH
+ * @mmu_idx: MMU index indicating required translation regime
+ * @s1_is_el0: if @mmu_idx is ARMMMUIdx_Stage2 (so this is a stage 2 page table
+ *             walk), must be true if this is stage 2 of a stage 1+2 walk for an
+ *             EL0 access). If @mmu_idx is anything else, @s1_is_el0 is ignored.
+ * @phys_ptr: set to the physical address corresponding to the virtual address
+ * @attrs: set to the memory transaction attributes to use
+ * @prot: set to the permissions for the page containing phys_ptr
+ * @page_size_ptr: set to the size of the page containing phys_ptr
+ * @fi: set to fault info if the translation fails
+ * @cacheattrs: (if non-NULL) set to the cacheability/shareability attributes
+ */
 static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
                                MMUAccessType access_type, ARMMMUIdx mmu_idx,
+                               bool s1_is_el0,
                                hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
                                target_ulong *page_size_ptr,
                                ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
@@ -11736,6 +11762,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
 
             /* S1 is done. Now do S2 translation.  */
             ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_Stage2,
+                                     mmu_idx == ARMMMUIdx_E10_0,
                                      phys_ptr, attrs, &s2_prot,
                                      page_size, fi,
                                      cacheattrs != NULL ? &cacheattrs2 : NULL);
@@ -11860,7 +11887,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
     }
 
     if (regime_using_lpae_format(env, mmu_idx)) {
-        return get_phys_addr_lpae(env, address, access_type, mmu_idx,
+        return get_phys_addr_lpae(env, address, access_type, mmu_idx, false,
                                   phys_ptr, attrs, prot, page_size,
                                   fi, cacheattrs);
     } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
-- 
2.20.1



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

* [PATCH 4/4] target/arm: Implement ARMv8.2-TTS2UXN
  2020-03-30 21:03 [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN Peter Maydell
                   ` (2 preceding siblings ...)
  2020-03-30 21:03 ` [PATCH 3/4] target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae() Peter Maydell
@ 2020-03-30 21:04 ` Peter Maydell
  2020-04-29 18:43   ` Richard Henderson
  2020-04-27 13:29 ` [PATCH 0/4] arm: " Peter Maydell
  2020-04-27 16:04 ` Edgar E. Iglesias
  5 siblings, 1 reply; 11+ messages in thread
From: Peter Maydell @ 2020-03-30 21:04 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Richard Henderson

The ARMv8.2-TTS2UXN feature extends the XN field in stage 2
translation table descriptors from just bit [54] to bits [54:53],
allowing stage 2 to control execution permissions separately for EL0
and EL1. Implement the new semantics of the XN field and enable
the feature for our 'max' CPU.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.h    | 15 +++++++++++++++
 target/arm/cpu.c    |  1 +
 target/arm/cpu64.c  |  2 ++
 target/arm/helper.c | 37 +++++++++++++++++++++++++++++++------
 4 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index fe03a74bf08..9aae324d0f6 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3610,6 +3610,11 @@ static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id)
     return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0;
 }
 
+static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id)
+{
+    return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0;
+}
+
 /*
  * 64-bit feature tests via id registers.
  */
@@ -3822,6 +3827,11 @@ static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
     return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
 }
 
+static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
+}
+
 /*
  * Feature tests for "does this exist in either 32-bit or 64-bit?"
  */
@@ -3850,6 +3860,11 @@ static inline bool isar_feature_any_ccidx(const ARMISARegisters *id)
     return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id);
 }
 
+static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
+{
+    return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
+}
+
 /*
  * Forward to the above feature tests given an ARMCPU pointer.
  */
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index a79f233b170..d5dfb30525d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2684,6 +2684,7 @@ static void arm_max_initfn(Object *obj)
             t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
             t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
             t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
+            t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
             cpu->isar.id_mmfr4 = t;
         }
 #endif
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 62d36f9e8d3..5fc6330c968 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -673,6 +673,7 @@ static void aarch64_max_initfn(Object *obj)
         t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
         t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
         t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */
+        t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* TTS2UXN */
         cpu->isar.id_aa64mmfr1 = t;
 
         t = cpu->isar.id_aa64mmfr2;
@@ -706,6 +707,7 @@ static void aarch64_max_initfn(Object *obj)
         u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */
         u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
         u = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
+        u = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
         cpu->isar.id_mmfr4 = u;
 
         u = cpu->isar.id_aa64dfr0;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 47a175b8e9d..cba8ac57983 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9891,9 +9891,10 @@ simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap)
  *
  * @env:     CPUARMState
  * @s2ap:    The 2-bit stage2 access permissions (S2AP)
- * @xn:      XN (execute-never) bit
+ * @xn:      XN (execute-never) bits
+ * @s1_is_el0: true if this is S2 of an S1+2 walk for EL0
  */
-static int get_S2prot(CPUARMState *env, int s2ap, int xn)
+static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
 {
     int prot = 0;
 
@@ -9903,9 +9904,32 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn)
     if (s2ap & 2) {
         prot |= PAGE_WRITE;
     }
-    if (!xn) {
-        if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) {
+
+    if (cpu_isar_feature(any_tts2uxn, env_archcpu(env))) {
+        switch (xn) {
+        case 0:
             prot |= PAGE_EXEC;
+            break;
+        case 1:
+            if (s1_is_el0) {
+                prot |= PAGE_EXEC;
+            }
+            break;
+        case 2:
+            break;
+        case 3:
+            if (!s1_is_el0) {
+                prot |= PAGE_EXEC;
+            }
+            break;
+        default:
+            g_assert_not_reached();
+        }
+    } else {
+        if (!extract32(xn, 1, 1)) {
+            if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) {
+                prot |= PAGE_EXEC;
+            }
         }
     }
     return prot;
@@ -10889,13 +10913,14 @@ 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_Stage2) {
         ns = true;
-        *prot = get_S2prot(env, ap, xn);
+        xn = extract32(attrs, 11, 2);
+        *prot = get_S2prot(env, ap, xn, s1_is_el0);
     } else {
         ns = extract32(attrs, 3, 1);
+        xn = extract32(attrs, 12, 1);
         pxn = extract32(attrs, 11, 1);
         *prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
     }
-- 
2.20.1



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

* Re: [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN
  2020-03-30 21:03 [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN Peter Maydell
                   ` (3 preceding siblings ...)
  2020-03-30 21:04 ` [PATCH 4/4] target/arm: Implement ARMv8.2-TTS2UXN Peter Maydell
@ 2020-04-27 13:29 ` Peter Maydell
  2020-04-27 16:04 ` Edgar E. Iglesias
  5 siblings, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2020-04-27 13:29 UTC (permalink / raw)
  To: qemu-arm, QEMU Developers; +Cc: Richard Henderson

Ping for code review, since 5.0 is nearly out the door...

thanks
-- PMM

On Mon, 30 Mar 2020 at 22:04, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> This is obviously not 5.0 material, but I figured it would be better
> to push it out for review now rather than hang on to it and forget...
>
> TTS2UXN is an ARMv8.2 extension which changes the 'XN' field in stage
> 2 translation table descriptors from just bit [54] to bits [54:53],
> allowing stage 2 to control execution permissions separately for EL0
> and EL1.
>
> For QEMU this had the potential to be awkward, because it means that
> the stage 2 translation now depends on whether it's being used
> for an EL0 or an EL1 stage 1 access (the address doesn't change
> but the access permissions do). Fortunately, although we allocated
> a QEMU TLB/MMU index for Stage 2, we never actually look anything
> up in the TLB. So patch 1 turns ARMMMUIdx_Stage2 into a 'NOTLB'
> index (ie one without a QEMU TLB), thus avoiding the complication
> of splitting it into separate Stage2-for-EL0 and Stage2-for-EL1
> indexes. Once we've done that the actual implementation is pretty
> trivial -- we just need to plumb an extra 's1_is_el0' argument
> into get_phys_addr_lpae(), and then use it to decide what to do.
>
> Peter Maydell (4):
>   target/arm: Don't use a TLB for ARMMMUIdx_Stage2
>   target/arm: Use enum constant in get_phys_addr_lpae() call
>   target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae()
>   target/arm: Implement ARMv8.2-TTS2UXN
>
>  target/arm/cpu-param.h |   2 +-
>  target/arm/cpu.h       |  36 ++++++--
>  target/arm/cpu.c       |   1 +
>  target/arm/cpu64.c     |   2 +
>  target/arm/helper.c    | 183 ++++++++++++++++-------------------------
>  5 files changed, 107 insertions(+), 117 deletions(-)


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

* Re: [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN
  2020-03-30 21:03 [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN Peter Maydell
                   ` (4 preceding siblings ...)
  2020-04-27 13:29 ` [PATCH 0/4] arm: " Peter Maydell
@ 2020-04-27 16:04 ` Edgar E. Iglesias
  5 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2020-04-27 16:04 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-arm, Richard Henderson, qemu-devel

On Mon, Mar 30, 2020 at 10:03:56PM +0100, Peter Maydell wrote:
> This is obviously not 5.0 material, but I figured it would be better
> to push it out for review now rather than hang on to it and forget...
> 
> TTS2UXN is an ARMv8.2 extension which changes the 'XN' field in stage
> 2 translation table descriptors from just bit [54] to bits [54:53],
> allowing stage 2 to control execution permissions separately for EL0
> and EL1.
> 
> For QEMU this had the potential to be awkward, because it means that
> the stage 2 translation now depends on whether it's being used
> for an EL0 or an EL1 stage 1 access (the address doesn't change
> but the access permissions do). Fortunately, although we allocated
> a QEMU TLB/MMU index for Stage 2, we never actually look anything
> up in the TLB. So patch 1 turns ARMMMUIdx_Stage2 into a 'NOTLB'
> index (ie one without a QEMU TLB), thus avoiding the complication
> of splitting it into separate Stage2-for-EL0 and Stage2-for-EL1
> indexes. Once we've done that the actual implementation is pretty
> trivial -- we just need to plumb an extra 's1_is_el0' argument
> into get_phys_addr_lpae(), and then use it to decide what to do.

Hi Peter,

The whole series looks good to me:

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

Cheers,
Edgar



> 
> Peter Maydell (4):
>   target/arm: Don't use a TLB for ARMMMUIdx_Stage2
>   target/arm: Use enum constant in get_phys_addr_lpae() call
>   target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae()
>   target/arm: Implement ARMv8.2-TTS2UXN
> 
>  target/arm/cpu-param.h |   2 +-
>  target/arm/cpu.h       |  36 ++++++--
>  target/arm/cpu.c       |   1 +
>  target/arm/cpu64.c     |   2 +
>  target/arm/helper.c    | 183 ++++++++++++++++-------------------------
>  5 files changed, 107 insertions(+), 117 deletions(-)
> 
> -- 
> 2.20.1
> 
> 


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

* Re: [PATCH 1/4] target/arm: Don't use a TLB for ARMMMUIdx_Stage2
  2020-03-30 21:03 ` [PATCH 1/4] target/arm: Don't use a TLB for ARMMMUIdx_Stage2 Peter Maydell
@ 2020-04-29 18:39   ` Richard Henderson
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2020-04-29 18:39 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 3/30/20 2:03 PM, Peter Maydell wrote:
> We define ARMMMUIdx_Stage2 as being an MMU index which uses a QEMU
> TLB.  However we never actually use the TLB -- all stage 2 lookups
> are done by direct calls to get_phys_addr_lpae() followed by a
> physical address load via address_space_ld*().
> 
> Remove Stage2 from the list of ARM MMU indexes which correspond to
> real core MMU indexes, and instead put it in the set of "NOTLB" ARM
> MMU indexes.
> 
> This allows us to drop NB_MMU_MODES to 11.  It also means we can
> safely add support for the ARMv8.3-TTS2UXN extension, which adds
> permission bits to the stage 2 descriptors which define execute
> permission separatel for EL0 and EL1; supporting that while keeping
> Stage2 in a QEMU TLB would require us to use separate TLBs for
> "Stage2 for an EL0 access" and "Stage2 for an EL1 access", which is a
> lot of extra complication given we aren't even using the QEMU TLB.
> 
> In the process of updating the comment on our MMU index use,
> fix a couple of other minor errors:
>  * NS EL2 EL2&0 was missing from the list in the comment
>  * some text hadn't been updated from when we bumped NB_MMU_MODES
>    above 8
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/cpu-param.h |   2 +-
>  target/arm/cpu.h       |  21 +++++---
>  target/arm/helper.c    | 112 ++++-------------------------------------
>  3 files changed, 27 insertions(+), 108 deletions(-)

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

r~


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

* Re: [PATCH 2/4] target/arm: Use enum constant in get_phys_addr_lpae() call
  2020-03-30 21:03 ` [PATCH 2/4] target/arm: Use enum constant in get_phys_addr_lpae() call Peter Maydell
@ 2020-04-29 18:39   ` Richard Henderson
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2020-04-29 18:39 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 3/30/20 2:03 PM, Peter Maydell wrote:
> The access_type argument to get_phys_addr_lpae() is an MMUAccessType;
> use the enum constant MMU_DATA_LOAD rather than a literal 0 when we
> call it in S1_ptw_translate().
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/helper.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)

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

r~


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

* Re: [PATCH 3/4] target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae()
  2020-03-30 21:03 ` [PATCH 3/4] target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae() Peter Maydell
@ 2020-04-29 18:41   ` Richard Henderson
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2020-04-29 18:41 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 3/30/20 2:03 PM, Peter Maydell wrote:
> For ARMv8.2-TTS2UXN, the stage 2 page table walk wants to know
> whether the stage 1 access is for EL0 or not, because whether
> exec permission is given can depend on whether this is an EL0
> or EL1 access. Add a new argument to get_phys_addr_lpae() so
> the call sites can pass this information in.
> 
> Since get_phys_addr_lpae() doesn't already have a doc comment,
> add one so we have a place to put the documentation of the
> semantics of the new s1_is_el0 argument.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/helper.c | 29 ++++++++++++++++++++++++++++-
>  1 file changed, 28 insertions(+), 1 deletion(-)

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

r~


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

* Re: [PATCH 4/4] target/arm: Implement ARMv8.2-TTS2UXN
  2020-03-30 21:04 ` [PATCH 4/4] target/arm: Implement ARMv8.2-TTS2UXN Peter Maydell
@ 2020-04-29 18:43   ` Richard Henderson
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2020-04-29 18:43 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 3/30/20 2:04 PM, Peter Maydell wrote:
> The ARMv8.2-TTS2UXN feature extends the XN field in stage 2
> translation table descriptors from just bit [54] to bits [54:53],
> allowing stage 2 to control execution permissions separately for EL0
> and EL1. Implement the new semantics of the XN field and enable
> the feature for our 'max' CPU.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/cpu.h    | 15 +++++++++++++++
>  target/arm/cpu.c    |  1 +
>  target/arm/cpu64.c  |  2 ++
>  target/arm/helper.c | 37 +++++++++++++++++++++++++++++++------
>  4 files changed, 49 insertions(+), 6 deletions(-)

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

r~


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

end of thread, other threads:[~2020-04-29 18:53 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-30 21:03 [PATCH 0/4] arm: Implement ARMv8.2-TTS2UXN Peter Maydell
2020-03-30 21:03 ` [PATCH 1/4] target/arm: Don't use a TLB for ARMMMUIdx_Stage2 Peter Maydell
2020-04-29 18:39   ` Richard Henderson
2020-03-30 21:03 ` [PATCH 2/4] target/arm: Use enum constant in get_phys_addr_lpae() call Peter Maydell
2020-04-29 18:39   ` Richard Henderson
2020-03-30 21:03 ` [PATCH 3/4] target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae() Peter Maydell
2020-04-29 18:41   ` Richard Henderson
2020-03-30 21:04 ` [PATCH 4/4] target/arm: Implement ARMv8.2-TTS2UXN Peter Maydell
2020-04-29 18:43   ` Richard Henderson
2020-04-27 13:29 ` [PATCH 0/4] arm: " Peter Maydell
2020-04-27 16:04 ` Edgar E. Iglesias

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