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