[PATCH] ARM v7: Fix register corruption in v7_mmu_cache_off

Sascha Hauer s.hauer at pengutronix.de
Wed Jan 23 04:43:45 EST 2013

v7_mmu_cache_flush stores registers on the stack and restores
them afterwards. Additionally v7_mmu_cache_flush is called
from v7_mmu_cache_off *after* disabling the MMU. With this
the following can happen:

- v7_mmu_cache_off disables the MMU. From now on no new values
  go to the data cache.
- v7_mmu_cache_off calls v7_mmu_cache_flush which in turn puts
  registers on the stack. Due to the MMU being disabled they
  do not go into the data cache.
- In v7_mmu_cache_flush the memory the stack is pointing to is
  overwritten with the values currently being in the cache.
- v7_mmu_cache_flush restores the registers from the stack with
  values from the cache and not the memory where the values have
  previously been written to.

Fix this by storing the registers on the stack *before* we disable
the MMU and restore them after we have called v7_mmu_cache_flush.
This way v7_mmu_cache_flush still restores corrupt register values
for the case when the MMU has been disabled, but we will restore
correct values afterwards.

This has been first observed when switching to gcc-4.7.2 when compiling
in Thumb2 mode, but could explain earlier problems also. The result
here was that the register holding the kernel address in start_linux()
was corrupted so that the kernel could not be started.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
 arch/arm/cpu/cache-armv7.S |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/cpu/cache-armv7.S b/arch/arm/cpu/cache-armv7.S
index 2d68f27..13542d9 100644
--- a/arch/arm/cpu/cache-armv7.S
+++ b/arch/arm/cpu/cache-armv7.S
@@ -34,6 +34,7 @@ ENDPROC(v7_mmu_cache_on)
 .section .text.v7_mmu_cache_off
+		stmfd	sp!, {r0-r7, r9-r11}
 		mrc	p15, 0, r0, c1, c0
 #ifdef CONFIG_MMU
 		bic	r0, r0, #0x000d
@@ -50,6 +51,7 @@ ENTRY(v7_mmu_cache_off)
 		mcr	p15, 0, r0, c7, c5, 6	@ invalidate BTC
 		mcr	p15, 0, r0, c7, c10, 4	@ DSB
 		mcr	p15, 0, r0, c7, c5, 4	@ ISB
+		ldmfd	sp!, {r0-r7, r9-r11}
 		mov	pc, r12

More information about the barebox mailing list