aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2014-04-03 12:48:54 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2014-05-09 10:47:45 -0400
commita41dc0e841523efe1df7fa5ad48b5e9027a921df (patch)
treec162086a45807902dd8c510132f3c3f82603d3e6
parent89ca3b881987f5a4be4c5dbaa7f0df12bbdde2fd (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/Kconfig3
-rw-r--r--arch/arm64/include/asm/cache.h13
-rw-r--r--arch/arm64/include/asm/cachetype.h11
-rw-r--r--arch/arm64/kernel/setup.c15
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
242config HAVE_ARCH_TRANSPARENT_HUGEPAGE 242config HAVE_ARCH_TRANSPARENT_HUGEPAGE
243 def_bool y 243 def_bool y
244 244
245config ARCH_HAS_CACHE_LINE_SIZE
246 def_bool y
247
245source "mm/Kconfig" 248source "mm/Kconfig"
246 249
247config XEN_DOM0 250config 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
35static 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
29static inline u32 icache_policy(void) 33static 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
52static 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.