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;

Reply via email to