diff options
Diffstat (limited to 'arch/arm/kernel/entry-header.S')
-rw-r--r-- | arch/arm/kernel/entry-header.S | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 8db307d0954b..2fdf8679b46e 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S | |||
@@ -208,26 +208,21 @@ | |||
208 | #endif | 208 | #endif |
209 | .endif | 209 | .endif |
210 | msr spsr_cxsf, \rpsr | 210 | msr spsr_cxsf, \rpsr |
211 | #if defined(CONFIG_CPU_V6) | 211 | #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) |
212 | ldr r0, [sp] | 212 | @ We must avoid clrex due to Cortex-A15 erratum #830321 |
213 | strex r1, r2, [sp] @ clear the exclusive monitor | 213 | sub r0, sp, #4 @ uninhabited address |
214 | ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr | 214 | strex r1, r2, [r0] @ clear the exclusive monitor |
215 | #elif defined(CONFIG_CPU_32v6K) | ||
216 | clrex @ clear the exclusive monitor | ||
217 | ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr | ||
218 | #else | ||
219 | ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr | ||
220 | #endif | 215 | #endif |
216 | ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr | ||
221 | .endm | 217 | .endm |
222 | 218 | ||
223 | .macro restore_user_regs, fast = 0, offset = 0 | 219 | .macro restore_user_regs, fast = 0, offset = 0 |
224 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr | 220 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr |
225 | ldr lr, [sp, #\offset + S_PC]! @ get pc | 221 | ldr lr, [sp, #\offset + S_PC]! @ get pc |
226 | msr spsr_cxsf, r1 @ save in spsr_svc | 222 | msr spsr_cxsf, r1 @ save in spsr_svc |
227 | #if defined(CONFIG_CPU_V6) | 223 | #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) |
224 | @ We must avoid clrex due to Cortex-A15 erratum #830321 | ||
228 | strex r1, r2, [sp] @ clear the exclusive monitor | 225 | strex r1, r2, [sp] @ clear the exclusive monitor |
229 | #elif defined(CONFIG_CPU_32v6K) | ||
230 | clrex @ clear the exclusive monitor | ||
231 | #endif | 226 | #endif |
232 | .if \fast | 227 | .if \fast |
233 | ldmdb sp, {r1 - lr}^ @ get calling r1 - lr | 228 | ldmdb sp, {r1 - lr}^ @ get calling r1 - lr |
@@ -261,7 +256,10 @@ | |||
261 | .endif | 256 | .endif |
262 | ldr lr, [sp, #S_SP] @ top of the stack | 257 | ldr lr, [sp, #S_SP] @ top of the stack |
263 | ldrd r0, r1, [sp, #S_LR] @ calling lr and pc | 258 | ldrd r0, r1, [sp, #S_LR] @ calling lr and pc |
264 | clrex @ clear the exclusive monitor | 259 | |
260 | @ We must avoid clrex due to Cortex-A15 erratum #830321 | ||
261 | strex r2, r1, [sp, #S_LR] @ clear the exclusive monitor | ||
262 | |||
265 | stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context | 263 | stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context |
266 | ldmia sp, {r0 - r12} | 264 | ldmia sp, {r0 - r12} |
267 | mov sp, lr | 265 | mov sp, lr |
@@ -282,13 +280,16 @@ | |||
282 | .endm | 280 | .endm |
283 | #else /* ifdef CONFIG_CPU_V7M */ | 281 | #else /* ifdef CONFIG_CPU_V7M */ |
284 | .macro restore_user_regs, fast = 0, offset = 0 | 282 | .macro restore_user_regs, fast = 0, offset = 0 |
285 | clrex @ clear the exclusive monitor | ||
286 | mov r2, sp | 283 | mov r2, sp |
287 | load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr | 284 | load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr |
288 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr | 285 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr |
289 | ldr lr, [sp, #\offset + S_PC] @ get pc | 286 | ldr lr, [sp, #\offset + S_PC] @ get pc |
290 | add sp, sp, #\offset + S_SP | 287 | add sp, sp, #\offset + S_SP |
291 | msr spsr_cxsf, r1 @ save in spsr_svc | 288 | msr spsr_cxsf, r1 @ save in spsr_svc |
289 | |||
290 | @ We must avoid clrex due to Cortex-A15 erratum #830321 | ||
291 | strex r1, r2, [sp] @ clear the exclusive monitor | ||
292 | |||
292 | .if \fast | 293 | .if \fast |
293 | ldmdb sp, {r1 - r12} @ get calling r1 - r12 | 294 | ldmdb sp, {r1 - r12} @ get calling r1 - r12 |
294 | .else | 295 | .else |