From 3214eedc80f73ab310e7361c0250c5cfc52553bc Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Fri, 20 Feb 2026 22:47:35 -0500 Subject: [PATCH] kernel/x86: Avoid unnecessary TLB invalidations. If a context switch happened between the messsage being sent and received, we don't need to invalidate. Brief testing on a 4-core VM shows this happens relatively rarely during compile jobs (expected, most processes are single-threaded), but very often while running multiprocess web browsers. Some INVALIDATE_PAGES are skipped, but mostly INVALIDATE_PAGE_LIST is (by the thousands.) Change-Id: If32ed95139e0db3770054f6ef3f72c9aecb9394d Reviewed-on: https://review.haiku-os.org/c/haiku/+/10350 Reviewed-by: waddlesplash Tested-by: Commit checker robot Reviewed-by: Adrien Destugues --- src/system/kernel/arch/x86/arch_cpu.cpp | 22 ++++++++++++------- .../arch/x86/paging/X86VMTranslationMap.cpp | 4 ++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index d5f018bfc5..6924dd53b7 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -1981,8 +1981,11 @@ arch_cpu_init_post_modules(kernel_args* args) void -arch_cpu_user_tlb_invalidate(intptr_t) +arch_cpu_user_tlb_invalidate(intptr_t context) { + if (context != 0 && (intptr_t)x86_read_cr3() != context) + return; + x86_write_cr3(x86_read_cr3()); } @@ -2006,10 +2009,12 @@ arch_cpu_global_tlb_invalidate() void -arch_cpu_invalidate_tlb_range(intptr_t, addr_t start, addr_t end) +arch_cpu_invalidate_tlb_range(intptr_t context, addr_t start, addr_t end) { - int32 num_pages = end / B_PAGE_SIZE - start / B_PAGE_SIZE; - while (num_pages-- >= 0) { + if (context != 0 && (intptr_t)x86_read_cr3() != context) + return; + + while (start <= end) { invalidate_TLB(start); start += B_PAGE_SIZE; } @@ -2017,12 +2022,13 @@ arch_cpu_invalidate_tlb_range(intptr_t, addr_t start, addr_t end) void -arch_cpu_invalidate_tlb_list(intptr_t, addr_t pages[], int num_pages) +arch_cpu_invalidate_tlb_list(intptr_t context, addr_t pages[], int num_pages) { - int i; - for (i = 0; i < num_pages; i++) { + if (context != 0 && (intptr_t)x86_read_cr3() != context) + return; + + for (int i = 0; i < num_pages; i++) invalidate_TLB(pages[i]); - } } diff --git a/src/system/kernel/arch/x86/paging/X86VMTranslationMap.cpp b/src/system/kernel/arch/x86/paging/X86VMTranslationMap.cpp index fee578beb4..ab695d15b5 100644 --- a/src/system/kernel/arch/x86/paging/X86VMTranslationMap.cpp +++ b/src/system/kernel/arch/x86/paging/X86VMTranslationMap.cpp @@ -118,7 +118,7 @@ X86VMTranslationMap::Flush() if (!cpuMask.IsEmpty()) { smp_send_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES, - 0, 0, 0, NULL, SMP_MSG_FLAG_SYNC); + x86_read_cr3(), 0, 0, NULL, SMP_MSG_FLAG_SYNC); } } } else { @@ -138,7 +138,7 @@ X86VMTranslationMap::Flush() if (!cpuMask.IsEmpty()) { smp_send_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST, - 0, (addr_t)fInvalidPages, fInvalidPagesCount, + x86_read_cr3(), (addr_t)fInvalidPages, fInvalidPagesCount, NULL, SMP_MSG_FLAG_SYNC); } }