From 2e886a242cf540d716d431a55071a717d562eb69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= <alex.bennee@linaro.org> Date: Fri, 5 Jun 2020 16:49:19 +0100 Subject: [PATCH] exec: flush the whole TLB if a watchpoint crosses a page boundary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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> --- exec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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;