[ARM] 3256/1: Make the function-returning ldm's use sp as the base register

Patch from Catalin Marinas

If the low interrupt latency mode is enabled for the CPU (from ARMv6
onwards), the ldm/stm instructions are no longer atomic. An ldm instruction
restoring the sp and pc registers can be interrupted immediately after sp
was updated but before the pc. If this happens, the CPU restores the base
register to the value before the ldm instruction but if the base register
is not sp, the interrupt routine will corrupt the stack and the restarted
ldm instruction will load garbage.

Note that future ARM cores might always run in the low interrupt latency
mode.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by Catalin Marinas and committed by Russell King 90303b10 ece5f7b3

+13 -11
+2 -2
arch/arm/kernel/fiq.c
··· 101 101 ldmia %1, {r8 - r14}\n\ 102 102 msr cpsr_c, %0 @ return to SVC mode\n\ 103 103 mov r0, r0\n\ 104 - ldmea fp, {fp, sp, pc}" 104 + ldmfd sp, {fp, sp, pc}" 105 105 : "=&r" (tmp) 106 106 : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)); 107 107 } ··· 119 119 stmia %1, {r8 - r14}\n\ 120 120 msr cpsr_c, %0 @ return to SVC mode\n\ 121 121 mov r0, r0\n\ 122 - ldmea fp, {fp, sp, pc}" 122 + ldmfd sp, {fp, sp, pc}" 123 123 : "=&r" (tmp) 124 124 : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)); 125 125 }
+4 -2
arch/arm/lib/csumpartialcopy.S
··· 18 18 */ 19 19 20 20 .macro save_regs 21 + mov ip, sp 21 22 stmfd sp!, {r1, r4 - r8, fp, ip, lr, pc} 23 + sub fp, ip, #4 22 24 .endm 23 25 24 - .macro load_regs,flags 25 - LOADREGS(\flags,fp,{r1, r4 - r8, fp, sp, pc}) 26 + .macro load_regs 27 + ldmfd sp, {r1, r4 - r8, fp, sp, pc} 26 28 .endm 27 29 28 30 .macro load1b, reg1
+2 -4
arch/arm/lib/csumpartialcopygeneric.S
··· 23 23 sum .req r3 24 24 25 25 .Lzero: mov r0, sum 26 - load_regs ea 26 + load_regs 27 27 28 28 /* 29 29 * Align an unaligned destination pointer. We know that ··· 87 87 b .Ldone 88 88 89 89 FN_ENTRY 90 - mov ip, sp 91 90 save_regs 92 - sub fp, ip, #4 93 91 94 92 cmp len, #8 @ Ensure that we have at least 95 93 blo .Lless8 @ 8 bytes to copy. ··· 161 163 ldr sum, [sp, #0] @ dst 162 164 tst sum, #1 163 165 movne r0, r0, ror #8 164 - load_regs ea 166 + load_regs 165 167 166 168 .Lsrc_not_aligned: 167 169 adc sum, sum, #0 @ include C from dst alignment
+5 -3
arch/arm/lib/csumpartialcopyuser.S
··· 18 18 .text 19 19 20 20 .macro save_regs 21 + mov ip, sp 21 22 stmfd sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc} 23 + sub fp, ip, #4 22 24 .endm 23 25 24 - .macro load_regs,flags 25 - ldm\flags fp, {r1, r2, r4-r8, fp, sp, pc} 26 + .macro load_regs 27 + ldmfd sp, {r1, r2, r4-r8, fp, sp, pc} 26 28 .endm 27 29 28 30 .macro load1b, reg1 ··· 102 100 6002: teq r2, r1 103 101 strneb r0, [r1], #1 104 102 bne 6002b 105 - load_regs ea 103 + load_regs 106 104 .previous