Re: [PATCH RESEND v3 1/2] mm/tlb: skip redundant IPI when TLB flush already synchronized
From: David Hildenbrand (Red Hat)
Date: Tue Jan 06 2026 - 10:19:20 EST
static void tlb_table_flush(struct mmu_gather *tlb)
@@ -367,7 +378,7 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table)
*batch = (struct mmu_table_batch *)__get_free_page(GFP_NOWAIT);
if (*batch == NULL) {
tlb_table_invalidate(tlb);
- tlb_remove_table_one(table);
+ tlb_remove_table_one(table, tlb);
return;
}
(*batch)->nr = 0;
@@ -427,6 +438,7 @@ static void __tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm,
tlb->vma_pfn = 0;
tlb->fully_unshared_tables = 0;
+ tlb->tlb_flush_sent_ipi = 0;
__tlb_reset_range(tlb);
inc_tlb_flush_pending(tlb->mm);
}
But when would we have to reset tlb->tlb_flush_sent_ipi = 0 later? That's where it gets tricky. Just imagine the MMU gather gets reused later.
Also,
+ if (info->freed_tables && info->tlb)
+ info->tlb->tlb_flush_sent_ipi = true;
in native_flush_tlb_multi() misses the fact that we have different flushing types for removed/unshared tables vs. other flush.
So this approach more here certainly gets more complicated and error prone.
tlb_table_flush_implies_ipi_broadcast() was clearer in that regard: if you flushed the TLB after removing /unsharing tables, the IPI for handling page tables can be skipped. It's on the code flow to assure that.
What could work is tracking "tlb_table_flush_sent_ipi" really when we are flushing the TLB for removed/unshared tables, and maybe resetting it ... I don't know when from the top of my head.
v2 was simpler IMHO.
--
Cheers
David