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
> 
> Allow mcontrol/mcontrol6 action=1 when Sdext is enabled. When such a
> trigger hits, enter Debug Mode with cause=trigger and stop with
> EXCP_DEBUG.
> 
> Also report inst-count triggers in tinfo and read their action field.
> 
> 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]>

Acked-by: Alistair Francis <[email protected]>

Alistair

> ---
>  target/riscv/tcg/debug.c | 54
> ++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 52 insertions(+), 2 deletions(-)
> 
> diff --git a/target/riscv/tcg/debug.c b/target/riscv/tcg/debug.c
> index 2537515f54..aaf2dca17e 100644
> --- a/target/riscv/tcg/debug.c
> +++ b/target/riscv/tcg/debug.c
> @@ -34,6 +34,7 @@
>  #include "exec/watchpoint.h"
>  #include "system/cpu-timers.h"
>  #include "exec/icount.h"
> +#include "accel/tcg/cpu-loop.h"
>  
>  /*
>   * The following M-mode trigger CSRs are implemented:
> @@ -117,6 +118,8 @@ static trigger_action_t
> get_trigger_action(CPURISCVState *env,
>          action = (tdata1 & TYPE6_ACTION) >> 12;
>          break;
>      case TRIGGER_TYPE_INST_CNT:
> +        action = tdata1 & ITRIGGER_ACTION;
> +        break;
>      case TRIGGER_TYPE_INT:
>      case TRIGGER_TYPE_EXCP:
>      case TRIGGER_TYPE_EXT_SRC:
> @@ -287,6 +290,7 @@ static target_ulong textra_validate(CPURISCVState
> *env, target_ulong tdata3)
>  
>  static void do_trigger_action(CPURISCVState *env, target_ulong
> trigger_index)
>  {
> +    CPUState *cs = env_cpu(env);
>      trigger_action_t action = get_trigger_action(env,
> trigger_index);
>  
>      switch (action) {
> @@ -296,6 +300,21 @@ static void do_trigger_action(CPURISCVState
> *env, target_ulong trigger_index)
>          riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0);
>          break;
>      case DBG_ACTION_DBG_MODE:
> +        if (!env_archcpu(env)->cfg.ext_sdext) {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                          "trigger action=debug mode requires
> Sdext\n");
> +            riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0);
> +        }
> +        riscv_cpu_enter_debug_mode(env, env->pc,
> DCSR_CAUSE_TRIGGER);
> +        /*
> +         * If this came from the Trigger Module's CPU
> breakpoint/watchpoint,
> +         * we're already returning via EXCP_DEBUG. Otherwise, stop
> now.
> +         */
> +        if (cs->exception_index != EXCP_DEBUG) {
> +            cs->exception_index = EXCP_DEBUG;
> +            cpu_loop_exit_restore(cs, GETPC());
> +        }
> +        break;
>      case DBG_ACTION_TRACE0:
>      case DBG_ACTION_TRACE1:
>      case DBG_ACTION_TRACE2:
> @@ -448,6 +467,7 @@ static target_ulong
> type2_mcontrol_validate(CPURISCVState *env,
>  {
>      target_ulong val;
>      uint32_t size;
> +    uint32_t action;
>  
>      /* validate the generic part first */
>      val = tdata1_validate(env, ctrl, TRIGGER_TYPE_AD_MATCH);
> @@ -455,11 +475,25 @@ static target_ulong
> type2_mcontrol_validate(CPURISCVState *env,
>      /* validate unimplemented (always zero) bits */
>      warn_always_zero_bit(ctrl, TYPE2_MATCH, "match");
>      warn_always_zero_bit(ctrl, TYPE2_CHAIN, "chain");
> -    warn_always_zero_bit(ctrl, TYPE2_ACTION, "action");
>      warn_always_zero_bit(ctrl, TYPE2_TIMING, "timing");
>      warn_always_zero_bit(ctrl, TYPE2_SELECT, "select");
>      warn_always_zero_bit(ctrl, TYPE2_HIT, "hit");
>  
> +    action = (ctrl & TYPE2_ACTION) >> 12;
> +    if (action == DBG_ACTION_BP) {
> +        val |= ctrl & TYPE2_ACTION;
> +    } else if (action == DBG_ACTION_DBG_MODE) {
> +        if (env_archcpu(env)->cfg.ext_sdext) {
> +            val |= ctrl & TYPE2_ACTION;
> +        } else {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                          "trigger action=debug mode requires
> Sdext\n");
> +        }
> +    } else {
> +        qemu_log_mask(LOG_UNIMP, "trigger action: %u is not
> supported\n",
> +                      action);
> +    }
> +
>      /* validate size encoding */
>      size = type2_breakpoint_size(env, ctrl);
>      if (access_size[size] == -1) {
> @@ -576,6 +610,7 @@ static target_ulong
> type6_mcontrol6_validate(CPURISCVState *env,
>  {
>      target_ulong val;
>      uint32_t size;
> +    uint32_t action;
>  
>      /* validate the generic part first */
>      val = tdata1_validate(env, ctrl, TRIGGER_TYPE_AD_MATCH6);
> @@ -583,7 +618,6 @@ static target_ulong
> type6_mcontrol6_validate(CPURISCVState *env,
>      /* validate unimplemented (always zero) bits */
>      warn_always_zero_bit(ctrl, TYPE6_MATCH, "match");
>      warn_always_zero_bit(ctrl, TYPE6_CHAIN, "chain");
> -    warn_always_zero_bit(ctrl, TYPE6_ACTION, "action");
>      warn_always_zero_bit(ctrl, TYPE6_SELECT, "select");
>      warn_always_zero_bit(ctrl, TYPE6_HIT, "hit");
>  
> @@ -593,6 +627,21 @@ static target_ulong
> type6_mcontrol6_validate(CPURISCVState *env,
>          warn_always_zero_bit(ctrl, TYPE6_TIMING_0_13, "timing");
>      }
>  
> +    action = (ctrl & TYPE6_ACTION) >> 12;
> +    if (action == DBG_ACTION_BP) {
> +        val |= ctrl & TYPE6_ACTION;
> +    } else if (action == DBG_ACTION_DBG_MODE) {
> +        if (env_archcpu(env)->cfg.ext_sdext) {
> +            val |= ctrl & TYPE6_ACTION;
> +        } else {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                          "trigger action=debug mode requires
> Sdext\n");
> +        }
> +    } else {
> +        qemu_log_mask(LOG_UNIMP, "trigger action: %u is not
> supported\n",
> +                      action);
> +    }
> +
>      /* validate size encoding */
>      size = extract32(ctrl, 16, 4);
>      if (access_size[size] == -1) {
> @@ -959,6 +1008,7 @@ void tdata_csr_write(CPURISCVState *env, int
> tdata_index, target_ulong val)
>  target_ulong tinfo_csr_read(CPURISCVState *env)
>  {
>      target_ulong val = BIT(TRIGGER_TYPE_AD_MATCH) |
> +                       BIT(TRIGGER_TYPE_INST_CNT) |
>                         BIT(TRIGGER_TYPE_AD_MATCH6);
>  
>      if (debug_trigger_version_1_0(env)) {

Reply via email to