#endif
.endif
msr spsr_cxsf, \rpsr
-#if defined(CONFIG_CPU_V6)
- ldr r0, [sp]
- strex r1, r2, [sp] @ clear the exclusive monitor
- ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr
-#elif defined(CONFIG_CPU_32v6K)
- clrex @ clear the exclusive monitor
- ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
-#else
- ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
+ @ We must avoid clrex due to Cortex-A15 erratum #830321
+ sub r0, sp, #4 @ uninhabited address
+ strex r1, r2, [r0] @ clear the exclusive monitor
#endif
+ ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+ .endm
+
+++ @
+++ @ svc_exit_via_fiq - like svc_exit but switches to FIQ mode before exit
+++ @
+++ @ This macro acts in a similar manner to svc_exit but switches to FIQ
+++ @ mode to restore the final part of the register state.
+++ @
+++ @ We cannot use the normal svc_exit procedure because that would
+++ @ clobber spsr_svc (FIQ could be delivered during the first few
+++ @ instructions of vector_swi meaning its contents have not been
+++ @ saved anywhere).
+++ @
+++ @ Note that, unlike svc_exit, this macro also does not allow a caller
+++ @ supplied rpsr. This is because the FIQ exceptions are not re-entrant
+++ @ and the handlers cannot call into the scheduler (meaning the value
+++ @ on the stack remains correct).
+++ @
+++ .macro svc_exit_via_fiq
+++ mov r0, sp
+++ ldmib r0, {r1 - r14} @ abort is deadly from here onward (it will
+++ @ clobber state restored below)
+++ msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT
+++ add r8, r0, #S_PC
+++ ldr r9, [r0, #S_PSR]
+++ msr spsr_cxsf, r9
+++ ldr r0, [r0, #S_R0]
+++ ldmia r8, {pc}^
++ .endm
++
.macro restore_user_regs, fast = 0, offset = 0
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
ldr lr, [sp, #\offset + S_PC]! @ get pc