4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
21 #include "qemu/main-loop.h"
22 #include "qemu/error-report.h"
23 #include "exec/exec-all.h"
24 #include "exec/translate-all.h"
25 #include "sysemu/tcg.h"
26 #include "sysemu/replay.h"
27 #include "hw/core/tcg-cpu-ops.h"
28 #include "hw/core/cpu.h"
31 * Return true if this watchpoint address matches the specified
32 * access (ie the address range covered by the watchpoint overlaps
33 * partially or completely with the address range covered by the
36 static inline bool watchpoint_address_matches(CPUWatchpoint
*wp
,
37 vaddr addr
, vaddr len
)
40 * We know the lengths are non-zero, but a little caution is
41 * required to avoid errors in the case where the range ends
42 * exactly at the top of the address space and so addr + len
43 * wraps round to zero.
45 vaddr wpend
= wp
->vaddr
+ wp
->len
- 1;
46 vaddr addrend
= addr
+ len
- 1;
48 return !(addr
> wpend
|| wp
->vaddr
> addrend
);
51 /* Return flags for watchpoints that match addr + prot. */
52 int cpu_watchpoint_address_matches(CPUState
*cpu
, vaddr addr
, vaddr len
)
57 QTAILQ_FOREACH(wp
, &cpu
->watchpoints
, entry
) {
58 if (watchpoint_address_matches(wp
, addr
, len
)) {
65 /* Generate a debug exception if a watchpoint has been hit. */
66 void cpu_check_watchpoint(CPUState
*cpu
, vaddr addr
, vaddr len
,
67 MemTxAttrs attrs
, int flags
, uintptr_t ra
)
69 CPUClass
*cc
= CPU_GET_CLASS(cpu
);
72 assert(tcg_enabled());
73 if (cpu
->watchpoint_hit
) {
75 * We re-entered the check after replacing the TB.
76 * Now raise the debug interrupt so that it will
77 * trigger after the current instruction.
80 cpu_interrupt(cpu
, CPU_INTERRUPT_DEBUG
);
85 if (cc
->tcg_ops
->adjust_watchpoint_address
) {
86 /* this is currently used only by ARM BE32 */
87 addr
= cc
->tcg_ops
->adjust_watchpoint_address(cpu
, addr
, len
);
90 assert((flags
& ~BP_MEM_ACCESS
) == 0);
91 QTAILQ_FOREACH(wp
, &cpu
->watchpoints
, entry
) {
92 int hit_flags
= wp
->flags
& flags
;
94 if (hit_flags
&& watchpoint_address_matches(wp
, addr
, len
)) {
95 if (replay_running_debug()) {
97 * replay_breakpoint reads icount.
98 * Force recompile to succeed, because icount may
99 * be read only at the end of the block.
101 if (!cpu
->neg
.can_do_io
) {
102 /* Force execution of one insn next time. */
103 cpu
->cflags_next_tb
= 1 | CF_NOIRQ
| curr_cflags(cpu
);
104 cpu_loop_exit_restore(cpu
, ra
);
107 * Don't process the watchpoints when we are
108 * in a reverse debugging operation.
114 wp
->flags
|= hit_flags
<< BP_HIT_SHIFT
;
115 wp
->hitaddr
= MAX(addr
, wp
->vaddr
);
116 wp
->hitattrs
= attrs
;
118 if (wp
->flags
& BP_CPU
119 && cc
->tcg_ops
->debug_check_watchpoint
120 && !cc
->tcg_ops
->debug_check_watchpoint(cpu
, wp
)) {
121 wp
->flags
&= ~BP_WATCHPOINT_HIT
;
124 cpu
->watchpoint_hit
= wp
;
127 /* This call also restores vCPU state */
128 tb_check_watchpoint(cpu
, ra
);
129 if (wp
->flags
& BP_STOP_BEFORE_ACCESS
) {
130 cpu
->exception_index
= EXCP_DEBUG
;
134 /* Force execution of one insn next time. */
135 cpu
->cflags_next_tb
= 1 | CF_NOIRQ
| curr_cflags(cpu
);
137 cpu_loop_exit_noexc(cpu
);
140 wp
->flags
&= ~BP_WATCHPOINT_HIT
;