Commit 7f94e9cc authored by Will Deacon's avatar Will Deacon Committed by Russell King

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: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 0744a3ee
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING) #define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
#define CACHEID_ASID_TAGGED (1 << 3) #define CACHEID_ASID_TAGGED (1 << 3)
#define CACHEID_VIPT_I_ALIASING (1 << 4) #define CACHEID_VIPT_I_ALIASING (1 << 4)
#define CACHEID_PIPT (1 << 5)
extern unsigned int cacheid; extern unsigned int cacheid;
...@@ -16,6 +17,7 @@ extern unsigned int cacheid; ...@@ -16,6 +17,7 @@ extern unsigned int cacheid;
#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING) #define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING)
#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED) #define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED)
#define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING) #define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING)
#define icache_is_pipt() cacheid_is(CACHEID_PIPT)
/* /*
* __LINUX_ARM_ARCH__ is the minimum supported CPU architecture * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
...@@ -26,7 +28,8 @@ extern unsigned int cacheid; ...@@ -26,7 +28,8 @@ extern unsigned int cacheid;
#if __LINUX_ARM_ARCH__ >= 7 #if __LINUX_ARM_ARCH__ >= 7
#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\ #define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\
CACHEID_ASID_TAGGED |\ CACHEID_ASID_TAGGED |\
CACHEID_VIPT_I_ALIASING) CACHEID_VIPT_I_ALIASING |\
CACHEID_PIPT)
#elif __LINUX_ARM_ARCH__ >= 6 #elif __LINUX_ARM_ARCH__ >= 6
#define __CACHEID_ARCH_MIN (~CACHEID_VIVT) #define __CACHEID_ARCH_MIN (~CACHEID_VIVT)
#else #else
......
...@@ -265,6 +265,10 @@ static int cpu_has_aliasing_icache(unsigned int arch) ...@@ -265,6 +265,10 @@ static int cpu_has_aliasing_icache(unsigned int arch)
int aliasing_icache; int aliasing_icache;
unsigned int id_reg, num_sets, line_size; unsigned int id_reg, num_sets, line_size;
/* PIPT caches never alias. */
if (icache_is_pipt())
return 0;
/* arch specifies the register format */ /* arch specifies the register format */
switch (arch) { switch (arch) {
case CPU_ARCH_ARMv7: case CPU_ARCH_ARMv7:
...@@ -299,8 +303,14 @@ static void __init cacheid_init(void) ...@@ -299,8 +303,14 @@ static void __init cacheid_init(void)
/* ARMv7 register format */ /* ARMv7 register format */
arch = CPU_ARCH_ARMv7; arch = CPU_ARCH_ARMv7;
cacheid = CACHEID_VIPT_NONALIASING; cacheid = CACHEID_VIPT_NONALIASING;
if ((cachetype & (3 << 14)) == 1 << 14) switch (cachetype & (3 << 14)) {
case (1 << 14):
cacheid |= CACHEID_ASID_TAGGED; cacheid |= CACHEID_ASID_TAGGED;
break;
case (3 << 14):
cacheid |= CACHEID_PIPT;
break;
}
} else { } else {
arch = CPU_ARCH_ARMv6; arch = CPU_ARCH_ARMv6;
if (cachetype & (1 << 23)) if (cachetype & (1 << 23))
...@@ -317,10 +327,11 @@ static void __init cacheid_init(void) ...@@ -317,10 +327,11 @@ static void __init cacheid_init(void)
printk("CPU: %s data cache, %s instruction cache\n", printk("CPU: %s data cache, %s instruction cache\n",
cache_is_vivt() ? "VIVT" : cache_is_vivt() ? "VIVT" :
cache_is_vipt_aliasing() ? "VIPT aliasing" : cache_is_vipt_aliasing() ? "VIPT aliasing" :
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
cache_is_vivt() ? "VIVT" : cache_is_vivt() ? "VIVT" :
icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
icache_is_vipt_aliasing() ? "VIPT aliasing" : icache_is_vipt_aliasing() ? "VIPT aliasing" :
icache_is_pipt() ? "PIPT" :
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment