RISC-V Debug Specification:
https://github.com/riscv/riscv-debug-spec/releases/tag/1.0 <https://
github.com/riscv/riscv-debug-spec/releases/tag/1.0>
Add architectural state for Sdext Debug Mode: debug_mode, dcsr, dpc
and dscratch0/1. Wire up CSR access for dcsr/dpc/dscratch and gate
them to Debug Mode (or host debugger access).
Signed-off-by: Chao Liu <[email protected]>
<mailto:[email protected]>
---
target/riscv/cpu.c | 9 +++
target/riscv/cpu.h | 4 +
target/riscv/cpu_bits.h | 33 ++++++++
target/riscv/cpu_cfg_fields.h.inc | 1 +
target/riscv/csr.c | 126 ++++++++++++++++++++++++++++++
target/riscv/machine.c | 20 +++++
6 files changed, 193 insertions(+)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f1b977f0ee..bd6cff33cf 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -211,6 +211,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(zvkt, PRIV_VERSION_1_12_0, ext_zvkt),
ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ ISA_EXT_DATA_ENTRY(sdext, PRIV_VERSION_1_12_0, ext_sdext),
ISA_EXT_DATA_ENTRY(sdtrig, PRIV_VERSION_1_12_0, ext_sdtrig),
ISA_EXT_DATA_ENTRY(shcounterenw, PRIV_VERSION_1_12_0,
has_priv_1_12),
ISA_EXT_DATA_ENTRY(sha, PRIV_VERSION_1_12_0, ext_sha),
@@ -788,6 +789,11 @@ static void riscv_cpu_reset_hold(Object *obj,
ResetType type)
set_ocp_fp8_same_canonical_nan(true, &env->fp_status);
set_ocp_fp8e5m2_no_signal_nan(true, &env->fp_status);
env->vill = true;
+ env->debug_mode = false;
+ env->dcsr = DCSR_DEBUGVER(4);
+ env->dpc = 0;
+ env->dscratch[0] = 0;
+ env->dscratch[1] = 0;
#ifndef CONFIG_USER_ONLY
if (cpu->cfg.ext_sdtrig) {
@@ -1140,6 +1146,9 @@ static void riscv_cpu_init(Object *obj)
*/
cpu->cfg.ext_sdtrig = true;
+ /* sdext is not fully implemented, so it is disabled by
default. */
+ cpu->cfg.ext_sdext = false;
+
if (mcc->def->profile) {
mcc->def->profile->enabled = true;
}
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 4c0676ed53..2a265faae5 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -476,6 +476,10 @@ struct CPUArchState {
/* True if in debugger mode. */
bool debugger;
+ bool debug_mode;
+ target_ulong dcsr;
+ target_ulong dpc;
+ target_ulong dscratch[2];
uint64_t mstateen[SMSTATEEN_MAX_COUNT];
uint64_t hstateen[SMSTATEEN_MAX_COUNT];
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index b62dd82fe7..bb59f7ff56 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -467,6 +467,39 @@
#define CSR_DCSR 0x7b0
#define CSR_DPC 0x7b1
#define CSR_DSCRATCH 0x7b2
+#define CSR_DSCRATCH1 0x7b3
+
+/* DCSR fields */
+#define DCSR_XDEBUGVER_SHIFT 28
+#define DCSR_XDEBUGVER_MASK (0xfu << DCSR_XDEBUGVER_SHIFT)
+#define DCSR_DEBUGVER(val) ((target_ulong)(val) <<
DCSR_XDEBUGVER_SHIFT)
+#define DCSR_EXTCAUSE_SHIFT 24
+#define DCSR_EXTCAUSE_MASK (0x7u << DCSR_EXTCAUSE_SHIFT)
+#define DCSR_CETRIG BIT(19)
+#define DCSR_PELP BIT(18)
+#define DCSR_EBREAKVS BIT(17)
+#define DCSR_EBREAKVU BIT(16)
+#define DCSR_EBREAKM BIT(15)
+#define DCSR_EBREAKS BIT(13)
+#define DCSR_EBREAKU BIT(12)
+#define DCSR_STEPIE BIT(11)
+#define DCSR_STOPCOUNT BIT(10)
+#define DCSR_STOPTIME BIT(9)
+#define DCSR_CAUSE_SHIFT 6
+#define DCSR_CAUSE_MASK (0x7u << DCSR_CAUSE_SHIFT)
+#define DCSR_V BIT(5)
+#define DCSR_MPRVEN BIT(4)
+#define DCSR_NMIP BIT(3)
+#define DCSR_STEP BIT(2)
+#define DCSR_PRV_MASK 0x3u
+
+#define DCSR_CAUSE_EBREAK 1
+#define DCSR_CAUSE_TRIGGER 2
+#define DCSR_CAUSE_HALTREQ 3
+#define DCSR_CAUSE_STEP 4
+#define DCSR_CAUSE_RESET 5
+#define DCSR_CAUSE_GROUP 6
+#define DCSR_CAUSE_OTHER 7
/* Performance Counters */
#define CSR_MHPMCOUNTER3 0xb03
diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/
cpu_cfg_fields.h.inc
index a8c133d663..99b5529161 100644
--- a/target/riscv/cpu_cfg_fields.h.inc
+++ b/target/riscv/cpu_cfg_fields.h.inc
@@ -46,6 +46,7 @@ BOOL_FIELD(ext_zilsd)
BOOL_FIELD(ext_zimop)
BOOL_FIELD(ext_zcmop)
BOOL_FIELD(ext_ztso)
+BOOL_FIELD(ext_sdext)
BOOL_FIELD(ext_sdtrig)
BOOL_FIELD(ext_smstateen)
BOOL_FIELD(ext_sstc)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 870fad87ac..3e38c943e0 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3136,6 +3136,126 @@ static RISCVException
write_mtval(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
+#if !defined(CONFIG_USER_ONLY)
+static RISCVException sdext(CPURISCVState *env, int csrno)
+{
+ if (!riscv_cpu_cfg(env)->ext_sdext) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ if (!env->debug_mode && !env->debugger) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return RISCV_EXCP_NONE;
+}
+
+static target_ulong dcsr_visible_mask(CPURISCVState *env)
+{
+ target_ulong mask = (target_ulong)-1;
+ RISCVCPU *cpu = env_archcpu(env);
+
+ if (!riscv_has_ext(env, RVH)) {
+ mask &= ~(DCSR_EBREAKVS | DCSR_EBREAKVU | DCSR_V);
+ }
+ if (!riscv_has_ext(env, RVS)) {
+ mask &= ~DCSR_EBREAKS;
+ }
+ if (!riscv_has_ext(env, RVU)) {
+ mask &= ~DCSR_EBREAKU;
+ }
+ if (!cpu->cfg.ext_zicfilp) {
+ mask &= ~DCSR_PELP;
+ }
+ if (!cpu->cfg.ext_smdbltrp) {
+ mask &= ~DCSR_CETRIG;
+ }
+
+ return mask;
+}
+
+static RISCVException read_dcsr(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = env->dcsr & dcsr_visible_mask(env);
+ return RISCV_EXCP_NONE;
+}
+
+static target_ulong dcsr_writable_mask(CPURISCVState *env)
+{
+ target_ulong mask = DCSR_EBREAKM | DCSR_EBREAKS | DCSR_EBREAKU |
+ DCSR_STEPIE | DCSR_STOPCOUNT | DCSR_STOPTIME |
+ DCSR_STEP | DCSR_PRV_MASK;
+ RISCVCPU *cpu = env_archcpu(env);
+
+ mask |= DCSR_MPRVEN;
+
+ if (riscv_has_ext(env, RVH)) {
+ mask |= DCSR_EBREAKVS | DCSR_EBREAKVU | DCSR_V;
+ }
+ if (riscv_has_ext(env, RVS)) {
+ mask |= DCSR_EBREAKS;
+ }
+ if (riscv_has_ext(env, RVU)) {
+ mask |= DCSR_EBREAKU;
+ }
+ if (cpu->cfg.ext_zicfilp) {
+ mask |= DCSR_PELP;
+ }
+ if (cpu->cfg.ext_smdbltrp) {
+ mask |= DCSR_CETRIG;
+ }
+
+ return mask;
+}
+
+static RISCVException write_dcsr(CPURISCVState *env, int csrno,
+ target_ulong val, uintptr_t ra)
+{
+ target_ulong mask = dcsr_writable_mask(env);
+ target_ulong new_val = env->dcsr;
+
+ new_val &= ~mask;
+ new_val |= val & mask;
+ new_val &= ~DCSR_XDEBUGVER_MASK;
+ new_val |= DCSR_DEBUGVER(4);
+ env->dcsr = new_val;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_dpc(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = env->dpc & get_xepc_mask(env);
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_dpc(CPURISCVState *env, int csrno,
+ target_ulong val, uintptr_t ra)
+{
+ env->dpc = val & get_xepc_mask(env);
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_dscratch(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ int index = (csrno == CSR_DSCRATCH1) ? 1 : 0;
+
+ *val = env->dscratch[index];
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_dscratch(CPURISCVState *env, int csrno,
+ target_ulong val, uintptr_t ra)
+{
+ int index = (csrno == CSR_DSCRATCH1) ? 1 : 0;
+
+ env->dscratch[index] = val;
+ return RISCV_EXCP_NONE;
+}
+#endif /* !CONFIG_USER_ONLY */
+
/* Execution environment configuration setup */
static RISCVException read_menvcfg(CPURISCVState *env, int csrno,
target_ulong *val)
@@ -6297,6 +6417,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_TDATA3] = { "tdata3", debug, read_tdata,
write_tdata },
[CSR_TINFO] = { "tinfo", debug, read_tinfo,
write_ignore },
[CSR_MCONTEXT] = { "mcontext", debug, read_mcontext,
write_mcontext },
+#if !defined(CONFIG_USER_ONLY)
+ [CSR_DCSR] = { "dcsr", sdext, read_dcsr, write_dcsr },
+ [CSR_DPC] = { "dpc", sdext, read_dpc, write_dpc },
+ [CSR_DSCRATCH] = { "dscratch0", sdext, read_dscratch,
write_dscratch },
+ [CSR_DSCRATCH1] = { "dscratch1", sdext, read_dscratch,
write_dscratch },
+#endif
[CSR_MCTRCTL] = { "mctrctl", ctr_mmode, NULL, NULL,
rmw_xctrctl },
[CSR_SCTRCTL] = { "sctrctl", ctr_smode, NULL, NULL,
rmw_xctrctl },
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 62c51c8033..52264cf047 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -248,6 +248,25 @@ static const VMStateDescription vmstate_sdtrig = {
VMSTATE_UINTTL_ARRAY(env.tdata1, RISCVCPU, RV_MAX_TRIGGERS),
VMSTATE_UINTTL_ARRAY(env.tdata2, RISCVCPU, RV_MAX_TRIGGERS),
VMSTATE_UINTTL_ARRAY(env.tdata3, RISCVCPU, RV_MAX_TRIGGERS),
+ VMSTATE_BOOL_V(env.debug_mode, RISCVCPU, 3),
+ VMSTATE_UINTTL_V(env.dcsr, RISCVCPU, 3),
+ VMSTATE_UINTTL_V(env.dpc, RISCVCPU, 3),
+ VMSTATE_UINTTL_ARRAY_V(env.dscratch, RISCVCPU, 2, 3),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_sdext = {
+ .name = "cpu/sdext",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = sdtrig_needed,
+ .post_load = sdtrig_post_load,
+ .fields = (const VMStateField[]) {
+ VMSTATE_BOOL_V(env.debug_mode, RISCVCPU, 3),
+ VMSTATE_UINTTL_V(env.dcsr, RISCVCPU, 3),
+ VMSTATE_UINTTL_V(env.dpc, RISCVCPU, 3),
+ VMSTATE_UINTTL_ARRAY_V(env.dscratch, RISCVCPU, 2, 3),
VMSTATE_END_OF_LIST()
}
};
@@ -499,6 +518,7 @@ const VMStateDescription vmstate_riscv_cpu = {
&vmstate_ctr,
&vmstate_sstc,
&vmstate_sdtrig,
+ &vmstate_sdext,
NULL
}
};