aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2011-08-23 17:22:11 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-10-17 04:13:41 -0400
commit7f94e9cc5e965519d865bf20215036f359a1e299 (patch)
tree0c3e4254e4d11255b15c64dcc613599f0a149f83
parent0744a3ee37784dfda0025963716a36c3f1e3adcc (diff)
ARM: 7062/1: cache: detect PIPT I-cache using CTR
The Cache Type Register L1Ip field identifies I-caches with a PIPT policy using the encoding 11b. This patch extends the cache policy parsing to identify PIPT I-caches correctly and prevent them from being treated as VIPT aliasing in cases where they are sufficiently large. Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/include/asm/cachetype.h5
-rw-r--r--arch/arm/kernel/setup.c15
2 files changed, 17 insertions, 3 deletions
diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h
index c023db09fcc1..7ea78144ae22 100644
--- a/arch/arm/include/asm/cachetype.h
+++ b/arch/arm/include/asm/cachetype.h
@@ -7,6 +7,7 @@
7#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING) 7#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
8#define CACHEID_ASID_TAGGED (1 << 3) 8#define CACHEID_ASID_TAGGED (1 << 3)
9#define CACHEID_VIPT_I_ALIASING (1 << 4) 9#define CACHEID_VIPT_I_ALIASING (1 << 4)
10#define CACHEID_PIPT (1 << 5)
10 11
11extern unsigned int cacheid; 12extern unsigned int cacheid;
12 13
@@ -16,6 +17,7 @@ extern unsigned int cacheid;
16#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING) 17#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING)
17#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED) 18#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED)
18#define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING) 19#define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING)
20#define icache_is_pipt() cacheid_is(CACHEID_PIPT)
19 21
20/* 22/*
21 * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture 23 * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
@@ -26,7 +28,8 @@ extern unsigned int cacheid;
26#if __LINUX_ARM_ARCH__ >= 7 28#if __LINUX_ARM_ARCH__ >= 7
27#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\ 29#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\
28 CACHEID_ASID_TAGGED |\ 30 CACHEID_ASID_TAGGED |\
29 CACHEID_VIPT_I_ALIASING) 31 CACHEID_VIPT_I_ALIASING |\
32 CACHEID_PIPT)
30#elif __LINUX_ARM_ARCH__ >= 6 33#elif __LINUX_ARM_ARCH__ >= 6
31#define __CACHEID_ARCH_MIN (~CACHEID_VIVT) 34#define __CACHEID_ARCH_MIN (~CACHEID_VIVT)
32#else 35#else
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 93e39a3d2c1e..3fe93f75b55a 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -265,6 +265,10 @@ static int cpu_has_aliasing_icache(unsigned int arch)
265 int aliasing_icache; 265 int aliasing_icache;
266 unsigned int id_reg, num_sets, line_size; 266 unsigned int id_reg, num_sets, line_size;
267 267
268 /* PIPT caches never alias. */
269 if (icache_is_pipt())
270 return 0;
271
268 /* arch specifies the register format */ 272 /* arch specifies the register format */
269 switch (arch) { 273 switch (arch) {
270 case CPU_ARCH_ARMv7: 274 case CPU_ARCH_ARMv7:
@@ -299,8 +303,14 @@ static void __init cacheid_init(void)
299 /* ARMv7 register format */ 303 /* ARMv7 register format */
300 arch = CPU_ARCH_ARMv7; 304 arch = CPU_ARCH_ARMv7;
301 cacheid = CACHEID_VIPT_NONALIASING; 305 cacheid = CACHEID_VIPT_NONALIASING;
302 if ((cachetype & (3 << 14)) == 1 << 14) 306 switch (cachetype & (3 << 14)) {
307 case (1 << 14):
303 cacheid |= CACHEID_ASID_TAGGED; 308 cacheid |= CACHEID_ASID_TAGGED;
309 break;
310 case (3 << 14):
311 cacheid |= CACHEID_PIPT;
312 break;
313 }
304 } else { 314 } else {
305 arch = CPU_ARCH_ARMv6; 315 arch = CPU_ARCH_ARMv6;
306 if (cachetype & (1 << 23)) 316 if (cachetype & (1 << 23))
@@ -317,10 +327,11 @@ static void __init cacheid_init(void)
317 printk("CPU: %s data cache, %s instruction cache\n", 327 printk("CPU: %s data cache, %s instruction cache\n",
318 cache_is_vivt() ? "VIVT" : 328 cache_is_vivt() ? "VIVT" :
319 cache_is_vipt_aliasing() ? "VIPT aliasing" : 329 cache_is_vipt_aliasing() ? "VIPT aliasing" :
320 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", 330 cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
321 cache_is_vivt() ? "VIVT" : 331 cache_is_vivt() ? "VIVT" :
322 icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : 332 icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
323 icache_is_vipt_aliasing() ? "VIPT aliasing" : 333 icache_is_vipt_aliasing() ? "VIPT aliasing" :
334 icache_is_pipt() ? "PIPT" :
324 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); 335 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
325} 336}
326 337