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

ARM: 8864/1: Add workaround for I-Cache line size mismatch between CPU cores

Some big.LITTLE systems have I-Cache line size mismatch between
LITTLE and big cores. This patch adds a workaround for proper I-Cache
support on such systems. Without it, some class of the userspace code
(typically self-modifying) might suffer from random SIGILL failures.

Similar workaround already exists for ARM64 architecture. I has been
added by commit 116c81f427ff ("arm64: Work around systems with mismatched
cache line sizes").

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

authored by

Marek Szyprowski and committed by
Russell King
5f41f919 304009a1

+48
+1
arch/arm/configs/exynos_defconfig
··· 9 9 CONFIG_PARTITION_ADVANCED=y 10 10 CONFIG_ARCH_EXYNOS=y 11 11 CONFIG_ARCH_EXYNOS3=y 12 + CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND=y 12 13 CONFIG_SMP=y 13 14 CONFIG_BIG_LITTLE=y 14 15 CONFIG_NR_CPUS=8
+7
arch/arm/include/asm/cacheflush.h
··· 479 479 void flush_uprobe_xol_access(struct page *page, unsigned long uaddr, 480 480 void *kaddr, unsigned long len); 481 481 482 + 483 + #ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND 484 + void check_cpu_icache_size(int cpuid); 485 + #else 486 + static inline void check_cpu_icache_size(int cpuid) { } 487 + #endif 488 + 482 489 #endif
+1
arch/arm/kernel/smp.c
··· 375 375 cpu_info->cpuid = read_cpuid_id(); 376 376 377 377 store_cpu_topology(cpuid); 378 + check_cpu_icache_size(cpuid); 378 379 } 379 380 380 381 /*
+8
arch/arm/mm/Kconfig
··· 780 780 Say Y here to disable the processor instruction cache. Unless 781 781 you have a reason not to or are unsure, say N. 782 782 783 + config CPU_ICACHE_MISMATCH_WORKAROUND 784 + bool "Workaround for I-Cache line size mismatch between CPU cores" 785 + depends on SMP && CPU_V7 786 + help 787 + Some big.LITTLE systems have I-Cache line size mismatch between 788 + LITTLE and big cores. Say Y here to enable a workaround for 789 + proper I-Cache support on such systems. If unsure, say N. 790 + 783 791 config CPU_DCACHE_DISABLE 784 792 bool "Disable D-Cache (C-bit)" 785 793 depends on (CPU_CP15 && !SMP) || CPU_V7M
+13
arch/arm/mm/cache-v7.S
··· 19 19 20 20 #include "proc-macros.S" 21 21 22 + #ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND 23 + .globl icache_size 24 + .data 25 + .align 2 26 + icache_size: 27 + .long 64 28 + .text 29 + #endif 22 30 /* 23 31 * The secondary kernel init calls v7_flush_dcache_all before it enables 24 32 * the L1; however, the L1 comes out of reset in an undefined state, so ··· 292 284 cmp r12, r1 293 285 blo 1b 294 286 dsb ishst 287 + #ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND 288 + ldr r3, =icache_size 289 + ldr r2, [r3, #0] 290 + #else 295 291 icache_line_size r2, r3 292 + #endif 296 293 sub r3, r2, #1 297 294 bic r12, r0, r3 298 295 2:
+16
arch/arm/mm/init.c
··· 242 242 #endif 243 243 } 244 244 245 + #ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND 246 + void check_cpu_icache_size(int cpuid) 247 + { 248 + u32 size, ctr; 249 + 250 + asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr)); 251 + 252 + size = 1 << ((ctr & 0xf) + 2); 253 + if (cpuid != 0 && icache_size != size) 254 + pr_info("CPU%u: detected I-Cache line size mismatch, workaround enabled\n", 255 + cpuid); 256 + if (icache_size > size) 257 + icache_size = size; 258 + } 259 + #endif 260 + 245 261 void __init arm_memblock_init(const struct machine_desc *mdesc) 246 262 { 247 263 /* Register the kernel text, kernel data and initrd with memblock. */
+2
arch/arm/mm/mm.h
··· 8 8 /* the upper-most page table pointer */ 9 9 extern pmd_t *top_pmd; 10 10 11 + extern int icache_size; 12 + 11 13 /* 12 14 * 0xffff8000 to 0xffffffff is reserved for any ARM architecture 13 15 * specific hacks for copying pages efficiently, while 0xffff4000