RISC-V Debug Specification: 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]> --- 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 } }; -- 2.52.0
