ARM: 8941/1: decompressor: enable CP15 barrier instructions in v7 cache setup code
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 22 Nov 2019 11:59:00 +0000 (12:59 +0100)
committerRussell King <rmk+kernel@armlinux.org.uk>
Sat, 25 Jan 2020 18:17:42 +0000 (18:17 +0000)
Commit e17b1af96b2afc38e684aa2f1033387e2ed10029

  "ARM: 8857/1: efi: enable CP15 DMB instructions before cleaning the cache"

added some explicit handling of the CP15BEN bit in the SCTLR system
register, to ensure that CP15 barrier instructions are enabled, even
if we enter the decompressor via the EFI stub.

However, as it turns out, there are other ways in which we may end up
using CP15 barrier instructions without them being enabled. I.e., when
the decompressor startup code skips the cache_on() initially, we end
up calling cache_clean_flush() with the caches and MMU off, in which
case the CP15BEN bit in SCTLR may not be programmed either. And in
fact, cache_on() itself issues CP15 barrier instructions before actually
enabling them by programming the new SCTLR value (and issuing an ISB)

Since these routines are shared between v7 CPUs and older ones that
implement the CPUID extension as well, using the ordinary v7 barrier
instructions in this code is not possible, and so we should enable the
CP15 ones explicitly before issuing them. Note that a v7 ISB is still
required between programming the SCTLR register and using the CP15 barrier
instructions, and we should take care to branch over it if the CP15BEN
bit is already set, given that in that case, the CPU may not support it.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
arch/arm/boot/compressed/head.S

index ead21e5..469a2b3 100644 (file)
 #endif
                .endm
 
+               .macro  enable_cp15_barriers, reg
+               mrc     p15, 0, \reg, c1, c0, 0 @ read SCTLR
+               tst     \reg, #(1 << 5)         @ CP15BEN bit set?
+               bne     .L_\@
+               orr     \reg, \reg, #(1 << 5)   @ CP15 barrier instructions
+               mcr     p15, 0, \reg, c1, c0, 0 @ write SCTLR
+ ARM(          .inst   0xf57ff06f              @ v7+ isb       )
+ THUMB(                isb                                             )
+.L_\@:
+               .endm
+
                .section ".start", "ax"
 /*
  * sort out different calling conventions
@@ -820,6 +831,7 @@ __armv4_mmu_cache_on:
                mov     pc, r12
 
 __armv7_mmu_cache_on:
+               enable_cp15_barriers    r11
                mov     r12, lr
 #ifdef CONFIG_MMU
                mrc     p15, 0, r11, c0, c1, 4  @ read ID_MMFR0
@@ -1209,6 +1221,7 @@ __armv6_mmu_cache_flush:
                mov     pc, lr
 
 __armv7_mmu_cache_flush:
+               enable_cp15_barriers    r10
                tst     r4, #1
                bne     iflush
                mrc     p15, 0, r10, c0, c1, 5  @ read ID_MMFR1