diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/include/asm/cacheflush.h | 7 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 1 | ||||
-rw-r--r-- | arch/arm/mm/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/mm/cache-v7.S | 13 | ||||
-rw-r--r-- | arch/arm/mm/init.c | 16 | ||||
-rw-r--r-- | arch/arm/mm/mm.h | 2 |
6 files changed, 47 insertions, 0 deletions
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 74504b154256..060edfc1c972 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -481,4 +481,11 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size) void flush_uprobe_xol_access(struct page *page, unsigned long uaddr, void *kaddr, unsigned long len); + +#ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND +void check_cpu_icache_size(int cpuid); +#else +static inline void check_cpu_icache_size(int cpuid) { } +#endif + #endif diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 80811a4e46f6..1865625db2d6 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -347,6 +347,7 @@ static void smp_store_cpu_info(unsigned int cpuid) cpu_info->cpuid = read_cpuid_id(); store_cpu_topology(cpuid); + check_cpu_icache_size(cpuid); } /* diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 50e0b45a22db..54c533135ffa 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -786,6 +786,14 @@ config CPU_ICACHE_DISABLE Say Y here to disable the processor instruction cache. Unless you have a reason not to or are unsure, say N. +config CPU_ICACHE_MISMATCH_WORKAROUND + bool "Workaround for I-Cache line size mismatch between CPU cores" + depends on (SMP && CPU_V7) + help + Some big.LITTLE systems have mismatch of I-Cache line size between + LITTLE and big cores. Say Y here to enable workaround for proper + I-Cache support on such systems. If unsure, say N. + config CPU_DCACHE_DISABLE bool "Disable D-Cache (C-bit)" depends on (CPU_CP15 && !SMP) || CPU_V7M diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 50a70edbc863..69cfee658794 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -18,6 +18,14 @@ #include "proc-macros.S" +#ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND +.globl icache_size + .data + .align 2 +icache_size: + .long 64 + .text +#endif /* * The secondary kernel init calls v7_flush_dcache_all before it enables * the L1; however, the L1 comes out of reset in an undefined state, so @@ -283,7 +291,12 @@ ENTRY(v7_coherent_user_range) cmp r12, r1 blo 1b dsb ishst +#ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND + ldr r3, =icache_size + ldr r2, [r3, #0] +#else icache_line_size r2, r3 +#endif sub r3, r2, #1 bic r12, r0, r3 2: diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index defb7fc26428..57d3643538ac 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -277,6 +277,22 @@ static void __init arm_initrd_init(void) #endif } +#ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND +void check_cpu_icache_size(int cpuid) +{ + u32 size, ctr; + + asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr)); + + size = 1 << ((ctr & 0xf) + 2); + if (cpuid != 0 && icache_size != size) + pr_info("CPU%u: detected I-Cache line size mismatch, workaround enabled\n", + cpuid); + if (icache_size > size) + icache_size = size; +} +#endif + void __init arm_memblock_init(const struct machine_desc *mdesc) { /* Register the kernel text, kernel data and initrd with memblock. */ diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 6b045c6653ea..941356d95a67 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -8,6 +8,8 @@ /* the upper-most page table pointer */ extern pmd_t *top_pmd; +extern int icache_size; + /* * 0xffff8000 to 0xffffffff is reserved for any ARM architecture * specific hacks for copying pages efficiently, while 0xffff4000 |