diff mbox series

[v2,06/10] target/arm: Use arm_hcr_el2_eff more places

Message ID 20181203203839.757-7-richard.henderson@linaro.org
State New
Headers show
Series target/arm: LOR, HPD, AA32HPD | expand

Commit Message

Richard Henderson Dec. 3, 2018, 8:38 p.m. UTC
Since arm_hcr_el2_eff includes a check against
arm_is_secure_below_el3, we can often remove a
nearby check against secure state.

In some cases, sort the call to arm_hcr_el2_eff
to the end of a short-circuit logical sequence.

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

---
 target/arm/helper.c    | 22 ++++++++++++----------
 target/arm/op_helper.c | 14 ++++++--------
 2 files changed, 18 insertions(+), 18 deletions(-)

-- 
2.17.2

Comments

Peter Maydell Dec. 6, 2018, 1:06 p.m. UTC | #1
On Mon, 3 Dec 2018 at 20:38, Richard Henderson
<richard.henderson@linaro.org> wrote:
>

> Since arm_hcr_el2_eff includes a check against

> arm_is_secure_below_el3, we can often remove a

> nearby check against secure state.

>

> In some cases, sort the call to arm_hcr_el2_eff

> to the end of a short-circuit logical sequence.

>

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

> ---



> @@ -8797,6 +8795,8 @@ static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)

>  static inline bool regime_translation_disabled(CPUARMState *env,

>                                                 ARMMMUIdx mmu_idx)

>  {

> +    uint64_t hcr_el2;

> +

>      if (arm_feature(env, ARM_FEATURE_M)) {

>          switch (env->v7m.mpu_ctrl[regime_is_secure(env, mmu_idx)] &

>                  (R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) {

> @@ -8815,19 +8815,21 @@ static inline bool regime_translation_disabled(CPUARMState *env,

>          }

>      }

>

> +    hcr_el2 = arm_hcr_el2_eff(env);


Changing this in this function makes me nervous, because
arm_hcr_el2_eff() looks at the current CPU state via
arm_is_secure_below_el3() rather than at the security state
of the translation regime we're asking about. I think
it probably doesn't change behaviour, but I'm finding
it hard to reason about...

> +

>      if (mmu_idx == ARMMMUIdx_S2NS) {

>          /* HCR.DC means HCR.VM behaves as 1 */

> -        return (env->cp15.hcr_el2 & (HCR_DC | HCR_VM)) == 0;

> +        return (hcr_el2 & (HCR_DC | HCR_VM)) == 0;

>      }

>

> -    if (env->cp15.hcr_el2 & HCR_TGE) {

> +    if (hcr_el2 & HCR_TGE) {

>          /* TGE means that NS EL0/1 act as if SCTLR_EL1.M is zero */

>          if (!regime_is_secure(env, mmu_idx) && regime_el(env, mmu_idx) == 1) {

>              return true;

>          }

>      }

>

> -    if ((env->cp15.hcr_el2 & HCR_DC) &&

> +    if ((hcr_el2 & HCR_DC) &&

>          (mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1)) {

>          /* HCR.DC means SCTLR_EL1.M behaves as 0 */

>          return true;



> @@ -995,7 +994,7 @@ void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)

>                          exception_target_el(env));

>      }

>

> -    if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {

> +    if (!secure && cur_el == 1 && (arm_hcr_el2_eff(env) & HCR_TSC)) {


Why can't we drop the !secure check here?

>          /* In NS EL1, HCR controlled routing to EL2 has priority over SMD.

>           * We also want an EL2 guest to be able to forbid its EL1 from

>           * making PSCI calls into QEMU's "firmware" via HCR.TSC.

> @@ -1098,8 +1097,7 @@ void HELPER(exception_return)(CPUARMState *env)

>          goto illegal_return;

>      }

>

> -    if (new_el == 1 && (env->cp15.hcr_el2 & HCR_TGE)

> -        && !arm_is_secure_below_el3(env)) {

> +    if (new_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {

>          goto illegal_return;

>      }


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


thanks
-- PMM
Richard Henderson Dec. 6, 2018, 1:32 p.m. UTC | #2
On 12/6/18 7:06 AM, Peter Maydell wrote:
> On Mon, 3 Dec 2018 at 20:38, Richard Henderson

> <richard.henderson@linaro.org> wrote:

>>

>> Since arm_hcr_el2_eff includes a check against

>> arm_is_secure_below_el3, we can often remove a

>> nearby check against secure state.

>>

>> In some cases, sort the call to arm_hcr_el2_eff

>> to the end of a short-circuit logical sequence.

>>

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

>> ---

> 

> 

>> @@ -8797,6 +8795,8 @@ static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)

>>  static inline bool regime_translation_disabled(CPUARMState *env,

>>                                                 ARMMMUIdx mmu_idx)

>>  {

>> +    uint64_t hcr_el2;

>> +

>>      if (arm_feature(env, ARM_FEATURE_M)) {

>>          switch (env->v7m.mpu_ctrl[regime_is_secure(env, mmu_idx)] &

>>                  (R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) {

>> @@ -8815,19 +8815,21 @@ static inline bool regime_translation_disabled(CPUARMState *env,

>>          }

>>      }

>>

>> +    hcr_el2 = arm_hcr_el2_eff(env);

> 

> Changing this in this function makes me nervous, because

> arm_hcr_el2_eff() looks at the current CPU state via

> arm_is_secure_below_el3() rather than at the security state

> of the translation regime we're asking about. I think

> it probably doesn't change behaviour, but I'm finding

> it hard to reason about...


Oops, I missed that we weren't talking about "current" here.

I can either just revert this function for now, or introduce a new
arm_hcr_el2_eff_ns that does not take secure into effect, but does adjust all
of the other flags within HCR relative to its own contents.

>> -    if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {

>> +    if (!secure && cur_el == 1 && (arm_hcr_el2_eff(env) & HCR_TSC)) {

> 

> Why can't we drop the !secure check here?


Either I missed it, or it was premature optimization of the form "well, it's
already computed into a local variable..."


r~
Peter Maydell Dec. 6, 2018, 1:50 p.m. UTC | #3
On Thu, 6 Dec 2018 at 13:32, Richard Henderson
<richard.henderson@linaro.org> wrote:
>

> On 12/6/18 7:06 AM, Peter Maydell wrote:

> > Changing this in this function makes me nervous, because

> > arm_hcr_el2_eff() looks at the current CPU state via

> > arm_is_secure_below_el3() rather than at the security state

> > of the translation regime we're asking about. I think

> > it probably doesn't change behaviour, but I'm finding

> > it hard to reason about...

>

> Oops, I missed that we weren't talking about "current" here.

>

> I can either just revert this function for now, or introduce a new

> arm_hcr_el2_eff_ns that does not take secure into effect, but does adjust all

> of the other flags within HCR relative to its own contents.


I think I'd just not change this function.

thanks
-- PMM
diff mbox series

Patch

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 5874c5a73f..b248dfcd39 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -448,7 +448,7 @@  static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri,
     int el = arm_current_el(env);
     bool mdcr_el2_tdosa = (env->cp15.mdcr_el2 & MDCR_TDOSA) ||
         (env->cp15.mdcr_el2 & MDCR_TDE) ||
-        (env->cp15.hcr_el2 & HCR_TGE);
+        (arm_hcr_el2_eff(env) & HCR_TGE);
 
     if (el < 2 && mdcr_el2_tdosa && !arm_is_secure_below_el3(env)) {
         return CP_ACCESS_TRAP_EL2;
@@ -468,7 +468,7 @@  static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri,
     int el = arm_current_el(env);
     bool mdcr_el2_tdra = (env->cp15.mdcr_el2 & MDCR_TDRA) ||
         (env->cp15.mdcr_el2 & MDCR_TDE) ||
-        (env->cp15.hcr_el2 & HCR_TGE);
+        (arm_hcr_el2_eff(env) & HCR_TGE);
 
     if (el < 2 && mdcr_el2_tdra && !arm_is_secure_below_el3(env)) {
         return CP_ACCESS_TRAP_EL2;
@@ -488,7 +488,7 @@  static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri,
     int el = arm_current_el(env);
     bool mdcr_el2_tda = (env->cp15.mdcr_el2 & MDCR_TDA) ||
         (env->cp15.mdcr_el2 & MDCR_TDE) ||
-        (env->cp15.hcr_el2 & HCR_TGE);
+        (arm_hcr_el2_eff(env) & HCR_TGE);
 
     if (el < 2 && mdcr_el2_tda && !arm_is_secure_below_el3(env)) {
         return CP_ACCESS_TRAP_EL2;
@@ -4548,8 +4548,7 @@  int sve_exception_el(CPUARMState *env, int el)
         if (disabled) {
             /* route_to_el2 */
             return (arm_feature(env, ARM_FEATURE_EL2)
-                    && !arm_is_secure(env)
-                    && (env->cp15.hcr_el2 & HCR_TGE) ? 2 : 1);
+                    && (arm_hcr_el2_eff(env) & HCR_TGE) ? 2 : 1);
         }
 
         /* Check CPACR.FPEN.  */
@@ -6194,9 +6193,8 @@  static int bad_mode_switch(CPUARMState *env, int mode, CPSRWriteType write_type)
          * and CPS are treated as illegal mode changes.
          */
         if (write_type == CPSRWriteByInstr &&
-            (env->cp15.hcr_el2 & HCR_TGE) &&
             (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON &&
-            !arm_is_secure_below_el3(env)) {
+            (arm_hcr_el2_eff(env) & HCR_TGE)) {
             return 1;
         }
         return 0;
@@ -8797,6 +8795,8 @@  static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
 static inline bool regime_translation_disabled(CPUARMState *env,
                                                ARMMMUIdx mmu_idx)
 {
+    uint64_t hcr_el2;
+
     if (arm_feature(env, ARM_FEATURE_M)) {
         switch (env->v7m.mpu_ctrl[regime_is_secure(env, mmu_idx)] &
                 (R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) {
@@ -8815,19 +8815,21 @@  static inline bool regime_translation_disabled(CPUARMState *env,
         }
     }
 
+    hcr_el2 = arm_hcr_el2_eff(env);
+
     if (mmu_idx == ARMMMUIdx_S2NS) {
         /* HCR.DC means HCR.VM behaves as 1 */
-        return (env->cp15.hcr_el2 & (HCR_DC | HCR_VM)) == 0;
+        return (hcr_el2 & (HCR_DC | HCR_VM)) == 0;
     }
 
-    if (env->cp15.hcr_el2 & HCR_TGE) {
+    if (hcr_el2 & HCR_TGE) {
         /* TGE means that NS EL0/1 act as if SCTLR_EL1.M is zero */
         if (!regime_is_secure(env, mmu_idx) && regime_el(env, mmu_idx) == 1) {
             return true;
         }
     }
 
-    if ((env->cp15.hcr_el2 & HCR_DC) &&
+    if ((hcr_el2 & HCR_DC) &&
         (mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1)) {
         /* HCR.DC means SCTLR_EL1.M behaves as 0 */
         return true;
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 0d6e89e474..780caf387b 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -33,8 +33,7 @@  void raise_exception(CPUARMState *env, uint32_t excp,
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
 
-    if ((env->cp15.hcr_el2 & HCR_TGE) &&
-        target_el == 1 && !arm_is_secure(env)) {
+    if (target_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
         /*
          * Redirect NS EL1 exceptions to NS EL2. These are reported with
          * their original syndrome register value, with the exception of
@@ -428,9 +427,9 @@  static inline int check_wfx_trap(CPUARMState *env, bool is_wfe)
      * No need for ARM_FEATURE check as if HCR_EL2 doesn't exist the
      * bits will be zero indicating no trap.
      */
-    if (cur_el < 2 && !arm_is_secure(env)) {
-        mask = (is_wfe) ? HCR_TWE : HCR_TWI;
-        if (env->cp15.hcr_el2 & mask) {
+    if (cur_el < 2) {
+        mask = is_wfe ? HCR_TWE : HCR_TWI;
+        if (arm_hcr_el2_eff(env) & mask) {
             return 2;
         }
     }
@@ -995,7 +994,7 @@  void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
                         exception_target_el(env));
     }
 
-    if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
+    if (!secure && cur_el == 1 && (arm_hcr_el2_eff(env) & HCR_TSC)) {
         /* In NS EL1, HCR controlled routing to EL2 has priority over SMD.
          * We also want an EL2 guest to be able to forbid its EL1 from
          * making PSCI calls into QEMU's "firmware" via HCR.TSC.
@@ -1098,8 +1097,7 @@  void HELPER(exception_return)(CPUARMState *env)
         goto illegal_return;
     }
 
-    if (new_el == 1 && (env->cp15.hcr_el2 & HCR_TGE)
-        && !arm_is_secure_below_el3(env)) {
+    if (new_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
         goto illegal_return;
     }