diff mbox series

[v6,17/20] target/arm: Rebuild hflags at MSR writes

Message ID 20191011155546.14342-18-richard.henderson@linaro.org
State Superseded
Headers show
Series target/arm: Reduce overhead of cpu_get_tb_cpu_state | expand

Commit Message

Richard Henderson Oct. 11, 2019, 3:55 p.m. UTC
Continue setting, but not relying upon, env->hflags.

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

---
 target/arm/translate-a64.c | 13 +++++++++++--
 target/arm/translate.c     | 28 +++++++++++++++++++++++-----
 2 files changed, 34 insertions(+), 7 deletions(-)

-- 
2.17.1

Comments

Alex Bennée Oct. 14, 2019, 7:03 p.m. UTC | #1
Richard Henderson <richard.henderson@linaro.org> writes:

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

>

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


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


> ---

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

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

>  2 files changed, 34 insertions(+), 7 deletions(-)

>

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

> index 2d6cd09634..d4bebbe629 100644

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

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

> @@ -1789,8 +1789,17 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,

>      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) */

>          s->base.is_jmp = DISAS_UPDATE;

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

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

> +    }

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

> +        /*

> +         * A write to any coprocessor regiser that ends a TB

> +         * must rebuild the hflags for the next TB.

> +         */

> +        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);

> +        /*

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

>           */

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

> index 698c594e8c..cb47cd9744 100644

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

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

> @@ -6890,6 +6890,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;

> @@ -7068,14 +7070,30 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)

>              }

>          }

>

> -        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_lookup_tb(s);

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

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

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

> +        need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&

> +                        (ri->type & ARM_CP_IO));

> +

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

> +            /*

> +             * A write to any coprocessor regiser that ends a TB

> +             * must rebuild the hflags for the next TB.

> +             */

> +            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);

> +            /*

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

>               */

> +            need_exit_tb = true;

> +        }

> +        if (need_exit_tb) {

>              gen_lookup_tb(s);

>          }



--
Alex Bennée
diff mbox series

Patch

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 2d6cd09634..d4bebbe629 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1789,8 +1789,17 @@  static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
     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) */
         s->base.is_jmp = DISAS_UPDATE;
-    } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
-        /* We default to ending the TB on a coprocessor register write,
+    }
+    if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
+        /*
+         * A write to any coprocessor regiser that ends a TB
+         * must rebuild the hflags for the next TB.
+         */
+        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);
+        /*
+         * 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).
          */
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 698c594e8c..cb47cd9744 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -6890,6 +6890,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;
@@ -7068,14 +7070,30 @@  static int disas_coproc_insn(DisasContext *s, uint32_t insn)
             }
         }
 
-        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_lookup_tb(s);
-        } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
-            /* We default to ending the TB on a coprocessor register write,
+        /* I/O operations must end the TB here (whether read or write) */
+        need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
+                        (ri->type & ARM_CP_IO));
+
+        if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
+            /*
+             * A write to any coprocessor regiser that ends a TB
+             * must rebuild the hflags for the next TB.
+             */
+            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);
+            /*
+             * 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).
              */
+            need_exit_tb = true;
+        }
+        if (need_exit_tb) {
             gen_lookup_tb(s);
         }