From 7a3ee5fd95f26decd0fc51eb04bb9336e28eaa8c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 25 Mar 2018 16:30:22 -0400 Subject: [PATCH] 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. Backports commit c900a2e62dd6dde11c8f5249b638caad05bb15be from qemu --- qemu/aarch64.h | 1 + qemu/aarch64eb.h | 1 + qemu/arm.h | 1 + qemu/armeb.h | 1 + qemu/header_gen.py | 1 + qemu/m68k.h | 1 + qemu/mips.h | 1 + qemu/mips64.h | 1 + qemu/mips64el.h | 1 + qemu/mipsel.h | 1 + qemu/powerpc.h | 1 + qemu/sparc.h | 1 + qemu/sparc64.h | 1 + qemu/target/arm/helper.h | 1 + qemu/target/arm/op_helper.c | 8 ++++++++ qemu/target/arm/translate-a64.c | 16 ++++++++++++++-- qemu/target/arm/translate.c | 20 +++++++++++++++----- qemu/x86_64.h | 1 + 18 files changed, 52 insertions(+), 7 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 6b8004dc..842415f2 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_aarch64 #define helper_divu_i64 helper_divu_i64_aarch64 #define helper_double_saturate helper_double_saturate_aarch64 +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_aarch64 #define helper_exception_internal helper_exception_internal_aarch64 #define helper_exception_return helper_exception_return_aarch64 #define helper_exception_with_syndrome helper_exception_with_syndrome_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 9205a359..05716ae8 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_aarch64eb #define helper_divu_i64 helper_divu_i64_aarch64eb #define helper_double_saturate helper_double_saturate_aarch64eb +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_aarch64eb #define helper_exception_internal helper_exception_internal_aarch64eb #define helper_exception_return helper_exception_return_aarch64eb #define helper_exception_with_syndrome helper_exception_with_syndrome_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 2c6d61ca..c5487240 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_arm #define helper_divu_i64 helper_divu_i64_arm #define helper_double_saturate helper_double_saturate_arm +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_arm #define helper_exception_internal helper_exception_internal_arm #define helper_exception_return helper_exception_return_arm #define helper_exception_with_syndrome helper_exception_with_syndrome_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 6ba9e124..7c8feead 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_armeb #define helper_divu_i64 helper_divu_i64_armeb #define helper_double_saturate helper_double_saturate_armeb +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_armeb #define helper_exception_internal helper_exception_internal_armeb #define helper_exception_return helper_exception_return_armeb #define helper_exception_with_syndrome helper_exception_with_syndrome_armeb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index fdafd258..86a971e3 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -973,6 +973,7 @@ symbols = ( 'helper_divu_i32', 'helper_divu_i64', 'helper_double_saturate', + 'helper_exception_bkpt_insn', 'helper_exception_internal', 'helper_exception_return', 'helper_exception_with_syndrome', diff --git a/qemu/m68k.h b/qemu/m68k.h index 32513a5f..25de61d1 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_m68k #define helper_divu_i64 helper_divu_i64_m68k #define helper_double_saturate helper_double_saturate_m68k +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_m68k #define helper_exception_internal helper_exception_internal_m68k #define helper_exception_return helper_exception_return_m68k #define helper_exception_with_syndrome helper_exception_with_syndrome_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 8b539661..a943b309 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_mips #define helper_divu_i64 helper_divu_i64_mips #define helper_double_saturate helper_double_saturate_mips +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_mips #define helper_exception_internal helper_exception_internal_mips #define helper_exception_return helper_exception_return_mips #define helper_exception_with_syndrome helper_exception_with_syndrome_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 9010919b..8ca8f55a 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_mips64 #define helper_divu_i64 helper_divu_i64_mips64 #define helper_double_saturate helper_double_saturate_mips64 +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_mips64 #define helper_exception_internal helper_exception_internal_mips64 #define helper_exception_return helper_exception_return_mips64 #define helper_exception_with_syndrome helper_exception_with_syndrome_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index a2e44acd..f64ab3e8 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_mips64el #define helper_divu_i64 helper_divu_i64_mips64el #define helper_double_saturate helper_double_saturate_mips64el +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_mips64el #define helper_exception_internal helper_exception_internal_mips64el #define helper_exception_return helper_exception_return_mips64el #define helper_exception_with_syndrome helper_exception_with_syndrome_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 6ff8943e..b2b86e55 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_mipsel #define helper_divu_i64 helper_divu_i64_mipsel #define helper_double_saturate helper_double_saturate_mipsel +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_mipsel #define helper_exception_internal helper_exception_internal_mipsel #define helper_exception_return helper_exception_return_mipsel #define helper_exception_with_syndrome helper_exception_with_syndrome_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 76036bd9..487bbb83 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_powerpc #define helper_divu_i64 helper_divu_i64_powerpc #define helper_double_saturate helper_double_saturate_powerpc +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_powerpc #define helper_exception_internal helper_exception_internal_powerpc #define helper_exception_return helper_exception_return_powerpc #define helper_exception_with_syndrome helper_exception_with_syndrome_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 2b96df45..25ca7e54 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_sparc #define helper_divu_i64 helper_divu_i64_sparc #define helper_double_saturate helper_double_saturate_sparc +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_sparc #define helper_exception_internal helper_exception_internal_sparc #define helper_exception_return helper_exception_return_sparc #define helper_exception_with_syndrome helper_exception_with_syndrome_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 9961a6ce..2bea55ae 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_sparc64 #define helper_divu_i64 helper_divu_i64_sparc64 #define helper_double_saturate helper_double_saturate_sparc64 +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_sparc64 #define helper_exception_internal helper_exception_internal_sparc64 #define helper_exception_return helper_exception_return_sparc64 #define helper_exception_with_syndrome helper_exception_with_syndrome_sparc64 diff --git a/qemu/target/arm/helper.h b/qemu/target/arm/helper.h index c25938a7..524e013d 100644 --- a/qemu/target/arm/helper.h +++ b/qemu/target/arm/helper.h @@ -49,6 +49,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) diff --git a/qemu/target/arm/op_helper.c b/qemu/target/arm/op_helper.c index d3460aa7..a71f3847 100644 --- a/qemu/target/arm/op_helper.c +++ b/qemu/target/arm/op_helper.c @@ -489,6 +489,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); diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 66e13fff..e7bc82cb 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -340,6 +340,19 @@ 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) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_i32 tcg_syn; + + gen_a64_set_pc_im(s, s->pc - offset); + tcg_syn = tcg_const_i32(tcg_ctx, syndrome); + gen_helper_exception_bkpt_insn(tcg_ctx, tcg_ctx->cpu_env, tcg_syn); + tcg_temp_free_i32(tcg_ctx, tcg_syn); + s->base.is_jmp = DISAS_NORETURN; +} + static void gen_ss_advance(DisasContext *s) { TCGContext *tcg_ctx = s->uc->tcg_ctx; @@ -1907,8 +1920,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) { diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 11f349e1..b8a8130f 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -1292,6 +1292,19 @@ 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) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_i32 tcg_syn; + + gen_set_condexec(s); + gen_set_pc_im(s, s->pc - offset); + tcg_syn = tcg_const_i32(tcg_ctx, syn); + gen_helper_exception_bkpt_insn(tcg_ctx, tcg_ctx->cpu_env, tcg_syn); + tcg_temp_free_i32(tcg_ctx, 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) { @@ -8953,9 +8966,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq 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) */ @@ -12191,8 +12202,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; } diff --git a/qemu/x86_64.h b/qemu/x86_64.h index d987b500..9461f5e4 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -967,6 +967,7 @@ #define helper_divu_i32 helper_divu_i32_x86_64 #define helper_divu_i64 helper_divu_i64_x86_64 #define helper_double_saturate helper_double_saturate_x86_64 +#define helper_exception_bkpt_insn helper_exception_bkpt_insn_x86_64 #define helper_exception_internal helper_exception_internal_x86_64 #define helper_exception_return helper_exception_return_x86_64 #define helper_exception_with_syndrome helper_exception_with_syndrome_x86_64