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 <[email protected]>
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Augustin Cavalier
2026-02-26 17:17:06 +00:00
committed by waddlesplash
parent 3e1ccaf329
commit 3214eedc80
2 changed files with 16 additions and 10 deletions
+14 -8
View File
@@ -1981,8 +1981,11 @@ arch_cpu_init_post_modules(kernel_args* args)
void 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()); x86_write_cr3(x86_read_cr3());
} }
@@ -2006,10 +2009,12 @@ arch_cpu_global_tlb_invalidate()
void 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; if (context != 0 && (intptr_t)x86_read_cr3() != context)
while (num_pages-- >= 0) { return;
while (start <= end) {
invalidate_TLB(start); invalidate_TLB(start);
start += B_PAGE_SIZE; start += B_PAGE_SIZE;
} }
@@ -2017,12 +2022,13 @@ arch_cpu_invalidate_tlb_range(intptr_t, addr_t start, addr_t end)
void 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; if (context != 0 && (intptr_t)x86_read_cr3() != context)
for (i = 0; i < num_pages; i++) { return;
for (int i = 0; i < num_pages; i++)
invalidate_TLB(pages[i]); invalidate_TLB(pages[i]);
}
} }
@@ -118,7 +118,7 @@ X86VMTranslationMap::Flush()
if (!cpuMask.IsEmpty()) { if (!cpuMask.IsEmpty()) {
smp_send_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES, 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 { } else {
@@ -138,7 +138,7 @@ X86VMTranslationMap::Flush()
if (!cpuMask.IsEmpty()) { if (!cpuMask.IsEmpty()) {
smp_send_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST, 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); NULL, SMP_MSG_FLAG_SYNC);
} }
} }