mm/mmu_gather: enable tlb flush range in generic mmu_gather
authorAlex Shi <alex.shi@intel.com>
Thu, 28 Jun 2012 01:02:21 +0000 (09:02 +0800)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 28 Jun 2012 02:29:11 +0000 (19:29 -0700)
This patch enabled the tlb flush range support in generic mmu layer.

Most of arch has self tlb flush range support, like ARM/IA64 etc.
X86 arch has no this support in hardware yet. But another instruction
'invlpg' can implement this function in some degree. So, enable this
feather in generic layer for x86 now. and maybe useful for other archs
in further.

Generic mmu_gather struct is protected by micro
HAVE_GENERIC_MMU_GATHER. Other archs that has flush range supported
own self mmu_gather struct. So, now this change is safe for them.

In future we may unify this struct and related functions on multiple
archs.

Thanks for Peter Zijlstra time and time reminder for multiple
architecture code safe!

Signed-off-by: Alex Shi <alex.shi@intel.com>
Link: http://lkml.kernel.org/r/1340845344-27557-7-git-send-email-alex.shi@intel.com
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
include/asm-generic/tlb.h
mm/memory.c

index 75e888b3cfd23fe06d90e7ad23b2046c3df30259..ed6642ad03e073fcd5a4d35d02ba9f6bcb5221b0 100644 (file)
@@ -86,6 +86,8 @@ struct mmu_gather {
 #ifdef CONFIG_HAVE_RCU_TABLE_FREE
        struct mmu_table_batch  *batch;
 #endif
+       unsigned long           start;
+       unsigned long           end;
        unsigned int            need_flush : 1, /* Did free PTEs */
                                fast_mode  : 1; /* No batching   */
 
index 1b7dc662bf9f229063cb3e7b97e8e4c22147b92b..32c99433cfdf7e9c2c5eb9d6ec9ac27350470e16 100644 (file)
@@ -206,6 +206,8 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm)
        tlb->mm = mm;
 
        tlb->fullmm     = fullmm;
+       tlb->start      = -1UL;
+       tlb->end        = 0;
        tlb->need_flush = 0;
        tlb->fast_mode  = (num_possible_cpus() == 1);
        tlb->local.next = NULL;
@@ -248,6 +250,8 @@ void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long e
 {
        struct mmu_gather_batch *batch, *next;
 
+       tlb->start = start;
+       tlb->end   = end;
        tlb_flush_mmu(tlb);
 
        /* keep the page table cache within bounds */
@@ -1204,6 +1208,11 @@ again:
         */
        if (force_flush) {
                force_flush = 0;
+
+#ifdef HAVE_GENERIC_MMU_GATHER
+               tlb->start = addr;
+               tlb->end = end;
+#endif
                tlb_flush_mmu(tlb);
                if (addr != end)
                        goto again;