Skip to content

Commit 858eaaa

Browse files
anadavtorvalds
authored andcommitted
mm/rmap: batched invalidations should use existing api
The recently introduced batched invalidations mechanism uses its own mechanism for shootdown. However, it does wrong accounting of interrupts (e.g., inc_irq_stat is called for local invalidations), trace-points (e.g., TLB_REMOTE_SHOOTDOWN for local invalidations) and may break some platforms as it bypasses the invalidation mechanisms of Xen and SGI UV. This patch reuses the existing TLB flushing mechnaisms instead. We use NULL as mm to indicate a global invalidation is required. Fixes 72b252a ("mm: send one IPI per CPU to TLB flush all entries after unmapping pages") Signed-off-by: Nadav Amit <namit@vmware.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Rik van Riel <riel@redhat.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Ingo Molnar <mingo@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 18c9824 commit 858eaaa

File tree

3 files changed

+8
-28
lines changed

3 files changed

+8
-28
lines changed

arch/x86/include/asm/tlbflush.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,12 +319,6 @@ static inline void reset_lazy_tlbstate(void)
319319

320320
#endif /* SMP */
321321

322-
/* Not inlined due to inc_irq_stat not being defined yet */
323-
#define flush_tlb_local() { \
324-
inc_irq_stat(irq_tlb_count); \
325-
local_flush_tlb(); \
326-
}
327-
328322
#ifndef CONFIG_PARAVIRT
329323
#define flush_tlb_others(mask, mm, start, end) \
330324
native_flush_tlb_others(mask, mm, start, end)

arch/x86/mm/tlb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ static void flush_tlb_func(void *info)
104104

105105
inc_irq_stat(irq_tlb_count);
106106

107-
if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
107+
if (f->flush_mm && f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
108108
return;
109109

110110
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);

mm/rmap.c

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -569,19 +569,6 @@ void page_unlock_anon_vma_read(struct anon_vma *anon_vma)
569569
}
570570

571571
#ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
572-
static void percpu_flush_tlb_batch_pages(void *data)
573-
{
574-
/*
575-
* All TLB entries are flushed on the assumption that it is
576-
* cheaper to flush all TLBs and let them be refilled than
577-
* flushing individual PFNs. Note that we do not track mm's
578-
* to flush as that might simply be multiple full TLB flushes
579-
* for no gain.
580-
*/
581-
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
582-
flush_tlb_local();
583-
}
584-
585572
/*
586573
* Flush TLB entries for recently unmapped pages from remote CPUs. It is
587574
* important if a PTE was dirty when it was unmapped that it's flushed
@@ -598,15 +585,14 @@ void try_to_unmap_flush(void)
598585

599586
cpu = get_cpu();
600587

601-
trace_tlb_flush(TLB_REMOTE_SHOOTDOWN, -1UL);
602-
603-
if (cpumask_test_cpu(cpu, &tlb_ubc->cpumask))
604-
percpu_flush_tlb_batch_pages(&tlb_ubc->cpumask);
605-
606-
if (cpumask_any_but(&tlb_ubc->cpumask, cpu) < nr_cpu_ids) {
607-
smp_call_function_many(&tlb_ubc->cpumask,
608-
percpu_flush_tlb_batch_pages, (void *)tlb_ubc, true);
588+
if (cpumask_test_cpu(cpu, &tlb_ubc->cpumask)) {
589+
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
590+
local_flush_tlb();
591+
trace_tlb_flush(TLB_LOCAL_SHOOTDOWN, TLB_FLUSH_ALL);
609592
}
593+
594+
if (cpumask_any_but(&tlb_ubc->cpumask, cpu) < nr_cpu_ids)
595+
flush_tlb_others(&tlb_ubc->cpumask, NULL, 0, TLB_FLUSH_ALL);
610596
cpumask_clear(&tlb_ubc->cpumask);
611597
tlb_ubc->flush_required = false;
612598
tlb_ubc->writable = false;

0 commit comments

Comments
 (0)