On Wed, Jan 5, 2022 at 1:15 PM Bin Meng <bmeng...@gmail.com> wrote: > > From: Bin Meng <bin.m...@windriver.com> > > This adds debug CSR read/write support to the RISC-V CSR RW table. > > Signed-off-by: Bin Meng <bin.m...@windriver.com> > --- > > Changes in v3: > - add riscv_trigger_init(), moved from patch #1 to this patch > > target/riscv/debug.h | 2 ++ > target/riscv/cpu.c | 6 +++++ > target/riscv/csr.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ > target/riscv/debug.c | 27 +++++++++++++++++++++ > 4 files changed, 92 insertions(+) > > diff --git a/target/riscv/debug.h b/target/riscv/debug.h > index d0f63e2414..f4da2db35d 100644 > --- a/target/riscv/debug.h > +++ b/target/riscv/debug.h > @@ -109,4 +109,6 @@ void riscv_cpu_debug_excp_handler(CPUState *cs); > bool riscv_cpu_debug_check_breakpoint(CPUState *cs); > bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp); > > +void riscv_trigger_init(CPURISCVState *env); > + > #endif /* RISCV_DEBUG_H */ > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index d36c31ce9a..17dcc3c14f 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -575,6 +575,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error > **errp) > > riscv_cpu_register_gdb_regs_for_features(cs); > > +#ifndef CONFIG_USER_ONLY > + if (riscv_feature(env, RISCV_FEATURE_DEBUG)) { > + riscv_trigger_init(env); > + } > +#endif > + > qemu_init_vcpu(cs); > cpu_reset(cs); > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index 146447eac5..189b9cc8c6 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -220,6 +220,15 @@ static RISCVException epmp(CPURISCVState *env, int csrno) > > return RISCV_EXCP_ILLEGAL_INST; > } > + > +static RISCVException debug(CPURISCVState *env, int csrno) > +{ > + if (riscv_feature(env, RISCV_FEATURE_DEBUG)) { > + return RISCV_EXCP_NONE; > + } > + > + return RISCV_EXCP_ILLEGAL_INST; > +} > #endif > > /* User Floating-Point CSRs */ > @@ -1464,6 +1473,48 @@ static RISCVException write_pmpaddr(CPURISCVState > *env, int csrno, > return RISCV_EXCP_NONE; > } > > +static RISCVException read_tselect(CPURISCVState *env, int csrno, > + target_ulong *val) > +{ > + *val = tselect_csr_read(env); > + return RISCV_EXCP_NONE; > +} > + > +static RISCVException write_tselect(CPURISCVState *env, int csrno, > + target_ulong val) > +{ > + tselect_csr_write(env, val); > + return RISCV_EXCP_NONE; > +} > + > +static RISCVException read_tdata(CPURISCVState *env, int csrno, > + target_ulong *val) > +{ > + /* return 0 in tdata1 to end the trigger enumeration */ > + if (env->trigger_cur >= TRIGGER_NUM && csrno == CSR_TDATA1) { > + *val = 0; > + return RISCV_EXCP_NONE; > + } > + > + if (!tdata_available(env, csrno - CSR_TDATA1)) { > + return RISCV_EXCP_ILLEGAL_INST; > + } > + > + *val = tdata_csr_read(env, csrno - CSR_TDATA1); > + return RISCV_EXCP_NONE; > +} > + > +static RISCVException write_tdata(CPURISCVState *env, int csrno, > + target_ulong val) > +{ > + if (!tdata_available(env, csrno - CSR_TDATA1)) { > + return RISCV_EXCP_ILLEGAL_INST; > + } > + > + tdata_csr_write(env, csrno - CSR_TDATA1, val); > + return RISCV_EXCP_NONE; > +} > + > /* > * Functions to access Pointer Masking feature registers > * We have to check if current priv lvl could modify > @@ -1962,6 +2013,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > [CSR_PMPADDR14] = { "pmpaddr14", pmp, read_pmpaddr, write_pmpaddr }, > [CSR_PMPADDR15] = { "pmpaddr15", pmp, read_pmpaddr, write_pmpaddr }, > > + /* Debug CSRs */ > + [CSR_TSELECT] = { "tselect", debug, read_tselect, write_tselect }, > + [CSR_TDATA1] = { "tdata1", debug, read_tdata, write_tdata }, > + [CSR_TDATA2] = { "tdata2", debug, read_tdata, write_tdata }, > + [CSR_TDATA3] = { "tdata3", debug, read_tdata, write_tdata }, > + > /* User Pointer Masking */ > [CSR_UMTE] = { "umte", pointer_masking, read_umte, > write_umte }, > [CSR_UPMMASK] = { "upmmask", pointer_masking, read_upmmask, > write_upmmask }, > diff --git a/target/riscv/debug.c b/target/riscv/debug.c > index 7760c4611f..041a0d3a89 100644 > --- a/target/riscv/debug.c > +++ b/target/riscv/debug.c > @@ -412,3 +412,30 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, > CPUWatchpoint *wp) > > return false; > } > + > +void riscv_trigger_init(CPURISCVState *env) > +{ > + target_ulong type2 = trigger_type(env, TRIGGER_TYPE_AD_MATCH); > + int i; > + > + /* type 2 triggers */ > + for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { > + /* > + * type = TRIGGER_TYPE_AD_MATCH > + * dmode = 0 (both debug and M-mode can write tdata) > + * maskmax = 0 (unimplemented, always 0) > + * sizehi = 0 (match against any size, RV64 only) > + * hit = 0 (unimplemented, always 0) > + * select = 0 (always 0, perform match on address) > + * timing = 0 (always 0, trigger before instruction) > + * sizelo = 0 (match against any size) > + * action = 0 (always 0, raise a breakpoint exception) > + * chain = 0 (unimplemented, always 0) > + * match = 0 (always 0, when any compare value equals tdata2) > + */ > + env->trigger_type2[i].mcontrol = type2; > + env->trigger_type2[i].maddress = 0; > + env->trigger_type2[i].bp = NULL; > + env->trigger_type2[i].wp = NULL; > + }
Should this be called at reset instead? Alistair > +} > -- > 2.25.1 > >