Implement a Sdtrig CPU configuration class that provides
details about the Sdtrig configuration.

It is stored as a pointer in RISCVCPUClass to avoid issues with
nested compound literals inside static initialisers with GCC 11.

For now, the number of supported triggers is configurable. This
requires some logic

Signed-off-by: Nicholas Piggin <[email protected]>
---
 target/riscv/cpu.c     | 25 +++++++++++++++++++++++++
 target/riscv/cpu.h     |  4 ++++
 target/riscv/debug.c   |  5 ++++-
 target/riscv/debug.h   |  4 ++++
 target/riscv/machine.c | 11 ++++++++---
 5 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 057e221808..6f7a327fc7 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -23,6 +23,7 @@
 #include "qemu/log.h"
 #include "cpu.h"
 #include "cpu_vendorid.h"
+#include "debug.h"
 #include "internals.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
@@ -2816,6 +2817,11 @@ static void riscv_cpu_class_base_init(ObjectClass *c, 
const void *data)
             mcc->def->vext_spec = def->vext_spec;
         }
         mcc->def->misa_ext |= def->misa_ext;
+#if !defined(CONFIG_USER_ONLY)
+        if (def->debug_cfg) {
+            mcc->def->debug_cfg = def->debug_cfg;
+        }
+#endif
 
         riscv_cpu_cfg_merge(&mcc->def->cfg, &def->cfg);
 
@@ -2951,6 +2957,18 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char 
*nodename)
     DEFINE_RISCV_CPU(type_name, parent_type_name,             \
         .profile = &(profile_))
 
+#if !defined(CONFIG_USER_ONLY)
+/* Sdtrig implementation has 2 triggers that support match, match6, icount */
+static const RISCVSdtrigConfig default_sdtrig_config = {
+    .nr_triggers = 2,
+};
+
+bool riscv_sdtrig_default_implementation(const RISCVSdtrigConfig *config)
+{
+    return config == &default_sdtrig_config;
+}
+#endif
+
 static const TypeInfo riscv_cpu_type_infos[] = {
     {
         .name = TYPE_RISCV_CPU,
@@ -2968,6 +2986,9 @@ static const TypeInfo riscv_cpu_type_infos[] = {
         .cfg.mmu = true,
         .cfg.pmp = true,
         .priv_spec = PRIV_VERSION_LATEST,
+#if !defined(CONFIG_USER_ONLY)
+        .debug_cfg = &default_sdtrig_config,
+#endif
     ),
 
     DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_VENDOR_CPU, TYPE_RISCV_CPU),
@@ -2995,6 +3016,10 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 #else
         .cfg.max_satp_mode = VM_1_10_SV57,
 #endif
+
+#if !defined(CONFIG_USER_ONLY)
+        .debug_cfg = &default_sdtrig_config,
+#endif
     ),
 
     DEFINE_RISCV_CPU(TYPE_RISCV_CPU_MAX, TYPE_RISCV_DYNAMIC_CPU,
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 44ed1665e2..c4f1cb0a9d 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -571,6 +571,9 @@ typedef struct RISCVCSR RISCVCSR;
 typedef struct RISCVCPUDef {
     RISCVMXL misa_mxl_max;  /* max mxl for this cpu */
     RISCVCPUProfile *profile;
+#if !defined(CONFIG_USER_ONLY)
+    const RISCVSdtrigConfig *debug_cfg;
+#endif
     uint32_t misa_ext;
     int priv_spec;
     int32_t vext_spec;
@@ -666,6 +669,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, 
uint32_t priv,
                                    void *rmw_fn_arg);
 
 RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
+bool riscv_sdtrig_default_implementation(const RISCVSdtrigConfig *config);
 #endif /* !CONFIG_USER_ONLY */
 
 void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool 
virt_en);
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 22f7958a79..93615b43fb 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -173,7 +173,10 @@ target_ulong tselect_csr_read(CPURISCVState *env)
 
 void tselect_csr_write(CPURISCVState *env, target_ulong val)
 {
-    if (val < RV_DEFAULT_TRIGGERS) {
+    CPUState *cs = env_cpu(env);
+    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cs);
+
+    if (val < mcc->def->debug_cfg->nr_triggers) {
         env->sdtrig_state.trigger_cur = val;
     }
 }
diff --git a/target/riscv/debug.h b/target/riscv/debug.h
index 8a047c8073..3ba12f95cd 100644
--- a/target/riscv/debug.h
+++ b/target/riscv/debug.h
@@ -135,6 +135,10 @@ enum {
 #define MHSELECT_IGNORE       0
 #define MHSELECT_MCONTEXT     4
 
+typedef struct RISCVSdtrigConfig {
+    unsigned int nr_triggers;
+} RISCVSdtrigConfig;
+
 bool tdata_available(CPURISCVState *env, int tdata_index);
 
 target_ulong tselect_csr_read(CPURISCVState *env);
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 23a5f60d2a..9f65bdca9b 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -221,10 +221,12 @@ static const VMStateDescription vmstate_kvmtimer = {
 static bool debug_needed(void *opaque)
 {
     RISCVCPU *cpu = opaque;
+    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
     CPURISCVState *env = &cpu->env;
 
     return cpu->cfg.debug &&
-           env->sdtrig_state.mcontext == 0;
+           (riscv_sdtrig_default_implementation(mcc->def->debug_cfg) &&
+            env->sdtrig_state.mcontext == 0);
 }
 
 static int debug_pre_save(void *opaque)
@@ -277,15 +279,18 @@ static const VMStateDescription vmstate_debug = {
 
 /*
  * This is a newer version of the debug (sdtrig) state, required
- * to migrate hcontext/mcontext.
+ * to migrate hcontext/mcontext, or machines with non-default
+ * sdtrig implementation.
  */
 static bool sdtrig_needed(void *opaque)
 {
     RISCVCPU *cpu = opaque;
+    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
     CPURISCVState *env = &cpu->env;
 
     return cpu->cfg.debug &&
-           env->sdtrig_state.mcontext != 0;
+           !(riscv_sdtrig_default_implementation(mcc->def->debug_cfg) &&
+             env->sdtrig_state.mcontext == 0);
 }
 
 static int sdtrig_post_load(void *opaque, int version_id)
-- 
2.51.0


Reply via email to