[PATCH] Optimize D-cache alias handling on fork
authorRalf Baechle <ralf@linux-mips.org>
Tue, 12 Dec 2006 17:14:57 +0000 (17:14 +0000)
committerLinus Torvalds <torvalds@woody.osdl.org>
Wed, 13 Dec 2006 17:27:08 +0000 (09:27 -0800)
Virtually index, physically tagged cache architectures can get away
without cache flushing when forking.  This patch adds a new cache
flushing function flush_cache_dup_mm(struct mm_struct *) which for the
moment I've implemented to do the same thing on all architectures
except on MIPS where it's a no-op.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
27 files changed:
Documentation/cachetlb.txt
include/asm-alpha/cacheflush.h
include/asm-arm/cacheflush.h
include/asm-arm26/cacheflush.h
include/asm-avr32/cacheflush.h
include/asm-cris/cacheflush.h
include/asm-frv/cacheflush.h
include/asm-h8300/cacheflush.h
include/asm-i386/cacheflush.h
include/asm-ia64/cacheflush.h
include/asm-m32r/cacheflush.h
include/asm-m68k/cacheflush.h
include/asm-m68knommu/cacheflush.h
include/asm-mips/cacheflush.h
include/asm-parisc/cacheflush.h
include/asm-powerpc/cacheflush.h
include/asm-s390/cacheflush.h
include/asm-sh/cpu-sh2/cacheflush.h
include/asm-sh/cpu-sh3/cacheflush.h
include/asm-sh/cpu-sh4/cacheflush.h
include/asm-sh64/cacheflush.h
include/asm-sparc/cacheflush.h
include/asm-sparc64/cacheflush.h
include/asm-v850/cacheflush.h
include/asm-x86_64/cacheflush.h
include/asm-xtensa/cacheflush.h
kernel/fork.c

index 53245c429f7d9f13999803ea4ced0813437fceb5..73e794f0ff0924e2432e305cb5520345f776160b 100644 (file)
@@ -179,10 +179,21 @@ Here are the routines, one by one:
        lines associated with 'mm'.
 
        This interface is used to handle whole address space
-       page table operations such as what happens during
-       fork, exit, and exec.
+       page table operations such as what happens during exit and exec.
+
+2) void flush_cache_dup_mm(struct mm_struct *mm)
+
+       This interface flushes an entire user address space from
+       the caches.  That is, after running, there will be no cache
+       lines associated with 'mm'.
+
+       This interface is used to handle whole address space
+       page table operations such as what happens during fork.
+
+       This option is separate from flush_cache_mm to allow some
+       optimizations for VIPT caches.
 
-2) void flush_cache_range(struct vm_area_struct *vma,
+3) void flush_cache_range(struct vm_area_struct *vma,
                          unsigned long start, unsigned long end)
 
        Here we are flushing a specific range of (user) virtual
@@ -199,7 +210,7 @@ Here are the routines, one by one:
        call flush_cache_page (see below) for each entry which may be
        modified.
 
-3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
+4) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
 
        This time we need to remove a PAGE_SIZE sized range
        from the cache.  The 'vma' is the backing structure used by
@@ -220,7 +231,7 @@ Here are the routines, one by one:
 
        This is used primarily during fault processing.
 
-4) void flush_cache_kmaps(void)
+5) void flush_cache_kmaps(void)
 
        This routine need only be implemented if the platform utilizes
        highmem.  It will be called right before all of the kmaps
@@ -232,7 +243,7 @@ Here are the routines, one by one:
 
        This routing should be implemented in asm/highmem.h
 
-5) void flush_cache_vmap(unsigned long start, unsigned long end)
+6) void flush_cache_vmap(unsigned long start, unsigned long end)
    void flush_cache_vunmap(unsigned long start, unsigned long end)
 
        Here in these two interfaces we are flushing a specific range
index 805640b4107815330274fd5699d9531fcb6aa5a0..b686cc7fc44e467d91a449b5e9dea7759cfe23fc 100644 (file)
@@ -6,6 +6,7 @@
 /* Caches aren't brain-dead on the Alpha. */
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
index f0845646aacb34a05332f7b7348cbbec436ed9f1..378a3a2ce8d93ea717dd1a64009153fd6aa5e96b 100644 (file)
@@ -319,6 +319,8 @@ extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
                                unsigned long len, int write);
 #endif
 
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
 /*
  * flush_cache_user_range is used when we want to ensure that the
  * Harvard caches are synchronised for the user space address range.
index 9c1b9c7f2ebd1513a252501ab4f02d02ee301244..14ae15b6faab8c5040df4b7ecce11bf806bb666d 100644 (file)
@@ -22,6 +22,7 @@
 
 #define flush_cache_all()                       do { } while (0)
 #define flush_cache_mm(mm)                      do { } while (0)
+#define flush_cache_dup_mm(mm)                  do { } while (0)
 #define flush_cache_range(vma,start,end)        do { } while (0)
 #define flush_cache_page(vma,vmaddr,pfn)        do { } while (0)
 #define flush_cache_vmap(start, end)           do { } while (0)
index f1bf1708980e4e292ef8a4c57c6f3be9b8672b2e..dfaaa88cd412bc402fb339cb8ffb516df567426b 100644 (file)
@@ -87,6 +87,7 @@ void invalidate_icache_region(void *start, size_t len);
  */
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_cache_vmap(start, end)           do { } while (0)
index 72cc71dffe70e38eb0bc6fe8e163bb4d6f741443..01af2de27c5bcf59eceaf758e27253fc303937f4 100644 (file)
@@ -9,6 +9,7 @@
  */
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
index eaa5826bc1c8f1627d890f4a7fcda630716c13fb..02500405a6fb26317ad2def7ea098ed3e93a3e0f 100644 (file)
@@ -20,6 +20,7 @@
  */
 #define flush_cache_all()                      do {} while(0)
 #define flush_cache_mm(mm)                     do {} while(0)
+#define flush_cache_dup_mm(mm)                 do {} while(0)
 #define flush_cache_range(mm, start, end)      do {} while(0)
 #define flush_cache_page(vma, vmaddr, pfn)     do {} while(0)
 #define flush_cache_vmap(start, end)           do {} while(0)
index 1e4d95bb5ec9c1d96b201869ee903fe637da5ce5..71210d141b64bb5b2a4d13c5155ec04e8396269e 100644 (file)
@@ -12,6 +12,7 @@
 
 #define flush_cache_all()
 #define        flush_cache_mm(mm)
+#define        flush_cache_dup_mm(mm)          do { } while (0)
 #define        flush_cache_range(vma,a,b)
 #define        flush_cache_page(vma,p,pfn)
 #define        flush_dcache_page(page)
index 7199f7b326f1e3fefc9b904742dabf92042f34b2..74e03c8f2e515e0837a0724aecf5124322ed0ec6 100644 (file)
@@ -7,6 +7,7 @@
 /* Caches aren't brain-dead on the intel. */
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
index f2dacb4245ec15580b8e8341b460225a7c3edbea..4906916d715b5d3ea95d53659218234afe0f42f3 100644 (file)
@@ -18,6 +18,7 @@
 
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_icache_page(vma,page)            do { } while (0)
index 8b261b49149e7cac1529bbe95dc153845410997f..56961a9511b2cea9a7f46b04fedc912799c2e05c 100644 (file)
@@ -9,6 +9,7 @@ extern void _flush_cache_copyback_all(void);
 #if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
@@ -29,6 +30,7 @@ extern void smp_flush_cache_all(void);
 #elif defined(CONFIG_CHIP_M32102)
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
@@ -41,6 +43,7 @@ extern void smp_flush_cache_all(void);
 #else
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
index 24d3ff44913570cbccb4632b83bf5e3c37747299..16bf375fdbe1c25a36992dfe94c066b074cbe736 100644 (file)
@@ -89,6 +89,8 @@ static inline void flush_cache_mm(struct mm_struct *mm)
                __flush_cache_030();
 }
 
+#define flush_cache_dup_mm(mm)                 flush_cache_mm(mm)
+
 /* flush_cache_range/flush_cache_page must be macros to avoid
    a dependency on linux/mm.h, which includes this file... */
 static inline void flush_cache_range(struct vm_area_struct *vma,
index c3aadf3b0d88fd1cbfd9184a4ce237ab694764b7..163dcb1a9689d3687aa6e5775bcaf82eee65932f 100644 (file)
@@ -8,6 +8,7 @@
 
 #define flush_cache_all()                      __flush_cache_all()
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     __flush_cache_all()
 #define flush_cache_page(vma, vmaddr)          do { } while (0)
 #define flush_dcache_range(start,len)          __flush_cache_all()
index e3c9925876a3ce4eb80ec67937362cd7d014ad2f..0ddada3bb0b69594e36831f107caa3caad6e0e04 100644 (file)
@@ -17,6 +17,7 @@
  *
  *  - flush_cache_all() flushes entire cache
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_dup mm(mm) handles cache flushing when forking
  *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *  - flush_icache_range(start, end) flush a range of instructions
@@ -31,6 +32,7 @@
 extern void (*flush_cache_all)(void);
 extern void (*__flush_cache_all)(void);
 extern void (*flush_cache_mm)(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) do { (void) (mm); } while (0)
 extern void (*flush_cache_range)(struct vm_area_struct *vma,
        unsigned long start, unsigned long end);
 extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
index 2bc41f2e0271c21813c6c62273af0875a36db0df..aedb0512cb049bac19f8b7616101abf6d9c4302f 100644 (file)
@@ -15,6 +15,8 @@
 #define flush_cache_mm(mm) flush_cache_all_local()
 #endif
 
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
 #define flush_kernel_dcache_range(start,size) \
        flush_kernel_dcache_range_asm((start), (start)+(size));
 
index 8a740c88d93df265b4f66b1bb31fda5d995e41da..08e93e7892191d40793ea5e6f63ec43a035c65a8 100644 (file)
@@ -18,6 +18,7 @@
  */
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_icache_page(vma, page)           do { } while (0)
index e399a8ba2ed76dd2c13a8b06fe64775a4cc867a0..f7cade8083f3378e8297493f984f3749b2552b9e 100644 (file)
@@ -7,6 +7,7 @@
 /* Caches aren't brain-dead on the s390. */
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
index f556fa80ea97559773f7d4f0c2872f26b815729a..2979efb26de3c1b63eb4a70d7487dfd214e1b3cc 100644 (file)
@@ -15,6 +15,7 @@
  *
  *  - flush_cache_all() flushes entire cache
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_dup mm(mm) handles cache flushing when forking
  *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *
@@ -27,6 +28,7 @@
  */
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
index 03fde97a7fd0eaf9d5ba8f6237f0b3aa5d76958e..f70d8ef76a15f6b3d980bb4e01eb36516b2bae86 100644 (file)
@@ -15,6 +15,7 @@
  *
  *  - flush_cache_all() flushes entire cache
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_dup mm(mm) handles cache flushing when forking
  *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *
@@ -39,6 +40,7 @@
 
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
                               unsigned long end);
 void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
@@ -48,6 +50,7 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page);
 #else
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
index 515fd574267c100dba1394ddf48445f67914aeb8..b01a10f312259e9f3e8bef29041a4d47c0f29b04 100644 (file)
@@ -18,6 +18,7 @@
  */
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
                       unsigned long end);
 void flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
index 55f71aa0aa6b8a007258749543a090bd5ea14e5b..1e53a47bdc9755f84486dc8b021b60515d5a8dca 100644 (file)
@@ -21,6 +21,8 @@ extern void flush_icache_user_range(struct vm_area_struct *vma,
                                    struct page *page, unsigned long addr,
                                    int len);
 
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
index fc632f811cd83eefc733df569ebfdf8840909a87..68ac109102715911f5ff244cfa8ee1a5cfb8d751 100644 (file)
@@ -48,6 +48,7 @@ BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long)
 
 #define flush_cache_all() BTFIXUP_CALL(flush_cache_all)()
 #define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
+#define flush_cache_dup_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
 #define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end)
 #define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
 #define flush_icache_range(start, end)         do { } while (0)
index 745d1ab6037196863cd5c1d03be99f15a0588fa2..122e4058dd9ec745ecc3645c402cc1fd0c674dae 100644 (file)
@@ -12,6 +12,7 @@
 /* These are the same regardless of whether this is an SMP kernel or not. */
 #define flush_cache_mm(__mm) \
        do { if ((__mm) == current->mm) flushw_user(); } while(0)
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
 #define flush_cache_range(vma, start, end) \
        flush_cache_mm((vma)->vm_mm)
 #define flush_cache_page(vma, page, pfn) \
index e1a87f82f1a4bc06817a67720cc2f1a6062f9fe5..9ece05a202ef7fd5afe0a425c27267fc6bba03e2 100644 (file)
@@ -24,6 +24,7 @@
    systems with MMUs, so we don't need them.  */
 #define flush_cache_all()                      ((void)0)
 #define flush_cache_mm(mm)                     ((void)0)
+#define flush_cache_dup_mm(mm)                 ((void)0)
 #define flush_cache_range(vma, start, end)     ((void)0)
 #define flush_cache_page(vma, vmaddr, pfn)     ((void)0)
 #define flush_dcache_page(page)                        ((void)0)
index d32f7f58752a7b6747965dbb981e3a8b3dc8fcc8..ab1cb5c7dc9296c91df181db8fe82b3aaf2ab2ad 100644 (file)
@@ -7,6 +7,7 @@
 /* Caches aren't brain-dead on the intel. */
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_dup_mm(mm)                 do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
index 337765b629de0dd38e42c2b714b4858ce7b2ef03..22ef901b7845fa27087cdfc2586c93047af16513 100644 (file)
@@ -75,6 +75,7 @@ extern void __flush_invalidate_dcache_range(unsigned long, unsigned long);
 
 #define flush_cache_all()              __flush_invalidate_cache_all();
 #define flush_cache_mm(mm)             __flush_invalidate_cache_all();
+#define flush_cache_dup_mm(mm)         __flush_invalidate_cache_all();
 
 #define flush_cache_vmap(start,end)    __flush_invalidate_cache_all();
 #define flush_cache_vunmap(start,end)  __flush_invalidate_cache_all();
@@ -88,6 +89,7 @@ extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned lon
 
 #define flush_cache_all()                              do { } while (0)
 #define flush_cache_mm(mm)                             do { } while (0)
+#define flush_cache_dup_mm(mm)                         do { } while (0)
 
 #define flush_cache_vmap(start,end)                    do { } while (0)
 #define flush_cache_vunmap(start,end)                  do { } while (0)
index d16c566eb645a6b7aae1bd7dd5a5489eeb3d3db9..fc723e595cd5ba2c95499ba058636005dd9946e3 100644 (file)
@@ -203,7 +203,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
        struct mempolicy *pol;
 
        down_write(&oldmm->mmap_sem);
-       flush_cache_mm(oldmm);
+       flush_cache_dup_mm(oldmm);
        /*
         * Not linked in yet - no deadlock potential:
         */