aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-09-25 10:35:28 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-09-25 10:35:28 -0400
commitc0e9587841a0fd79bbf8296034faefb9afe72fb4 (patch)
treeb82e0e79706f9f63985b4591e1fa02eaa2df73d2 /arch
parent90f1e084783be9bbff4861fa8e460b76de2787f4 (diff)
[ARM] Introduce new bitmask based cache type macros
Rather than trying to (inaccurately) decode the cache type from the registers each time we need to decide what type of cache we have, use a bitmask initialized early during boot. Since the setup is a one-off initialization, we can be a little more clever and take account of the CPU architecture as well. Note that we continue to achieve the compactness on optimised kernels by forcing tests to always-false or always-true as appropriate, thereby allowing the compiler to do build-time code elimination. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/cachetype.h118
-rw-r--r--arch/arm/kernel/setup.c22
2 files changed, 59 insertions, 81 deletions
diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h
index b52386bfd50..d3a4c2cb9f2 100644
--- a/arch/arm/include/asm/cachetype.h
+++ b/arch/arm/include/asm/cachetype.h
@@ -1,96 +1,52 @@
1#ifndef __ASM_ARM_CACHETYPE_H 1#ifndef __ASM_ARM_CACHETYPE_H
2#define __ASM_ARM_CACHETYPE_H 2#define __ASM_ARM_CACHETYPE_H
3 3
4#include <asm/cputype.h> 4#define CACHEID_VIVT (1 << 0)
5#define CACHEID_VIPT_NONALIASING (1 << 1)
6#define CACHEID_VIPT_ALIASING (1 << 2)
7#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
8#define CACHEID_ASID_TAGGED (1 << 3)
5 9
6#define __cacheid_present(val) (val != read_cpuid_id()) 10extern unsigned int cacheid;
7#define __cacheid_type_v7(val) ((val & (7 << 29)) == (4 << 29))
8 11
9#define __cacheid_vivt_prev7(val) ((val & (15 << 25)) != (14 << 25)) 12#define cache_is_vivt() cacheid_is(CACHEID_VIVT)
10#define __cacheid_vipt_prev7(val) ((val & (15 << 25)) == (14 << 25)) 13#define cache_is_vipt() cacheid_is(CACHEID_VIPT)
11#define __cacheid_vipt_nonaliasing_prev7(val) ((val & (15 << 25 | 1 << 23)) == (14 << 25)) 14#define cache_is_vipt_nonaliasing() cacheid_is(CACHEID_VIPT_NONALIASING)
12#define __cacheid_vipt_aliasing_prev7(val) ((val & (15 << 25 | 1 << 23)) == (14 << 25 | 1 << 23)) 15#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING)
16#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED)
13 17
14#define __cacheid_vivt(val) (__cacheid_type_v7(val) ? 0 : __cacheid_vivt_prev7(val))
15#define __cacheid_vipt(val) (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_prev7(val))
16#define __cacheid_vipt_nonaliasing(val) (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_nonaliasing_prev7(val))
17#define __cacheid_vipt_aliasing(val) (__cacheid_type_v7(val) ? 0 : __cacheid_vipt_aliasing_prev7(val))
18#define __cacheid_vivt_asid_tagged_instr(val) (__cacheid_type_v7(val) ? ((val & (3 << 14)) == (1 << 14)) : 0)
19
20#if defined(CONFIG_CPU_CACHE_VIVT) && !defined(CONFIG_CPU_CACHE_VIPT)
21/* 18/*
22 * VIVT caches only 19 * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
20 * Mask out support which will never be present on newer CPUs.
21 * - v6+ is never VIVT
22 * - v7+ VIPT never aliases
23 */ 23 */
24#define cache_is_vivt() 1 24#if __LINUX_ARM_ARCH__ >= 7
25#define cache_is_vipt() 0 25#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING | CACHEID_ASID_TAGGED)
26#define cache_is_vipt_nonaliasing() 0 26#elif __LINUX_ARM_ARCH__ >= 6
27#define cache_is_vipt_aliasing() 0 27#define __CACHEID_ARCH_MIN (~CACHEID_VIVT)
28#define icache_is_vivt_asid_tagged() 0 28#else
29#define __CACHEID_ARCH_MIN (~0)
30#endif
29 31
30#elif !defined(CONFIG_CPU_CACHE_VIVT) && defined(CONFIG_CPU_CACHE_VIPT)
31/* 32/*
32 * VIPT caches only 33 * Mask out support which isn't configured
33 */ 34 */
34#define cache_is_vivt() 0 35#if defined(CONFIG_CPU_CACHE_VIVT) && !defined(CONFIG_CPU_CACHE_VIPT)
35#define cache_is_vipt() 1 36#define __CACHEID_ALWAYS (CACHEID_VIVT)
36#define cache_is_vipt_nonaliasing() \ 37#define __CACHEID_NEVER (~CACHEID_VIVT)
37 ({ \ 38#elif !defined(CONFIG_CPU_CACHE_VIVT) && defined(CONFIG_CPU_CACHE_VIPT)
38 unsigned int __val = read_cpuid_cachetype(); \ 39#define __CACHEID_ALWAYS (0)
39 __cacheid_vipt_nonaliasing(__val); \ 40#define __CACHEID_NEVER (CACHEID_VIVT)
40 })
41
42#define cache_is_vipt_aliasing() \
43 ({ \
44 unsigned int __val = read_cpuid_cachetype(); \
45 __cacheid_vipt_aliasing(__val); \
46 })
47
48#define icache_is_vivt_asid_tagged() \
49 ({ \
50 unsigned int __val = read_cpuid_cachetype(); \
51 __cacheid_vivt_asid_tagged_instr(__val); \
52 })
53
54#else 41#else
55/* 42#define __CACHEID_ALWAYS (0)
56 * VIVT or VIPT caches. Note that this is unreliable since ARM926 43#define __CACHEID_NEVER (0)
57 * and V6 CPUs satisfy the "(val & (15 << 25)) == (14 << 25)" test.
58 * There's no way to tell from the CacheType register what type (!)
59 * the cache is.
60 */
61#define cache_is_vivt() \
62 ({ \
63 unsigned int __val = read_cpuid_cachetype(); \
64 (!__cacheid_present(__val)) || __cacheid_vivt(__val); \
65 })
66
67#define cache_is_vipt() \
68 ({ \
69 unsigned int __val = read_cpuid_cachetype(); \
70 __cacheid_present(__val) && __cacheid_vipt(__val); \
71 })
72
73#define cache_is_vipt_nonaliasing() \
74 ({ \
75 unsigned int __val = read_cpuid_cachetype(); \
76 __cacheid_present(__val) && \
77 __cacheid_vipt_nonaliasing(__val); \
78 })
79
80#define cache_is_vipt_aliasing() \
81 ({ \
82 unsigned int __val = read_cpuid_cachetype(); \
83 __cacheid_present(__val) && \
84 __cacheid_vipt_aliasing(__val); \
85 })
86
87#define icache_is_vivt_asid_tagged() \
88 ({ \
89 unsigned int __val = read_cpuid_cachetype(); \
90 __cacheid_present(__val) && \
91 __cacheid_vivt_asid_tagged_instr(__val); \
92 })
93
94#endif 44#endif
95 45
46static inline unsigned int __attribute__((pure)) cacheid_is(unsigned int mask)
47{
48 return (__CACHEID_ALWAYS & mask) |
49 (~__CACHEID_NEVER & __CACHEID_ARCH_MIN & mask & cacheid);
50}
51
96#endif 52#endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 1939c904dae..5b121d81f9e 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -67,6 +67,8 @@ unsigned int processor_id;
67EXPORT_SYMBOL(processor_id); 67EXPORT_SYMBOL(processor_id);
68unsigned int __machine_arch_type; 68unsigned int __machine_arch_type;
69EXPORT_SYMBOL(__machine_arch_type); 69EXPORT_SYMBOL(__machine_arch_type);
70unsigned int cacheid;
71EXPORT_SYMBOL(cacheid);
70 72
71unsigned int __atags_pointer __initdata; 73unsigned int __atags_pointer __initdata;
72 74
@@ -229,6 +231,25 @@ int cpu_architecture(void)
229 return cpu_arch; 231 return cpu_arch;
230} 232}
231 233
234static void __init cacheid_init(void)
235{
236 unsigned int cachetype = read_cpuid_cachetype();
237 unsigned int arch = cpu_architecture();
238
239 if (arch >= CPU_ARCH_ARMv7) {
240 cacheid = CACHEID_VIPT_NONALIASING;
241 if ((cachetype & (3 << 14)) == 1 << 14)
242 cacheid |= CACHEID_ASID_TAGGED;
243 } else if (arch >= CPU_ARCH_ARMv6) {
244 if (cachetype & (1 << 23))
245 cacheid = CACHEID_VIPT_ALIASING;
246 else
247 cacheid = CACHEID_VIPT_NONALIASING;
248 } else {
249 cacheid = CACHEID_VIVT;
250 }
251}
252
232/* 253/*
233 * These functions re-use the assembly code in head.S, which 254 * These functions re-use the assembly code in head.S, which
234 * already provide the required functionality. 255 * already provide the required functionality.
@@ -278,6 +299,7 @@ static void __init setup_processor(void)
278 elf_hwcap &= ~HWCAP_THUMB; 299 elf_hwcap &= ~HWCAP_THUMB;
279#endif 300#endif
280 301
302 cacheid_init();
281 cpu_proc_init(); 303 cpu_proc_init();
282} 304}
283 305