diff options
| -rw-r--r-- | arch/arm/include/asm/cachetype.h | 8 | ||||
| -rw-r--r-- | arch/arm/kernel/setup.c | 39 |
2 files changed, 42 insertions, 5 deletions
diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h index d3a4c2cb9f2f..c023db09fcc1 100644 --- a/arch/arm/include/asm/cachetype.h +++ b/arch/arm/include/asm/cachetype.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #define CACHEID_VIPT_ALIASING (1 << 2) | 6 | #define CACHEID_VIPT_ALIASING (1 << 2) |
| 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 | 10 | ||
| 10 | extern unsigned int cacheid; | 11 | extern unsigned int cacheid; |
| 11 | 12 | ||
| @@ -14,15 +15,18 @@ extern unsigned int cacheid; | |||
| 14 | #define cache_is_vipt_nonaliasing() cacheid_is(CACHEID_VIPT_NONALIASING) | 15 | #define cache_is_vipt_nonaliasing() cacheid_is(CACHEID_VIPT_NONALIASING) |
| 15 | #define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING) | 16 | #define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING) |
| 16 | #define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED) | 17 | #define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED) |
| 18 | #define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING) | ||
| 17 | 19 | ||
| 18 | /* | 20 | /* |
| 19 | * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture | 21 | * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture |
| 20 | * Mask out support which will never be present on newer CPUs. | 22 | * Mask out support which will never be present on newer CPUs. |
| 21 | * - v6+ is never VIVT | 23 | * - v6+ is never VIVT |
| 22 | * - v7+ VIPT never aliases | 24 | * - v7+ VIPT never aliases on D-side |
| 23 | */ | 25 | */ |
| 24 | #if __LINUX_ARM_ARCH__ >= 7 | 26 | #if __LINUX_ARM_ARCH__ >= 7 |
| 25 | #define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING | CACHEID_ASID_TAGGED) | 27 | #define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\ |
| 28 | CACHEID_ASID_TAGGED |\ | ||
| 29 | CACHEID_VIPT_I_ALIASING) | ||
| 26 | #elif __LINUX_ARM_ARCH__ >= 6 | 30 | #elif __LINUX_ARM_ARCH__ >= 6 |
| 27 | #define __CACHEID_ARCH_MIN (~CACHEID_VIVT) | 31 | #define __CACHEID_ARCH_MIN (~CACHEID_VIVT) |
| 28 | #else | 32 | #else |
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 | ||
