Message ID | 20211030135513.18517-4-bin.meng@windriver.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | target/riscv: Initial support for native debug feature via M-mode CSRs | expand |
On Sat, Oct 30, 2021 at 11:59 PM Bin Meng <bmeng.cn@gmail.com> wrote: > > Implement .debug_excp_handler, .debug_check_{breakpoint, watchpoint} > TCGCPUOps and hook them into riscv_tcg_ops. > > Signed-off-by: Bin Meng <bin.meng@windriver.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > > --- > > Changes in v2: > - use 0 instead of GETPC() > > target/riscv/debug.h | 4 +++ > target/riscv/cpu.c | 3 ++ > target/riscv/debug.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 82 insertions(+) > > diff --git a/target/riscv/debug.h b/target/riscv/debug.h > index cb8a6e0024..fddc103650 100644 > --- a/target/riscv/debug.h > +++ b/target/riscv/debug.h > @@ -107,4 +107,8 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val); > > void riscv_trigger_init(CPURISCVState *env); > > +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); > + > #endif /* RISCV_DEBUG_H */ > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 7d53125dbc..7061ae05fb 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -701,6 +701,9 @@ static const struct TCGCPUOps riscv_tcg_ops = { > .do_interrupt = riscv_cpu_do_interrupt, > .do_transaction_failed = riscv_cpu_do_transaction_failed, > .do_unaligned_access = riscv_cpu_do_unaligned_access, > + .debug_excp_handler = riscv_cpu_debug_excp_handler, > + .debug_check_breakpoint = riscv_cpu_debug_check_breakpoint, > + .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint, > #endif /* !CONFIG_USER_ONLY */ > }; > > diff --git a/target/riscv/debug.c b/target/riscv/debug.c > index 9bcca27b72..9cb2a6d7ba 100644 > --- a/target/riscv/debug.c > +++ b/target/riscv/debug.c > @@ -364,3 +364,78 @@ void riscv_trigger_init(CPURISCVState *env) > env->trigger_type2[i].wp = NULL; > } > } > + > +void riscv_cpu_debug_excp_handler(CPUState *cs) > +{ > + RISCVCPU *cpu = RISCV_CPU(cs); > + CPURISCVState *env = &cpu->env; > + > + if (cs->watchpoint_hit) { > + if (cs->watchpoint_hit->flags & BP_CPU) { > + cs->watchpoint_hit = NULL; > + riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); > + } > + } else { > + if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) { > + riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); > + } > + } > +} > + > +bool riscv_cpu_debug_check_breakpoint(CPUState *cs) > +{ > + RISCVCPU *cpu = RISCV_CPU(cs); > + CPURISCVState *env = &cpu->env; > + CPUBreakpoint *bp; > + target_ulong ctrl; > + target_ulong pc; > + int i; > + > + QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { > + for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { > + ctrl = env->trigger_type2[i].mcontrol; > + pc = env->trigger_type2[i].maddress; > + > + if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) { > + /* check U/S/M bit against current privilege level */ > + if ((ctrl >> 3) & BIT(env->priv)) { > + return true; > + } > + } > + } > + } > + > + return false; > +} > + > +bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) > +{ > + RISCVCPU *cpu = RISCV_CPU(cs); > + CPURISCVState *env = &cpu->env; > + target_ulong ctrl; > + target_ulong addr; > + int flags; > + int i; > + > + for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { > + ctrl = env->trigger_type2[i].mcontrol; > + addr = env->trigger_type2[i].maddress; > + flags = 0; > + > + if (ctrl & TYPE2_LOAD) { > + flags |= BP_MEM_READ; > + } > + if (ctrl & TYPE2_STORE) { > + flags |= BP_MEM_WRITE; > + } > + > + if ((wp->flags & flags) && (wp->vaddr == addr)) { > + /* check U/S/M bit against current privilege level */ > + if ((ctrl >> 3) & BIT(env->priv)) { > + return true; > + } > + } > + } > + > + return false; > +} > -- > 2.25.1 > >
diff --git a/target/riscv/debug.h b/target/riscv/debug.h index cb8a6e0024..fddc103650 100644 --- a/target/riscv/debug.h +++ b/target/riscv/debug.h @@ -107,4 +107,8 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val); void riscv_trigger_init(CPURISCVState *env); +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); + #endif /* RISCV_DEBUG_H */ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 7d53125dbc..7061ae05fb 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -701,6 +701,9 @@ static const struct TCGCPUOps riscv_tcg_ops = { .do_interrupt = riscv_cpu_do_interrupt, .do_transaction_failed = riscv_cpu_do_transaction_failed, .do_unaligned_access = riscv_cpu_do_unaligned_access, + .debug_excp_handler = riscv_cpu_debug_excp_handler, + .debug_check_breakpoint = riscv_cpu_debug_check_breakpoint, + .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint, #endif /* !CONFIG_USER_ONLY */ }; diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 9bcca27b72..9cb2a6d7ba 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -364,3 +364,78 @@ void riscv_trigger_init(CPURISCVState *env) env->trigger_type2[i].wp = NULL; } } + +void riscv_cpu_debug_excp_handler(CPUState *cs) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + + if (cs->watchpoint_hit) { + if (cs->watchpoint_hit->flags & BP_CPU) { + cs->watchpoint_hit = NULL; + riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); + } + } else { + if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) { + riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); + } + } +} + +bool riscv_cpu_debug_check_breakpoint(CPUState *cs) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + CPUBreakpoint *bp; + target_ulong ctrl; + target_ulong pc; + int i; + + QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { + for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { + ctrl = env->trigger_type2[i].mcontrol; + pc = env->trigger_type2[i].maddress; + + if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) { + /* check U/S/M bit against current privilege level */ + if ((ctrl >> 3) & BIT(env->priv)) { + return true; + } + } + } + } + + return false; +} + +bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + target_ulong ctrl; + target_ulong addr; + int flags; + int i; + + for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { + ctrl = env->trigger_type2[i].mcontrol; + addr = env->trigger_type2[i].maddress; + flags = 0; + + if (ctrl & TYPE2_LOAD) { + flags |= BP_MEM_READ; + } + if (ctrl & TYPE2_STORE) { + flags |= BP_MEM_WRITE; + } + + if ((wp->flags & flags) && (wp->vaddr == addr)) { + /* check U/S/M bit against current privilege level */ + if ((ctrl >> 3) & BIT(env->priv)) { + return true; + } + } + } + + return false; +}
Implement .debug_excp_handler, .debug_check_{breakpoint, watchpoint} TCGCPUOps and hook them into riscv_tcg_ops. Signed-off-by: Bin Meng <bin.meng@windriver.com> --- Changes in v2: - use 0 instead of GETPC() target/riscv/debug.h | 4 +++ target/riscv/cpu.c | 3 ++ target/riscv/debug.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+)