ARMv7-A: Exception register save/restore needs to work a little differently if we support user mode processes
This commit is contained in:
parent
17e798993d
commit
57d78ddd93
2
TODO
2
TODO
@ -1439,7 +1439,7 @@ o ARM (arch/arm/)
|
||||
Priority: Low
|
||||
|
||||
Title: CORTEX-M3 STACK OVERFLOW
|
||||
Description: There is bit bit logic inf up_fullcontextrestore() that executes on
|
||||
Description: There is bit bit logic in up_fullcontextrestore() that executes on
|
||||
return from interrupts (and other context switches) that looks like:
|
||||
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the stored CPSR value */
|
||||
|
@ -57,6 +57,11 @@
|
||||
g_irqtmp:
|
||||
.word 0 /* Saved lr */
|
||||
.word 0 /* Saved spsr */
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
g_svctmp:
|
||||
.word 0 /* User R13 */
|
||||
.word 0 /* User R14 */
|
||||
#endif
|
||||
g_undeftmp:
|
||||
.word 0 /* Saved lr */
|
||||
.word 0 /* Saved spsr */
|
||||
@ -123,15 +128,46 @@ arm_vectorirq:
|
||||
sub sp, sp, #XCPTCONTEXT_SIZE
|
||||
stmia sp, {r0-r12} /* Save the SVC mode regs */
|
||||
|
||||
/* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
|
||||
ldr r0, .Lirqtmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r3=lr_IRQ, r4=spsr_IRQ */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r1, r4, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r1, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lirqentersvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
stmia r0, {r13, r14}^ /* Get user mode R13/R14 into scratch area */
|
||||
ldmia r0, {r1, r2} /* Then reload into R1 and R2 */
|
||||
b .Lirqcontinue
|
||||
|
||||
.Lirqentersvc:
|
||||
/* Otherwise, get the correct values of SVC r13(sp) and r14(lr) in r1
|
||||
* and r2.
|
||||
*/
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
.Lirqcontinue:
|
||||
|
||||
ldr r0, .Lirqtmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
|
||||
#else
|
||||
/* Get the correct values of SVC r13(sp) and r14(lr) in r1 and r2 */
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
#endif
|
||||
|
||||
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
|
||||
|
||||
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
|
||||
stmia r0, {r1-r4}
|
||||
@ -163,8 +199,30 @@ arm_vectorirq:
|
||||
|
||||
/* Restore the CPSR, SVC mode registers and return */
|
||||
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr, r1
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the return SPSR */
|
||||
msr spsr, r1 /* Establish the return mode SPSR */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r2, r1, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r2, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lirqleavesvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
add r1, r0, #(4*REG_R13) /* R1=address of R13/R14 storage */
|
||||
ldmia r1, {r13, r14}^ /* Restore to user mode USER R13/R14 */
|
||||
ldmia r0, {r0-R12,r15}^ /* Return */
|
||||
|
||||
.Lirqleavesvc:
|
||||
#endif
|
||||
/* Life is simple when everything is SVC mode */
|
||||
|
||||
ldmia r0, {r0-r15}^ /* Return */
|
||||
|
||||
.Lirqtmp:
|
||||
@ -197,14 +255,47 @@ arm_vectorsvc:
|
||||
sub sp, sp, #XCPTCONTEXT_SIZE
|
||||
stmia sp, {r0-r12} /* Save the SVC mode regs */
|
||||
|
||||
/* Get the correct values of r13(sp), r14(lr), r15(pc)
|
||||
* and CPSR in r1-r4.
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
|
||||
mov r3, r14 /* Save r14 as the PC as well */
|
||||
mrs r4, spsr /* Get the saved CPSR */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r1, r4, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r1, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lsvcentersvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
ldr r0, .Lsvctmp /* Points to temp storage */
|
||||
stmia r0, {r13, r14}^ /* Get user mode R13/R14 into temp storage */
|
||||
ldmia r0, {r1, r2} /* Then reload into R1 and R2 */
|
||||
b .Lsvccontinue
|
||||
|
||||
.Lsvcentersvc:
|
||||
/* Otherwise, get the correct values of SVC r13(sp) and r14(lr) in r1
|
||||
* and r2.
|
||||
*/
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14 /* R14 is altered on return from SVC */
|
||||
mov r3, r14 /* Save r14 as the PC as well */
|
||||
mrs r4, spsr /* Get the saved CPSR */
|
||||
mov r2, r14
|
||||
|
||||
.Lsvccontinue:
|
||||
|
||||
#else
|
||||
/* Get the correct values of SVC r13(sp) and r14(lr) in r1 and r2 */
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
#endif
|
||||
|
||||
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
|
||||
|
||||
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
|
||||
stmia r0, {r1-r4}
|
||||
@ -229,8 +320,35 @@ arm_vectorsvc:
|
||||
/* Restore the CPSR, SVC mode registers and return */
|
||||
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr, r1
|
||||
msr spsr, r1 /* Establish the return mode SPSR */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r2, r1, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r2, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lleavesvcsvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
add r1, r0, #(4*REG_R13) /* R1=address of R13/R14 storage */
|
||||
ldmia r1, {r13, r14}^ /* Restore to user mode USER R13/R14 */
|
||||
ldmia r0, {r0-R12,r15}^ /* Return */
|
||||
|
||||
.Lleavesvcsvc:
|
||||
#endif
|
||||
/* Life is simple when everything is SVC mode */
|
||||
|
||||
ldmia r0, {r0-r15}^ /* Return */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
.Lsvctmp:
|
||||
.word g_svctmp
|
||||
#endif
|
||||
.size arm_vectorsvc, . - arm_vectorsvc
|
||||
|
||||
.align 5
|
||||
@ -274,15 +392,46 @@ arm_vectordata:
|
||||
sub sp, sp, #XCPTCONTEXT_SIZE
|
||||
stmia sp, {r0-r12} /* Save the SVC mode regs */
|
||||
|
||||
/* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
|
||||
ldr r0, .Ldaborttmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r3=lr_ABT, r4=spsr_ABT */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r1, r4, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r1, #PSR_MODE_USR /* User mode? */
|
||||
bne .Ldabtentersvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
stmia r0, {r13, r14}^ /* Get user mode R13/R14 into scratch area */
|
||||
ldmia r0, {r1, r2} /* Then reload into R1 and R2 */
|
||||
b .Ldabtcontinue
|
||||
|
||||
.Ldabtentersvc:
|
||||
/* Otherwise, get the correct values of SVC r13(sp) and r14(lr) in r1
|
||||
* and r2.
|
||||
*/
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
.Ldabtcontinue:
|
||||
|
||||
ldr r0, .Ldaborttmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
|
||||
#else
|
||||
/* Get the correct values of SVC r13(sp) and r14(lr) in r1 and r2 */
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
#endif
|
||||
|
||||
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
|
||||
|
||||
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
|
||||
stmia r0, {r1-r4}
|
||||
@ -309,7 +458,29 @@ arm_vectordata:
|
||||
/* Restore the CPSR, SVC mode registers and return */
|
||||
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr_cxsf, r1
|
||||
msr spsr_cxsf, r1 /* Establish the return mode SPSR */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r2, r1, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r2, #PSR_MODE_USR /* User mode? */
|
||||
bne .Ldabtleavesvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
add r1, r0, #(4*REG_R13) /* R1=address of R13/R14 storage */
|
||||
ldmia r1, {r13, r14}^ /* Restore to user mode USER R13/R14 */
|
||||
ldmia r0, {r0-R12,r15}^ /* Return */
|
||||
|
||||
.Ldabtleavesvc:
|
||||
#endif
|
||||
/* Life is simple when everything is SVC mode */
|
||||
|
||||
ldmia r0, {r1-r15}^ /* Return */
|
||||
|
||||
.Ldaborttmp:
|
||||
@ -357,15 +528,46 @@ arm_vectorprefetch:
|
||||
sub sp, sp, #XCPTCONTEXT_SIZE
|
||||
stmia sp, {r0-r12} /* Save the SVC mode regs */
|
||||
|
||||
/* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
|
||||
ldr r0, .Lpaborttmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r3=lr_ABT, r4=spsr_ABT */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r1, r4, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r1, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lpabtentersvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
stmia r0, {r13, r14}^ /* Get user mode R13/R14 into scratch area */
|
||||
ldmia r0, {r1, r2} /* Then reload into R1 and R2 */
|
||||
b .Lpabtcontinue
|
||||
|
||||
.Lpabtentersvc:
|
||||
/* Otherwise, get the correct values of SVC r13(sp) and r14(lr) in r1
|
||||
* and r2.
|
||||
*/
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
.Lpabtcontinue:
|
||||
|
||||
ldr r0, .Lpaborttmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
|
||||
#else
|
||||
/* Get the correct values of SVC r13(sp) and r14(lr) in r1 and r2 */
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
#endif
|
||||
|
||||
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
|
||||
|
||||
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
|
||||
stmia r0, {r1-r4}
|
||||
@ -392,7 +594,29 @@ arm_vectorprefetch:
|
||||
/* Restore the CPSR, SVC mode registers and return */
|
||||
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr_cxsf, r1
|
||||
msr spsr_cxsf, r1 /* Establish the return mode SPSR */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r2, r1, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r2, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lpabtleavesvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
add r1, r0, #(4*REG_R13) /* R1=address of R13/R14 storage */
|
||||
ldmia r1, {r13, r14}^ /* Restore to user mode USER R13/R14 */
|
||||
ldmia r0, {r0-R12,r15}^ /* Return */
|
||||
|
||||
.Lpabtleavesvc:
|
||||
#endif
|
||||
/* Life is simple when everything is SVC mode */
|
||||
|
||||
ldmia r0, {r0-r15}^ /* Return */
|
||||
|
||||
.Lpaborttmp:
|
||||
@ -437,15 +661,46 @@ arm_vectorundefinsn:
|
||||
sub sp, sp, #XCPTCONTEXT_SIZE
|
||||
stmia sp, {r0-r12} /* Save the SVC mode regs */
|
||||
|
||||
/* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
|
||||
ldr r0, .Lundeftmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r3=lr_UND, r4=spsr_UND */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r1, r4, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r1, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lundefentersvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
stmia r0, {r13, r14}^ /* Get user mode R13/R14 into scratch area */
|
||||
ldmia r0, {r1, r2} /* Then reload into R1 and R2 */
|
||||
b .Lundefcontinue
|
||||
|
||||
.Lundefentersvc:
|
||||
/* Otherwise, get the correct values of SVC r13(sp) and r14(lr) in r1
|
||||
* and r2.
|
||||
*/
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
.Lundefcontinue:
|
||||
|
||||
ldr r0, .Lundeftmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
|
||||
#else
|
||||
/* Get the correct values of SVC r13(sp) and r14(lr) in r1 and r2 */
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
#endif
|
||||
|
||||
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
|
||||
|
||||
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
|
||||
stmia r0, {r1-r4}
|
||||
@ -470,7 +725,29 @@ arm_vectorundefinsn:
|
||||
/* Restore the CPSR, SVC mode registers and return */
|
||||
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr_cxsf, r1
|
||||
msr spsr_cxsf, r1 /* Establish the return mode SPSR */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r2, r1, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r2, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lundefleavesvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
add r1, r0, #(4*REG_R13) /* R1=address of R13/R14 storage */
|
||||
ldmia r1, {r13, r14}^ /* Restore to user mode USER R13/R14 */
|
||||
ldmia r0, {r0-R12,r15}^ /* Return */
|
||||
|
||||
.Lundefleavesvc:
|
||||
#endif
|
||||
/* Life is simple when everything is SVC mode */
|
||||
|
||||
ldmia r0, {r0-r15}^ /* Return */
|
||||
|
||||
.Lundeftmp:
|
||||
@ -517,15 +794,46 @@ arm_vectorfiq:
|
||||
sub sp, sp, #XCPTCONTEXT_SIZE
|
||||
stmia sp, {r0-r12} /* Save the SVC mode regs */
|
||||
|
||||
/* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
|
||||
ldr r0, .Lfiqtmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r3=lr_SVC, r4=spsr_SVC */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r1, r4, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r1, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lfiqentersvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
stmia r0, {r13, r14}^ /* Get user mode R13/R14 into scratch area */
|
||||
ldmia r0, {r1, r2} /* Then reload into R1 and R2 */
|
||||
b .Lfiqcontinue
|
||||
|
||||
.Lfiqentersvc:
|
||||
/* Otherwise, get the correct values of SVC r13(sp) and r14(lr) in r1
|
||||
* and r2.
|
||||
*/
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
|
||||
/* Get the values for r15(pc) and CPSR in r3 and r4 */
|
||||
.Lfiqcontinue:
|
||||
|
||||
ldr r0, .Lfiqtmp /* Points to temp storage */
|
||||
ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
|
||||
#else
|
||||
/* Get the correct values of SVC r13(sp) and r14(lr) in r1 and r2 */
|
||||
|
||||
add r1, sp, #XCPTCONTEXT_SIZE
|
||||
mov r2, r14
|
||||
#endif
|
||||
|
||||
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
|
||||
|
||||
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
|
||||
stmia r0, {r1-r4}
|
||||
@ -558,7 +866,29 @@ arm_vectorfiq:
|
||||
/* Restore the CPSR, SVC mode registers and return */
|
||||
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr, r1
|
||||
msr spsr, r1 /* Establish the return mode SPSR */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* Did we enter from user mode? If so then we need get the values of
|
||||
* USER mode r13(sp) and r14(lr) in r1 and r2.
|
||||
*/
|
||||
|
||||
and r2, r1, #PSR_MODE_MASK /* Interrupted mode */
|
||||
cmp r2, #PSR_MODE_USR /* User mode? */
|
||||
bne .Lfiqleavesvc /* Branch if not user mode */
|
||||
|
||||
/* ldmia with ^ will return the user mode registers (provided that r15
|
||||
* is not in the register list).
|
||||
*/
|
||||
|
||||
add r1, r0, #(4*REG_R13) /* R1=address of R13/R14 storage */
|
||||
ldmia r1, {r13, r14}^ /* Restore to user mode USER R13/R14 */
|
||||
ldmia r0, {r0-R12,r15}^ /* Return */
|
||||
|
||||
.Lfiqleavesvc:
|
||||
#endif
|
||||
/* Life is simple when everything is SVC mode */
|
||||
|
||||
ldmia r0, {r0-r15}^ /* Return */
|
||||
|
||||
.Lfiqtmp:
|
||||
|
Loading…
Reference in New Issue
Block a user