diff options
author | Will Deacon <will.deacon@arm.com> | 2011-08-23 17:22:11 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-10-17 04:13:41 -0400 |
commit | 7f94e9cc5e965519d865bf20215036f359a1e299 (patch) | |
tree | 0c3e4254e4d11255b15c64dcc613599f0a149f83 | |
parent | 0744a3ee37784dfda0025963716a36c3f1e3adcc (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.h | 5 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 15 |
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 | ||
11 | extern unsigned int cacheid; | 12 | extern 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 | ||