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]> --- target/riscv/cpu.c | 11 +++++++++++ target/riscv/cpu.h | 19 ++++++++++++++++++- target/riscv/debug.c | 16 ++++++++-------- target/riscv/machine.c | 4 ++-- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c1b10cc7ef..eed7b0b76e 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1154,6 +1154,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); @@ -2606,6 +2611,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), @@ -2749,6 +2756,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 8345b9a207..726a79f03a 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 8b31efdbc6..9578e3e913 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); diff --git a/target/riscv/machine.c b/target/riscv/machine.c index b6b53a4840..ba96ceceef 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -240,8 +240,8 @@ static int debug_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_debug = { .name = "cpu/debug", - .version_id = 3, - .minimum_version_id = 3, + .version_id = 4, + .minimum_version_id = 4, .needed = debug_needed, .post_load = debug_post_load, .fields = (const VMStateField[]) { -- 2.43.0
