aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2006-01-12 11:53:51 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-01-12 11:53:51 -0500
commit90303b102353302e84758f245906368907e6a23b (patch)
tree3e417666985ee5875c2d3435518de2c4bdc9b88d /arch
parentece5f7b3c4fde70a1ae4add7372ebca5c90bc34d (diff)
[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>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/fiq.c4
-rw-r--r--arch/arm/lib/csumpartialcopy.S6
-rw-r--r--arch/arm/lib/csumpartialcopygeneric.S6
-rw-r--r--arch/arm/lib/csumpartialcopyuser.S8
4 files changed, 13 insertions, 11 deletions
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index 9299dfc25698..1ec3f7faa259 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -101,7 +101,7 @@ void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs)
101 ldmia %1, {r8 - r14}\n\ 101 ldmia %1, {r8 - r14}\n\
102 msr cpsr_c, %0 @ return to SVC mode\n\ 102 msr cpsr_c, %0 @ return to SVC mode\n\
103 mov r0, r0\n\ 103 mov r0, r0\n\
104 ldmea fp, {fp, sp, pc}" 104 ldmfd sp, {fp, sp, pc}"
105 : "=&r" (tmp) 105 : "=&r" (tmp)
106 : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)); 106 : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
107} 107}
@@ -119,7 +119,7 @@ void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs)
119 stmia %1, {r8 - r14}\n\ 119 stmia %1, {r8 - r14}\n\
120 msr cpsr_c, %0 @ return to SVC mode\n\ 120 msr cpsr_c, %0 @ return to SVC mode\n\
121 mov r0, r0\n\ 121 mov r0, r0\n\
122 ldmea fp, {fp, sp, pc}" 122 ldmfd sp, {fp, sp, pc}"
123 : "=&r" (tmp) 123 : "=&r" (tmp)
124 : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)); 124 : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
125} 125}
diff --git a/arch/arm/lib/csumpartialcopy.S b/arch/arm/lib/csumpartialcopy.S
index 990ee63b2465..21effe0dbf97 100644
--- a/arch/arm/lib/csumpartialcopy.S
+++ b/arch/arm/lib/csumpartialcopy.S
@@ -18,11 +18,13 @@
18 */ 18 */
19 19
20 .macro save_regs 20 .macro save_regs
21 mov ip, sp
21 stmfd sp!, {r1, r4 - r8, fp, ip, lr, pc} 22 stmfd sp!, {r1, r4 - r8, fp, ip, lr, pc}
23 sub fp, ip, #4
22 .endm 24 .endm
23 25
24 .macro load_regs,flags 26 .macro load_regs
25 LOADREGS(\flags,fp,{r1, r4 - r8, fp, sp, pc}) 27 ldmfd sp, {r1, r4 - r8, fp, sp, pc}
26 .endm 28 .endm
27 29
28 .macro load1b, reg1 30 .macro load1b, reg1
diff --git a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S
index 4a4609c19095..c50e8f5285d1 100644
--- a/arch/arm/lib/csumpartialcopygeneric.S
+++ b/arch/arm/lib/csumpartialcopygeneric.S
@@ -23,7 +23,7 @@ len .req r2
23sum .req r3 23sum .req r3
24 24
25.Lzero: mov r0, sum 25.Lzero: mov r0, sum
26 load_regs ea 26 load_regs
27 27
28 /* 28 /*
29 * Align an unaligned destination pointer. We know that 29 * Align an unaligned destination pointer. We know that
@@ -87,9 +87,7 @@ sum .req r3
87 b .Ldone 87 b .Ldone
88 88
89FN_ENTRY 89FN_ENTRY
90 mov ip, sp
91 save_regs 90 save_regs
92 sub fp, ip, #4
93 91
94 cmp len, #8 @ Ensure that we have at least 92 cmp len, #8 @ Ensure that we have at least
95 blo .Lless8 @ 8 bytes to copy. 93 blo .Lless8 @ 8 bytes to copy.
@@ -163,7 +161,7 @@ FN_ENTRY
163 ldr sum, [sp, #0] @ dst 161 ldr sum, [sp, #0] @ dst
164 tst sum, #1 162 tst sum, #1
165 movne r0, r0, ror #8 163 movne r0, r0, ror #8
166 load_regs ea 164 load_regs
167 165
168.Lsrc_not_aligned: 166.Lsrc_not_aligned:
169 adc sum, sum, #0 @ include C from dst alignment 167 adc sum, sum, #0 @ include C from dst alignment
diff --git a/arch/arm/lib/csumpartialcopyuser.S b/arch/arm/lib/csumpartialcopyuser.S
index 333bca292de9..c3b93e22ea25 100644
--- a/arch/arm/lib/csumpartialcopyuser.S
+++ b/arch/arm/lib/csumpartialcopyuser.S
@@ -18,11 +18,13 @@
18 .text 18 .text
19 19
20 .macro save_regs 20 .macro save_regs
21 mov ip, sp
21 stmfd sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc} 22 stmfd sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc}
23 sub fp, ip, #4
22 .endm 24 .endm
23 25
24 .macro load_regs,flags 26 .macro load_regs
25 ldm\flags fp, {r1, r2, r4-r8, fp, sp, pc} 27 ldmfd sp, {r1, r2, r4-r8, fp, sp, pc}
26 .endm 28 .endm
27 29
28 .macro load1b, reg1 30 .macro load1b, reg1
@@ -100,5 +102,5 @@
1006002: teq r2, r1 1026002: teq r2, r1
101 strneb r0, [r1], #1 103 strneb r0, [r1], #1
102 bne 6002b 104 bne 6002b
103 load_regs ea 105 load_regs
104 .previous 106 .previous