On Wed, 2026-09-09 at 11:48 -0300, Daniel Henrique Barboza wrote: > From: Chao Liu <[email protected]> > > 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]> > Reviewed-by: Daniel Henrique Barboza > <[email protected]> > Tested-by: Tao Tang <[email protected]> > Signed-off-by: Daniel Henrique Barboza > <[email protected]>
Reviewed-by: Alistair Francis <[email protected]> Alistair > --- > target/riscv/helper.h | 1 + > .../tcg/insn_trans/trans_privileged.c.inc | 6 ++++ > target/riscv/tcg/op_helper.c | 34 > +++++++++++++++++++ > 3 files changed, 41 insertions(+) > > diff --git a/target/riscv/helper.h b/target/riscv/helper.h > index b4c47d0738..0d9ae15e3e 100644 > --- a/target/riscv/helper.h > +++ b/target/riscv/helper.h > @@ -142,6 +142,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/tcg/insn_trans/trans_privileged.c.inc > b/target/riscv/tcg/insn_trans/trans_privileged.c.inc > index 4e57901880..42bf2ffb53 100644 > --- a/target/riscv/tcg/insn_trans/trans_privileged.c.inc > +++ b/target/riscv/tcg/insn_trans/trans_privileged.c.inc > @@ -68,9 +68,15 @@ static bool trans_ebreak(DisasContext *ctx, > arg_ebreak *a) > if (pre == 0x01f01013 && ebreak == 0x00100073 && post == > 0x40705013) { > generate_exception(ctx, RISCV_EXCP_SEMIHOST); > } else { > +#ifndef CONFIG_USER_ONLY > + gen_update_pc(ctx, 0); > + gen_helper_sdext_ebreak(tcg_env, > tcg_constant_tl(ebreak_addr)); > + ctx->base.is_jmp = DISAS_NORETURN; > +#else > tcg_gen_st_i64(tcg_constant_i64(ebreak_addr), tcg_env, > offsetof(CPURISCVState, badaddr)); > generate_exception(ctx, RISCV_EXCP_BREAKPOINT); > +#endif > } > return true; > } > diff --git a/target/riscv/tcg/op_helper.c > b/target/riscv/tcg/op_helper.c > index 54269efee1..5db4f6aacd 100644 > --- a/target/riscv/tcg/op_helper.c > +++ b/target/riscv/tcg/op_helper.c > @@ -489,6 +489,40 @@ target_ulong helper_dret(CPURISCVState *env) > #endif > } > > +void helper_sdext_ebreak(CPURISCVState *env, target_ulong pc) > +{ > + 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()); > +} > + > target_ulong helper_mnret(CPURISCVState *env) > { > target_ulong retpc = env->mnepc;
