summaryrefslogtreecommitdiffstats
path: root/accel
diff options
context:
space:
mode:
authorRichard Henderson2022-10-05 18:44:52 +0200
committerRichard Henderson2022-10-26 03:11:28 +0200
commit8f39e01db9f82033543f707f7b06f81cb675ff67 (patch)
tree6eb1fd76a6fd6749587722789e7dab1a3048aaf9 /accel
parentaccel/tcg: Use tb_invalidate_phys_page in page_set_flags (diff)
downloadqemu-8f39e01db9f82033543f707f7b06f81cb675ff67.tar.gz
qemu-8f39e01db9f82033543f707f7b06f81cb675ff67.tar.xz
qemu-8f39e01db9f82033543f707f7b06f81cb675ff67.zip
accel/tcg: Call tb_invalidate_phys_page for PAGE_RESET
When PAGE_RESET is set, we are replacing pages with new content, which means that we need to invalidate existing cached data, such as TranslationBlocks. Perform the reset invalidate while we're doing other invalidates, which allows us to remove the separate invalidates from the user-only mmap/munmap/mprotect routines. In addition, restrict invalidation to PAGE_EXEC pages. Since cdf713085131, we have validated PAGE_EXEC is present before translation, which means we can assume that if the bit is not present, there are no translations to invalidate. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'accel')
-rw-r--r--accel/tcg/translate-all.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 8d5233fa9e..478301f227 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1352,7 +1352,7 @@ int page_get_flags(target_ulong address)
void page_set_flags(target_ulong start, target_ulong end, int flags)
{
target_ulong addr, len;
- bool reset_target_data;
+ bool reset;
/* This function should never be called with addresses outside the
guest address space. If this assert fires, it probably indicates
@@ -1369,7 +1369,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
if (flags & PAGE_WRITE) {
flags |= PAGE_WRITE_ORG;
}
- reset_target_data = !(flags & PAGE_VALID) || (flags & PAGE_RESET);
+ reset = !(flags & PAGE_VALID) || (flags & PAGE_RESET);
flags &= ~PAGE_RESET;
for (addr = start, len = end - start;
@@ -1377,14 +1377,17 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, true);
- /* If the write protection bit is set, then we invalidate
- the code inside. */
- if (!(p->flags & PAGE_WRITE) &&
- (flags & PAGE_WRITE) &&
- p->first_tb) {
+ /*
+ * If the page was executable, but is reset, or is no longer
+ * executable, or has become writable, then invalidate any code.
+ */
+ if ((p->flags & PAGE_EXEC)
+ && (reset ||
+ !(flags & PAGE_EXEC) ||
+ (flags & ~p->flags & PAGE_WRITE))) {
tb_invalidate_phys_page(addr);
}
- if (reset_target_data) {
+ if (reset) {
g_free(p->target_data);
p->target_data = NULL;
p->flags = flags;