Commit 69d66864 authored by Richard Henderson's avatar Richard Henderson Committed by Peter Maydell
Browse files

target/arm: Rebuild hflags at MSR writes



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

Reviewed-by: default avatarAlex Bennée <alex.bennee@linaro.org>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-id: 20191023150057.25731-18-richard.henderson@linaro.org
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent a8a79c7a
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -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).
         */
+23 −5
Original line number Diff line number Diff line
@@ -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,
        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);
        }