From d73a8fe7505434fd37998074b072bd3a70ef7b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Holz?= Date: Sun, 22 Dec 2024 17:20:07 +0100 Subject: [PATCH] Kernel/MM: Synchronize executable memory after handling an inode fault ARM requires an explicit cache flush when modifying executable memory: https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/caches-and-self-modifying-code __builtin___clear_cache compiles to a no-op if no explicit flushing is needed (like on x86): https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005f_005f_005fclear_005fcache --- Kernel/Memory/Region.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Kernel/Memory/Region.cpp b/Kernel/Memory/Region.cpp index ef48d10ad7c..5b8e4cc5f4b 100644 --- a/Kernel/Memory/Region.cpp +++ b/Kernel/Memory/Region.cpp @@ -623,6 +623,17 @@ PageFaultResponse Region::handle_inode_fault(size_t page_index_in_region, bool m InterruptDisabler disabler; u8* dest_ptr = MM.quickmap_page(*new_physical_page); memcpy(dest_ptr, page_buffer, PAGE_SIZE); + + if (is_executable()) { + // Some architectures require an explicit synchronization operation after writing to memory that will be executed. + // This is required even if no instructions were previously fetched from that (physical) memory location, + // because some systems have an I-cache that is not coherent with the D-cache, + // resulting in the I-cache being filled with old values if the contents of the D-cache aren't written back yet. + + // __builtin___clear_cache is a no-op on architectures where this isn't needed, like on x86. + __builtin___clear_cache(reinterpret_cast(dest_ptr), reinterpret_cast(dest_ptr + PAGE_SIZE)); + } + MM.unquickmap_page(); }