aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Bennée <alex.bennee@linaro.org>2020-06-05 16:49:19 +0100
committerAlex Bennée <alex.bennee@linaro.org>2020-06-08 17:04:13 +0100
commit2e886a242cf540d716d431a55071a717d562eb69 (patch)
tree82bb77ccef09921b0db33e19012784dd5dd9cd17
parent4e62bfa9ee54d071c656d12057b7d293ca22d423 (diff)
exec: flush the whole TLB if a watchpoint crosses a page boundary
There is no particular reason why you can't have a watchpoint in TCG that covers a large chunk of the address space. We could be clever about it but these cases are pretty rare and we can assume the user will expect a little performance degradation. NB: In my testing gdb will silently squash a watchpoint like: watch (char[0x7fffffffff]) *0x0 to a 4 byte watchpoint. Practically it will limit the maximum size based on max-value-size. However given enough of a tweak the sky is the limit. Reported-by: Alexander Bulekov <alxndr@bu.edu> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20200605154929.26910-5-alex.bennee@linaro.org>
-rw-r--r--exec.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/exec.c b/exec.c
index be4be2df3a..a0bf9d61c8 100644
--- a/exec.c
+++ b/exec.c
@@ -1038,6 +1038,7 @@ 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) {
@@ -1058,7 +1059,12 @@ int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry);
}
- tlb_flush_page(cpu, addr);
+ in_page = -(addr | TARGET_PAGE_MASK);
+ if (len <= in_page) {
+ tlb_flush_page(cpu, addr);
+ } else {
+ tlb_flush(cpu);
+ }
if (watchpoint)
*watchpoint = wp;