]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ARM: mm: implement LoUIS API for cache maintenance ops
authorLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Thu, 6 Sep 2012 13:05:13 +0000 (18:35 +0530)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tue, 25 Sep 2012 10:20:25 +0000 (11:20 +0100)
ARM v7 architecture introduced the concept of cache levels and related
control registers. New processors like A7 and A15 embed an L2 unified cache
controller that becomes part of the cache level hierarchy. Some operations in
the kernel like cpu_suspend and __cpu_disable do not require a flush of the
entire cache hierarchy to DRAM but just the cache levels belonging to the
Level of Unification Inner Shareable (LoUIS), which in most of ARM v7 systems
correspond to L1.

The current cache flushing API used in cpu_suspend and __cpu_disable,
flush_cache_all(), ends up flushing the whole cache hierarchy since for
v7 it cleans and invalidates all cache levels up to Level of Coherency
(LoC) which cripples system performance when used in hot paths like hotplug
and cpuidle.

Therefore a new kernel cache maintenance API must be added to cope with
latest ARM system requirements.

This patch adds flush_cache_louis() to the ARM kernel cache maintenance API.

This function cleans and invalidates all data cache levels up to the
Level of Unification Inner Shareable (LoUIS) and invalidates the instruction
cache for processors that support it (> v7).

This patch also creates an alias of the cache LoUIS function to flush_kern_all
for all processor versions prior to v7, so that the current cache flushing
behaviour is unchanged for those processors.

v7 cache maintenance code implements a cache LoUIS function that cleans and
invalidates the D-cache up to LoUIS and invalidates the I-cache, according
to the new API.

Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
24 files changed:
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/glue-cache.h
arch/arm/mm/cache-fa.S
arch/arm/mm/cache-v3.S
arch/arm/mm/cache-v4.S
arch/arm/mm/cache-v4wb.S
arch/arm/mm/cache-v4wt.S
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-feroceon.S
arch/arm/mm/proc-macros.S
arch/arm/mm/proc-mohawk.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S

index e4448e16046dd32ab69ca17ef65a6b21745a3e0b..e1489c54cd12b4dcb8b997e8e327e2875b183b0c 100644 (file)
  *
  *             Unconditionally clean and invalidate the entire cache.
  *
+ *     flush_kern_louis()
+ *
+ *             Flush data cache levels up to the level of unification
+ *             inner shareable and invalidate the I-cache.
+ *             Only needed from v7 onwards, falls back to flush_cache_all()
+ *             for all other processor versions.
+ *
  *     flush_user_all()
  *
  *             Clean and invalidate all user space cache entries
 struct cpu_cache_fns {
        void (*flush_icache_all)(void);
        void (*flush_kern_all)(void);
+       void (*flush_kern_louis)(void);
        void (*flush_user_all)(void);
        void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
 
@@ -119,6 +127,7 @@ extern struct cpu_cache_fns cpu_cache;
 
 #define __cpuc_flush_icache_all                cpu_cache.flush_icache_all
 #define __cpuc_flush_kern_all          cpu_cache.flush_kern_all
+#define __cpuc_flush_kern_louis                cpu_cache.flush_kern_louis
 #define __cpuc_flush_user_all          cpu_cache.flush_user_all
 #define __cpuc_flush_user_range                cpu_cache.flush_user_range
 #define __cpuc_coherent_kern_range     cpu_cache.coherent_kern_range
@@ -139,6 +148,7 @@ extern struct cpu_cache_fns cpu_cache;
 
 extern void __cpuc_flush_icache_all(void);
 extern void __cpuc_flush_kern_all(void);
+extern void __cpuc_flush_kern_louis(void);
 extern void __cpuc_flush_user_all(void);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
 extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
@@ -204,6 +214,11 @@ static inline void __flush_icache_all(void)
        __flush_icache_preferred();
 }
 
+/*
+ * Flush caches up to Level of Unification Inner Shareable
+ */
+#define flush_cache_louis()            __cpuc_flush_kern_louis()
+
 #define flush_cache_all()              __cpuc_flush_kern_all()
 
 static inline void vivt_flush_cache_mm(struct mm_struct *mm)
index 7e30874377e67bede33d1f4a047bfc4f1de65fc0..2d6a7de87a88bcf9de7a1588b47da2043eeffd9f 100644 (file)
 #ifndef MULTI_CACHE
 #define __cpuc_flush_icache_all                __glue(_CACHE,_flush_icache_all)
 #define __cpuc_flush_kern_all          __glue(_CACHE,_flush_kern_cache_all)
+#define __cpuc_flush_kern_louis                __glue(_CACHE,_flush_kern_cache_louis)
 #define __cpuc_flush_user_all          __glue(_CACHE,_flush_user_cache_all)
 #define __cpuc_flush_user_range                __glue(_CACHE,_flush_user_cache_range)
 #define __cpuc_coherent_kern_range     __glue(_CACHE,_coherent_kern_range)
index 072016371093546cc95519289b30a66b381d79a9..e505befe51b54b77e850049f38633c5d1c2c20af 100644 (file)
@@ -240,6 +240,9 @@ ENTRY(fa_dma_unmap_area)
        mov     pc, lr
 ENDPROC(fa_dma_unmap_area)
 
+       .globl  fa_flush_kern_cache_louis
+       .equ    fa_flush_kern_cache_louis, fa_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 52e35f32eefb293589ce6c8ce11b4871cf178c62..8a3fadece8d3739b9d3199c5fa7d6de45bf385f4 100644 (file)
@@ -128,6 +128,9 @@ ENTRY(v3_dma_map_area)
 ENDPROC(v3_dma_unmap_area)
 ENDPROC(v3_dma_map_area)
 
+       .globl  v3_flush_kern_cache_louis
+       .equ    v3_flush_kern_cache_louis, v3_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 022135d2b7e4394313e1bad6ad3deb67ab8e4e14..43e5d77be677a329f497f9829364f392b254fa75 100644 (file)
@@ -140,6 +140,9 @@ ENTRY(v4_dma_map_area)
 ENDPROC(v4_dma_unmap_area)
 ENDPROC(v4_dma_map_area)
 
+       .globl  v4_flush_kern_cache_louis
+       .equ    v4_flush_kern_cache_louis, v4_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 8f1eeae340c84b6b948d3ca4a4f0af91250facb3..cd49453214070f24b8cab5c64b583c5aff8309e0 100644 (file)
@@ -251,6 +251,9 @@ ENTRY(v4wb_dma_unmap_area)
        mov     pc, lr
 ENDPROC(v4wb_dma_unmap_area)
 
+       .globl  v4wb_flush_kern_cache_louis
+       .equ    v4wb_flush_kern_cache_louis, v4wb_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index b34a5f908a82345bd6f4c4eb8b20f44f587cad48..11e5e5838bc59eb8d99e2e5d5d74830e86c652f0 100644 (file)
@@ -196,6 +196,9 @@ ENTRY(v4wt_dma_map_area)
 ENDPROC(v4wt_dma_unmap_area)
 ENDPROC(v4wt_dma_map_area)
 
+       .globl  v4wt_flush_kern_cache_louis
+       .equ    v4wt_flush_kern_cache_louis, v4wt_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 4b10760c56d6fe081dd9ab0988119d2378cd9369..d8fd4d4bd3d45ecdc66ad2c74885795df9681ea7 100644 (file)
@@ -326,6 +326,9 @@ ENTRY(v6_dma_unmap_area)
        mov     pc, lr
 ENDPROC(v6_dma_unmap_area)
 
+       .globl  v6_flush_kern_cache_louis
+       .equ    v6_flush_kern_cache_louis, v6_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 39e3fb3db80123b1f276f811f8b26921e77564ee..d1fa2f66d8c010f12eaa9493b60d234324f648f3 100644 (file)
@@ -33,6 +33,24 @@ ENTRY(v7_flush_icache_all)
        mov     pc, lr
 ENDPROC(v7_flush_icache_all)
 
+ /*
+ *     v7_flush_dcache_louis()
+ *
+ *     Flush the D-cache up to the Level of Unification Inner Shareable
+ *
+ *     Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
+ */
+
+ENTRY(v7_flush_dcache_louis)
+       dmb                                     @ ensure ordering with previous memory accesses
+       mrc     p15, 1, r0, c0, c0, 1           @ read clidr, r0 = clidr
+       ands    r3, r0, #0xe00000               @ extract LoUIS from clidr
+       mov     r3, r3, lsr #20                 @ r3 = LoUIS * 2
+       moveq   pc, lr                          @ return if level == 0
+       mov     r10, #0                         @ r10 (starting level) = 0
+       b       loop1                           @ start flushing cache levels
+ENDPROC(v7_flush_dcache_louis)
+
 /*
  *     v7_flush_dcache_all()
  *
@@ -120,6 +138,24 @@ ENTRY(v7_flush_kern_cache_all)
        mov     pc, lr
 ENDPROC(v7_flush_kern_cache_all)
 
+ /*
+ *     v7_flush_kern_cache_louis(void)
+ *
+ *     Flush the data cache up to Level of Unification Inner Shareable.
+ *     Invalidate the I-cache to the point of unification.
+ */
+ENTRY(v7_flush_kern_cache_louis)
+ ARM(  stmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
+ THUMB(        stmfd   sp!, {r4-r7, r9-r11, lr}        )
+       bl      v7_flush_dcache_louis
+       mov     r0, #0
+       ALT_SMP(mcr     p15, 0, r0, c7, c1, 0)  @ invalidate I-cache inner shareable
+       ALT_UP(mcr      p15, 0, r0, c7, c5, 0)  @ I+BTB cache invalidate
+ ARM(  ldmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
+ THUMB(        ldmfd   sp!, {r4-r7, r9-r11, lr}        )
+       mov     pc, lr
+ENDPROC(v7_flush_kern_cache_louis)
+
 /*
  *     v7_flush_cache_all()
  *
index 0650bb87c1e3a68feb64f465bf547c2e3de52771..2bb61e703d6c4d042cbbb86e6c655cbc0e94d762 100644 (file)
@@ -368,6 +368,9 @@ ENTRY(arm1020_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1020_dma_unmap_area)
 
+       .globl  arm1020_flush_kern_cache_louis
+       .equ    arm1020_flush_kern_cache_louis, arm1020_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1020
 
index 4188478325a6398fbe8ada36c109694b81f177ea..8f96aa40f5107987edf065c451d4d0879e5e108c 100644 (file)
@@ -354,6 +354,9 @@ ENTRY(arm1020e_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1020e_dma_unmap_area)
 
+       .globl  arm1020e_flush_kern_cache_louis
+       .equ    arm1020e_flush_kern_cache_louis, arm1020e_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1020e
 
index 33c68824bff0999d6f718eb065f1c5b1daad9cac..8ebe4a469a22534c9a828681d57552a546fb820b 100644 (file)
@@ -343,6 +343,9 @@ ENTRY(arm1022_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1022_dma_unmap_area)
 
+       .globl  arm1022_flush_kern_cache_louis
+       .equ    arm1022_flush_kern_cache_louis, arm1022_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1022
 
index fbc1d5fc24dcd0b5df37e4f508b4ea7fb9c4bafc..093fc7e520c341fb270b45e3ef2f4fbed694ae3c 100644 (file)
@@ -337,6 +337,9 @@ ENTRY(arm1026_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1026_dma_unmap_area)
 
+       .globl  arm1026_flush_kern_cache_louis
+       .equ    arm1026_flush_kern_cache_louis, arm1026_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1026
 
index 1a8c138eb8975697b8d15dee01f71ad2e9e5917c..2c3b9421ab5eca938dfe9289fc39472259ada3c1 100644 (file)
@@ -319,6 +319,9 @@ ENTRY(arm920_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm920_dma_unmap_area)
 
+       .globl  arm920_flush_kern_cache_louis
+       .equ    arm920_flush_kern_cache_louis, arm920_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm920
 #endif
index 4c44d7e1c3ca214f4debab4538928ef68113bafd..4464c49d7449b386b04c017f33fdeb79ef718f05 100644 (file)
@@ -321,6 +321,9 @@ ENTRY(arm922_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm922_dma_unmap_area)
 
+       .globl  arm922_flush_kern_cache_louis
+       .equ    arm922_flush_kern_cache_louis, arm922_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm922
 #endif
index ec5b1180994fb7b01779a8c457737f803f613e75..281eb9b9c1d654061e0bc8d2e6d350f6d7a3b2ff 100644 (file)
@@ -376,6 +376,9 @@ ENTRY(arm925_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm925_dma_unmap_area)
 
+       .globl  arm925_flush_kern_cache_louis
+       .equ    arm925_flush_kern_cache_louis, arm925_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm925
 
index c31e62c606c0b6eebf5390c2de640a7fb63ad949..f1803f7e29728460965675b6722a978d0cc33dcd 100644 (file)
@@ -339,6 +339,9 @@ ENTRY(arm926_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm926_dma_unmap_area)
 
+       .globl  arm926_flush_kern_cache_louis
+       .equ    arm926_flush_kern_cache_louis, arm926_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm926
 
index a613a7dd71465c994f6d57093954d9110aee12e4..8da189d4a4021a9184d1c78ac4cda76209406f02 100644 (file)
@@ -267,6 +267,9 @@ ENTRY(arm940_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm940_dma_unmap_area)
 
+       .globl  arm940_flush_kern_cache_louis
+       .equ    arm940_flush_kern_cache_louis, arm940_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm940
 
index 9f4f2999fdd076e5c13aceaa9e5f3734c6ec65ba..f666cf34075a1a8e7e496fd9c0a09657a0627040 100644 (file)
@@ -310,6 +310,9 @@ ENTRY(arm946_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm946_dma_unmap_area)
 
+       .globl  arm946_flush_kern_cache_louis
+       .equ    arm946_flush_kern_cache_louis, arm946_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm946
 
index 23a8e4c7f2bdc5c8a2431e3aba75eea54e08a6b7..85e5e3baa3d44a84278ee4bf4200948acf4249fe 100644 (file)
@@ -415,6 +415,9 @@ ENTRY(feroceon_dma_unmap_area)
        mov     pc, lr
 ENDPROC(feroceon_dma_unmap_area)
 
+       .globl  feroceon_flush_kern_cache_louis
+       .equ    feroceon_flush_kern_cache_louis, feroceon_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions feroceon
 
index 2d8ff3ad86d3e1a2b9d9abd83a1bdd3ab42eba3a..b29a2265af01b56f4c911b4c74fdd2cfadc3f892 100644 (file)
@@ -299,6 +299,7 @@ ENTRY(\name\()_processor_functions)
 ENTRY(\name\()_cache_fns)
        .long   \name\()_flush_icache_all
        .long   \name\()_flush_kern_cache_all
+       .long   \name\()_flush_kern_cache_louis
        .long   \name\()_flush_user_cache_all
        .long   \name\()_flush_user_cache_range
        .long   \name\()_coherent_kern_range
index fbb2124a547d125266d35cbce88348506c1eab65..82f9cdc751d6421d01bcb4eca3de51dd211f1868 100644 (file)
@@ -303,6 +303,9 @@ ENTRY(mohawk_dma_unmap_area)
        mov     pc, lr
 ENDPROC(mohawk_dma_unmap_area)
 
+       .globl  mohawk_flush_kern_cache_louis
+       .equ    mohawk_flush_kern_cache_louis, mohawk_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions mohawk
 
index b0d57869da2d95f1af47702bf039f3ef90ad5f02..eb93d6487f3598fcb0cc6e92c0f3e23faa36fb11 100644 (file)
@@ -337,6 +337,9 @@ ENTRY(xsc3_dma_unmap_area)
        mov     pc, lr
 ENDPROC(xsc3_dma_unmap_area)
 
+       .globl  xsc3_flush_kern_cache_louis
+       .equ    xsc3_flush_kern_cache_louis, xsc3_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions xsc3
 
index 4ffebaa595eec597d37e556bd66edc4af28f2a20..b5ea31d6daaca86a60e81dad6782ae068ba7a5dd 100644 (file)
@@ -410,6 +410,9 @@ ENTRY(xscale_dma_unmap_area)
        mov     pc, lr
 ENDPROC(xscale_dma_unmap_area)
 
+       .globl  xscale_flush_kern_cache_louis
+       .equ    xscale_flush_kern_cache_louis, xscale_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions xscale