diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2014-04-03 12:48:54 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2014-05-09 10:47:45 -0400 |
commit | a41dc0e841523efe1df7fa5ad48b5e9027a921df (patch) | |
tree | c162086a45807902dd8c510132f3c3f82603d3e6 | |
parent | 89ca3b881987f5a4be4c5dbaa7f0df12bbdde2fd (diff) |
arm64: Implement cache_line_size() based on CTR_EL0.CWG
The hardware provides the maximum cache line size in the system via the
CTR_EL0.CWG bits. This patch implements the cache_line_size() function
to read such information, together with a sanity check if the statically
defined L1_CACHE_BYTES is smaller than the hardware value.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | arch/arm64/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm64/include/asm/cache.h | 13 | ||||
-rw-r--r-- | arch/arm64/include/asm/cachetype.h | 11 | ||||
-rw-r--r-- | arch/arm64/kernel/setup.c | 15 |
4 files changed, 41 insertions, 1 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index e759af5d7098..9a5b5fea86ba 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -242,6 +242,9 @@ config ARCH_WANT_HUGE_PMD_SHARE | |||
242 | config HAVE_ARCH_TRANSPARENT_HUGEPAGE | 242 | config HAVE_ARCH_TRANSPARENT_HUGEPAGE |
243 | def_bool y | 243 | def_bool y |
244 | 244 | ||
245 | config ARCH_HAS_CACHE_LINE_SIZE | ||
246 | def_bool y | ||
247 | |||
245 | source "mm/Kconfig" | 248 | source "mm/Kconfig" |
246 | 249 | ||
247 | config XEN_DOM0 | 250 | config XEN_DOM0 |
diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h index 390308a67f0d..88cc05b5f3ac 100644 --- a/arch/arm64/include/asm/cache.h +++ b/arch/arm64/include/asm/cache.h | |||
@@ -16,6 +16,8 @@ | |||
16 | #ifndef __ASM_CACHE_H | 16 | #ifndef __ASM_CACHE_H |
17 | #define __ASM_CACHE_H | 17 | #define __ASM_CACHE_H |
18 | 18 | ||
19 | #include <asm/cachetype.h> | ||
20 | |||
19 | #define L1_CACHE_SHIFT 6 | 21 | #define L1_CACHE_SHIFT 6 |
20 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | 22 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) |
21 | 23 | ||
@@ -27,6 +29,15 @@ | |||
27 | * the CPU. | 29 | * the CPU. |
28 | */ | 30 | */ |
29 | #define ARCH_DMA_MINALIGN L1_CACHE_BYTES | 31 | #define ARCH_DMA_MINALIGN L1_CACHE_BYTES |
30 | #define ARCH_SLAB_MINALIGN 8 | 32 | |
33 | #ifndef __ASSEMBLY__ | ||
34 | |||
35 | static inline int cache_line_size(void) | ||
36 | { | ||
37 | u32 cwg = cache_type_cwg(); | ||
38 | return cwg ? 4 << cwg : L1_CACHE_BYTES; | ||
39 | } | ||
40 | |||
41 | #endif /* __ASSEMBLY__ */ | ||
31 | 42 | ||
32 | #endif | 43 | #endif |
diff --git a/arch/arm64/include/asm/cachetype.h b/arch/arm64/include/asm/cachetype.h index 85f5f511352a..4b23e758d5e0 100644 --- a/arch/arm64/include/asm/cachetype.h +++ b/arch/arm64/include/asm/cachetype.h | |||
@@ -20,12 +20,16 @@ | |||
20 | 20 | ||
21 | #define CTR_L1IP_SHIFT 14 | 21 | #define CTR_L1IP_SHIFT 14 |
22 | #define CTR_L1IP_MASK 3 | 22 | #define CTR_L1IP_MASK 3 |
23 | #define CTR_CWG_SHIFT 24 | ||
24 | #define CTR_CWG_MASK 15 | ||
23 | 25 | ||
24 | #define ICACHE_POLICY_RESERVED 0 | 26 | #define ICACHE_POLICY_RESERVED 0 |
25 | #define ICACHE_POLICY_AIVIVT 1 | 27 | #define ICACHE_POLICY_AIVIVT 1 |
26 | #define ICACHE_POLICY_VIPT 2 | 28 | #define ICACHE_POLICY_VIPT 2 |
27 | #define ICACHE_POLICY_PIPT 3 | 29 | #define ICACHE_POLICY_PIPT 3 |
28 | 30 | ||
31 | #ifndef __ASSEMBLY__ | ||
32 | |||
29 | static inline u32 icache_policy(void) | 33 | static inline u32 icache_policy(void) |
30 | { | 34 | { |
31 | return (read_cpuid_cachetype() >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK; | 35 | return (read_cpuid_cachetype() >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK; |
@@ -45,4 +49,11 @@ static inline int icache_is_aivivt(void) | |||
45 | return icache_policy() == ICACHE_POLICY_AIVIVT; | 49 | return icache_policy() == ICACHE_POLICY_AIVIVT; |
46 | } | 50 | } |
47 | 51 | ||
52 | static inline u32 cache_type_cwg(void) | ||
53 | { | ||
54 | return (read_cpuid_cachetype() >> CTR_CWG_SHIFT) & CTR_CWG_MASK; | ||
55 | } | ||
56 | |||
57 | #endif /* __ASSEMBLY__ */ | ||
58 | |||
48 | #endif /* __ASM_CACHETYPE_H */ | 59 | #endif /* __ASM_CACHETYPE_H */ |
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 7ec784653b29..5b9e046d580e 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/utsname.h> | 25 | #include <linux/utsname.h> |
26 | #include <linux/initrd.h> | 26 | #include <linux/initrd.h> |
27 | #include <linux/console.h> | 27 | #include <linux/console.h> |
28 | #include <linux/cache.h> | ||
28 | #include <linux/bootmem.h> | 29 | #include <linux/bootmem.h> |
29 | #include <linux/seq_file.h> | 30 | #include <linux/seq_file.h> |
30 | #include <linux/screen_info.h> | 31 | #include <linux/screen_info.h> |
@@ -198,6 +199,8 @@ static void __init setup_processor(void) | |||
198 | { | 199 | { |
199 | struct cpu_info *cpu_info; | 200 | struct cpu_info *cpu_info; |
200 | u64 features, block; | 201 | u64 features, block; |
202 | u32 cwg; | ||
203 | int cls; | ||
201 | 204 | ||
202 | cpu_info = lookup_processor_type(read_cpuid_id()); | 205 | cpu_info = lookup_processor_type(read_cpuid_id()); |
203 | if (!cpu_info) { | 206 | if (!cpu_info) { |
@@ -215,6 +218,18 @@ static void __init setup_processor(void) | |||
215 | elf_hwcap = 0; | 218 | elf_hwcap = 0; |
216 | 219 | ||
217 | /* | 220 | /* |
221 | * Check for sane CTR_EL0.CWG value. | ||
222 | */ | ||
223 | cwg = cache_type_cwg(); | ||
224 | cls = cache_line_size(); | ||
225 | if (!cwg) | ||
226 | pr_warn("No Cache Writeback Granule information, assuming cache line size %d\n", | ||
227 | cls); | ||
228 | if (L1_CACHE_BYTES < cls) | ||
229 | pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n", | ||
230 | L1_CACHE_BYTES, cls); | ||
231 | |||
232 | /* | ||
218 | * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks. | 233 | * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks. |
219 | * The blocks we test below represent incremental functionality | 234 | * The blocks we test below represent incremental functionality |
220 | * for non-negative values. Negative values are reserved. | 235 | * for non-negative values. Negative values are reserved. |