accel/tcg: Use interval tree for user-only page tracking
Finish weaning user-only away from PageDesc.
Using an interval tree to track page permissions means that
we can represent very large regions efficiently.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/290
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/967
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1214
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
index 8da2c64..20e86c8 100644
--- a/accel/tcg/tb-maint.c
+++ b/accel/tcg/tb-maint.c
@@ -68,15 +68,23 @@
/* Call with mmap_lock held. */
static void tb_record(TranslationBlock *tb, PageDesc *p1, PageDesc *p2)
{
- /* translator_loop() must have made all TB pages non-writable */
- assert(!(p1->flags & PAGE_WRITE));
- if (p2) {
- assert(!(p2->flags & PAGE_WRITE));
- }
+ target_ulong addr;
+ int flags;
assert_memory_lock();
-
tb->itree.last = tb->itree.start + tb->size - 1;
+
+ /* translator_loop() must have made all TB pages non-writable */
+ addr = tb_page_addr0(tb);
+ flags = page_get_flags(addr);
+ assert(!(flags & PAGE_WRITE));
+
+ addr = tb_page_addr1(tb);
+ if (addr != -1) {
+ flags = page_get_flags(addr);
+ assert(!(flags & PAGE_WRITE));
+ }
+
interval_tree_insert(&tb->itree, &tb_root);
}