Skip to content

Commit ca6c99c

Browse files
amlutoIngo Molnar
authored andcommitted
x86/mm: Reimplement flush_tlb_page() using flush_tlb_mm_range()
flush_tlb_page() was very similar to flush_tlb_mm_range() except that it had a couple of issues: - It was missing an smp_mb() in the case where current->active_mm != mm. (This is a longstanding bug reported by Nadav Amit) - It was missing tracepoints and vm counter updates. The only reason that I can see for keeping it at as a separate function is that it could avoid a few branches that flush_tlb_mm_range() needs to decide to flush just one page. This hardly seems worthwhile. If we decide we want to get rid of those branches again, a better way would be to introduce an __flush_tlb_mm_range() helper and make both flush_tlb_page() and flush_tlb_mm_range() use it. Signed-off-by: Andy Lutomirski <luto@kernel.org> Acked-by: Kees Cook <keescook@chromium.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bpetkov@suse.de> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mel Gorman <mgorman@suse.de> Cc: Michal Hocko <mhocko@suse.com> Cc: Nadav Amit <nadav.amit@gmail.com> Cc: Nadav Amit <namit@vmware.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/3cc3847cf888d8907577569b8bac3f01992ef8f9.1495492063.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 56fff1b commit ca6c99c

File tree

2 files changed

+5
-28
lines changed

2 files changed

+5
-28
lines changed

arch/x86/include/asm/tlbflush.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,15 @@ static inline void flush_tlb_kernel_range(unsigned long start,
307307
flush_tlb_mm_range(vma->vm_mm, start, end, vma->vm_flags)
308308

309309
extern void flush_tlb_all(void);
310-
extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
311310
extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
312311
unsigned long end, unsigned long vmflag);
313312
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
314313

314+
static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long a)
315+
{
316+
flush_tlb_mm_range(vma->vm_mm, a, a + PAGE_SIZE, VM_NONE);
317+
}
318+
315319
void native_flush_tlb_others(const struct cpumask *cpumask,
316320
struct mm_struct *mm,
317321
unsigned long start, unsigned long end);

arch/x86/mm/tlb.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -354,33 +354,6 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
354354
preempt_enable();
355355
}
356356

357-
void flush_tlb_page(struct vm_area_struct *vma, unsigned long start)
358-
{
359-
struct mm_struct *mm = vma->vm_mm;
360-
361-
preempt_disable();
362-
363-
if (current->active_mm == mm) {
364-
if (current->mm) {
365-
/*
366-
* Implicit full barrier (INVLPG) that synchronizes
367-
* with switch_mm.
368-
*/
369-
__flush_tlb_one(start);
370-
} else {
371-
leave_mm(smp_processor_id());
372-
373-
/* Synchronize with switch_mm. */
374-
smp_mb();
375-
}
376-
}
377-
378-
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
379-
flush_tlb_others(mm_cpumask(mm), mm, start, start + PAGE_SIZE);
380-
381-
preempt_enable();
382-
}
383-
384357
static void do_flush_tlb_all(void *info)
385358
{
386359
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);

0 commit comments

Comments
 (0)