diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-07-07 21:40:44 +0100 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2023-07-15 08:02:32 +0100 |
commit | f2bb7cf29991121e427883f26f9737a409f56ee7 (patch) | |
tree | 3cb6811e0086a736cc7a426df57d4e5750e0e2ee /accel | |
parent | 99982beb4d0030470aa761b8b7bc6dc66c39a707 (diff) |
accel/tcg: Introduce page_find_range_empty
Use the interval tree to locate an unused range in the VM.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20230707204054.8792-17-richard.henderson@linaro.org>
Diffstat (limited to 'accel')
-rw-r--r-- | accel/tcg/user-exec.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index ab684a3ea2..e4f9563730 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -605,6 +605,47 @@ bool page_check_range_empty(target_ulong start, target_ulong last) return pageflags_find(start, last) == NULL; } +target_ulong page_find_range_empty(target_ulong min, target_ulong max, + target_ulong len, target_ulong align) +{ + target_ulong len_m1, align_m1; + + assert(min <= max); + assert(max <= GUEST_ADDR_MAX); + assert(len != 0); + assert(is_power_of_2(align)); + assert_memory_lock(); + + len_m1 = len - 1; + align_m1 = align - 1; + + /* Iteratively narrow the search region. */ + while (1) { + PageFlagsNode *p; + + /* Align min and double-check there's enough space remaining. */ + min = (min + align_m1) & ~align_m1; + if (min > max) { + return -1; + } + if (len_m1 > max - min) { + return -1; + } + + p = pageflags_find(min, min + len_m1); + if (p == NULL) { + /* Found! */ + return min; + } + if (max <= p->itree.last) { + /* Existing allocation fills the remainder of the search region. */ + return -1; + } + /* Skip across existing allocation. */ + min = p->itree.last + 1; + } +} + void page_protect(tb_page_addr_t address) { PageFlagsNode *p; |