Re: [PATCH 1/2] target/xtensa: use generic instruction breakpoint infrastructure

2023-11-30 Thread Richard Henderson

On 11/30/23 11:19, Max Filippov wrote:

Don't embed ibreak exception generation into TB and don't invalidate TB
on ibreak address change. Add CPUBreakpoint pointers to xtensa
CPUArchState, use cpu_breakpoint_insert/cpu_breakpoint_remove_by_ref to
manage ibreak breakpoints and provide TCGCPUOps::debug_check_breakpoint
callback that recognizes valid instruction breakpoints.

Signed-off-by: Max Filippov 
---
  target/xtensa/cpu.c|  1 +
  target/xtensa/cpu.h|  4 
  target/xtensa/dbg_helper.c | 46 +-
  target/xtensa/helper.c | 12 ++
  target/xtensa/translate.c  | 17 --
  5 files changed, 47 insertions(+), 33 deletions(-)


Thanks a bunch,

Reviewed-by: Richard Henderson 


r~



[PATCH 1/2] target/xtensa: use generic instruction breakpoint infrastructure

2023-11-30 Thread Max Filippov
Don't embed ibreak exception generation into TB and don't invalidate TB
on ibreak address change. Add CPUBreakpoint pointers to xtensa
CPUArchState, use cpu_breakpoint_insert/cpu_breakpoint_remove_by_ref to
manage ibreak breakpoints and provide TCGCPUOps::debug_check_breakpoint
callback that recognizes valid instruction breakpoints.

Signed-off-by: Max Filippov 
---
 target/xtensa/cpu.c|  1 +
 target/xtensa/cpu.h|  4 
 target/xtensa/dbg_helper.c | 46 +-
 target/xtensa/helper.c | 12 ++
 target/xtensa/translate.c  | 17 --
 5 files changed, 47 insertions(+), 33 deletions(-)

diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index e20fe87bf255..b74ee8917065 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -235,6 +235,7 @@ static const struct TCGCPUOps xtensa_tcg_ops = {
 .do_interrupt = xtensa_cpu_do_interrupt,
 .do_transaction_failed = xtensa_cpu_do_transaction_failed,
 .do_unaligned_access = xtensa_cpu_do_unaligned_access,
+.debug_check_breakpoint = xtensa_debug_check_breakpoint,
 #endif /* !CONFIG_USER_ONLY */
 };
 
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index dd8172930653..8a423706d8c0 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -229,6 +229,7 @@ enum {
 #define MAX_NCCOMPARE 3
 #define MAX_TLB_WAY_SIZE 8
 #define MAX_NDBREAK 2
+#define MAX_NIBREAK 2
 #define MAX_NMEMORY 4
 #define MAX_MPU_FOREGROUND_SEGMENTS 32
 
@@ -547,6 +548,8 @@ struct CPUArchState {
 
 /* Watchpoints for DBREAK registers */
 struct CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK];
+/* Breakpoints for IBREAK registers */
+struct CPUBreakpoint *cpu_breakpoint[MAX_NIBREAK];
 };
 
 /**
@@ -590,6 +593,7 @@ void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr 
physaddr, vaddr addr,
   int mmu_idx, MemTxAttrs attrs,
   MemTxResult response, uintptr_t retaddr);
 hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+bool xtensa_debug_check_breakpoint(CPUState *cs);
 #endif
 void xtensa_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
 void xtensa_count_regs(const XtensaConfig *config,
diff --git a/target/xtensa/dbg_helper.c b/target/xtensa/dbg_helper.c
index 3e0c9e8e8be0..497dafca719c 100644
--- a/target/xtensa/dbg_helper.c
+++ b/target/xtensa/dbg_helper.c
@@ -33,27 +33,21 @@
 #include "exec/exec-all.h"
 #include "exec/address-spaces.h"
 
-static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr)
-{
-uint32_t paddr;
-uint32_t page_size;
-unsigned access;
-int ret = xtensa_get_physical_addr(env, false, vaddr, 2, 0,
-   , _size, );
-if (ret == 0) {
-tb_invalidate_phys_addr(_space_memory, paddr,
-MEMTXATTRS_UNSPECIFIED);
-}
-}
-
 void HELPER(wsr_ibreakenable)(CPUXtensaState *env, uint32_t v)
 {
+CPUState *cs = env_cpu(env);
 uint32_t change = v ^ env->sregs[IBREAKENABLE];
 unsigned i;
 
 for (i = 0; i < env->config->nibreak; ++i) {
 if (change & (1 << i)) {
-tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]);
+if (v & (1 << i)) {
+cpu_breakpoint_insert(cs, env->sregs[IBREAKA + i],
+  BP_CPU, >cpu_breakpoint[i]);
+} else {
+cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[i]);
+env->cpu_breakpoint[i] = NULL;
+}
 }
 }
 env->sregs[IBREAKENABLE] = v & ((1 << env->config->nibreak) - 1);
@@ -62,12 +56,32 @@ void HELPER(wsr_ibreakenable)(CPUXtensaState *env, uint32_t 
v)
 void HELPER(wsr_ibreaka)(CPUXtensaState *env, uint32_t i, uint32_t v)
 {
 if (env->sregs[IBREAKENABLE] & (1 << i) && env->sregs[IBREAKA + i] != v) {
-tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]);
-tb_invalidate_virtual_addr(env, v);
+CPUState *cs = env_cpu(env);
+
+cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[i]);
+cpu_breakpoint_insert(cs, v, BP_CPU, >cpu_breakpoint[i]);
 }
 env->sregs[IBREAKA + i] = v;
 }
 
+bool xtensa_debug_check_breakpoint(CPUState *cs)
+{
+XtensaCPU *cpu = XTENSA_CPU(cs);
+CPUXtensaState *env = >env;
+unsigned int i;
+
+if (xtensa_get_cintlevel(env) >= env->config->debug_level) {
+return false;
+}
+for (i = 0; i < env->config->nibreak; ++i) {
+if (env->sregs[IBREAKENABLE] & (1 << i) &&
+env->sregs[IBREAKA + i] == env->pc) {
+return true;
+}
+}
+return false;
+}
+
 static void set_dbreak(CPUXtensaState *env, unsigned i, uint32_t dbreaka,
 uint32_t dbreakc)
 {
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index dbeb97a953cc..151da75a41c5 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -231,6 +231,18 @@ void