diff options
author | Will Deacon <will.deacon@arm.com> | 2010-09-13 11:18:30 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-10-04 15:57:09 -0400 |
commit | 8925ec4c530094b878e7e28a1fd78e7122afd973 (patch) | |
tree | 2b7200f64892299c185d3a07d1f793ea9217b5d4 /arch/arm/kernel/setup.c | |
parent | f8b63c184ad13cc8adc3dadb557d4fbc29f76e4d (diff) |
ARM: 6385/1: setup: detect aliasing I-cache when D-cache is non-aliasing
Currently, the Kernel assumes that if a CPU has a non-aliasing D-cache
then the I-cache is also non-aliasing. This may not be true on ARM cores
from v6 onwards, which may have aliasing I-caches but non-aliasing
D-caches.
This patch adds a cpu_has_aliasing_icache function, which is called from
cacheid_init and adds CACHEID_VIPT_I_ALIASING to the cacheid when
appropriate. A utility macro, icache_is_vipt_aliasing(), is also
provided.
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel/setup.c')
-rw-r--r-- | arch/arm/kernel/setup.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index d5231ae7355a..9fc483393bae 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -238,6 +238,34 @@ int cpu_architecture(void) | |||
238 | return cpu_arch; | 238 | return cpu_arch; |
239 | } | 239 | } |
240 | 240 | ||
241 | static int cpu_has_aliasing_icache(unsigned int arch) | ||
242 | { | ||
243 | int aliasing_icache; | ||
244 | unsigned int id_reg, num_sets, line_size; | ||
245 | |||
246 | /* arch specifies the register format */ | ||
247 | switch (arch) { | ||
248 | case CPU_ARCH_ARMv7: | ||
249 | asm("mcr p15, 2, %1, c0, c0, 0 @ set CSSELR\n" | ||
250 | "isb\n" | ||
251 | "mrc p15, 1, %0, c0, c0, 0 @ read CCSIDR" | ||
252 | : "=r" (id_reg) | ||
253 | : "r" (1)); | ||
254 | line_size = 4 << ((id_reg & 0x7) + 2); | ||
255 | num_sets = ((id_reg >> 13) & 0x7fff) + 1; | ||
256 | aliasing_icache = (line_size * num_sets) > PAGE_SIZE; | ||
257 | break; | ||
258 | case CPU_ARCH_ARMv6: | ||
259 | aliasing_icache = read_cpuid_cachetype() & (1 << 11); | ||
260 | break; | ||
261 | default: | ||
262 | /* I-cache aliases will be handled by D-cache aliasing code */ | ||
263 | aliasing_icache = 0; | ||
264 | } | ||
265 | |||
266 | return aliasing_icache; | ||
267 | } | ||
268 | |||
241 | static void __init cacheid_init(void) | 269 | static void __init cacheid_init(void) |
242 | { | 270 | { |
243 | unsigned int cachetype = read_cpuid_cachetype(); | 271 | unsigned int cachetype = read_cpuid_cachetype(); |
@@ -249,10 +277,15 @@ static void __init cacheid_init(void) | |||
249 | cacheid = CACHEID_VIPT_NONALIASING; | 277 | cacheid = CACHEID_VIPT_NONALIASING; |
250 | if ((cachetype & (3 << 14)) == 1 << 14) | 278 | if ((cachetype & (3 << 14)) == 1 << 14) |
251 | cacheid |= CACHEID_ASID_TAGGED; | 279 | cacheid |= CACHEID_ASID_TAGGED; |
252 | } else if (cachetype & (1 << 23)) | 280 | else if (cpu_has_aliasing_icache(CPU_ARCH_ARMv7)) |
281 | cacheid |= CACHEID_VIPT_I_ALIASING; | ||
282 | } else if (cachetype & (1 << 23)) { | ||
253 | cacheid = CACHEID_VIPT_ALIASING; | 283 | cacheid = CACHEID_VIPT_ALIASING; |
254 | else | 284 | } else { |
255 | cacheid = CACHEID_VIPT_NONALIASING; | 285 | cacheid = CACHEID_VIPT_NONALIASING; |
286 | if (cpu_has_aliasing_icache(CPU_ARCH_ARMv6)) | ||
287 | cacheid |= CACHEID_VIPT_I_ALIASING; | ||
288 | } | ||
256 | } else { | 289 | } else { |
257 | cacheid = CACHEID_VIVT; | 290 | cacheid = CACHEID_VIVT; |
258 | } | 291 | } |
@@ -263,7 +296,7 @@ static void __init cacheid_init(void) | |||
263 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", | 296 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", |
264 | cache_is_vivt() ? "VIVT" : | 297 | cache_is_vivt() ? "VIVT" : |
265 | icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : | 298 | icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : |
266 | cache_is_vipt_aliasing() ? "VIPT aliasing" : | 299 | icache_is_vipt_aliasing() ? "VIPT aliasing" : |
267 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); | 300 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); |
268 | } | 301 | } |
269 | 302 | ||