aboutsummaryrefslogtreecommitdiff
path: root/accel
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-03-06 04:30:11 +0300
committerRichard Henderson <richard.henderson@linaro.org>2023-03-28 15:23:10 -0700
commite506ad6a05c806bbef460a7d014a184ff8d707a6 (patch)
treeb4361a63b5f78973093f87ec79add51a44f00d9e /accel
parent73f96d51ff23592741ef75322cb2dda37b38248f (diff)
accel/tcg: Pass last not end to tb_invalidate_phys_range
Pass the address of the last byte to be changed, rather than the first address past the last byte. This avoids overflow when the last page of the address space is involved. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'accel')
-rw-r--r--accel/tcg/tb-maint.c31
-rw-r--r--accel/tcg/translate-all.c2
-rw-r--r--accel/tcg/user-exec.c2
3 files changed, 18 insertions, 17 deletions
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
index 74823ba464..cb1f806f00 100644
--- a/accel/tcg/tb-maint.c
+++ b/accel/tcg/tb-maint.c
@@ -991,11 +991,10 @@ TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
* Called with mmap_lock held for user-mode emulation.
* NOTE: this function must not be called while a TB is running.
*/
-void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
+void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t last)
{
TranslationBlock *tb;
PageForEachNext n;
- tb_page_addr_t last = end - 1;
assert_memory_lock();
@@ -1011,11 +1010,11 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
*/
void tb_invalidate_phys_page(tb_page_addr_t addr)
{
- tb_page_addr_t start, end;
+ tb_page_addr_t start, last;
start = addr & TARGET_PAGE_MASK;
- end = start + TARGET_PAGE_SIZE;
- tb_invalidate_phys_range(start, end);
+ last = addr | ~TARGET_PAGE_MASK;
+ tb_invalidate_phys_range(start, last);
}
/*
@@ -1169,28 +1168,30 @@ void tb_invalidate_phys_page(tb_page_addr_t addr)
/*
* Invalidate all TBs which intersect with the target physical address range
- * [start;end[. NOTE: start and end may refer to *different* physical pages.
+ * [start;last]. NOTE: start and end may refer to *different* physical pages.
* 'is_cpu_write_access' should be true if called from a real cpu write
* access: the virtual CPU will exit the current TB if code is modified inside
* this TB.
*/
-void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
+void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t last)
{
struct page_collection *pages;
- tb_page_addr_t next;
+ tb_page_addr_t index, index_last;
+
+ pages = page_collection_lock(start, last);
- pages = page_collection_lock(start, end - 1);
- for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- start < end;
- start = next, next += TARGET_PAGE_SIZE) {
- PageDesc *pd = page_find(start >> TARGET_PAGE_BITS);
- tb_page_addr_t bound = MIN(next, end);
+ index_last = last >> TARGET_PAGE_BITS;
+ for (index = start >> TARGET_PAGE_BITS; index <= index_last; index++) {
+ PageDesc *pd = page_find(index);
+ tb_page_addr_t bound;
if (pd == NULL) {
continue;
}
assert_page_locked(pd);
- tb_invalidate_phys_page_range__locked(pages, pd, start, bound - 1, 0);
+ bound = (index << TARGET_PAGE_BITS) | ~TARGET_PAGE_MASK;
+ bound = MIN(bound, last);
+ tb_invalidate_phys_page_range__locked(pages, pd, start, bound, 0);
}
page_collection_unlock(pages);
}
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 74deb18bd0..5b13281119 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -572,7 +572,7 @@ void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
addr = get_page_addr_code(env, pc);
if (addr != -1) {
- tb_invalidate_phys_range(addr, addr + 1);
+ tb_invalidate_phys_range(addr, addr);
}
}
}
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 20b6fc2f6e..a7e0c3e2f4 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -516,7 +516,7 @@ void page_set_flags(target_ulong start, target_ulong last, int flags)
~(reset ? 0 : PAGE_STICKY));
}
if (inval_tb) {
- tb_invalidate_phys_range(start, last + 1);
+ tb_invalidate_phys_range(start, last);
}
}