On Thu, Jun 11, 2026 at 10:35 PM Daniel Henrique Barboza
<[email protected]> wrote:
>
> All CPUs have the same amount of triggers: 2 triggers per hart, set via
> RV_MAX_TRIGGERS.  This is not enough anymore: we'll have at least one
> future CPU that will demand more triggers per hart when implementing the
> RISC-V Server Ref Platform, requiring at least 11 triggers per hart.
>
> Parametrize the trigger amount using a new 'num_triggers' property.  The
> default amount is kept at 2 for backwards compatibility.  The new
> maximum is bumped to a generous 1024 triggers per hart, which hopefully
> will be enough for the foreseeable future.
>
> The property can be set in two ways:
>
> - a '.num_triggers' CPU definition flag, allowing CPUs to set a custom
>   amount inside the CPU def in DEFINE_RISCV_CPU();
> - a new 'num-triggers' user property.  The user property has a higher
>   priority than an existing '.num_triggers' CPU def setting.
>
> Assuming a hypothetical case where a CPU 'X' is defined with
> '.num_triggers = 8':
>
> - -cpu X,num-triggers=30 => num_triggers set to 30
> - -cpu X (...)           => num_triggers set to 8
>
> For a CPU that doesn't set '.num_triggers':
>
> - -cpu rv64,num-triggers=30 => num_triggers set to 30
> - -cpu rv64 (...)           => num_triggers set to 2
>
> Signed-off-by: Daniel Henrique Barboza <[email protected]>
> Reviewed-by: Philippe Mathieu-Daudé <[email protected]>

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

Alistair

> ---
>  target/riscv/cpu.c   | 11 +++++++++++
>  target/riscv/cpu.h   | 19 ++++++++++++++++++-
>  target/riscv/debug.c | 16 ++++++++--------
>  3 files changed, 37 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index b20271a220..6d8f9ad3a6 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1167,6 +1167,11 @@ static void riscv_cpu_init(Object *obj)
>                        IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
>      qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_nmi,
>                              "riscv.cpu.rnmi", RNMI_MAX);
> +
> +    if (mcc->def->num_triggers) {
> +        env->num_triggers = mcc->def->num_triggers;
> +    }
> +
>  #endif /* CONFIG_USER_ONLY */
>
>      general_user_opts = g_hash_table_new(g_str_hash, g_str_equal);
> @@ -2619,6 +2624,8 @@ static const Property riscv_cpu_properties[] = {
>                         DEFAULT_RNMI_IRQVEC),
>      DEFINE_PROP_UINT64("rnmi-exception-vector", RISCVCPU, env.rnmi_excpvec,
>                         DEFAULT_RNMI_EXCPVEC),
> +    DEFINE_PROP_UINT32("num-triggers", RISCVCPU, env.num_triggers,
> +                       RV_DEFAULT_NUM_TRIGGERS),
>  #endif
>
>      DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, 
> false),
> @@ -2764,6 +2771,10 @@ static void riscv_cpu_class_base_init(ObjectClass *c, 
> const void *data)
>                  !valid_vm_1_10_32[mcc->def->cfg.max_satp_mode]) {
>                  mcc->def->cfg.max_satp_mode = VM_1_10_SV32;
>              }
> +
> +            if (def->num_triggers) {
> +                mcc->def->num_triggers = def->num_triggers;
> +            }
>  #endif
>          }
>          if (def->priv_spec != RISCV_PROFILE_ATTR_UNUSED) {
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index ea92e2c68c..38f02a9dc7 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -189,7 +189,22 @@ extern RISCVCPUImpliedExtsRule 
> *riscv_multi_ext_implied_rules[];
>  #define RV_VLEN_MAX 1024
>  #define RV_MAX_MHPMEVENTS 32
>  #define RV_MAX_MHPMCOUNTERS 32
> -#define RV_MAX_TRIGGERS 2
> +
> +/*
> + * The Debug 1.0 spec allows a humongous amount of triggers.  Section
> + * "Enumeration" says: "The above algorithm reads back tselect so that
> + * implementations which have 2^n triggers only need to implement n
> + * bits of tselect.".  tselect can have up to XLEN bits, so the max
> + * theoretical RV_MAX_TRIGGERS value is 2^XLEN.
> + *
> + * Allowing 2^XLEN triggers per hart is silly so we'll set a max to a
> + * modest 1024 triggers, which is way more than what we see current
> + * hardware use (most chips uses 2-4 triggers per hart, RISC-V Server
> + * Ref requires at least 11).  With a 1024 max per hart we'll be set
> + * for a long time ... hopefully.
> + */
> +#define RV_MAX_TRIGGERS 1024
> +#define RV_DEFAULT_NUM_TRIGGERS 2
>
>  FIELD(VTYPE, VLMUL, 0, 3)
>  FIELD(VTYPE, VSEW, 3, 3)
> @@ -576,6 +591,8 @@ typedef struct RISCVCPUDef {
>      RISCVCPUConfig cfg;
>      bool bare;
>      const RISCVCSR *custom_csrs;
> +    /* This is just a setter for env->num_triggers.  */
> +    uint32_t num_triggers;
>  } RISCVCPUDef;
>
>  /**
> diff --git a/target/riscv/debug.c b/target/riscv/debug.c
> index 9a4910c431..ba5bc6ae13 100644
> --- a/target/riscv/debug.c
> +++ b/target/riscv/debug.c
> @@ -26,6 +26,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/log.h"
>  #include "qapi/error.h"
> +#include "qemu/error-report.h"
>  #include "cpu.h"
>  #include "target/riscv/debug.h"
>  #include "trace.h"
> @@ -1049,14 +1050,13 @@ void riscv_trigger_realize(CPURISCVState *env)
>  {
>      int i;
>
> -    /*
> -     * Alloc env->tdata1/2/3, cpu_breakpoint, cpu_watchpoint and
> -     * itrigger_timer dynamically.  This is overkill now
> -     * given that they could be static arrays with RV_MAX_TRIGGERS
> -     * but we'll parametrize the trigger number later, i.e. the
> -     * array length won't be static.
> -     */
> -    env->num_triggers = RV_MAX_TRIGGERS;
> +    if (env->num_triggers > RV_MAX_TRIGGERS) {
> +        error_report(
> +                "Invalid configuration: 'num-triggers' must be less than %u",
> +                RV_MAX_TRIGGERS);
> +        exit(1);
> +    }
> +
>      env->tdata1 = g_new0(uint64_t, env->num_triggers);
>      env->tdata2 = g_new0(uint64_t, env->num_triggers);
>      env->tdata3 = g_new0(uint64_t, env->num_triggers);
> --
> 2.43.0
>
>

Reply via email to