diff options
author | Tony Lindgren <tony@atomide.com> | 2010-09-21 12:16:40 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-10-04 15:23:36 -0400 |
commit | 81d11955bf0b5ae25e3adbec930cd84840385dae (patch) | |
tree | d58cd15acd7f7f1b90397a5c00fd92193866be4d /arch/arm | |
parent | f9e417e901e891d139f4d5fd750959e4a862d9f7 (diff) |
ARM: 6405/1: Handle __flush_icache_all for CONFIG_SMP_ON_UP
Do this by adding flush_icache_all to cache_fns for ARMv6 and 7.
As flush_icache_all may neeed to be called from flush_kern_cache_all,
add it as the first entry in the cache_fns.
Note that now we can remove the ARM_ERRATA_411920 dependency
to !SMP so it can be selected on UP ARMv6 processors, such
as omap2.
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/cacheflush.h | 56 | ||||
-rw-r--r-- | arch/arm/mm/cache-v6.S | 30 | ||||
-rw-r--r-- | arch/arm/mm/cache-v7.S | 16 |
4 files changed, 77 insertions, 27 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f6cdc21b562c..7562f884f2c5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1002,7 +1002,7 @@ endif | |||
1002 | 1002 | ||
1003 | config ARM_ERRATA_411920 | 1003 | config ARM_ERRATA_411920 |
1004 | bool "ARM errata: Invalidation of the Instruction Cache operation can fail" | 1004 | bool "ARM errata: Invalidation of the Instruction Cache operation can fail" |
1005 | depends on CPU_V6 && !SMP | 1005 | depends on CPU_V6 |
1006 | help | 1006 | help |
1007 | Invalidation of the Instruction Cache operation can | 1007 | Invalidation of the Instruction Cache operation can |
1008 | fail. This erratum is present in 1136 (before r1p4), 1156 and 1176. | 1008 | fail. This erratum is present in 1136 (before r1p4), 1156 and 1176. |
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 4656a24058d2..a3db768ee5cc 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
@@ -156,6 +156,12 @@ | |||
156 | * Please note that the implementation of these, and the required | 156 | * Please note that the implementation of these, and the required |
157 | * effects are cache-type (VIVT/VIPT/PIPT) specific. | 157 | * effects are cache-type (VIVT/VIPT/PIPT) specific. |
158 | * | 158 | * |
159 | * flush_icache_all() | ||
160 | * | ||
161 | * Unconditionally clean and invalidate the entire icache. | ||
162 | * Currently only needed for cache-v6.S and cache-v7.S, see | ||
163 | * __flush_icache_all for the generic implementation. | ||
164 | * | ||
159 | * flush_kern_all() | 165 | * flush_kern_all() |
160 | * | 166 | * |
161 | * Unconditionally clean and invalidate the entire cache. | 167 | * Unconditionally clean and invalidate the entire cache. |
@@ -206,6 +212,7 @@ | |||
206 | */ | 212 | */ |
207 | 213 | ||
208 | struct cpu_cache_fns { | 214 | struct cpu_cache_fns { |
215 | void (*flush_icache_all)(void); | ||
209 | void (*flush_kern_all)(void); | 216 | void (*flush_kern_all)(void); |
210 | void (*flush_user_all)(void); | 217 | void (*flush_user_all)(void); |
211 | void (*flush_user_range)(unsigned long, unsigned long, unsigned int); | 218 | void (*flush_user_range)(unsigned long, unsigned long, unsigned int); |
@@ -227,6 +234,7 @@ struct cpu_cache_fns { | |||
227 | 234 | ||
228 | extern struct cpu_cache_fns cpu_cache; | 235 | extern struct cpu_cache_fns cpu_cache; |
229 | 236 | ||
237 | #define __cpuc_flush_icache_all cpu_cache.flush_icache_all | ||
230 | #define __cpuc_flush_kern_all cpu_cache.flush_kern_all | 238 | #define __cpuc_flush_kern_all cpu_cache.flush_kern_all |
231 | #define __cpuc_flush_user_all cpu_cache.flush_user_all | 239 | #define __cpuc_flush_user_all cpu_cache.flush_user_all |
232 | #define __cpuc_flush_user_range cpu_cache.flush_user_range | 240 | #define __cpuc_flush_user_range cpu_cache.flush_user_range |
@@ -246,6 +254,7 @@ extern struct cpu_cache_fns cpu_cache; | |||
246 | 254 | ||
247 | #else | 255 | #else |
248 | 256 | ||
257 | #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) | ||
249 | #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) | 258 | #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) |
250 | #define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) | 259 | #define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) |
251 | #define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) | 260 | #define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) |
@@ -253,6 +262,7 @@ extern struct cpu_cache_fns cpu_cache; | |||
253 | #define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range) | 262 | #define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range) |
254 | #define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area) | 263 | #define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area) |
255 | 264 | ||
265 | extern void __cpuc_flush_icache_all(void); | ||
256 | extern void __cpuc_flush_kern_all(void); | 266 | extern void __cpuc_flush_kern_all(void); |
257 | extern void __cpuc_flush_user_all(void); | 267 | extern void __cpuc_flush_user_all(void); |
258 | extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); | 268 | extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); |
@@ -291,6 +301,37 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *, | |||
291 | /* | 301 | /* |
292 | * Convert calls to our calling convention. | 302 | * Convert calls to our calling convention. |
293 | */ | 303 | */ |
304 | |||
305 | /* Invalidate I-cache */ | ||
306 | #define __flush_icache_all_generic() \ | ||
307 | asm("mcr p15, 0, %0, c7, c5, 0" \ | ||
308 | : : "r" (0)); | ||
309 | |||
310 | /* Invalidate I-cache inner shareable */ | ||
311 | #define __flush_icache_all_v7_smp() \ | ||
312 | asm("mcr p15, 0, %0, c7, c1, 0" \ | ||
313 | : : "r" (0)); | ||
314 | |||
315 | /* | ||
316 | * Optimized __flush_icache_all for the common cases. Note that UP ARMv7 | ||
317 | * will fall through to use __flush_icache_all_generic. | ||
318 | */ | ||
319 | #if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) || \ | ||
320 | defined(CONFIG_SMP_ON_UP) | ||
321 | #define __flush_icache_preferred __cpuc_flush_icache_all | ||
322 | #elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) | ||
323 | #define __flush_icache_preferred __flush_icache_all_v7_smp | ||
324 | #elif __LINUX_ARM_ARCH__ == 6 && defined(CONFIG_ARM_ERRATA_411920) | ||
325 | #define __flush_icache_preferred __cpuc_flush_icache_all | ||
326 | #else | ||
327 | #define __flush_icache_preferred __flush_icache_all_generic | ||
328 | #endif | ||
329 | |||
330 | static inline void __flush_icache_all(void) | ||
331 | { | ||
332 | __flush_icache_preferred(); | ||
333 | } | ||
334 | |||
294 | #define flush_cache_all() __cpuc_flush_kern_all() | 335 | #define flush_cache_all() __cpuc_flush_kern_all() |
295 | 336 | ||
296 | static inline void vivt_flush_cache_mm(struct mm_struct *mm) | 337 | static inline void vivt_flush_cache_mm(struct mm_struct *mm) |
@@ -366,21 +407,6 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr | |||
366 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | 407 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 |
367 | extern void flush_dcache_page(struct page *); | 408 | extern void flush_dcache_page(struct page *); |
368 | 409 | ||
369 | static inline void __flush_icache_all(void) | ||
370 | { | ||
371 | #ifdef CONFIG_ARM_ERRATA_411920 | ||
372 | extern void v6_icache_inval_all(void); | ||
373 | v6_icache_inval_all(); | ||
374 | #elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7 | ||
375 | asm("mcr p15, 0, %0, c7, c1, 0 @ invalidate I-cache inner shareable\n" | ||
376 | : | ||
377 | : "r" (0)); | ||
378 | #else | ||
379 | asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" | ||
380 | : | ||
381 | : "r" (0)); | ||
382 | #endif | ||
383 | } | ||
384 | static inline void flush_kernel_vmap_range(void *addr, int size) | 410 | static inline void flush_kernel_vmap_range(void *addr, int size) |
385 | { | 411 | { |
386 | if ((cache_is_vivt() || cache_is_vipt_aliasing())) | 412 | if ((cache_is_vivt() || cache_is_vipt_aliasing())) |
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 86aa689ef1aa..99fa688dfadd 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S | |||
@@ -21,18 +21,22 @@ | |||
21 | #define D_CACHE_LINE_SIZE 32 | 21 | #define D_CACHE_LINE_SIZE 32 |
22 | #define BTB_FLUSH_SIZE 8 | 22 | #define BTB_FLUSH_SIZE 8 |
23 | 23 | ||
24 | #ifdef CONFIG_ARM_ERRATA_411920 | ||
25 | /* | 24 | /* |
26 | * Invalidate the entire I cache (this code is a workaround for the ARM1136 | 25 | * v6_flush_icache_all() |
27 | * erratum 411920 - Invalidate Instruction Cache operation can fail. This | 26 | * |
28 | * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore. | 27 | * Flush the whole I-cache. |
29 | * | 28 | * |
30 | * Registers: | 29 | * ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail. |
31 | * r0 - set to 0 | 30 | * This erratum is present in 1136, 1156 and 1176. It does not affect the |
32 | * r1 - corrupted | 31 | * MPCore. |
32 | * | ||
33 | * Registers: | ||
34 | * r0 - set to 0 | ||
35 | * r1 - corrupted | ||
33 | */ | 36 | */ |
34 | ENTRY(v6_icache_inval_all) | 37 | ENTRY(v6_flush_icache_all) |
35 | mov r0, #0 | 38 | mov r0, #0 |
39 | #ifdef CONFIG_ARM_ERRATA_411920 | ||
36 | mrs r1, cpsr | 40 | mrs r1, cpsr |
37 | cpsid ifa @ disable interrupts | 41 | cpsid ifa @ disable interrupts |
38 | mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache | 42 | mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache |
@@ -43,8 +47,11 @@ ENTRY(v6_icache_inval_all) | |||
43 | .rept 11 @ ARM Ltd recommends at least | 47 | .rept 11 @ ARM Ltd recommends at least |
44 | nop @ 11 NOPs | 48 | nop @ 11 NOPs |
45 | .endr | 49 | .endr |
46 | mov pc, lr | 50 | #else |
51 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I-cache | ||
47 | #endif | 52 | #endif |
53 | mov pc, lr | ||
54 | ENDPROC(v6_flush_icache_all) | ||
48 | 55 | ||
49 | /* | 56 | /* |
50 | * v6_flush_cache_all() | 57 | * v6_flush_cache_all() |
@@ -60,7 +67,7 @@ ENTRY(v6_flush_kern_cache_all) | |||
60 | #ifndef CONFIG_ARM_ERRATA_411920 | 67 | #ifndef CONFIG_ARM_ERRATA_411920 |
61 | mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate | 68 | mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate |
62 | #else | 69 | #else |
63 | b v6_icache_inval_all | 70 | b v6_flush_icache_all |
64 | #endif | 71 | #endif |
65 | #else | 72 | #else |
66 | mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate | 73 | mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate |
@@ -138,7 +145,7 @@ ENTRY(v6_coherent_user_range) | |||
138 | #ifndef CONFIG_ARM_ERRATA_411920 | 145 | #ifndef CONFIG_ARM_ERRATA_411920 |
139 | mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate | 146 | mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate |
140 | #else | 147 | #else |
141 | b v6_icache_inval_all | 148 | b v6_flush_icache_all |
142 | #endif | 149 | #endif |
143 | #else | 150 | #else |
144 | mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB | 151 | mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB |
@@ -312,6 +319,7 @@ ENDPROC(v6_dma_unmap_area) | |||
312 | 319 | ||
313 | .type v6_cache_fns, #object | 320 | .type v6_cache_fns, #object |
314 | ENTRY(v6_cache_fns) | 321 | ENTRY(v6_cache_fns) |
322 | .long v6_flush_icache_all | ||
315 | .long v6_flush_kern_cache_all | 323 | .long v6_flush_kern_cache_all |
316 | .long v6_flush_user_cache_all | 324 | .long v6_flush_user_cache_all |
317 | .long v6_flush_user_cache_range | 325 | .long v6_flush_user_cache_range |
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index e8ea1a071f43..a3ebf7a4f49b 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S | |||
@@ -18,6 +18,21 @@ | |||
18 | #include "proc-macros.S" | 18 | #include "proc-macros.S" |
19 | 19 | ||
20 | /* | 20 | /* |
21 | * v7_flush_icache_all() | ||
22 | * | ||
23 | * Flush the whole I-cache. | ||
24 | * | ||
25 | * Registers: | ||
26 | * r0 - set to 0 | ||
27 | */ | ||
28 | ENTRY(v7_flush_icache_all) | ||
29 | mov r0, #0 | ||
30 | ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable | ||
31 | ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate | ||
32 | mov pc, lr | ||
33 | ENDPROC(v7_flush_icache_all) | ||
34 | |||
35 | /* | ||
21 | * v7_flush_dcache_all() | 36 | * v7_flush_dcache_all() |
22 | * | 37 | * |
23 | * Flush the whole D-cache. | 38 | * Flush the whole D-cache. |
@@ -303,6 +318,7 @@ ENDPROC(v7_dma_unmap_area) | |||
303 | 318 | ||
304 | .type v7_cache_fns, #object | 319 | .type v7_cache_fns, #object |
305 | ENTRY(v7_cache_fns) | 320 | ENTRY(v7_cache_fns) |
321 | .long v7_flush_icache_all | ||
306 | .long v7_flush_kern_cache_all | 322 | .long v7_flush_kern_cache_all |
307 | .long v7_flush_user_cache_all | 323 | .long v7_flush_user_cache_all |
308 | .long v7_flush_user_cache_range | 324 | .long v7_flush_user_cache_range |