@samitouri / QOSamiQemu / commits / d55ea4cb4e

target/riscv: add 'num-triggers' debug property

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 <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260617131710.1855353-4-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Daniel Henrique Barboza committed Jun 17, 2026 at 10:17 UTC d55ea4cb4e033204f331974acfcb063a10b13c67
3 files changed +37 -9
target/riscv/cpu.c
+11
@@ -1164,6 +1164,11 @@ static void riscv_cpu_init(Object *obj)
1164 IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
1165 qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_nmi,
1166 "riscv.cpu.rnmi", RNMI_MAX);
1167 +
1168 + if (mcc->def->num_triggers) {
1169 + env->num_triggers = mcc->def->num_triggers;
1170 + }
1171 +
1172 #endif /* CONFIG_USER_ONLY */
1173
1174 cpu->user_options = g_hash_table_new(g_str_hash, g_str_equal);
@@ -2616,6 +2621,8 @@ static const Property riscv_cpu_properties[] = {
2621 DEFAULT_RNMI_IRQVEC),
2622 DEFINE_PROP_UINT64("rnmi-exception-vector", RISCVCPU, env.rnmi_excpvec,
2623 DEFAULT_RNMI_EXCPVEC),
2624 + DEFINE_PROP_UINT32("num-triggers", RISCVCPU, env.num_triggers,
2625 + RV_DEFAULT_NUM_TRIGGERS),
2626 #endif
2627
2628 DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false),
@@ -2761,6 +2768,10 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data)
2768 !valid_vm_1_10_32[mcc->def->cfg.max_satp_mode]) {
2769 mcc->def->cfg.max_satp_mode = VM_1_10_SV32;
2770 }
2771 +
2772 + if (def->num_triggers) {
2773 + mcc->def->num_triggers = def->num_triggers;
2774 + }
2775 #endif
2776 }
2777 if (def->priv_spec != RISCV_PROFILE_ATTR_UNUSED) {
target/riscv/cpu.h
+18 -1
@@ -189,7 +189,22 @@ extern RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[];
189 #define RV_VLEN_MAX 1024
190 #define RV_MAX_MHPMEVENTS 32
191 #define RV_MAX_MHPMCOUNTERS 32
192 -#define RV_MAX_TRIGGERS 2
192 +
193 +/*
194 + * The Debug 1.0 spec allows a humongous amount of triggers. Section
195 + * "Enumeration" says: "The above algorithm reads back tselect so that
196 + * implementations which have 2^n triggers only need to implement n
197 + * bits of tselect.". tselect can have up to XLEN bits, so the max
198 + * theoretical RV_MAX_TRIGGERS value is 2^XLEN.
199 + *
200 + * Allowing 2^XLEN triggers per hart is silly so we'll set a max to a
201 + * modest 1024 triggers, which is way more than what we see current
202 + * hardware use (most chips uses 2-4 triggers per hart, RISC-V Server
203 + * Ref requires at least 11). With a 1024 max per hart we'll be set
204 + * for a long time ... hopefully.
205 + */
206 +#define RV_MAX_TRIGGERS 1024
207 +#define RV_DEFAULT_NUM_TRIGGERS 2
208
209 FIELD(VTYPE, VLMUL, 0, 3)
210 FIELD(VTYPE, VSEW, 3, 3)
@@ -577,6 +592,8 @@ typedef struct RISCVCPUDef {
592 RISCVCPUConfig cfg;
593 bool bare;
594 const RISCVCSR *custom_csrs;
595 + /* This is just a setter for env->num_triggers. */
596 + uint32_t num_triggers;
597 } RISCVCPUDef;
598
599 /**
target/riscv/debug.c
+8 -8
@@ -26,6 +26,7 @@
26 #include "qemu/osdep.h"
27 #include "qemu/log.h"
28 #include "qapi/error.h"
29 +#include "qemu/error-report.h"
30 #include "cpu.h"
31 #include "target/riscv/debug.h"
32 #include "trace.h"
@@ -1049,14 +1050,13 @@ void riscv_trigger_realize(CPURISCVState *env)
1050 {
1051 int i;
1052
1052 - /*
1053 - * Alloc env->tdata1/2/3, cpu_breakpoint, cpu_watchpoint and
1054 - * itrigger_timer dynamically. This is overkill now
1055 - * given that they could be static arrays with RV_MAX_TRIGGERS
1056 - * but we'll parametrize the trigger number later, i.e. the
1057 - * array length won't be static.
1058 - */
1059 - env->num_triggers = RV_MAX_TRIGGERS;
1053 + if (env->num_triggers > RV_MAX_TRIGGERS) {
1054 + error_report(
1055 + "Invalid configuration: 'num-triggers' must be less than %u",
1056 + RV_MAX_TRIGGERS);
1057 + exit(1);
1058 + }
1059 +
1060 env->tdata1 = g_new0(uint64_t, env->num_triggers);
1061 env->tdata2 = g_new0(uint64_t, env->num_triggers);
1062 env->tdata3 = g_new0(uint64_t, env->num_triggers);