diff options
author | Nicolas Pitre <nicolas.pitre@linaro.org> | 2013-10-18 17:06:03 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-10-29 07:06:23 -0400 |
commit | 39792c7cf3111d69dc4aa0923859d8b929e9039f (patch) | |
tree | 97e96f823d34ba2324efeafa5541893b062f112c /arch/arm/include | |
parent | 3c8828f6a0cb3bf1bae04a98135da3c53e20c217 (diff) |
ARM: 7861/1: cacheflush: consolidate single-CPU ARMv7 cache disabling code
This code is becoming duplicated in many places. So let's consolidate
it into a handy macro that is known to be right and available for reuse.
Signed-off-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Dave Martin <Dave.Martin@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/include')
-rw-r--r-- | arch/arm/include/asm/cacheflush.h | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 15f2d5bf8875..ee753f1749cd 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
@@ -435,4 +435,50 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size) | |||
435 | #define sync_cache_w(ptr) __sync_cache_range_w(ptr, sizeof *(ptr)) | 435 | #define sync_cache_w(ptr) __sync_cache_range_w(ptr, sizeof *(ptr)) |
436 | #define sync_cache_r(ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) | 436 | #define sync_cache_r(ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) |
437 | 437 | ||
438 | /* | ||
439 | * Disabling cache access for one CPU in an ARMv7 SMP system is tricky. | ||
440 | * To do so we must: | ||
441 | * | ||
442 | * - Clear the SCTLR.C bit to prevent further cache allocations | ||
443 | * - Flush the desired level of cache | ||
444 | * - Clear the ACTLR "SMP" bit to disable local coherency | ||
445 | * | ||
446 | * ... and so without any intervening memory access in between those steps, | ||
447 | * not even to the stack. | ||
448 | * | ||
449 | * WARNING -- After this has been called: | ||
450 | * | ||
451 | * - No ldrex/strex (and similar) instructions must be used. | ||
452 | * - The CPU is obviously no longer coherent with the other CPUs. | ||
453 | * - This is unlikely to work as expected if Linux is running non-secure. | ||
454 | * | ||
455 | * Note: | ||
456 | * | ||
457 | * - This is known to apply to several ARMv7 processor implementations, | ||
458 | * however some exceptions may exist. Caveat emptor. | ||
459 | * | ||
460 | * - The clobber list is dictated by the call to v7_flush_dcache_*. | ||
461 | * fp is preserved to the stack explicitly prior disabling the cache | ||
462 | * since adding it to the clobber list is incompatible with having | ||
463 | * CONFIG_FRAME_POINTER=y. ip is saved as well if ever r12-clobbering | ||
464 | * trampoline are inserted by the linker and to keep sp 64-bit aligned. | ||
465 | */ | ||
466 | #define v7_exit_coherency_flush(level) \ | ||
467 | asm volatile( \ | ||
468 | "stmfd sp!, {fp, ip} \n\t" \ | ||
469 | "mrc p15, 0, r0, c1, c0, 0 @ get SCTLR \n\t" \ | ||
470 | "bic r0, r0, #"__stringify(CR_C)" \n\t" \ | ||
471 | "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR \n\t" \ | ||
472 | "isb \n\t" \ | ||
473 | "bl v7_flush_dcache_"__stringify(level)" \n\t" \ | ||
474 | "clrex \n\t" \ | ||
475 | "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR \n\t" \ | ||
476 | "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ | ||
477 | "mcr p15, 0, r0, c1, c0, 1 @ set ACTLR \n\t" \ | ||
478 | "isb \n\t" \ | ||
479 | "dsb \n\t" \ | ||
480 | "ldmfd sp!, {fp, ip}" \ | ||
481 | : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ | ||
482 | "r9","r10","lr","memory" ) | ||
483 | |||
438 | #endif | 484 | #endif |