qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO
@ 2020-02-02  1:04 Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2 Richard Henderson
                   ` (13 more replies)
  0 siblings, 14 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Based-on: <20200201192916.31796-1-richard.henderson@linaro.org>
("[v6] target/arm: Implement ARMv8.1-VHE")

Version 2 addresses review commentary, and also merges the 4 UAO
patches into the PAN + ATS1E1 omnibus patch set.

Changes:
  * Moved reginfo to file scope.
  * Rename arm_mmu_idx_is_stage1 to arm_mmu_idx_is_stage1_of_2
  * Mask PAN + UAO when not supported.


r~


Richard Henderson (14):
  target/arm: Add arm_mmu_idx_is_stage1_of_2
  target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled
  target/arm: Add isar_feature tests for PAN + ATS1E1
  target/arm: Move LOR regdefs to file scope
  target/arm: Update MSR access for PAN
  target/arm: Update arm_mmu_idx_el for PAN
  target/arm: Enforce PAN semantics in get_S1prot
  target/arm: Set PAN bit as required on exception entry
  target/arm: Implement ATS1E1 system registers
  target/arm: Enable ARMv8.2-ATS1E1 in -cpu max
  target/arm: Add ID_AA64MMFR2_EL1
  target/arm: Update MSR access to UAO
  target/arm: Implement UAO semantics
  target/arm: Enable ARMv8.2-UAO in -cpu max

 target/arm/cpu-param.h     |   2 +-
 target/arm/cpu.h           |  96 ++++++++++--
 target/arm/internals.h     |  40 +++++
 target/arm/cpu.c           |   4 +
 target/arm/cpu64.c         |   9 ++
 target/arm/helper-a64.c    |   9 ++
 target/arm/helper.c        | 314 ++++++++++++++++++++++++++++---------
 target/arm/kvm64.c         |   2 +
 target/arm/op_helper.c     |   9 +-
 target/arm/translate-a64.c |  31 ++++
 target/arm/translate.c     |   8 +-
 11 files changed, 437 insertions(+), 87 deletions(-)

-- 
2.20.1



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

* [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-03 11:46   ` Alex Bennée
  2020-02-02  1:04 ` [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled Richard Henderson
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, Philippe Mathieu-Daudé

Use a common predicate for querying stage1-ness.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Rename from arm_mmu_idx_is_stage1 to arm_mmu_idx_is_stage1_of_2
---
 target/arm/internals.h | 18 ++++++++++++++++++
 target/arm/helper.c    |  8 +++-----
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 6d4a942bde..1f8ee5f573 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1034,6 +1034,24 @@ static inline ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
 ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
 #endif
 
+/**
+ * arm_mmu_idx_is_stage1_of_2:
+ * @mmu_idx: The ARMMMUIdx to test
+ *
+ * Return true if @mmu_idx is a NOTLB mmu_idx that is the
+ * first stage of a two stage regime.
+ */
+static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
+{
+    switch (mmu_idx) {
+    case ARMMMUIdx_Stage1_E0:
+    case ARMMMUIdx_Stage1_E1:
+        return true;
+    default:
+        return false;
+    }
+}
+
 /*
  * Parameters of a given virtual address, as extracted from the
  * translation control register (TCR) for a given regime.
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 70b10428c5..852fd71dcc 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3261,8 +3261,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
         bool take_exc = false;
 
         if (fi.s1ptw && current_el == 1 && !arm_is_secure(env)
-            && (mmu_idx == ARMMMUIdx_Stage1_E1 ||
-                mmu_idx == ARMMMUIdx_Stage1_E0)) {
+            && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
             /*
              * Synchronous stage 2 fault on an access made as part of the
              * translation table walk for AT S1E0* or AT S1E1* insn
@@ -9294,8 +9293,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
         }
     }
 
-    if ((env->cp15.hcr_el2 & HCR_DC) &&
-        (mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1)) {
+    if ((env->cp15.hcr_el2 & HCR_DC) && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
         /* HCR.DC means SCTLR_EL1.M behaves as 0 */
         return true;
     }
@@ -9604,7 +9602,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
                                hwaddr addr, MemTxAttrs txattrs,
                                ARMMMUFaultInfo *fi)
 {
-    if ((mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1) &&
+    if (arm_mmu_idx_is_stage1_of_2(mmu_idx) &&
         !regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
         target_ulong s2size;
         hwaddr s2pa;
-- 
2.20.1



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

* [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2 Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-03 11:54   ` Alex Bennée
  2020-02-02  1:04 ` [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1 Richard Henderson
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

To implement PAN, we will want to swap, for short periods
of time, to a different privileged mmu_idx.  In addition,
we cannot do this with flushing alone, because the AT*
instructions have both PAN and PAN-less versions.

Add the ARMMMUIdx*_PAN constants where necessary next to
the corresponding ARMMMUIdx* constant.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu-param.h     |  2 +-
 target/arm/cpu.h           | 33 ++++++++++++++-------
 target/arm/internals.h     |  9 ++++++
 target/arm/helper.c        | 60 +++++++++++++++++++++++++++++++-------
 target/arm/translate-a64.c |  3 ++
 target/arm/translate.c     |  2 ++
 6 files changed, 87 insertions(+), 22 deletions(-)

diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
index 18ac562346..d593b60b28 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 9
+#define NB_MMU_MODES 12
 
 #endif
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0b3036c484..c63bceaaa5 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2751,20 +2751,24 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
  *  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.
+ *  6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
+ *     Never (PAN) bit within PSTATE.
  *
  * This gives us the following list of cases:
  *
  * NS EL0 EL1&0 stage 1+2 (aka NS PL0)
  * 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 9 different mmu_idx.
+ * for a total of 12 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
@@ -2819,19 +2823,22 @@ typedef enum ARMMMUIdx {
     /*
      * A-profile.
      */
-    ARMMMUIdx_E10_0 =  0 | ARM_MMU_IDX_A,
-    ARMMMUIdx_E20_0 =  1 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E10_0      =  0 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E20_0      =  1 | ARM_MMU_IDX_A,
 
-    ARMMMUIdx_E10_1 =  2 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E10_1      =  2 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E10_1_PAN  =  3 | ARM_MMU_IDX_A,
 
-    ARMMMUIdx_E2 =     3 | ARM_MMU_IDX_A,
-    ARMMMUIdx_E20_2 =  4 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E2         =  4 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E20_2      =  5 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E20_2_PAN  =  6 | ARM_MMU_IDX_A,
 
-    ARMMMUIdx_SE10_0 = 5 | ARM_MMU_IDX_A,
-    ARMMMUIdx_SE10_1 = 6 | ARM_MMU_IDX_A,
-    ARMMMUIdx_SE3 =    7 | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE10_0     = 7 | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE10_1     = 8 | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE3        = 10 | ARM_MMU_IDX_A,
 
-    ARMMMUIdx_Stage2 = 8 | ARM_MMU_IDX_A,
+    ARMMMUIdx_Stage2     = 11 | ARM_MMU_IDX_A,
 
     /*
      * These are not allocated TLBs and are used only for AT system
@@ -2839,6 +2846,7 @@ 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,
 
     /*
      * M-profile.
@@ -2864,10 +2872,13 @@ typedef enum ARMMMUIdxBit {
     TO_CORE_BIT(E10_0),
     TO_CORE_BIT(E20_0),
     TO_CORE_BIT(E10_1),
+    TO_CORE_BIT(E10_1_PAN),
     TO_CORE_BIT(E2),
     TO_CORE_BIT(E20_2),
+    TO_CORE_BIT(E20_2_PAN),
     TO_CORE_BIT(SE10_0),
     TO_CORE_BIT(SE10_1),
+    TO_CORE_BIT(SE10_1_PAN),
     TO_CORE_BIT(SE3),
     TO_CORE_BIT(Stage2),
 
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 1f8ee5f573..6be8b2d1a9 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -843,12 +843,16 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
     switch (mmu_idx) {
     case ARMMMUIdx_Stage1_E0:
     case ARMMMUIdx_Stage1_E1:
+    case ARMMMUIdx_Stage1_E1_PAN:
     case ARMMMUIdx_E10_0:
     case ARMMMUIdx_E10_1:
+    case ARMMMUIdx_E10_1_PAN:
     case ARMMMUIdx_E20_0:
     case ARMMMUIdx_E20_2:
+    case ARMMMUIdx_E20_2_PAN:
     case ARMMMUIdx_SE10_0:
     case ARMMMUIdx_SE10_1:
+    case ARMMMUIdx_SE10_1_PAN:
         return true;
     default:
         return false;
@@ -861,10 +865,13 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
     switch (mmu_idx) {
     case ARMMMUIdx_E10_0:
     case ARMMMUIdx_E10_1:
+    case ARMMMUIdx_E10_1_PAN:
     case ARMMMUIdx_E20_0:
     case ARMMMUIdx_E20_2:
+    case ARMMMUIdx_E20_2_PAN:
     case ARMMMUIdx_Stage1_E0:
     case ARMMMUIdx_Stage1_E1:
+    case ARMMMUIdx_Stage1_E1_PAN:
     case ARMMMUIdx_E2:
     case ARMMMUIdx_Stage2:
     case ARMMMUIdx_MPrivNegPri:
@@ -875,6 +882,7 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
     case ARMMMUIdx_SE3:
     case ARMMMUIdx_SE10_0:
     case ARMMMUIdx_SE10_1:
+    case ARMMMUIdx_SE10_1_PAN:
     case ARMMMUIdx_MSPrivNegPri:
     case ARMMMUIdx_MSUserNegPri:
     case ARMMMUIdx_MSPriv:
@@ -1046,6 +1054,7 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
     switch (mmu_idx) {
     case ARMMMUIdx_Stage1_E0:
     case ARMMMUIdx_Stage1_E1:
+    case ARMMMUIdx_Stage1_E1_PAN:
         return true;
     default:
         return false;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 852fd71dcc..739d2d4cc5 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -671,6 +671,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);
 }
@@ -682,6 +683,7 @@ 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);
 }
@@ -2700,6 +2702,7 @@ static int gt_phys_redir_timeridx(CPUARMState *env)
     switch (arm_mmu_idx(env)) {
     case ARMMMUIdx_E20_0:
     case ARMMMUIdx_E20_2:
+    case ARMMMUIdx_E20_2_PAN:
         return GTIMER_HYP;
     default:
         return GTIMER_PHYS;
@@ -2711,6 +2714,7 @@ static int gt_virt_redir_timeridx(CPUARMState *env)
     switch (arm_mmu_idx(env)) {
     case ARMMMUIdx_E20_0:
     case ARMMMUIdx_E20_2:
+    case ARMMMUIdx_E20_2_PAN:
         return GTIMER_HYPVIRT;
     default:
         return GTIMER_VIRT;
@@ -3337,7 +3341,9 @@ 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_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
+            if (mmu_idx == ARMMMUIdx_E10_0 ||
+                mmu_idx == ARMMMUIdx_E10_1 ||
+                mmu_idx == ARMMMUIdx_E10_1_PAN) {
                 format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
             } else {
                 format64 |= arm_current_el(env) == 2;
@@ -3797,7 +3803,9 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
     if (extract64(raw_read(env, ri) ^ value, 48, 16) &&
         (arm_hcr_el2_eff(env) & HCR_E2H)) {
         tlb_flush_by_mmuidx(env_cpu(env),
-                            ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0);
+                            ARMMMUIdxBit_E20_2 |
+                            ARMMMUIdxBit_E20_2_PAN |
+                            ARMMMUIdxBit_E20_0);
     }
     raw_write(env, ri, value);
 }
@@ -3815,6 +3823,7 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
     if (raw_read(env, ri) != value) {
         tlb_flush_by_mmuidx(cs,
                             ARMMMUIdxBit_E10_1 |
+                            ARMMMUIdxBit_E10_1_PAN |
                             ARMMMUIdxBit_E10_0 |
                             ARMMMUIdxBit_Stage2);
         raw_write(env, ri, value);
@@ -4175,12 +4184,18 @@ 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_SE10_1 | ARMMMUIdxBit_SE10_0;
+        return ARMMMUIdxBit_SE10_1 |
+               ARMMMUIdxBit_SE10_1_PAN |
+               ARMMMUIdxBit_SE10_0;
     } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
                == (HCR_E2H | HCR_TGE)) {
-        return ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0;
+        return ARMMMUIdxBit_E20_2 |
+               ARMMMUIdxBit_E20_2_PAN |
+               ARMMMUIdxBit_E20_0;
     } else {
-        return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
+        return ARMMMUIdxBit_E10_1 |
+               ARMMMUIdxBit_E10_1_PAN |
+               ARMMMUIdxBit_E10_0;
     }
 }
 
@@ -4214,18 +4229,28 @@ static int alle1_tlbmask(CPUARMState *env)
      * stage 1 translations.
      */
     if (arm_is_secure_below_el3(env)) {
-        return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
+        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_0 | ARMMMUIdxBit_Stage2;
+        return ARMMMUIdxBit_E10_1 |
+               ARMMMUIdxBit_E10_1_PAN |
+               ARMMMUIdxBit_E10_0 |
+               ARMMMUIdxBit_Stage2;
     } else {
-        return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
+        return ARMMMUIdxBit_E10_1 |
+               ARMMMUIdxBit_E10_1_PAN |
+               ARMMMUIdxBit_E10_0;
     }
 }
 
 static int alle2_tlbmask(CPUARMState *env)
 {
     /* TODO: ARMv8.4-SecEL2 */
-    return ARMMMUIdxBit_E20_0 | ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E2;
+    return ARMMMUIdxBit_E20_0 |
+           ARMMMUIdxBit_E20_2 |
+           ARMMMUIdxBit_E20_2_PAN |
+           ARMMMUIdxBit_E2;
 }
 
 static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -9215,6 +9240,7 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
     switch (mmu_idx) {
     case ARMMMUIdx_E20_0:
     case ARMMMUIdx_E20_2:
+    case ARMMMUIdx_E20_2_PAN:
     case ARMMMUIdx_Stage2:
     case ARMMMUIdx_E2:
         return 2;
@@ -9223,10 +9249,13 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
     case ARMMMUIdx_SE10_0:
         return arm_el_is_aa64(env, 3) ? 1 : 3;
     case ARMMMUIdx_SE10_1:
+    case ARMMMUIdx_SE10_1_PAN:
     case ARMMMUIdx_Stage1_E0:
     case ARMMMUIdx_Stage1_E1:
+    case ARMMMUIdx_Stage1_E1_PAN:
     case ARMMMUIdx_E10_0:
     case ARMMMUIdx_E10_1:
+    case ARMMMUIdx_E10_1_PAN:
     case ARMMMUIdx_MPrivNegPri:
     case ARMMMUIdx_MUserNegPri:
     case ARMMMUIdx_MPriv:
@@ -9342,6 +9371,8 @@ static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
         return ARMMMUIdx_Stage1_E0;
     case ARMMMUIdx_E10_1:
         return ARMMMUIdx_Stage1_E1;
+    case ARMMMUIdx_E10_1_PAN:
+        return ARMMMUIdx_Stage1_E1_PAN;
     default:
         return mmu_idx;
     }
@@ -9388,6 +9419,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
         return false;
     case ARMMMUIdx_E10_0:
     case ARMMMUIdx_E10_1:
+    case ARMMMUIdx_E10_1_PAN:
         g_assert_not_reached();
     }
 }
@@ -11280,7 +11312,9 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
                    target_ulong *page_size,
                    ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
 {
-    if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
+    if (mmu_idx == ARMMMUIdx_E10_0 ||
+        mmu_idx == ARMMMUIdx_E10_1 ||
+        mmu_idx == ARMMMUIdx_E10_1_PAN) {
         /* Call ourselves recursively to do the stage 1 and then stage 2
          * translations.
          */
@@ -11807,10 +11841,13 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
     case ARMMMUIdx_SE10_0:
         return 0;
     case ARMMMUIdx_E10_1:
+    case ARMMMUIdx_E10_1_PAN:
     case ARMMMUIdx_SE10_1:
+    case ARMMMUIdx_SE10_1_PAN:
         return 1;
     case ARMMMUIdx_E2:
     case ARMMMUIdx_E20_2:
+    case ARMMMUIdx_E20_2_PAN:
         return 2;
     case ARMMMUIdx_SE3:
         return 3;
@@ -12027,11 +12064,14 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
     /* TODO: ARMv8.2-UAO */
     switch (mmu_idx) {
     case ARMMMUIdx_E10_1:
+    case ARMMMUIdx_E10_1_PAN:
     case ARMMMUIdx_SE10_1:
+    case ARMMMUIdx_SE10_1_PAN:
         /* TODO: ARMv8.3-NV */
         flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
         break;
     case ARMMMUIdx_E20_2:
+    case ARMMMUIdx_E20_2_PAN:
         /* TODO: ARMv8.4-SecEL2 */
         /*
          * Note that E20_2 is gated by HCR_EL2.E2H == 1, but E20_0 is
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 6e82486884..49631c2340 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -124,12 +124,15 @@ static int get_a64_user_mem_index(DisasContext *s)
          */
         switch (useridx) {
         case ARMMMUIdx_E10_1:
+        case ARMMMUIdx_E10_1_PAN:
             useridx = ARMMMUIdx_E10_0;
             break;
         case ARMMMUIdx_E20_2:
+        case ARMMMUIdx_E20_2_PAN:
             useridx = ARMMMUIdx_E20_0;
             break;
         case ARMMMUIdx_SE10_1:
+        case ARMMMUIdx_SE10_1_PAN:
             useridx = ARMMMUIdx_SE10_0;
             break;
         default:
diff --git a/target/arm/translate.c b/target/arm/translate.c
index e11a5871d0..d58c328e08 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -155,10 +155,12 @@ static inline int get_a32_user_mem_index(DisasContext *s)
     case ARMMMUIdx_E2:        /* this one is UNPREDICTABLE */
     case ARMMMUIdx_E10_0:
     case ARMMMUIdx_E10_1:
+    case ARMMMUIdx_E10_1_PAN:
         return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
     case ARMMMUIdx_SE3:
     case ARMMMUIdx_SE10_0:
     case ARMMMUIdx_SE10_1:
+    case ARMMMUIdx_SE10_1_PAN:
         return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
     case ARMMMUIdx_MUser:
     case ARMMMUIdx_MPriv:
-- 
2.20.1



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

* [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2 Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-03 12:24   ` Alex Bennée
  2020-02-02  1:04 ` [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope Richard Henderson
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Include definitions for all of the bits in ID_MMFR3.
We already have a definition for ID_AA64MMFR1.PAN.

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

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c63bceaaa5..08b2f5d73e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1727,6 +1727,15 @@ FIELD(ID_ISAR6, FHM, 8, 4)
 FIELD(ID_ISAR6, SB, 12, 4)
 FIELD(ID_ISAR6, SPECRES, 16, 4)
 
+FIELD(ID_MMFR3, CMAINTVA, 0, 4)
+FIELD(ID_MMFR3, CMAINTSW, 4, 4)
+FIELD(ID_MMFR3, BPMAINT, 8, 4)
+FIELD(ID_MMFR3, MAINTBCST, 12, 4)
+FIELD(ID_MMFR3, PAN, 16, 4)
+FIELD(ID_MMFR3, COHWALK, 20, 4)
+FIELD(ID_MMFR3, CMEMSZ, 24, 4)
+FIELD(ID_MMFR3, SUPERSEC, 28, 4)
+
 FIELD(ID_MMFR4, SPECSEI, 0, 4)
 FIELD(ID_MMFR4, AC2, 4, 4)
 FIELD(ID_MMFR4, XNX, 8, 4)
@@ -3443,6 +3452,16 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
     return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
 }
 
+static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0;
+}
+
+static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
+}
+
 /*
  * 64-bit feature tests via id registers.
  */
@@ -3602,6 +3621,16 @@ static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
     return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
 }
 
+static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0;
+}
+
+static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
+}
+
 static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
 {
     return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
-- 
2.20.1



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

* [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (2 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1 Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-03 12:25   ` Alex Bennée
  2020-02-02  1:04 ` [PATCH v2 05/14] target/arm: Update MSR access for PAN Richard Henderson
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

For static const regdefs, file scope is preferred.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 739d2d4cc5..795ef727d0 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6343,6 +6343,35 @@ static CPAccessResult access_lor_other(CPUARMState *env,
     return access_lor_ns(env);
 }
 
+/*
+ * A trivial implementation of ARMv8.1-LOR leaves all of these
+ * registers fixed at 0, which indicates that there are zero
+ * supported Limited Ordering regions.
+ */
+static const ARMCPRegInfo lor_reginfo[] = {
+    { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
+      .access = PL1_RW, .accessfn = access_lor_other,
+      .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
+      .access = PL1_RW, .accessfn = access_lor_other,
+      .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
+      .access = PL1_RW, .accessfn = access_lor_other,
+      .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
+      .access = PL1_RW, .accessfn = access_lor_other,
+      .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
+      .access = PL1_R, .accessfn = access_lorid,
+      .type = ARM_CP_CONST, .resetvalue = 0 },
+    REGINFO_SENTINEL
+};
+
 #ifdef TARGET_AARCH64
 static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *ri,
                                    bool isread)
@@ -7577,34 +7606,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
     }
 
     if (cpu_isar_feature(aa64_lor, cpu)) {
-        /*
-         * A trivial implementation of ARMv8.1-LOR leaves all of these
-         * registers fixed at 0, which indicates that there are zero
-         * supported Limited Ordering regions.
-         */
-        static const ARMCPRegInfo lor_reginfo[] = {
-            { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
-              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
-              .access = PL1_RW, .accessfn = access_lor_other,
-              .type = ARM_CP_CONST, .resetvalue = 0 },
-            { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
-              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
-              .access = PL1_RW, .accessfn = access_lor_other,
-              .type = ARM_CP_CONST, .resetvalue = 0 },
-            { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
-              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
-              .access = PL1_RW, .accessfn = access_lor_other,
-              .type = ARM_CP_CONST, .resetvalue = 0 },
-            { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
-              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
-              .access = PL1_RW, .accessfn = access_lor_other,
-              .type = ARM_CP_CONST, .resetvalue = 0 },
-            { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
-              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
-              .access = PL1_R, .accessfn = access_lorid,
-              .type = ARM_CP_CONST, .resetvalue = 0 },
-            REGINFO_SENTINEL
-        };
         define_arm_cp_regs(cpu, lor_reginfo);
     }
 
-- 
2.20.1



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

* [PATCH v2 05/14] target/arm: Update MSR access for PAN
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (3 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-03 13:37   ` Alex Bennée
  2020-02-02  1:04 ` [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el " Richard Henderson
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

For aarch64, there's a dedicated msr (imm, reg) insn.
For aarch32, this is done via msr to cpsr; and writes
from el0 are ignored.

Since v8.0, the CPSR_RESERVED bits have been allocated.
We are not yet implementing ARMv8.0-SSBS or ARMv8.4-DIT,
so retain CPSR_RESERVED for now, so that the bits remain RES0.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Move regdef to file scope; merge patch for CPSR_RESERVED:
    do not remove CPSR_SSBS from CPSR_RESERVED yet, mask PAN
    from CPSR if feature not enabled (pmm).
---
 target/arm/cpu.h           | 11 +++++++++--
 target/arm/helper-a64.c    |  6 ++++++
 target/arm/helper.c        | 21 +++++++++++++++++++++
 target/arm/op_helper.c     |  9 ++++++++-
 target/arm/translate-a64.c | 14 ++++++++++++++
 target/arm/translate.c     |  6 +++++-
 6 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 08b2f5d73e..b11fdc3001 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1186,12 +1186,18 @@ void pmu_init(ARMCPU *cpu);
 #define CPSR_IT_2_7 (0xfc00U)
 #define CPSR_GE (0xfU << 16)
 #define CPSR_IL (1U << 20)
-/* Note that the RESERVED bits include bit 21, which is PSTATE_SS in
+/*
+ * Note that the RESERVED bits include bit 21, which is PSTATE_SS in
  * an AArch64 SPSR but RES0 in AArch32 SPSR and CPSR. In QEMU we use
  * env->uncached_cpsr bit 21 to store PSTATE.SS when executing in AArch32,
  * where it is live state but not accessible to the AArch32 code.
+ *
+ * TODO: With ARMv8.4-DIT, bit 21 is DIT in AArch32 (bit 24 for AArch64).
+ * We will need to move AArch32 SS somewhere else at that point.
+ * TODO: With ARMv8.0-SSBS, bit 23 is SSBS in AArch32 (bit 12 for AArch64).
  */
-#define CPSR_RESERVED (0x7U << 21)
+#define CPSR_RESERVED (5U << 21)
+#define CPSR_PAN (1U << 22)
 #define CPSR_J (1U << 24)
 #define CPSR_IT_0_1 (3U << 25)
 #define CPSR_Q (1U << 27)
@@ -1258,6 +1264,7 @@ void pmu_init(ARMCPU *cpu);
 #define PSTATE_BTYPE (3U << 10)
 #define PSTATE_IL (1U << 20)
 #define PSTATE_SS (1U << 21)
+#define PSTATE_PAN (1U << 22)
 #define PSTATE_V (1U << 28)
 #define PSTATE_C (1U << 29)
 #define PSTATE_Z (1U << 30)
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index bf45f8a785..70d6407f80 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -1014,6 +1014,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
          * will sort the register banks out for us, and we've already
          * caught all the bad-mode cases in el_from_spsr().
          */
+        if (!cpu_isar_feature(aa32_pan, env_archcpu(env))) {
+            spsr &= ~CPSR_PAN;
+        }
         cpsr_write(env, spsr, ~0, CPSRWriteRaw);
         if (!arm_singlestep_active(env)) {
             env->uncached_cpsr &= ~PSTATE_SS;
@@ -1031,6 +1034,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
                       cur_el, new_el, env->regs[15]);
     } else {
         env->aarch64 = 1;
+        if (!cpu_isar_feature(aa64_pan, env_archcpu(env))) {
+            spsr &= ~PSTATE_PAN;
+        }
         pstate_write(env, spsr);
         if (!arm_singlestep_active(env)) {
             env->pstate &= ~PSTATE_SS;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 795ef727d0..90a22921dc 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4163,6 +4163,24 @@ static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
     env->daif = value & PSTATE_DAIF;
 }
 
+static uint64_t aa64_pan_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    return env->pstate & PSTATE_PAN;
+}
+
+static void aa64_pan_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                           uint64_t value)
+{
+    env->pstate = (env->pstate & ~PSTATE_PAN) | (value & PSTATE_PAN);
+}
+
+static const ARMCPRegInfo pan_reginfo = {
+    .name = "PAN", .state = ARM_CP_STATE_AA64,
+    .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 3,
+    .type = ARM_CP_NO_RAW, .access = PL1_RW,
+    .readfn = aa64_pan_read, .writefn = aa64_pan_write
+};
+
 static CPAccessResult aa64_cacheop_access(CPUARMState *env,
                                           const ARMCPRegInfo *ri,
                                           bool isread)
@@ -7608,6 +7626,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
     if (cpu_isar_feature(aa64_lor, cpu)) {
         define_arm_cp_regs(cpu, lor_reginfo);
     }
+    if (cpu_isar_feature(aa64_pan, cpu)) {
+        define_one_arm_cp_reg(cpu, &pan_reginfo);
+    }
 
     if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
         define_arm_cp_regs(cpu, vhe_reginfo);
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 27d16ad9ad..7ba578e826 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -400,11 +400,18 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
 /* Write the CPSR for a 32-bit exception return */
 void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
 {
+    uint32_t mask;
+
     qemu_mutex_lock_iothread();
     arm_call_pre_el_change_hook(env_archcpu(env));
     qemu_mutex_unlock_iothread();
 
-    cpsr_write(env, val, CPSR_ERET_MASK, CPSRWriteExceptionReturn);
+    mask = CPSR_ERET_MASK;
+    if (!cpu_isar_feature(aa32_pan, env_archcpu(env))) {
+        mask &= ~CPSR_PAN;
+    }
+
+    cpsr_write(env, val, mask, CPSRWriteExceptionReturn);
 
     /* Generated code has already stored the new PC value, but
      * without masking out its low bits, because which bits need
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 49631c2340..d8ba240a15 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1602,6 +1602,20 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
         s->base.is_jmp = DISAS_NEXT;
         break;
 
+    case 0x04: /* PAN */
+        if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
+            goto do_unallocated;
+        }
+        if (crm & 1) {
+            set_pstate_bits(PSTATE_PAN);
+        } else {
+            clear_pstate_bits(PSTATE_PAN);
+        }
+        t1 = tcg_const_i32(s->current_el);
+        gen_helper_rebuild_hflags_a64(cpu_env, t1);
+        tcg_temp_free_i32(t1);
+        break;
+
     case 0x05: /* SPSel */
         if (s->current_el == 0) {
             goto do_unallocated;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index d58c328e08..0b1f0e0fea 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -2760,13 +2760,17 @@ static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
     if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
         mask &= ~CPSR_IT;
     }
+    if (!dc_isar_feature(aa32_pan, s)) {
+        mask &= ~CPSR_PAN;
+    }
     /* Mask out execution state and reserved bits.  */
     if (!spsr) {
         mask &= ~(CPSR_EXEC | CPSR_RESERVED);
     }
     /* Mask out privileged bits.  */
-    if (IS_USER(s))
+    if (IS_USER(s)) {
         mask &= CPSR_USER;
+    }
     return mask;
 }
 
-- 
2.20.1



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

* [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el for PAN
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (4 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 05/14] target/arm: Update MSR access for PAN Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-03 13:38   ` Alex Bennée
  2020-02-02  1:04 ` [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot Richard Henderson
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Examine the PAN bit for EL1, EL2, and Secure EL1 to
determine if it applies.

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 90a22921dc..638abe6af0 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11904,13 +11904,22 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
         return ARMMMUIdx_E10_0;
     case 1:
         if (arm_is_secure_below_el3(env)) {
+            if (env->pstate & PSTATE_PAN) {
+                return ARMMMUIdx_SE10_1_PAN;
+            }
             return ARMMMUIdx_SE10_1;
         }
+        if (env->pstate & PSTATE_PAN) {
+            return ARMMMUIdx_E10_1_PAN;
+        }
         return ARMMMUIdx_E10_1;
     case 2:
         /* TODO: ARMv8.4-SecEL2 */
         /* Note that TGE does not apply at EL2.  */
         if ((env->cp15.hcr_el2 & HCR_E2H) && arm_el_is_aa64(env, 2)) {
+            if (env->pstate & PSTATE_PAN) {
+                return ARMMMUIdx_E20_2_PAN;
+            }
             return ARMMMUIdx_E20_2;
         }
         return ARMMMUIdx_E2;
-- 
2.20.1



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

* [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (5 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el " Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-03 14:30   ` Alex Bennée
  2020-02-02  1:04 ` [PATCH v2 08/14] target/arm: Set PAN bit as required on exception entry Richard Henderson
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

If we have a PAN-enforcing mmu_idx, set prot == 0 if user_rw != 0.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/internals.h | 13 +++++++++++++
 target/arm/helper.c    |  3 +++
 2 files changed, 16 insertions(+)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 6be8b2d1a9..819de9037f 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -893,6 +893,19 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
     }
 }
 
+static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
+{
+    switch (mmu_idx) {
+    case ARMMMUIdx_Stage1_E1_PAN:
+    case ARMMMUIdx_E10_1_PAN:
+    case ARMMMUIdx_E20_2_PAN:
+    case ARMMMUIdx_SE10_1_PAN:
+        return true;
+    default:
+        return false;
+    }
+}
+
 /* Return the FSR value for a debug exception (watchpoint, hardware
  * breakpoint or BKPT insn) targeting the specified exception level.
  */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 638abe6af0..18e4cbb63c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9578,6 +9578,9 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
     if (is_user) {
         prot_rw = user_rw;
     } else {
+        if (user_rw && regime_is_pan(env, mmu_idx)) {
+            return 0;
+        }
         prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
     }
 
-- 
2.20.1



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

* [PATCH v2 08/14] target/arm: Set PAN bit as required on exception entry
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (6 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 09/14] target/arm: Implement ATS1E1 system registers Richard Henderson
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

The PAN bit is preserved, or set as per SCTLR_ELx.SPAN,
plus several other conditions listed in the ARM ARM.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Tidy preservation of CPSR_PAN in take_aarch32_exception (pmm).
---
 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 18e4cbb63c..4c0eb7e7d9 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8772,8 +8772,12 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
                                    uint32_t mask, uint32_t offset,
                                    uint32_t newpc)
 {
+    int new_el;
+
     /* Change the CPU state so as to actually take the exception. */
     switch_mode(env, new_mode);
+    new_el = arm_current_el(env);
+
     /*
      * For exceptions taken to AArch32 we must clear the SS bit in both
      * PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now.
@@ -8786,7 +8790,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 (env->cp15.sctlr_el[new_el] & SCTLR_EE) {
         env->uncached_cpsr |= CPSR_E;
     }
     /* J and IL must always be cleared for exception entry */
@@ -8797,6 +8801,12 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
         env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
         env->elr_el[2] = env->regs[15];
     } else {
+        /* CPSR.PAN is preserved unless target is EL1 and SCTLR.SPAN == 0. */
+        if (cpu_isar_feature(aa64_pan, env_archcpu(env))
+            && new_el == 1
+            && !(env->cp15.sctlr_el[1] & SCTLR_SPAN)) {
+            env->uncached_cpsr |= CPSR_PAN;
+        }
         /*
          * this is a lie, as there was no c1_sys on V4T/V5, but who cares
          * and we should just guard the thumb mode on V4
@@ -9059,6 +9069,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
     unsigned int new_el = env->exception.target_el;
     target_ulong addr = env->cp15.vbar_el[new_el];
     unsigned int new_mode = aarch64_pstate_mode(new_el, true);
+    unsigned int old_mode;
     unsigned int cur_el = arm_current_el(env);
 
     /*
@@ -9138,20 +9149,43 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
     }
 
     if (is_a64(env)) {
-        env->banked_spsr[aarch64_banked_spsr_index(new_el)] = pstate_read(env);
+        old_mode = pstate_read(env);
         aarch64_save_sp(env, arm_current_el(env));
         env->elr_el[new_el] = env->pc;
     } else {
-        env->banked_spsr[aarch64_banked_spsr_index(new_el)] = cpsr_read(env);
+        old_mode = cpsr_read(env);
         env->elr_el[new_el] = env->regs[15];
 
         aarch64_sync_32_to_64(env);
 
         env->condexec_bits = 0;
     }
+    env->banked_spsr[aarch64_banked_spsr_index(new_el)] = old_mode;
+
     qemu_log_mask(CPU_LOG_INT, "...with ELR 0x%" PRIx64 "\n",
                   env->elr_el[new_el]);
 
+    if (cpu_isar_feature(aa64_pan, cpu)) {
+        /* The value of PSTATE.PAN is normally preserved, except when ... */
+        new_mode |= old_mode & PSTATE_PAN;
+        switch (new_el) {
+        case 2:
+            /* ... the target is EL2 with HCR_EL2.{E2H,TGE} == '11' ...  */
+            if ((arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE))
+                != (HCR_E2H | HCR_TGE)) {
+                break;
+            }
+            /* fall through */
+        case 1:
+            /* ... the target is EL1 ... */
+            /* ... and SCTLR_ELx.SPAN == 0, then set to 1.  */
+            if ((env->cp15.sctlr_el[new_el] & SCTLR_SPAN) == 0) {
+                new_mode |= PSTATE_PAN;
+            }
+            break;
+        }
+    }
+
     pstate_write(env, PSTATE_DAIF | new_mode);
     env->aarch64 = 1;
     aarch64_restore_sp(env, new_el);
-- 
2.20.1



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

* [PATCH v2 09/14] target/arm: Implement ATS1E1 system registers
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (7 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 08/14] target/arm: Set PAN bit as required on exception entry Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 10/14] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max Richard Henderson
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

This is a minor enhancement over ARMv8.1-PAN.
The *_PAN mmu_idx are used with the existing do_ats_write.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Move regdefs to file scope (pmm).
---
 target/arm/helper.c | 56 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 50 insertions(+), 6 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 4c0eb7e7d9..e69cde801f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3409,16 +3409,21 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 
     switch (ri->opc2 & 6) {
     case 0:
-        /* stage 1 current state PL1: ATS1CPR, ATS1CPW */
+        /* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP */
         switch (el) {
         case 3:
             mmu_idx = ARMMMUIdx_SE3;
             break;
         case 2:
-            mmu_idx = ARMMMUIdx_Stage1_E1;
-            break;
+            g_assert(!secure);  /* TODO: ARMv8.4-SecEL2 */
+            /* fall through */
         case 1:
-            mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+            if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
+                mmu_idx = (secure ? ARMMMUIdx_SE10_1_PAN
+                           : ARMMMUIdx_Stage1_E1_PAN);
+            } else {
+                mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+            }
             break;
         default:
             g_assert_not_reached();
@@ -3487,8 +3492,13 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
     switch (ri->opc2 & 6) {
     case 0:
         switch (ri->opc1) {
-        case 0: /* AT S1E1R, AT S1E1W */
-            mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+        case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */
+            if (ri->crm == 9 && (env->pstate & PSTATE_PAN)) {
+                mmu_idx = (secure ? ARMMMUIdx_SE10_1_PAN
+                           : ARMMMUIdx_Stage1_E1_PAN);
+            } else {
+                mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+            }
             break;
         case 4: /* AT S1E2R, AT S1E2W */
             mmu_idx = ARMMMUIdx_E2;
@@ -6692,6 +6702,32 @@ static const ARMCPRegInfo vhe_reginfo[] = {
     REGINFO_SENTINEL
 };
 
+#ifndef CONFIG_USER_ONLY
+static const ARMCPRegInfo ats1e1_reginfo[] = {
+    { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
+      .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+      .writefn = ats_write64 },
+    { .name = "AT_S1E1W", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
+      .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+      .writefn = ats_write64 },
+    REGINFO_SENTINEL
+};
+
+static const ARMCPRegInfo ats1cp_reginfo[] = {
+    { .name = "ATS1CPRP",
+      .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
+      .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+      .writefn = ats_write },
+    { .name = "ATS1CPWP",
+      .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
+      .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+      .writefn = ats_write },
+    REGINFO_SENTINEL
+};
+#endif
+
 void register_cp_regs_for_features(ARMCPU *cpu)
 {
     /* Register all the coprocessor registers based on feature bits */
@@ -7629,6 +7665,14 @@ void register_cp_regs_for_features(ARMCPU *cpu)
     if (cpu_isar_feature(aa64_pan, cpu)) {
         define_one_arm_cp_reg(cpu, &pan_reginfo);
     }
+#ifndef CONFIG_USER_ONLY
+    if (cpu_isar_feature(aa64_ats1e1, cpu)) {
+        define_arm_cp_regs(cpu, ats1e1_reginfo);
+    }
+    if (cpu_isar_feature(aa32_ats1e1, cpu)) {
+        define_arm_cp_regs(cpu, ats1cp_reginfo);
+    }
+#endif
 
     if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
         define_arm_cp_regs(cpu, vhe_reginfo);
-- 
2.20.1



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

* [PATCH v2 10/14] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (8 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 09/14] target/arm: Implement ATS1E1 system registers Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 11/14] target/arm: Add ID_AA64MMFR2_EL1 Richard Henderson
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

This includes enablement of ARMv8.1-PAN.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.c   | 4 ++++
 target/arm/cpu64.c | 5 +++++
 2 files changed, 9 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index b0762a76c4..de733aceeb 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2709,6 +2709,10 @@ static void arm_max_initfn(Object *obj)
             t = FIELD_DP32(t, MVFR2, FPMISC, 4);   /* FP MaxNum */
             cpu->isar.mvfr2 = t;
 
+            t = cpu->id_mmfr3;
+            t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
+            cpu->id_mmfr3 = t;
+
             t = cpu->id_mmfr4;
             t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
             cpu->id_mmfr4 = t;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index c80fb5fd43..57fbc5eade 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, HPDS, 1); /* HPD */
         t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
         t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
+        t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
         cpu->isar.id_aa64mmfr1 = t;
 
         /* Replicate the same data to the 32-bit id registers.  */
@@ -693,6 +694,10 @@ static void aarch64_max_initfn(Object *obj)
         u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
         cpu->isar.id_isar6 = u;
 
+        u = cpu->id_mmfr3;
+        u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
+        cpu->id_mmfr3 = u;
+
         /*
          * FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
          * so do not set MVFR1.FPHP.  Strictly speaking this is not legal,
-- 
2.20.1



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

* [PATCH v2 11/14] target/arm: Add ID_AA64MMFR2_EL1
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (9 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 10/14] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 12/14] target/arm: Update MSR access to UAO Richard Henderson
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Add definitions for all of the fields, up to ARMv8.5.
Convert the existing RESERVED register to a full register.
Query KVM for the value of the register for the host.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h    | 17 +++++++++++++++++
 target/arm/helper.c |  4 ++--
 target/arm/kvm64.c  |  2 ++
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index b11fdc3001..a6a8f74be8 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -871,6 +871,7 @@ struct ARMCPU {
         uint64_t id_aa64pfr1;
         uint64_t id_aa64mmfr0;
         uint64_t id_aa64mmfr1;
+        uint64_t id_aa64mmfr2;
     } isar;
     uint32_t midr;
     uint32_t revidr;
@@ -1816,6 +1817,22 @@ FIELD(ID_AA64MMFR1, PAN, 20, 4)
 FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
 FIELD(ID_AA64MMFR1, XNX, 28, 4)
 
+FIELD(ID_AA64MMFR2, CNP, 0, 4)
+FIELD(ID_AA64MMFR2, UAO, 4, 4)
+FIELD(ID_AA64MMFR2, LSM, 8, 4)
+FIELD(ID_AA64MMFR2, IESB, 12, 4)
+FIELD(ID_AA64MMFR2, VARANGE, 16, 4)
+FIELD(ID_AA64MMFR2, CCIDX, 20, 4)
+FIELD(ID_AA64MMFR2, NV, 24, 4)
+FIELD(ID_AA64MMFR2, ST, 28, 4)
+FIELD(ID_AA64MMFR2, AT, 32, 4)
+FIELD(ID_AA64MMFR2, IDS, 36, 4)
+FIELD(ID_AA64MMFR2, FWB, 40, 4)
+FIELD(ID_AA64MMFR2, TTL, 48, 4)
+FIELD(ID_AA64MMFR2, BBM, 52, 4)
+FIELD(ID_AA64MMFR2, EVT, 56, 4)
+FIELD(ID_AA64MMFR2, E0PD, 60, 4)
+
 FIELD(ID_DFR0, COPDBG, 0, 4)
 FIELD(ID_DFR0, COPSDBG, 4, 4)
 FIELD(ID_DFR0, MMAPDBG, 8, 4)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e69cde801f..a48f37dc05 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7082,11 +7082,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
               .resetvalue = cpu->isar.id_aa64mmfr1 },
-            { .name = "ID_AA64MMFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
+            { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = 0 },
+              .resetvalue = cpu->isar.id_aa64mmfr2 },
             { .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index fb21ab9e73..3bae9e4a66 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -549,6 +549,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
                               ARM64_SYS_REG(3, 0, 0, 7, 0));
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
                               ARM64_SYS_REG(3, 0, 0, 7, 1));
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2,
+                              ARM64_SYS_REG(3, 0, 0, 7, 2));
 
         /*
          * Note that if AArch32 support is not present in the host,
-- 
2.20.1



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

* [PATCH v2 12/14] target/arm: Update MSR access to UAO
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (10 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 11/14] target/arm: Add ID_AA64MMFR2_EL1 Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 13/14] target/arm: Implement UAO semantics Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 14/14] target/arm: Enable ARMv8.2-UAO in -cpu max Richard Henderson
  13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Move reginfo to file scope; avoid setting uao from spsr
    when the feature is not enabled (pmm).
---
 target/arm/cpu.h           |  6 ++++++
 target/arm/helper-a64.c    |  3 +++
 target/arm/helper.c        | 21 +++++++++++++++++++++
 target/arm/translate-a64.c | 14 ++++++++++++++
 4 files changed, 44 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index a6a8f74be8..a0ac70e0fb 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1266,6 +1266,7 @@ void pmu_init(ARMCPU *cpu);
 #define PSTATE_IL (1U << 20)
 #define PSTATE_SS (1U << 21)
 #define PSTATE_PAN (1U << 22)
+#define PSTATE_UAO (1U << 23)
 #define PSTATE_V (1U << 28)
 #define PSTATE_C (1U << 29)
 #define PSTATE_Z (1U << 30)
@@ -3655,6 +3656,11 @@ static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
     return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
 }
 
+static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
+}
+
 static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
 {
     return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 70d6407f80..9dda94644f 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -1037,6 +1037,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
         if (!cpu_isar_feature(aa64_pan, env_archcpu(env))) {
             spsr &= ~PSTATE_PAN;
         }
+        if (!cpu_isar_feature(aa64_uao, env_archcpu(env))) {
+            spsr &= ~PSTATE_UAO;
+        }
         pstate_write(env, spsr);
         if (!arm_singlestep_active(env)) {
             env->pstate &= ~PSTATE_SS;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a48f37dc05..d847b0f40b 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4191,6 +4191,24 @@ static const ARMCPRegInfo pan_reginfo = {
     .readfn = aa64_pan_read, .writefn = aa64_pan_write
 };
 
+static uint64_t aa64_uao_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    return env->pstate & PSTATE_UAO;
+}
+
+static void aa64_uao_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                           uint64_t value)
+{
+    env->pstate = (env->pstate & ~PSTATE_UAO) | (value & PSTATE_UAO);
+}
+
+static const ARMCPRegInfo uao_reginfo = {
+    .name = "UAO", .state = ARM_CP_STATE_AA64,
+    .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 4,
+    .type = ARM_CP_NO_RAW, .access = PL1_RW,
+    .readfn = aa64_uao_read, .writefn = aa64_uao_write
+};
+
 static CPAccessResult aa64_cacheop_access(CPUARMState *env,
                                           const ARMCPRegInfo *ri,
                                           bool isread)
@@ -7673,6 +7691,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         define_arm_cp_regs(cpu, ats1cp_reginfo);
     }
 #endif
+    if (cpu_isar_feature(aa64_uao, cpu)) {
+        define_one_arm_cp_reg(cpu, &uao_reginfo);
+    }
 
     if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
         define_arm_cp_regs(cpu, vhe_reginfo);
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d8ba240a15..7c26c3bfeb 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1602,6 +1602,20 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
         s->base.is_jmp = DISAS_NEXT;
         break;
 
+    case 0x03: /* UAO */
+        if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
+            goto do_unallocated;
+        }
+        if (crm & 1) {
+            set_pstate_bits(PSTATE_UAO);
+        } else {
+            clear_pstate_bits(PSTATE_UAO);
+        }
+        t1 = tcg_const_i32(s->current_el);
+        gen_helper_rebuild_hflags_a64(cpu_env, t1);
+        tcg_temp_free_i32(t1);
+        break;
+
     case 0x04: /* PAN */
         if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
             goto do_unallocated;
-- 
2.20.1



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

* [PATCH v2 13/14] target/arm: Implement UAO semantics
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (11 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 12/14] target/arm: Update MSR access to UAO Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  2020-02-02  1:04 ` [PATCH v2 14/14] target/arm: Enable ARMv8.2-UAO in -cpu max Richard Henderson
  13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

We need only override the current condition under which
TBFLAG_A64.UNPRIV is set.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper.c | 41 +++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index d847b0f40b..b24a6a6526 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -12194,28 +12194,29 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
     }
 
     /* Compute the condition for using AccType_UNPRIV for LDTR et al. */
-    /* TODO: ARMv8.2-UAO */
-    switch (mmu_idx) {
-    case ARMMMUIdx_E10_1:
-    case ARMMMUIdx_E10_1_PAN:
-    case ARMMMUIdx_SE10_1:
-    case ARMMMUIdx_SE10_1_PAN:
-        /* TODO: ARMv8.3-NV */
-        flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
-        break;
-    case ARMMMUIdx_E20_2:
-    case ARMMMUIdx_E20_2_PAN:
-        /* TODO: ARMv8.4-SecEL2 */
-        /*
-         * Note that E20_2 is gated by HCR_EL2.E2H == 1, but E20_0 is
-         * gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
-         */
-        if (env->cp15.hcr_el2 & HCR_TGE) {
+    if (!(env->pstate & PSTATE_UAO)) {
+        switch (mmu_idx) {
+        case ARMMMUIdx_E10_1:
+        case ARMMMUIdx_E10_1_PAN:
+        case ARMMMUIdx_SE10_1:
+        case ARMMMUIdx_SE10_1_PAN:
+            /* TODO: ARMv8.3-NV */
             flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
+            break;
+        case ARMMMUIdx_E20_2:
+        case ARMMMUIdx_E20_2_PAN:
+            /* TODO: ARMv8.4-SecEL2 */
+            /*
+             * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is
+             * gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
+             */
+            if (env->cp15.hcr_el2 & HCR_TGE) {
+                flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
+            }
+            break;
+        default:
+            break;
         }
-        break;
-    default:
-        break;
     }
 
     return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
-- 
2.20.1



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

* [PATCH v2 14/14] target/arm: Enable ARMv8.2-UAO in -cpu max
  2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
                   ` (12 preceding siblings ...)
  2020-02-02  1:04 ` [PATCH v2 13/14] target/arm: Implement UAO semantics Richard Henderson
@ 2020-02-02  1:04 ` Richard Henderson
  13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02  1:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee

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

diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 57fbc5eade..1359564c55 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -676,6 +676,10 @@ static void aarch64_max_initfn(Object *obj)
         t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
         cpu->isar.id_aa64mmfr1 = t;
 
+        t = cpu->isar.id_aa64mmfr2;
+        t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
+        cpu->isar.id_aa64mmfr2 = t;
+
         /* Replicate the same data to the 32-bit id registers.  */
         u = cpu->isar.id_isar5;
         u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */
-- 
2.20.1



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

* Re: [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2
  2020-02-02  1:04 ` [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2 Richard Henderson
@ 2020-02-03 11:46   ` Alex Bennée
  0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 11:46 UTC (permalink / raw)
  To: Richard Henderson; +Cc: peter.maydell, Philippe Mathieu-Daudé, qemu-devel


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

> Use a common predicate for querying stage1-ness.
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

> ---
> v2: Rename from arm_mmu_idx_is_stage1 to arm_mmu_idx_is_stage1_of_2
> ---
>  target/arm/internals.h | 18 ++++++++++++++++++
>  target/arm/helper.c    |  8 +++-----
>  2 files changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 6d4a942bde..1f8ee5f573 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -1034,6 +1034,24 @@ static inline ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
>  ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
>  #endif
>  
> +/**
> + * arm_mmu_idx_is_stage1_of_2:
> + * @mmu_idx: The ARMMMUIdx to test
> + *
> + * Return true if @mmu_idx is a NOTLB mmu_idx that is the
> + * first stage of a two stage regime.
> + */
> +static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
> +{
> +    switch (mmu_idx) {
> +    case ARMMMUIdx_Stage1_E0:
> +    case ARMMMUIdx_Stage1_E1:
> +        return true;
> +    default:
> +        return false;
> +    }
> +}
> +
>  /*
>   * Parameters of a given virtual address, as extracted from the
>   * translation control register (TCR) for a given regime.
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 70b10428c5..852fd71dcc 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3261,8 +3261,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
>          bool take_exc = false;
>  
>          if (fi.s1ptw && current_el == 1 && !arm_is_secure(env)
> -            && (mmu_idx == ARMMMUIdx_Stage1_E1 ||
> -                mmu_idx == ARMMMUIdx_Stage1_E0)) {
> +            && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
>              /*
>               * Synchronous stage 2 fault on an access made as part of the
>               * translation table walk for AT S1E0* or AT S1E1* insn
> @@ -9294,8 +9293,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
>          }
>      }
>  
> -    if ((env->cp15.hcr_el2 & HCR_DC) &&
> -        (mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1)) {
> +    if ((env->cp15.hcr_el2 & HCR_DC) && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
>          /* HCR.DC means SCTLR_EL1.M behaves as 0 */
>          return true;
>      }
> @@ -9604,7 +9602,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
>                                 hwaddr addr, MemTxAttrs txattrs,
>                                 ARMMMUFaultInfo *fi)
>  {
> -    if ((mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1) &&
> +    if (arm_mmu_idx_is_stage1_of_2(mmu_idx) &&
>          !regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
>          target_ulong s2size;
>          hwaddr s2pa;


-- 
Alex Bennée


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

* Re: [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled
  2020-02-02  1:04 ` [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled Richard Henderson
@ 2020-02-03 11:54   ` Alex Bennée
  0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 11:54 UTC (permalink / raw)
  To: Richard Henderson; +Cc: peter.maydell, qemu-devel


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

> To implement PAN, we will want to swap, for short periods
> of time, to a different privileged mmu_idx.  In addition,
> we cannot do this with flushing alone, because the AT*
> instructions have both PAN and PAN-less versions.
>
> Add the ARMMMUIdx*_PAN constants where necessary next to
> the corresponding ARMMMUIdx* constant.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

> ---
>  target/arm/cpu-param.h     |  2 +-
>  target/arm/cpu.h           | 33 ++++++++++++++-------
>  target/arm/internals.h     |  9 ++++++
>  target/arm/helper.c        | 60 +++++++++++++++++++++++++++++++-------
>  target/arm/translate-a64.c |  3 ++
>  target/arm/translate.c     |  2 ++
>  6 files changed, 87 insertions(+), 22 deletions(-)
>
> diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
> index 18ac562346..d593b60b28 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 9
> +#define NB_MMU_MODES 12
>  
>  #endif
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 0b3036c484..c63bceaaa5 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2751,20 +2751,24 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
>   *  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.
> + *  6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
> + *     Never (PAN) bit within PSTATE.
>   *
>   * This gives us the following list of cases:
>   *
>   * NS EL0 EL1&0 stage 1+2 (aka NS PL0)
>   * 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 9 different mmu_idx.
> + * for a total of 12 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
> @@ -2819,19 +2823,22 @@ typedef enum ARMMMUIdx {
>      /*
>       * A-profile.
>       */
> -    ARMMMUIdx_E10_0 =  0 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_E20_0 =  1 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E10_0      =  0 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E20_0      =  1 | ARM_MMU_IDX_A,
>  
> -    ARMMMUIdx_E10_1 =  2 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E10_1      =  2 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E10_1_PAN  =  3 | ARM_MMU_IDX_A,
>  
> -    ARMMMUIdx_E2 =     3 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_E20_2 =  4 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E2         =  4 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E20_2      =  5 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_E20_2_PAN  =  6 | ARM_MMU_IDX_A,
>  
> -    ARMMMUIdx_SE10_0 = 5 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_SE10_1 = 6 | ARM_MMU_IDX_A,
> -    ARMMMUIdx_SE3 =    7 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_SE10_0     = 7 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_SE10_1     = 8 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_SE3        = 10 | ARM_MMU_IDX_A,
>  
> -    ARMMMUIdx_Stage2 = 8 | ARM_MMU_IDX_A,
> +    ARMMMUIdx_Stage2     = 11 | ARM_MMU_IDX_A,
>  
>      /*
>       * These are not allocated TLBs and are used only for AT system
> @@ -2839,6 +2846,7 @@ 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,
>  
>      /*
>       * M-profile.
> @@ -2864,10 +2872,13 @@ typedef enum ARMMMUIdxBit {
>      TO_CORE_BIT(E10_0),
>      TO_CORE_BIT(E20_0),
>      TO_CORE_BIT(E10_1),
> +    TO_CORE_BIT(E10_1_PAN),
>      TO_CORE_BIT(E2),
>      TO_CORE_BIT(E20_2),
> +    TO_CORE_BIT(E20_2_PAN),
>      TO_CORE_BIT(SE10_0),
>      TO_CORE_BIT(SE10_1),
> +    TO_CORE_BIT(SE10_1_PAN),
>      TO_CORE_BIT(SE3),
>      TO_CORE_BIT(Stage2),
>  
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 1f8ee5f573..6be8b2d1a9 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -843,12 +843,16 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
>      switch (mmu_idx) {
>      case ARMMMUIdx_Stage1_E0:
>      case ARMMMUIdx_Stage1_E1:
> +    case ARMMMUIdx_Stage1_E1_PAN:
>      case ARMMMUIdx_E10_0:
>      case ARMMMUIdx_E10_1:
> +    case ARMMMUIdx_E10_1_PAN:
>      case ARMMMUIdx_E20_0:
>      case ARMMMUIdx_E20_2:
> +    case ARMMMUIdx_E20_2_PAN:
>      case ARMMMUIdx_SE10_0:
>      case ARMMMUIdx_SE10_1:
> +    case ARMMMUIdx_SE10_1_PAN:
>          return true;
>      default:
>          return false;
> @@ -861,10 +865,13 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
>      switch (mmu_idx) {
>      case ARMMMUIdx_E10_0:
>      case ARMMMUIdx_E10_1:
> +    case ARMMMUIdx_E10_1_PAN:
>      case ARMMMUIdx_E20_0:
>      case ARMMMUIdx_E20_2:
> +    case ARMMMUIdx_E20_2_PAN:
>      case ARMMMUIdx_Stage1_E0:
>      case ARMMMUIdx_Stage1_E1:
> +    case ARMMMUIdx_Stage1_E1_PAN:
>      case ARMMMUIdx_E2:
>      case ARMMMUIdx_Stage2:
>      case ARMMMUIdx_MPrivNegPri:
> @@ -875,6 +882,7 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
>      case ARMMMUIdx_SE3:
>      case ARMMMUIdx_SE10_0:
>      case ARMMMUIdx_SE10_1:
> +    case ARMMMUIdx_SE10_1_PAN:
>      case ARMMMUIdx_MSPrivNegPri:
>      case ARMMMUIdx_MSUserNegPri:
>      case ARMMMUIdx_MSPriv:
> @@ -1046,6 +1054,7 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
>      switch (mmu_idx) {
>      case ARMMMUIdx_Stage1_E0:
>      case ARMMMUIdx_Stage1_E1:
> +    case ARMMMUIdx_Stage1_E1_PAN:
>          return true;
>      default:
>          return false;
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 852fd71dcc..739d2d4cc5 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -671,6 +671,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);
>  }
> @@ -682,6 +683,7 @@ 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);
>  }
> @@ -2700,6 +2702,7 @@ static int gt_phys_redir_timeridx(CPUARMState *env)
>      switch (arm_mmu_idx(env)) {
>      case ARMMMUIdx_E20_0:
>      case ARMMMUIdx_E20_2:
> +    case ARMMMUIdx_E20_2_PAN:
>          return GTIMER_HYP;
>      default:
>          return GTIMER_PHYS;
> @@ -2711,6 +2714,7 @@ static int gt_virt_redir_timeridx(CPUARMState *env)
>      switch (arm_mmu_idx(env)) {
>      case ARMMMUIdx_E20_0:
>      case ARMMMUIdx_E20_2:
> +    case ARMMMUIdx_E20_2_PAN:
>          return GTIMER_HYPVIRT;
>      default:
>          return GTIMER_VIRT;
> @@ -3337,7 +3341,9 @@ 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_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
> +            if (mmu_idx == ARMMMUIdx_E10_0 ||
> +                mmu_idx == ARMMMUIdx_E10_1 ||
> +                mmu_idx == ARMMMUIdx_E10_1_PAN) {
>                  format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
>              } else {
>                  format64 |= arm_current_el(env) == 2;
> @@ -3797,7 +3803,9 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      if (extract64(raw_read(env, ri) ^ value, 48, 16) &&
>          (arm_hcr_el2_eff(env) & HCR_E2H)) {
>          tlb_flush_by_mmuidx(env_cpu(env),
> -                            ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0);
> +                            ARMMMUIdxBit_E20_2 |
> +                            ARMMMUIdxBit_E20_2_PAN |
> +                            ARMMMUIdxBit_E20_0);
>      }
>      raw_write(env, ri, value);
>  }
> @@ -3815,6 +3823,7 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      if (raw_read(env, ri) != value) {
>          tlb_flush_by_mmuidx(cs,
>                              ARMMMUIdxBit_E10_1 |
> +                            ARMMMUIdxBit_E10_1_PAN |
>                              ARMMMUIdxBit_E10_0 |
>                              ARMMMUIdxBit_Stage2);
>          raw_write(env, ri, value);
> @@ -4175,12 +4184,18 @@ 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_SE10_1 | ARMMMUIdxBit_SE10_0;
> +        return ARMMMUIdxBit_SE10_1 |
> +               ARMMMUIdxBit_SE10_1_PAN |
> +               ARMMMUIdxBit_SE10_0;
>      } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
>                 == (HCR_E2H | HCR_TGE)) {
> -        return ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0;
> +        return ARMMMUIdxBit_E20_2 |
> +               ARMMMUIdxBit_E20_2_PAN |
> +               ARMMMUIdxBit_E20_0;
>      } else {
> -        return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
> +        return ARMMMUIdxBit_E10_1 |
> +               ARMMMUIdxBit_E10_1_PAN |
> +               ARMMMUIdxBit_E10_0;
>      }
>  }
>  
> @@ -4214,18 +4229,28 @@ static int alle1_tlbmask(CPUARMState *env)
>       * stage 1 translations.
>       */
>      if (arm_is_secure_below_el3(env)) {
> -        return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
> +        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_0 | ARMMMUIdxBit_Stage2;
> +        return ARMMMUIdxBit_E10_1 |
> +               ARMMMUIdxBit_E10_1_PAN |
> +               ARMMMUIdxBit_E10_0 |
> +               ARMMMUIdxBit_Stage2;
>      } else {
> -        return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
> +        return ARMMMUIdxBit_E10_1 |
> +               ARMMMUIdxBit_E10_1_PAN |
> +               ARMMMUIdxBit_E10_0;
>      }
>  }
>  
>  static int alle2_tlbmask(CPUARMState *env)
>  {
>      /* TODO: ARMv8.4-SecEL2 */
> -    return ARMMMUIdxBit_E20_0 | ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E2;
> +    return ARMMMUIdxBit_E20_0 |
> +           ARMMMUIdxBit_E20_2 |
> +           ARMMMUIdxBit_E20_2_PAN |
> +           ARMMMUIdxBit_E2;
>  }
>  
>  static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -9215,6 +9240,7 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
>      switch (mmu_idx) {
>      case ARMMMUIdx_E20_0:
>      case ARMMMUIdx_E20_2:
> +    case ARMMMUIdx_E20_2_PAN:
>      case ARMMMUIdx_Stage2:
>      case ARMMMUIdx_E2:
>          return 2;
> @@ -9223,10 +9249,13 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
>      case ARMMMUIdx_SE10_0:
>          return arm_el_is_aa64(env, 3) ? 1 : 3;
>      case ARMMMUIdx_SE10_1:
> +    case ARMMMUIdx_SE10_1_PAN:
>      case ARMMMUIdx_Stage1_E0:
>      case ARMMMUIdx_Stage1_E1:
> +    case ARMMMUIdx_Stage1_E1_PAN:
>      case ARMMMUIdx_E10_0:
>      case ARMMMUIdx_E10_1:
> +    case ARMMMUIdx_E10_1_PAN:
>      case ARMMMUIdx_MPrivNegPri:
>      case ARMMMUIdx_MUserNegPri:
>      case ARMMMUIdx_MPriv:
> @@ -9342,6 +9371,8 @@ static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
>          return ARMMMUIdx_Stage1_E0;
>      case ARMMMUIdx_E10_1:
>          return ARMMMUIdx_Stage1_E1;
> +    case ARMMMUIdx_E10_1_PAN:
> +        return ARMMMUIdx_Stage1_E1_PAN;
>      default:
>          return mmu_idx;
>      }
> @@ -9388,6 +9419,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
>          return false;
>      case ARMMMUIdx_E10_0:
>      case ARMMMUIdx_E10_1:
> +    case ARMMMUIdx_E10_1_PAN:
>          g_assert_not_reached();
>      }
>  }
> @@ -11280,7 +11312,9 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
>                     target_ulong *page_size,
>                     ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
>  {
> -    if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
> +    if (mmu_idx == ARMMMUIdx_E10_0 ||
> +        mmu_idx == ARMMMUIdx_E10_1 ||
> +        mmu_idx == ARMMMUIdx_E10_1_PAN) {
>          /* Call ourselves recursively to do the stage 1 and then stage 2
>           * translations.
>           */
> @@ -11807,10 +11841,13 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
>      case ARMMMUIdx_SE10_0:
>          return 0;
>      case ARMMMUIdx_E10_1:
> +    case ARMMMUIdx_E10_1_PAN:
>      case ARMMMUIdx_SE10_1:
> +    case ARMMMUIdx_SE10_1_PAN:
>          return 1;
>      case ARMMMUIdx_E2:
>      case ARMMMUIdx_E20_2:
> +    case ARMMMUIdx_E20_2_PAN:
>          return 2;
>      case ARMMMUIdx_SE3:
>          return 3;
> @@ -12027,11 +12064,14 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
>      /* TODO: ARMv8.2-UAO */
>      switch (mmu_idx) {
>      case ARMMMUIdx_E10_1:
> +    case ARMMMUIdx_E10_1_PAN:
>      case ARMMMUIdx_SE10_1:
> +    case ARMMMUIdx_SE10_1_PAN:
>          /* TODO: ARMv8.3-NV */
>          flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
>          break;
>      case ARMMMUIdx_E20_2:
> +    case ARMMMUIdx_E20_2_PAN:
>          /* TODO: ARMv8.4-SecEL2 */
>          /*
>           * Note that E20_2 is gated by HCR_EL2.E2H == 1, but E20_0 is
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 6e82486884..49631c2340 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -124,12 +124,15 @@ static int get_a64_user_mem_index(DisasContext *s)
>           */
>          switch (useridx) {
>          case ARMMMUIdx_E10_1:
> +        case ARMMMUIdx_E10_1_PAN:
>              useridx = ARMMMUIdx_E10_0;
>              break;
>          case ARMMMUIdx_E20_2:
> +        case ARMMMUIdx_E20_2_PAN:
>              useridx = ARMMMUIdx_E20_0;
>              break;
>          case ARMMMUIdx_SE10_1:
> +        case ARMMMUIdx_SE10_1_PAN:
>              useridx = ARMMMUIdx_SE10_0;
>              break;
>          default:
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index e11a5871d0..d58c328e08 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -155,10 +155,12 @@ static inline int get_a32_user_mem_index(DisasContext *s)
>      case ARMMMUIdx_E2:        /* this one is UNPREDICTABLE */
>      case ARMMMUIdx_E10_0:
>      case ARMMMUIdx_E10_1:
> +    case ARMMMUIdx_E10_1_PAN:
>          return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
>      case ARMMMUIdx_SE3:
>      case ARMMMUIdx_SE10_0:
>      case ARMMMUIdx_SE10_1:
> +    case ARMMMUIdx_SE10_1_PAN:
>          return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
>      case ARMMMUIdx_MUser:
>      case ARMMMUIdx_MPriv:


-- 
Alex Bennée


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

* Re: [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1
  2020-02-02  1:04 ` [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1 Richard Henderson
@ 2020-02-03 12:24   ` Alex Bennée
  0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 12:24 UTC (permalink / raw)
  To: Richard Henderson; +Cc: peter.maydell, qemu-devel


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

> Include definitions for all of the bits in ID_MMFR3.
> We already have a definition for ID_AA64MMFR1.PAN.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

> ---
>  target/arm/cpu.h | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index c63bceaaa5..08b2f5d73e 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1727,6 +1727,15 @@ FIELD(ID_ISAR6, FHM, 8, 4)
>  FIELD(ID_ISAR6, SB, 12, 4)
>  FIELD(ID_ISAR6, SPECRES, 16, 4)
>  
> +FIELD(ID_MMFR3, CMAINTVA, 0, 4)
> +FIELD(ID_MMFR3, CMAINTSW, 4, 4)
> +FIELD(ID_MMFR3, BPMAINT, 8, 4)
> +FIELD(ID_MMFR3, MAINTBCST, 12, 4)
> +FIELD(ID_MMFR3, PAN, 16, 4)
> +FIELD(ID_MMFR3, COHWALK, 20, 4)
> +FIELD(ID_MMFR3, CMEMSZ, 24, 4)
> +FIELD(ID_MMFR3, SUPERSEC, 28, 4)
> +
>  FIELD(ID_MMFR4, SPECSEI, 0, 4)
>  FIELD(ID_MMFR4, AC2, 4, 4)
>  FIELD(ID_MMFR4, XNX, 8, 4)
> @@ -3443,6 +3452,16 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
>      return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
>  }
>  
> +static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
> +{
> +    return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0;
> +}
> +
> +static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
> +{
> +    return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
> +}
> +
>  /*
>   * 64-bit feature tests via id registers.
>   */
> @@ -3602,6 +3621,16 @@ static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
>      return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
>  }
>  
> +static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
> +{
> +    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0;
> +}
> +
> +static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
> +{
> +    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
> +}
> +
>  static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
>  {
>      return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;


-- 
Alex Bennée


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

* Re: [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope
  2020-02-02  1:04 ` [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope Richard Henderson
@ 2020-02-03 12:25   ` Alex Bennée
  0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 12:25 UTC (permalink / raw)
  To: Richard Henderson; +Cc: peter.maydell, qemu-devel


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

> For static const regdefs, file scope is preferred.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

> ---
>  target/arm/helper.c | 57 +++++++++++++++++++++++----------------------
>  1 file changed, 29 insertions(+), 28 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 739d2d4cc5..795ef727d0 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -6343,6 +6343,35 @@ static CPAccessResult access_lor_other(CPUARMState *env,
>      return access_lor_ns(env);
>  }
>  
> +/*
> + * A trivial implementation of ARMv8.1-LOR leaves all of these
> + * registers fixed at 0, which indicates that there are zero
> + * supported Limited Ordering regions.
> + */
> +static const ARMCPRegInfo lor_reginfo[] = {
> +    { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
> +      .access = PL1_RW, .accessfn = access_lor_other,
> +      .type = ARM_CP_CONST, .resetvalue = 0 },
> +    { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
> +      .access = PL1_RW, .accessfn = access_lor_other,
> +      .type = ARM_CP_CONST, .resetvalue = 0 },
> +    { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
> +      .access = PL1_RW, .accessfn = access_lor_other,
> +      .type = ARM_CP_CONST, .resetvalue = 0 },
> +    { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
> +      .access = PL1_RW, .accessfn = access_lor_other,
> +      .type = ARM_CP_CONST, .resetvalue = 0 },
> +    { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
> +      .access = PL1_R, .accessfn = access_lorid,
> +      .type = ARM_CP_CONST, .resetvalue = 0 },
> +    REGINFO_SENTINEL
> +};
> +
>  #ifdef TARGET_AARCH64
>  static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *ri,
>                                     bool isread)
> @@ -7577,34 +7606,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>      }
>  
>      if (cpu_isar_feature(aa64_lor, cpu)) {
> -        /*
> -         * A trivial implementation of ARMv8.1-LOR leaves all of these
> -         * registers fixed at 0, which indicates that there are zero
> -         * supported Limited Ordering regions.
> -         */
> -        static const ARMCPRegInfo lor_reginfo[] = {
> -            { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
> -              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
> -              .access = PL1_RW, .accessfn = access_lor_other,
> -              .type = ARM_CP_CONST, .resetvalue = 0 },
> -            { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
> -              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
> -              .access = PL1_RW, .accessfn = access_lor_other,
> -              .type = ARM_CP_CONST, .resetvalue = 0 },
> -            { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
> -              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
> -              .access = PL1_RW, .accessfn = access_lor_other,
> -              .type = ARM_CP_CONST, .resetvalue = 0 },
> -            { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
> -              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
> -              .access = PL1_RW, .accessfn = access_lor_other,
> -              .type = ARM_CP_CONST, .resetvalue = 0 },
> -            { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
> -              .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
> -              .access = PL1_R, .accessfn = access_lorid,
> -              .type = ARM_CP_CONST, .resetvalue = 0 },
> -            REGINFO_SENTINEL
> -        };
>          define_arm_cp_regs(cpu, lor_reginfo);
>      }


-- 
Alex Bennée


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

* Re: [PATCH v2 05/14] target/arm: Update MSR access for PAN
  2020-02-02  1:04 ` [PATCH v2 05/14] target/arm: Update MSR access for PAN Richard Henderson
@ 2020-02-03 13:37   ` Alex Bennée
  0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 13:37 UTC (permalink / raw)
  To: Richard Henderson; +Cc: peter.maydell, qemu-devel


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

> For aarch64, there's a dedicated msr (imm, reg) insn.
> For aarch32, this is done via msr to cpsr; and writes
> from el0 are ignored.
>
> Since v8.0, the CPSR_RESERVED bits have been allocated.
> We are not yet implementing ARMv8.0-SSBS or ARMv8.4-DIT,
> so retain CPSR_RESERVED for now, so that the bits remain RES0.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

> ---
> v2: Move regdef to file scope; merge patch for CPSR_RESERVED:
>     do not remove CPSR_SSBS from CPSR_RESERVED yet, mask PAN
>     from CPSR if feature not enabled (pmm).
> ---
>  target/arm/cpu.h           | 11 +++++++++--
>  target/arm/helper-a64.c    |  6 ++++++
>  target/arm/helper.c        | 21 +++++++++++++++++++++
>  target/arm/op_helper.c     |  9 ++++++++-
>  target/arm/translate-a64.c | 14 ++++++++++++++
>  target/arm/translate.c     |  6 +++++-
>  6 files changed, 63 insertions(+), 4 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 08b2f5d73e..b11fdc3001 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1186,12 +1186,18 @@ void pmu_init(ARMCPU *cpu);
>  #define CPSR_IT_2_7 (0xfc00U)
>  #define CPSR_GE (0xfU << 16)
>  #define CPSR_IL (1U << 20)
> -/* Note that the RESERVED bits include bit 21, which is PSTATE_SS in
> +/*
> + * Note that the RESERVED bits include bit 21, which is PSTATE_SS in
>   * an AArch64 SPSR but RES0 in AArch32 SPSR and CPSR. In QEMU we use
>   * env->uncached_cpsr bit 21 to store PSTATE.SS when executing in AArch32,
>   * where it is live state but not accessible to the AArch32 code.
> + *
> + * TODO: With ARMv8.4-DIT, bit 21 is DIT in AArch32 (bit 24 for AArch64).
> + * We will need to move AArch32 SS somewhere else at that point.
> + * TODO: With ARMv8.0-SSBS, bit 23 is SSBS in AArch32 (bit 12 for AArch64).
>   */
> -#define CPSR_RESERVED (0x7U << 21)
> +#define CPSR_RESERVED (5U << 21)
> +#define CPSR_PAN (1U << 22)
>  #define CPSR_J (1U << 24)
>  #define CPSR_IT_0_1 (3U << 25)
>  #define CPSR_Q (1U << 27)
> @@ -1258,6 +1264,7 @@ void pmu_init(ARMCPU *cpu);
>  #define PSTATE_BTYPE (3U << 10)
>  #define PSTATE_IL (1U << 20)
>  #define PSTATE_SS (1U << 21)
> +#define PSTATE_PAN (1U << 22)
>  #define PSTATE_V (1U << 28)
>  #define PSTATE_C (1U << 29)
>  #define PSTATE_Z (1U << 30)
> diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
> index bf45f8a785..70d6407f80 100644
> --- a/target/arm/helper-a64.c
> +++ b/target/arm/helper-a64.c
> @@ -1014,6 +1014,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
>           * will sort the register banks out for us, and we've already
>           * caught all the bad-mode cases in el_from_spsr().
>           */
> +        if (!cpu_isar_feature(aa32_pan, env_archcpu(env))) {
> +            spsr &= ~CPSR_PAN;
> +        }
>          cpsr_write(env, spsr, ~0, CPSRWriteRaw);
>          if (!arm_singlestep_active(env)) {
>              env->uncached_cpsr &= ~PSTATE_SS;
> @@ -1031,6 +1034,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
>                        cur_el, new_el, env->regs[15]);
>      } else {
>          env->aarch64 = 1;
> +        if (!cpu_isar_feature(aa64_pan, env_archcpu(env))) {
> +            spsr &= ~PSTATE_PAN;
> +        }
>          pstate_write(env, spsr);
>          if (!arm_singlestep_active(env)) {
>              env->pstate &= ~PSTATE_SS;
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 795ef727d0..90a22921dc 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -4163,6 +4163,24 @@ static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
>      env->daif = value & PSTATE_DAIF;
>  }
>  
> +static uint64_t aa64_pan_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> +    return env->pstate & PSTATE_PAN;
> +}
> +
> +static void aa64_pan_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                           uint64_t value)
> +{
> +    env->pstate = (env->pstate & ~PSTATE_PAN) | (value & PSTATE_PAN);
> +}
> +
> +static const ARMCPRegInfo pan_reginfo = {
> +    .name = "PAN", .state = ARM_CP_STATE_AA64,
> +    .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 3,
> +    .type = ARM_CP_NO_RAW, .access = PL1_RW,
> +    .readfn = aa64_pan_read, .writefn = aa64_pan_write
> +};
> +
>  static CPAccessResult aa64_cacheop_access(CPUARMState *env,
>                                            const ARMCPRegInfo *ri,
>                                            bool isread)
> @@ -7608,6 +7626,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>      if (cpu_isar_feature(aa64_lor, cpu)) {
>          define_arm_cp_regs(cpu, lor_reginfo);
>      }
> +    if (cpu_isar_feature(aa64_pan, cpu)) {
> +        define_one_arm_cp_reg(cpu, &pan_reginfo);
> +    }
>  
>      if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
>          define_arm_cp_regs(cpu, vhe_reginfo);
> diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
> index 27d16ad9ad..7ba578e826 100644
> --- a/target/arm/op_helper.c
> +++ b/target/arm/op_helper.c
> @@ -400,11 +400,18 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
>  /* Write the CPSR for a 32-bit exception return */
>  void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
>  {
> +    uint32_t mask;
> +
>      qemu_mutex_lock_iothread();
>      arm_call_pre_el_change_hook(env_archcpu(env));
>      qemu_mutex_unlock_iothread();
>  
> -    cpsr_write(env, val, CPSR_ERET_MASK, CPSRWriteExceptionReturn);
> +    mask = CPSR_ERET_MASK;
> +    if (!cpu_isar_feature(aa32_pan, env_archcpu(env))) {
> +        mask &= ~CPSR_PAN;
> +    }
> +
> +    cpsr_write(env, val, mask, CPSRWriteExceptionReturn);
>  
>      /* Generated code has already stored the new PC value, but
>       * without masking out its low bits, because which bits need
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 49631c2340..d8ba240a15 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -1602,6 +1602,20 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
>          s->base.is_jmp = DISAS_NEXT;
>          break;
>  
> +    case 0x04: /* PAN */
> +        if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
> +            goto do_unallocated;
> +        }
> +        if (crm & 1) {
> +            set_pstate_bits(PSTATE_PAN);
> +        } else {
> +            clear_pstate_bits(PSTATE_PAN);
> +        }
> +        t1 = tcg_const_i32(s->current_el);
> +        gen_helper_rebuild_hflags_a64(cpu_env, t1);
> +        tcg_temp_free_i32(t1);
> +        break;
> +
>      case 0x05: /* SPSel */
>          if (s->current_el == 0) {
>              goto do_unallocated;
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index d58c328e08..0b1f0e0fea 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -2760,13 +2760,17 @@ static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
>      if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
>          mask &= ~CPSR_IT;
>      }
> +    if (!dc_isar_feature(aa32_pan, s)) {
> +        mask &= ~CPSR_PAN;
> +    }
>      /* Mask out execution state and reserved bits.  */
>      if (!spsr) {
>          mask &= ~(CPSR_EXEC | CPSR_RESERVED);
>      }
>      /* Mask out privileged bits.  */
> -    if (IS_USER(s))
> +    if (IS_USER(s)) {
>          mask &= CPSR_USER;
> +    }
>      return mask;
>  }


-- 
Alex Bennée


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

* Re: [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el for PAN
  2020-02-02  1:04 ` [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el " Richard Henderson
@ 2020-02-03 13:38   ` Alex Bennée
  0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 13:38 UTC (permalink / raw)
  To: Richard Henderson; +Cc: peter.maydell, qemu-devel


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

> Examine the PAN bit for EL1, EL2, and Secure EL1 to
> determine if it applies.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

> ---
>  target/arm/helper.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 90a22921dc..638abe6af0 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -11904,13 +11904,22 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
>          return ARMMMUIdx_E10_0;
>      case 1:
>          if (arm_is_secure_below_el3(env)) {
> +            if (env->pstate & PSTATE_PAN) {
> +                return ARMMMUIdx_SE10_1_PAN;
> +            }
>              return ARMMMUIdx_SE10_1;
>          }
> +        if (env->pstate & PSTATE_PAN) {
> +            return ARMMMUIdx_E10_1_PAN;
> +        }
>          return ARMMMUIdx_E10_1;
>      case 2:
>          /* TODO: ARMv8.4-SecEL2 */
>          /* Note that TGE does not apply at EL2.  */
>          if ((env->cp15.hcr_el2 & HCR_E2H) && arm_el_is_aa64(env, 2)) {
> +            if (env->pstate & PSTATE_PAN) {
> +                return ARMMMUIdx_E20_2_PAN;
> +            }
>              return ARMMMUIdx_E20_2;
>          }
>          return ARMMMUIdx_E2;


-- 
Alex Bennée


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

* Re: [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot
  2020-02-02  1:04 ` [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot Richard Henderson
@ 2020-02-03 14:30   ` Alex Bennée
  0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 14:30 UTC (permalink / raw)
  To: Richard Henderson; +Cc: peter.maydell, qemu-devel


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

> If we have a PAN-enforcing mmu_idx, set prot == 0 if user_rw != 0.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

> ---
>  target/arm/internals.h | 13 +++++++++++++
>  target/arm/helper.c    |  3 +++
>  2 files changed, 16 insertions(+)
>
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 6be8b2d1a9..819de9037f 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -893,6 +893,19 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
>      }
>  }
>  
> +static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
> +{
> +    switch (mmu_idx) {
> +    case ARMMMUIdx_Stage1_E1_PAN:
> +    case ARMMMUIdx_E10_1_PAN:
> +    case ARMMMUIdx_E20_2_PAN:
> +    case ARMMMUIdx_SE10_1_PAN:
> +        return true;
> +    default:
> +        return false;
> +    }
> +}
> +
>  /* Return the FSR value for a debug exception (watchpoint, hardware
>   * breakpoint or BKPT insn) targeting the specified exception level.
>   */
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 638abe6af0..18e4cbb63c 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -9578,6 +9578,9 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
>      if (is_user) {
>          prot_rw = user_rw;
>      } else {
> +        if (user_rw && regime_is_pan(env, mmu_idx)) {
> +            return 0;
> +        }
>          prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
>      }


-- 
Alex Bennée


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

end of thread, other threads:[~2020-02-03 14:31 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-02-02  1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
2020-02-02  1:04 ` [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2 Richard Henderson
2020-02-03 11:46   ` Alex Bennée
2020-02-02  1:04 ` [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled Richard Henderson
2020-02-03 11:54   ` Alex Bennée
2020-02-02  1:04 ` [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1 Richard Henderson
2020-02-03 12:24   ` Alex Bennée
2020-02-02  1:04 ` [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope Richard Henderson
2020-02-03 12:25   ` Alex Bennée
2020-02-02  1:04 ` [PATCH v2 05/14] target/arm: Update MSR access for PAN Richard Henderson
2020-02-03 13:37   ` Alex Bennée
2020-02-02  1:04 ` [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el " Richard Henderson
2020-02-03 13:38   ` Alex Bennée
2020-02-02  1:04 ` [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot Richard Henderson
2020-02-03 14:30   ` Alex Bennée
2020-02-02  1:04 ` [PATCH v2 08/14] target/arm: Set PAN bit as required on exception entry Richard Henderson
2020-02-02  1:04 ` [PATCH v2 09/14] target/arm: Implement ATS1E1 system registers Richard Henderson
2020-02-02  1:04 ` [PATCH v2 10/14] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max Richard Henderson
2020-02-02  1:04 ` [PATCH v2 11/14] target/arm: Add ID_AA64MMFR2_EL1 Richard Henderson
2020-02-02  1:04 ` [PATCH v2 12/14] target/arm: Update MSR access to UAO Richard Henderson
2020-02-02  1:04 ` [PATCH v2 13/14] target/arm: Implement UAO semantics Richard Henderson
2020-02-02  1:04 ` [PATCH v2 14/14] target/arm: Enable ARMv8.2-UAO in -cpu max Richard Henderson

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).