MIPS: c-r4k: Split user/kernel flush_icache_range()
authorJames Hogan <james.hogan@imgtec.com>
Thu, 1 Sep 2016 16:30:11 +0000 (17:30 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Tue, 4 Oct 2016 14:13:57 +0000 (16:13 +0200)
flush_icache_range() is used for both user addresses (i.e.
cacheflush(2)), and kernel addresses (as the API documentation
describes).

This isn't really suitable however for Enhanced Virtual Addressing (EVA)
where cache operations on usermode addresses must use a different
instruction, and the protected cache ops assume user addresses, making
flush_icache_range() ineffective on kernel addresses.

Split out a new __flush_icache_user_range() and
__local_flush_icache_user_range() for users which actually want to flush
usermode addresses (note that flush_icache_user_range() already exists
on various architectures but with different arguments).

The implementation of flush_icache_range() will be changed in an
upcoming commit to use unprotected normal cache ops so as to always work
on the kernel mode address space.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/14152/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/include/asm/cacheflush.h
arch/mips/mm/c-octeon.c
arch/mips/mm/c-r3k.c
arch/mips/mm/c-r4k.c
arch/mips/mm/c-tx39.c
arch/mips/mm/cache.c

index 34ed22ec6c33e7917386b31007f6f14e597a1e10..4812d1fed0c2ccf7390830c719daad0546a2b0b3 100644 (file)
@@ -28,6 +28,7 @@
  *  - flush_cache_sigtramp() flush signal trampoline
  *  - flush_icache_all() flush the entire instruction cache
  *  - flush_data_cache_page() flushes a page from the data cache
+ *  - __flush_icache_user_range(start, end) flushes range of user instructions
  */
 
  /*
@@ -80,6 +81,10 @@ static inline void flush_icache_page(struct vm_area_struct *vma,
 
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
 extern void (*local_flush_icache_range)(unsigned long start, unsigned long end);
+extern void (*__flush_icache_user_range)(unsigned long start,
+                                        unsigned long end);
+extern void (*__local_flush_icache_user_range)(unsigned long start,
+                                              unsigned long end);
 
 extern void (*__flush_cache_vmap)(void);
 
index 05b1d7cf9514c71422c587ddd4955a2a4992623e..0e45b061e514153a397b9d953986a6cc077f721e 100644 (file)
@@ -294,6 +294,8 @@ void octeon_cache_init(void)
        flush_data_cache_page           = octeon_flush_data_cache_page;
        flush_icache_range              = octeon_flush_icache_range;
        local_flush_icache_range        = local_octeon_flush_icache_range;
+       __flush_icache_user_range       = octeon_flush_icache_range;
+       __local_flush_icache_user_range = local_octeon_flush_icache_range;
 
        __flush_kernel_vmap_range       = octeon_flush_kernel_vmap_range;
 
index 135ec313c1f6594b31fbda33a7f8fcfc05735e95..21e4e662c1fa6c29597a37ab837643d68141a88b 100644 (file)
@@ -325,6 +325,8 @@ void r3k_cache_init(void)
        flush_cache_page = r3k_flush_cache_page;
        flush_icache_range = r3k_flush_icache_range;
        local_flush_icache_range = r3k_flush_icache_range;
+       __flush_icache_user_range = r3k_flush_icache_range;
+       __local_flush_icache_user_range = r3k_flush_icache_range;
 
        __flush_kernel_vmap_range = r3k_flush_kernel_vmap_range;
 
index bbb7dfea40f9f4c61555a6df42600bb1a392308d..5e0a44a0c55720bbd527c4ff9d7f55839ee34bb2 100644 (file)
@@ -1904,6 +1904,8 @@ void r4k_cache_init(void)
        flush_data_cache_page   = r4k_flush_data_cache_page;
        flush_icache_range      = r4k_flush_icache_range;
        local_flush_icache_range        = local_r4k_flush_icache_range;
+       __flush_icache_user_range       = r4k_flush_icache_range;
+       __local_flush_icache_user_range = local_r4k_flush_icache_range;
 
 #if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
        if (coherentio) {
index 596e18458e041cf74d2cdf2974fcc701144591c0..5c282583edf16a5c95a638707199e80be3cd734b 100644 (file)
@@ -411,6 +411,9 @@ void tx39_cache_init(void)
                break;
        }
 
+       __flush_icache_user_range = flush_icache_range;
+       __local_flush_icache_user_range = local_flush_icache_range;
+
        current_cpu_data.icache.waysize = icache_size / current_cpu_data.icache.ways;
        current_cpu_data.dcache.waysize = dcache_size / current_cpu_data.dcache.ways;
 
index bf04c6c479a4e6ec3f99a90a8d14c093c63d5b6f..5a644c3fe155137120ac3ad72101a24a9f611c2b 100644 (file)
@@ -33,6 +33,10 @@ void (*flush_icache_range)(unsigned long start, unsigned long end);
 EXPORT_SYMBOL_GPL(flush_icache_range);
 void (*local_flush_icache_range)(unsigned long start, unsigned long end);
 EXPORT_SYMBOL_GPL(local_flush_icache_range);
+void (*__flush_icache_user_range)(unsigned long start, unsigned long end);
+EXPORT_SYMBOL_GPL(__flush_icache_user_range);
+void (*__local_flush_icache_user_range)(unsigned long start, unsigned long end);
+EXPORT_SYMBOL_GPL(__local_flush_icache_user_range);
 
 void (*__flush_cache_vmap)(void);
 void (*__flush_cache_vunmap)(void);