Commit c900a2e6 authored by Peter Maydell's avatar Peter Maydell
Browse files

target/arm: Honour MDCR_EL2.TDE when routing exceptions due to BKPT/BRK



The MDCR_EL2.TDE bit allows the exception level targeted by debug
exceptions to be set to EL2 for code executing at EL0.  We handle
this in the arm_debug_target_el() function, but this is only used for
hardware breakpoint and watchpoint exceptions, not for the exception
generated when the guest executes an AArch32 BKPT or AArch64 BRK
instruction.  We don't have enough information for a translate-time
equivalent of arm_debug_target_el(), so instead make BKPT and BRK
call a special purpose helper which can do the routing, rather than
the generic exception_with_syndrome helper.

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Reviewed-by: default avatarPhilippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180320134114.30418-2-peter.maydell@linaro.org
parent dfadc3bf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
                   i32, i32, i32, i32)
DEF_HELPER_2(exception_internal, void, env, i32)
DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
DEF_HELPER_2(exception_bkpt_insn, void, env, i32)
DEF_HELPER_1(setend, void, env)
DEF_HELPER_2(wfi, void, env, i32)
DEF_HELPER_1(wfe, void, env)
+8 −0
Original line number Diff line number Diff line
@@ -483,6 +483,14 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
    raise_exception(env, excp, syndrome, target_el);
}

/* Raise an EXCP_BKPT with the specified syndrome register value,
 * targeting the correct exception level for debug exceptions.
 */
void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
{
    raise_exception(env, EXCP_BKPT, syndrome, arm_debug_target_el(env));
}

uint32_t HELPER(cpsr_read)(CPUARMState *env)
{
    return cpsr_read(env) & ~(CPSR_EXEC | CPSR_RESERVED);
+13 −2
Original line number Diff line number Diff line
@@ -321,6 +321,18 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
    s->base.is_jmp = DISAS_NORETURN;
}

static void gen_exception_bkpt_insn(DisasContext *s, int offset,
                                    uint32_t syndrome)
{
    TCGv_i32 tcg_syn;

    gen_a64_set_pc_im(s->pc - offset);
    tcg_syn = tcg_const_i32(syndrome);
    gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
    tcg_temp_free_i32(tcg_syn);
    s->base.is_jmp = DISAS_NORETURN;
}

static void gen_ss_advance(DisasContext *s)
{
    /* If the singlestep state is Active-not-pending, advance to
@@ -1839,8 +1851,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
            break;
        }
        /* BRK */
        gen_exception_insn(s, 4, EXCP_BKPT, syn_aa64_bkpt(imm16),
                           default_exception_el(s));
        gen_exception_bkpt_insn(s, 4, syn_aa64_bkpt(imm16));
        break;
    case 2:
        if (op2_ll != 0) {
+14 −5
Original line number Diff line number Diff line
@@ -1248,6 +1248,18 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
    s->base.is_jmp = DISAS_NORETURN;
}

static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
{
    TCGv_i32 tcg_syn;

    gen_set_condexec(s);
    gen_set_pc_im(s, s->pc - offset);
    tcg_syn = tcg_const_i32(syn);
    gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
    tcg_temp_free_i32(tcg_syn);
    s->base.is_jmp = DISAS_NORETURN;
}

/* Force a TB lookup after an instruction that changes the CPU state.  */
static inline void gen_lookup_tb(DisasContext *s)
{
@@ -8774,9 +8786,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
            case 1:
                /* bkpt */
                ARCH(5);
                gen_exception_insn(s, 4, EXCP_BKPT,
                                   syn_aa32_bkpt(imm16, false),
                                   default_exception_el(s));
                gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
                break;
            case 2:
                /* Hypervisor call (v7) */
@@ -11983,8 +11993,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
        {
            int imm8 = extract32(insn, 0, 8);
            ARCH(5);
            gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true),
                               default_exception_el(s));
            gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
            break;
        }