RISC-V Debug Specification: https://github.com/riscv/riscv-debug-spec/releases/tag/1.0
Route EBREAK via helper_sdext_ebreak. If Sdext is enabled and the matching dcsr.ebreak* bit is set, enter Debug Mode with cause=ebreak and stop with EXCP_DEBUG. Otherwise keep the normal breakpoint trap. Signed-off-by: Chao Liu <[email protected]> --- target/riscv/helper.h | 1 + .../riscv/insn_trans/trans_privileged.c.inc | 6 ++-- target/riscv/op_helper.c | 36 +++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 6140b6340d..acff73051b 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -141,6 +141,7 @@ DEF_HELPER_1(tlb_flush_all, void, env) DEF_HELPER_4(ctr_add_entry, void, env, tl, tl, tl) /* Native Debug */ DEF_HELPER_1(itrigger_match, void, env) +DEF_HELPER_2(sdext_ebreak, void, env, tl) #endif /* Hypervisor functions */ diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc index f8641b1977..377f551bb3 100644 --- a/target/riscv/insn_trans/trans_privileged.c.inc +++ b/target/riscv/insn_trans/trans_privileged.c.inc @@ -68,9 +68,9 @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a) if (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) { generate_exception(ctx, RISCV_EXCP_SEMIHOST); } else { - tcg_gen_st_tl(tcg_constant_tl(ebreak_addr), tcg_env, - offsetof(CPURISCVState, badaddr)); - generate_exception(ctx, RISCV_EXCP_BREAKPOINT); + gen_update_pc(ctx, 0); + gen_helper_sdext_ebreak(tcg_env, tcg_constant_tl(ebreak_addr)); + ctx->base.is_jmp = DISAS_NORETURN; } return true; } diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 99736bbebb..dfe5388ab7 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -470,6 +470,42 @@ target_ulong helper_dret(CPURISCVState *env) #endif } +void helper_sdext_ebreak(CPURISCVState *env, target_ulong pc) +{ +#ifndef CONFIG_USER_ONLY + CPUState *cs = env_cpu(env); + bool enter_debug = false; + + if (riscv_cpu_cfg(env)->ext_sdext && !env->debug_mode) { + if (env->virt_enabled) { + if (env->priv == PRV_S) { + enter_debug = env->dcsr & DCSR_EBREAKVS; + } else if (env->priv == PRV_U) { + enter_debug = env->dcsr & DCSR_EBREAKVU; + } + } else { + if (env->priv == PRV_M) { + enter_debug = env->dcsr & DCSR_EBREAKM; + } else if (env->priv == PRV_S) { + enter_debug = env->dcsr & DCSR_EBREAKS; + } else if (env->priv == PRV_U) { + enter_debug = env->dcsr & DCSR_EBREAKU; + } + } + } + + env->badaddr = pc; + + if (enter_debug) { + riscv_cpu_enter_debug_mode(env, pc, DCSR_CAUSE_EBREAK); + cs->exception_index = EXCP_DEBUG; + cpu_loop_exit_restore(cs, GETPC()); + } + + riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, GETPC()); +#endif +} + target_ulong helper_mnret(CPURISCVState *env) { target_ulong retpc = env->mnepc; -- 2.52.0
