aboutsummaryrefslogtreecommitdiff
path: root/softmmu/physmem.c
diff options
context:
space:
mode:
authorPhilippe Mathieu-Daudé <philmd@linaro.org>2022-12-09 14:47:52 +0100
committerPhilippe Mathieu-Daudé <philmd@linaro.org>2023-02-27 22:29:01 +0100
commit2609ec2868e6c286e755a73b4504714a0296aba3 (patch)
treefee76fef4553db8adccb0a1a55999abb8ff857ef /softmmu/physmem.c
parentfeea81d8de5c2c5374ab77ab963fa8c045b9fa4e (diff)
softmmu: Extract watchpoint API from physmem.c
The watchpoint API is specific to TCG system emulation. Move it to a new compile unit. The inlined stubs are used for user-mode and non-TCG accelerators. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20221209141254.68662-1-philmd@linaro.org>
Diffstat (limited to 'softmmu/physmem.c')
-rw-r--r--softmmu/physmem.c191
1 files changed, 0 insertions, 191 deletions
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index cb998cdf23..df54b917a9 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -781,197 +781,6 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
return cpu->cpu_ases[asidx].as;
}
-/* Add a watchpoint. */
-int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
- int flags, CPUWatchpoint **watchpoint)
-{
- CPUWatchpoint *wp;
- vaddr in_page;
-
- /* forbid ranges which are empty or run off the end of the address space */
- if (len == 0 || (addr + len - 1) < addr) {
- error_report("tried to set invalid watchpoint at %"
- VADDR_PRIx ", len=%" VADDR_PRIu, addr, len);
- return -EINVAL;
- }
- wp = g_malloc(sizeof(*wp));
-
- wp->vaddr = addr;
- wp->len = len;
- wp->flags = flags;
-
- /* keep all GDB-injected watchpoints in front */
- if (flags & BP_GDB) {
- QTAILQ_INSERT_HEAD(&cpu->watchpoints, wp, entry);
- } else {
- QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry);
- }
-
- in_page = -(addr | TARGET_PAGE_MASK);
- if (len <= in_page) {
- tlb_flush_page(cpu, addr);
- } else {
- tlb_flush(cpu);
- }
-
- if (watchpoint)
- *watchpoint = wp;
- return 0;
-}
-
-/* Remove a specific watchpoint. */
-int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, vaddr len,
- int flags)
-{
- CPUWatchpoint *wp;
-
- QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
- if (addr == wp->vaddr && len == wp->len
- && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
- cpu_watchpoint_remove_by_ref(cpu, wp);
- return 0;
- }
- }
- return -ENOENT;
-}
-
-/* Remove a specific watchpoint by reference. */
-void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint)
-{
- QTAILQ_REMOVE(&cpu->watchpoints, watchpoint, entry);
-
- tlb_flush_page(cpu, watchpoint->vaddr);
-
- g_free(watchpoint);
-}
-
-/* Remove all matching watchpoints. */
-void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
-{
- CPUWatchpoint *wp, *next;
-
- QTAILQ_FOREACH_SAFE(wp, &cpu->watchpoints, entry, next) {
- if (wp->flags & mask) {
- cpu_watchpoint_remove_by_ref(cpu, wp);
- }
- }
-}
-
-#ifdef CONFIG_TCG
-/* Return true if this watchpoint address matches the specified
- * access (ie the address range covered by the watchpoint overlaps
- * partially or completely with the address range covered by the
- * access).
- */
-static inline bool watchpoint_address_matches(CPUWatchpoint *wp,
- vaddr addr, vaddr len)
-{
- /* We know the lengths are non-zero, but a little caution is
- * required to avoid errors in the case where the range ends
- * exactly at the top of the address space and so addr + len
- * wraps round to zero.
- */
- vaddr wpend = wp->vaddr + wp->len - 1;
- vaddr addrend = addr + len - 1;
-
- return !(addr > wpend || wp->vaddr > addrend);
-}
-
-/* Return flags for watchpoints that match addr + prot. */
-int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len)
-{
- CPUWatchpoint *wp;
- int ret = 0;
-
- QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
- if (watchpoint_address_matches(wp, addr, len)) {
- ret |= wp->flags;
- }
- }
- return ret;
-}
-
-/* Generate a debug exception if a watchpoint has been hit. */
-void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
- MemTxAttrs attrs, int flags, uintptr_t ra)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
- CPUWatchpoint *wp;
-
- assert(tcg_enabled());
- if (cpu->watchpoint_hit) {
- /*
- * We re-entered the check after replacing the TB.
- * Now raise the debug interrupt so that it will
- * trigger after the current instruction.
- */
- qemu_mutex_lock_iothread();
- cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG);
- qemu_mutex_unlock_iothread();
- return;
- }
-
- if (cc->tcg_ops->adjust_watchpoint_address) {
- /* this is currently used only by ARM BE32 */
- addr = cc->tcg_ops->adjust_watchpoint_address(cpu, addr, len);
- }
- QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
- if (watchpoint_address_matches(wp, addr, len)
- && (wp->flags & flags)) {
- if (replay_running_debug()) {
- /*
- * replay_breakpoint reads icount.
- * Force recompile to succeed, because icount may
- * be read only at the end of the block.
- */
- if (!cpu->can_do_io) {
- /* Force execution of one insn next time. */
- cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(cpu);
- cpu_loop_exit_restore(cpu, ra);
- }
- /*
- * Don't process the watchpoints when we are
- * in a reverse debugging operation.
- */
- replay_breakpoint();
- return;
- }
- if (flags == BP_MEM_READ) {
- wp->flags |= BP_WATCHPOINT_HIT_READ;
- } else {
- wp->flags |= BP_WATCHPOINT_HIT_WRITE;
- }
- wp->hitaddr = MAX(addr, wp->vaddr);
- wp->hitattrs = attrs;
-
- if (wp->flags & BP_CPU && cc->tcg_ops->debug_check_watchpoint &&
- !cc->tcg_ops->debug_check_watchpoint(cpu, wp)) {
- wp->flags &= ~BP_WATCHPOINT_HIT;
- continue;
- }
- cpu->watchpoint_hit = wp;
-
- mmap_lock();
- /* This call also restores vCPU state */
- tb_check_watchpoint(cpu, ra);
- if (wp->flags & BP_STOP_BEFORE_ACCESS) {
- cpu->exception_index = EXCP_DEBUG;
- mmap_unlock();
- cpu_loop_exit(cpu);
- } else {
- /* Force execution of one insn next time. */
- cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(cpu);
- mmap_unlock();
- cpu_loop_exit_noexc(cpu);
- }
- } else {
- wp->flags &= ~BP_WATCHPOINT_HIT;
- }
- }
-}
-
-#endif /* CONFIG_TCG */
-
/* Called from RCU critical section */
static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
{