[ARM] 3256/1: Make the function-returning ldm's use sp as the base register
authorCatalin Marinas <catalin.marinas@arm.com>
Thu, 12 Jan 2006 16:53:51 +0000 (16:53 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 12 Jan 2006 16:53:51 +0000 (16:53 +0000)
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>
arch/arm/kernel/fiq.c
arch/arm/lib/csumpartialcopy.S
arch/arm/lib/csumpartialcopygeneric.S
arch/arm/lib/csumpartialcopyuser.S

index 9299dfc25698220beee832edbac717ac948c2ae8..1ec3f7faa259eedba5ccf3973ca827fb869cdfcd 100644 (file)
@@ -101,7 +101,7 @@ void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs)
        ldmia   %1, {r8 - r14}\n\
        msr     cpsr_c, %0      @ return to SVC mode\n\
        mov     r0, r0\n\
-       ldmea   fp, {fp, sp, pc}"
+       ldmfd   sp, {fp, sp, pc}"
        : "=&r" (tmp)
        : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
 }
@@ -119,7 +119,7 @@ void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs)
        stmia   %1, {r8 - r14}\n\
        msr     cpsr_c, %0      @ return to SVC mode\n\
        mov     r0, r0\n\
-       ldmea   fp, {fp, sp, pc}"
+       ldmfd   sp, {fp, sp, pc}"
        : "=&r" (tmp)
        : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
 }
index 990ee63b246551f20e7db1f628d75a26a4a8ded0..21effe0dbf97e2b2f15ad1c3f6a2ab96a0ed9d43 100644 (file)
  */
 
                .macro  save_regs
+               mov     ip, sp
                stmfd   sp!, {r1, r4 - r8, fp, ip, lr, pc}
+               sub     fp, ip, #4
                .endm
 
-               .macro  load_regs,flags
-               LOADREGS(\flags,fp,{r1, r4 - r8, fp, sp, pc})
+               .macro  load_regs
+               ldmfd   sp, {r1, r4 - r8, fp, sp, pc}
                .endm
 
                .macro  load1b, reg1
index 4a4609c19095f9188005e4e2e9b68d235008b079..c50e8f5285d17e7851de9d03c5c7e7e25f3b86cd 100644 (file)
@@ -23,7 +23,7 @@ len   .req    r2
 sum    .req    r3
 
 .Lzero:                mov     r0, sum
-               load_regs       ea
+               load_regs
 
                /*
                 * Align an unaligned destination pointer.  We know that
@@ -87,9 +87,7 @@ sum   .req    r3
                b       .Ldone
 
 FN_ENTRY
-               mov     ip, sp
                save_regs
-               sub     fp, ip, #4
 
                cmp     len, #8                 @ Ensure that we have at least
                blo     .Lless8                 @ 8 bytes to copy.
@@ -163,7 +161,7 @@ FN_ENTRY
                ldr     sum, [sp, #0]           @ dst
                tst     sum, #1
                movne   r0, r0, ror #8
-               load_regs       ea
+               load_regs
 
 .Lsrc_not_aligned:
                adc     sum, sum, #0            @ include C from dst alignment
index 333bca292de93a5b0eec17405207089395dbf88f..c3b93e22ea25a05d80654016bb13e1c4f27879f5 100644 (file)
                .text
 
                .macro  save_regs
+               mov     ip, sp
                stmfd   sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc}
+               sub     fp, ip, #4
                .endm
 
-               .macro  load_regs,flags
-               ldm\flags       fp, {r1, r2, r4-r8, fp, sp, pc}
+               .macro  load_regs
+               ldmfd   sp, {r1, r2, r4-r8, fp, sp, pc}
                .endm
 
                .macro  load1b, reg1
 6002:          teq     r2, r1
                strneb  r0, [r1], #1
                bne     6002b
-               load_regs       ea
+               load_regs
                .previous