Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+41 -1
+3
arch/arm64/Kconfig
··· 242 242 config HAVE_ARCH_TRANSPARENT_HUGEPAGE 243 243 def_bool y 244 244 245 + config ARCH_HAS_CACHE_LINE_SIZE 246 + def_bool y 247 + 245 248 source "mm/Kconfig" 246 249 247 250 config XEN_DOM0
+12 -1
arch/arm64/include/asm/cache.h
··· 16 16 #ifndef __ASM_CACHE_H 17 17 #define __ASM_CACHE_H 18 18 19 + #include <asm/cachetype.h> 20 + 19 21 #define L1_CACHE_SHIFT 6 20 22 #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) 21 23 ··· 29 27 * the CPU. 30 28 */ 31 29 #define ARCH_DMA_MINALIGN L1_CACHE_BYTES 32 - #define ARCH_SLAB_MINALIGN 8 30 + 31 + #ifndef __ASSEMBLY__ 32 + 33 + static inline int cache_line_size(void) 34 + { 35 + u32 cwg = cache_type_cwg(); 36 + return cwg ? 4 << cwg : L1_CACHE_BYTES; 37 + } 38 + 39 + #endif /* __ASSEMBLY__ */ 33 40 34 41 #endif
+11
arch/arm64/include/asm/cachetype.h
··· 20 20 21 21 #define CTR_L1IP_SHIFT 14 22 22 #define CTR_L1IP_MASK 3 23 + #define CTR_CWG_SHIFT 24 24 + #define CTR_CWG_MASK 15 23 25 24 26 #define ICACHE_POLICY_RESERVED 0 25 27 #define ICACHE_POLICY_AIVIVT 1 26 28 #define ICACHE_POLICY_VIPT 2 27 29 #define ICACHE_POLICY_PIPT 3 30 + 31 + #ifndef __ASSEMBLY__ 28 32 29 33 static inline u32 icache_policy(void) 30 34 { ··· 48 44 { 49 45 return icache_policy() == ICACHE_POLICY_AIVIVT; 50 46 } 47 + 48 + static inline u32 cache_type_cwg(void) 49 + { 50 + return (read_cpuid_cachetype() >> CTR_CWG_SHIFT) & CTR_CWG_MASK; 51 + } 52 + 53 + #endif /* __ASSEMBLY__ */ 51 54 52 55 #endif /* __ASM_CACHETYPE_H */
+15
arch/arm64/kernel/setup.c
··· 25 25 #include <linux/utsname.h> 26 26 #include <linux/initrd.h> 27 27 #include <linux/console.h> 28 + #include <linux/cache.h> 28 29 #include <linux/bootmem.h> 29 30 #include <linux/seq_file.h> 30 31 #include <linux/screen_info.h> ··· 199 198 { 200 199 struct cpu_info *cpu_info; 201 200 u64 features, block; 201 + u32 cwg; 202 + int cls; 202 203 203 204 cpu_info = lookup_processor_type(read_cpuid_id()); 204 205 if (!cpu_info) { ··· 216 213 217 214 sprintf(init_utsname()->machine, ELF_PLATFORM); 218 215 elf_hwcap = 0; 216 + 217 + /* 218 + * Check for sane CTR_EL0.CWG value. 219 + */ 220 + cwg = cache_type_cwg(); 221 + cls = cache_line_size(); 222 + if (!cwg) 223 + pr_warn("No Cache Writeback Granule information, assuming cache line size %d\n", 224 + cls); 225 + if (L1_CACHE_BYTES < cls) 226 + pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n", 227 + L1_CACHE_BYTES, cls); 219 228 220 229 /* 221 230 * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks.