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
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]);
}
}
@@ -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);
}
}