Commit c0e95878 authored by Russell King's avatar Russell King Committed by Russell King

[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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 90f1e084
#ifndef __ASM_ARM_CACHETYPE_H #ifndef __ASM_ARM_CACHETYPE_H
#define __ASM_ARM_CACHETYPE_H #define __ASM_ARM_CACHETYPE_H
#include <asm/cputype.h> #define CACHEID_VIVT (1 << 0)
#define CACHEID_VIPT_NONALIASING (1 << 1)
#define CACHEID_VIPT_ALIASING (1 << 2)
#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
#define CACHEID_ASID_TAGGED (1 << 3)
#define __cacheid_present(val) (val != read_cpuid_id()) extern unsigned int cacheid;
#define __cacheid_type_v7(val) ((val & (7 << 29)) == (4 << 29))
#define __cacheid_vivt_prev7(val) ((val & (15 << 25)) != (14 << 25)) #define cache_is_vivt() cacheid_is(CACHEID_VIVT)
#define __cacheid_vipt_prev7(val) ((val & (15 << 25)) == (14 << 25)) #define cache_is_vipt() cacheid_is(CACHEID_VIPT)
#define __cacheid_vipt_nonaliasing_prev7(val) ((val & (15 << 25 | 1 << 23)) == (14 << 25)) #define cache_is_vipt_nonaliasing() cacheid_is(CACHEID_VIPT_NONALIASING)
#define __cacheid_vipt_aliasing_prev7(val) ((val & (15 << 25 | 1 << 23)) == (14 << 25 | 1 << 23)) #define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING)
#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED)
#define __cacheid_vivt(val) (__cacheid_type_v7(val) ? 0 : __cacheid_vivt_prev7(val))
#define __cacheid_vipt(val) (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_prev7(val))
#define __cacheid_vipt_nonaliasing(val) (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_nonaliasing_prev7(val))
#define __cacheid_vipt_aliasing(val) (__cacheid_type_v7(val) ? 0 : __cacheid_vipt_aliasing_prev7(val))
#define __cacheid_vivt_asid_tagged_instr(val) (__cacheid_type_v7(val) ? ((val & (3 << 14)) == (1 << 14)) : 0)
#if defined(CONFIG_CPU_CACHE_VIVT) && !defined(CONFIG_CPU_CACHE_VIPT)
/* /*
* VIVT caches only * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
* Mask out support which will never be present on newer CPUs.
* - v6+ is never VIVT
* - v7+ VIPT never aliases
*/ */
#define cache_is_vivt() 1 #if __LINUX_ARM_ARCH__ >= 7
#define cache_is_vipt() 0 #define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING | CACHEID_ASID_TAGGED)
#define cache_is_vipt_nonaliasing() 0 #elif __LINUX_ARM_ARCH__ >= 6
#define cache_is_vipt_aliasing() 0 #define __CACHEID_ARCH_MIN (~CACHEID_VIVT)
#define icache_is_vivt_asid_tagged() 0 #else
#define __CACHEID_ARCH_MIN (~0)
#endif
#elif !defined(CONFIG_CPU_CACHE_VIVT) && defined(CONFIG_CPU_CACHE_VIPT)
/* /*
* VIPT caches only * Mask out support which isn't configured
*/ */
#define cache_is_vivt() 0 #if defined(CONFIG_CPU_CACHE_VIVT) && !defined(CONFIG_CPU_CACHE_VIPT)
#define cache_is_vipt() 1 #define __CACHEID_ALWAYS (CACHEID_VIVT)
#define cache_is_vipt_nonaliasing() \ #define __CACHEID_NEVER (~CACHEID_VIVT)
({ \ #elif !defined(CONFIG_CPU_CACHE_VIVT) && defined(CONFIG_CPU_CACHE_VIPT)
unsigned int __val = read_cpuid_cachetype(); \ #define __CACHEID_ALWAYS (0)
__cacheid_vipt_nonaliasing(__val); \ #define __CACHEID_NEVER (CACHEID_VIVT)
})
#define cache_is_vipt_aliasing() \
({ \
unsigned int __val = read_cpuid_cachetype(); \
__cacheid_vipt_aliasing(__val); \
})
#define icache_is_vivt_asid_tagged() \
({ \
unsigned int __val = read_cpuid_cachetype(); \
__cacheid_vivt_asid_tagged_instr(__val); \
})
#else #else
/* #define __CACHEID_ALWAYS (0)
* VIVT or VIPT caches. Note that this is unreliable since ARM926 #define __CACHEID_NEVER (0)
* and V6 CPUs satisfy the "(val & (15 << 25)) == (14 << 25)" test.
* There's no way to tell from the CacheType register what type (!)
* the cache is.
*/
#define cache_is_vivt() \
({ \
unsigned int __val = read_cpuid_cachetype(); \
(!__cacheid_present(__val)) || __cacheid_vivt(__val); \
})
#define cache_is_vipt() \
({ \
unsigned int __val = read_cpuid_cachetype(); \
__cacheid_present(__val) && __cacheid_vipt(__val); \
})
#define cache_is_vipt_nonaliasing() \
({ \
unsigned int __val = read_cpuid_cachetype(); \
__cacheid_present(__val) && \
__cacheid_vipt_nonaliasing(__val); \
})
#define cache_is_vipt_aliasing() \
({ \
unsigned int __val = read_cpuid_cachetype(); \
__cacheid_present(__val) && \
__cacheid_vipt_aliasing(__val); \
})
#define icache_is_vivt_asid_tagged() \
({ \
unsigned int __val = read_cpuid_cachetype(); \
__cacheid_present(__val) && \
__cacheid_vivt_asid_tagged_instr(__val); \
})
#endif #endif
static inline unsigned int __attribute__((pure)) cacheid_is(unsigned int mask)
{
return (__CACHEID_ALWAYS & mask) |
(~__CACHEID_NEVER & __CACHEID_ARCH_MIN & mask & cacheid);
}
#endif #endif
...@@ -67,6 +67,8 @@ unsigned int processor_id; ...@@ -67,6 +67,8 @@ unsigned int processor_id;
EXPORT_SYMBOL(processor_id); EXPORT_SYMBOL(processor_id);
unsigned int __machine_arch_type; unsigned int __machine_arch_type;
EXPORT_SYMBOL(__machine_arch_type); EXPORT_SYMBOL(__machine_arch_type);
unsigned int cacheid;
EXPORT_SYMBOL(cacheid);
unsigned int __atags_pointer __initdata; unsigned int __atags_pointer __initdata;
...@@ -229,6 +231,25 @@ int cpu_architecture(void) ...@@ -229,6 +231,25 @@ int cpu_architecture(void)
return cpu_arch; return cpu_arch;
} }
static void __init cacheid_init(void)
{
unsigned int cachetype = read_cpuid_cachetype();
unsigned int arch = cpu_architecture();
if (arch >= CPU_ARCH_ARMv7) {
cacheid = CACHEID_VIPT_NONALIASING;
if ((cachetype & (3 << 14)) == 1 << 14)
cacheid |= CACHEID_ASID_TAGGED;
} else if (arch >= CPU_ARCH_ARMv6) {
if (cachetype & (1 << 23))
cacheid = CACHEID_VIPT_ALIASING;
else
cacheid = CACHEID_VIPT_NONALIASING;
} else {
cacheid = CACHEID_VIVT;
}
}
/* /*
* These functions re-use the assembly code in head.S, which * These functions re-use the assembly code in head.S, which
* already provide the required functionality. * already provide the required functionality.
...@@ -278,6 +299,7 @@ static void __init setup_processor(void) ...@@ -278,6 +299,7 @@ static void __init setup_processor(void)
elf_hwcap &= ~HWCAP_THUMB; elf_hwcap &= ~HWCAP_THUMB;
#endif #endif
cacheid_init();
cpu_proc_init(); cpu_proc_init();
} }
......
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