Message ID | 20220105030844.780642-6-bmeng.cn@gmail.com |
---|---|
State | Superseded |
Headers | show |
Series | target/riscv: Initial support for native debug feature via M-mode CSRs | expand |
On Wed, Jan 5, 2022 at 1:15 PM Bin Meng <bmeng.cn@gmail.com> wrote: > > From: Bin Meng <bin.meng@windriver.com> > > This adds debug CSR read/write support to the RISC-V CSR RW table. > > Signed-off-by: Bin Meng <bin.meng@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 > >
On Wed, Jan 19, 2022 at 11:06 AM Alistair Francis <alistair23@gmail.com> wrote: > > On Wed, Jan 5, 2022 at 1:15 PM Bin Meng <bmeng.cn@gmail.com> wrote: > > > > From: Bin Meng <bin.meng@windriver.com> > > > > This adds debug CSR read/write support to the RISC-V CSR RW table. > > > > Signed-off-by: Bin Meng <bin.meng@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? Yes, I think so. Regards, Bin
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; + } +}