diff mbox series

[v5,16/17] target/arm: Rebuild hflags at EL changes and MSR writes

Message ID 20190820210720.18976-17-richard.henderson@linaro.org
State New
Headers show
Series target/arm: Reduce overhead of cpu_get_tb_cpu_state | expand

Commit Message

Richard Henderson Aug. 20, 2019, 9:07 p.m. UTC
Now setting, but not relying upon, env->hflags.

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

---
 linux-user/syscall.c       |  1 +
 target/arm/cpu.c           |  1 +
 target/arm/helper-a64.c    |  3 +++
 target/arm/helper.c        |  2 ++
 target/arm/machine.c       |  1 +
 target/arm/op_helper.c     |  1 +
 target/arm/translate-a64.c |  6 +++++-
 target/arm/translate.c     | 18 ++++++++++++++++--
 8 files changed, 30 insertions(+), 3 deletions(-)

-- 
2.17.1

Comments

Alex Bennée Sept. 5, 2019, 1:53 p.m. UTC | #1
Richard Henderson <richard.henderson@linaro.org> writes:

> Now setting, but not relying upon, env->hflags.

>

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

> ---

>  linux-user/syscall.c       |  1 +

>  target/arm/cpu.c           |  1 +

>  target/arm/helper-a64.c    |  3 +++

>  target/arm/helper.c        |  2 ++

>  target/arm/machine.c       |  1 +

>  target/arm/op_helper.c     |  1 +

>  target/arm/translate-a64.c |  6 +++++-

>  target/arm/translate.c     | 18 ++++++++++++++++--

>  8 files changed, 30 insertions(+), 3 deletions(-)

>

> diff --git a/linux-user/syscall.c b/linux-user/syscall.c

> index 8b41a03901..be01c33759 100644

<snip>

I had to manually fix these up due to the patch failing to apply. I
think because 9e9b10c64911 removes the gen_io_end() calls.

> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c

> index fc3e5f5c38..4412c60383 100644

> --- a/target/arm/translate-a64.c

> +++ b/target/arm/translate-a64.c

> @@ -1777,11 +1777,15 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,

>          /* I/O operations must end the TB here (whether read or write) */

>          gen_io_end();

>          s->base.is_jmp = DISAS_UPDATE;

> -    } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {

> +    }

> +    if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {

>          /* We default to ending the TB on a coprocessor register write,

>           * but allow this to be suppressed by the register definition

>           * (usually only necessary to work around guest bugs).

>           */

> +        TCGv_i32 tcg_el = tcg_const_i32(s->current_el);

> +        gen_helper_rebuild_hflags_a64(cpu_env, tcg_el);

> +        tcg_temp_free_i32(tcg_el);

>          s->base.is_jmp = DISAS_UPDATE;

>      }

>  }

> diff --git a/target/arm/translate.c b/target/arm/translate.c

> index d948757131..2f7beca065 100644

> --- a/target/arm/translate.c

> +++ b/target/arm/translate.c

> @@ -7130,6 +7130,8 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)

>      ri = get_arm_cp_reginfo(s->cp_regs,

>              ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));

>      if (ri) {

> +        bool need_exit_tb;

> +

>          /* Check access permissions */

>          if (!cp_access_ok(s->current_el, ri, isread)) {

>              return 1;

> @@ -7301,15 +7303,27 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)

>              }

>          }

>

> +        need_exit_tb = false;

>          if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {

>              /* I/O operations must end the TB here (whether read or write) */

>              gen_io_end();

> -            gen_lookup_tb(s);

> -        } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {

> +            need_exit_tb = true;

> +        }

> +        if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {

>              /* We default to ending the TB on a coprocessor register write,

>               * but allow this to be suppressed by the register definition

>               * (usually only necessary to work around guest bugs).

>               */

> +            TCGv_i32 tcg_el = tcg_const_i32(s->current_el);

> +            if (arm_dc_feature(s, ARM_FEATURE_M)) {

> +                gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);

> +            } else {

> +                gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);

> +            }

> +            tcg_temp_free_i32(tcg_el);

> +            need_exit_tb = true;

> +        }

> +        if (need_exit_tb) {

>              gen_lookup_tb(s);

>          }



--
Alex Bennée
diff mbox series

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8b41a03901..be01c33759 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9980,6 +9980,7 @@  static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                     aarch64_sve_narrow_vq(env, vq);
                 }
                 env->vfp.zcr_el[1] = vq - 1;
+                arm_rebuild_hflags(env);
                 ret = vq * 16;
             }
             return ret;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 2399c14471..d043e75166 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -406,6 +406,7 @@  static void arm_cpu_reset(CPUState *s)
 
     hw_breakpoint_update_all(cpu);
     hw_watchpoint_update_all(cpu);
+    arm_rebuild_hflags(env);
 }
 
 bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index bca80bdc38..b4cd680fc4 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -1025,6 +1025,7 @@  void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
         } else {
             env->regs[15] = new_pc & ~0x3;
         }
+        helper_rebuild_hflags_a32(env, new_el);
         qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
                       "AArch32 EL%d PC 0x%" PRIx32 "\n",
                       cur_el, new_el, env->regs[15]);
@@ -1036,10 +1037,12 @@  void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
         }
         aarch64_restore_sp(env, new_el);
         env->pc = new_pc;
+        helper_rebuild_hflags_a64(env, new_el);
         qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
                       "AArch64 EL%d PC 0x%" PRIx64 "\n",
                       cur_el, new_el, env->pc);
     }
+
     /*
      * Note that cur_el can never be 0.  If new_el is 0, then
      * el0_a64 is return_to_aa64, else el0_a64 is ignored.
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 53a7bd796b..d1bf71a260 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7908,6 +7908,7 @@  static void take_aarch32_exception(CPUARMState *env, int new_mode,
         env->regs[14] = env->regs[15] + offset;
     }
     env->regs[15] = newpc;
+    arm_rebuild_hflags(env);
 }
 
 static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
@@ -8255,6 +8256,7 @@  static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
     pstate_write(env, PSTATE_DAIF | new_mode);
     env->aarch64 = 1;
     aarch64_restore_sp(env, new_el);
+    helper_rebuild_hflags_a64(env, new_el);
 
     env->pc = addr;
 
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 5c36707a7c..eb28b2381b 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -756,6 +756,7 @@  static int cpu_post_load(void *opaque, int version_id)
     if (!kvm_enabled()) {
         pmu_op_finish(&cpu->env);
     }
+    arm_rebuild_hflags(&cpu->env);
 
     return 0;
 }
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 0fd4bd0238..ccc2cecb46 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -404,6 +404,7 @@  void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
      * state. Do the masking now.
      */
     env->regs[15] &= (env->thumb ? ~1 : ~3);
+    arm_rebuild_hflags(env);
 
     qemu_mutex_lock_iothread();
     arm_call_el_change_hook(env_archcpu(env));
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index fc3e5f5c38..4412c60383 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1777,11 +1777,15 @@  static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
         /* I/O operations must end the TB here (whether read or write) */
         gen_io_end();
         s->base.is_jmp = DISAS_UPDATE;
-    } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
+    }
+    if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
         /* We default to ending the TB on a coprocessor register write,
          * but allow this to be suppressed by the register definition
          * (usually only necessary to work around guest bugs).
          */
+        TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
+        gen_helper_rebuild_hflags_a64(cpu_env, tcg_el);
+        tcg_temp_free_i32(tcg_el);
         s->base.is_jmp = DISAS_UPDATE;
     }
 }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index d948757131..2f7beca065 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7130,6 +7130,8 @@  static int disas_coproc_insn(DisasContext *s, uint32_t insn)
     ri = get_arm_cp_reginfo(s->cp_regs,
             ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
     if (ri) {
+        bool need_exit_tb;
+
         /* Check access permissions */
         if (!cp_access_ok(s->current_el, ri, isread)) {
             return 1;
@@ -7301,15 +7303,27 @@  static int disas_coproc_insn(DisasContext *s, uint32_t insn)
             }
         }
 
+        need_exit_tb = false;
         if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
             /* I/O operations must end the TB here (whether read or write) */
             gen_io_end();
-            gen_lookup_tb(s);
-        } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
+            need_exit_tb = true;
+        }
+        if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
             /* We default to ending the TB on a coprocessor register write,
              * but allow this to be suppressed by the register definition
              * (usually only necessary to work around guest bugs).
              */
+            TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
+            if (arm_dc_feature(s, ARM_FEATURE_M)) {
+                gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
+            } else {
+                gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
+            }
+            tcg_temp_free_i32(tcg_el);
+            need_exit_tb = true;
+        }
+        if (need_exit_tb) {
             gen_lookup_tb(s);
         }