/* ************************************************************************* * * Interrupt handling * ************************************************************************* */
@ @ IRQ stack frame. @ #define S_FRAME_SIZE 72
#define S_OLD_R0 68 #define S_PSR 64 #define S_PC 60 #define S_LR 56 #define S_SP 52
#define S_IP 48 #define S_FP 44 #define S_R10 40 #define S_R9 36 #define S_R8 32 #define S_R7 28 #define S_R6 24 #define S_R5 20 #define S_R4 16 #define S_R3 12 #define S_R2 8 #define S_R1 4 #define S_R0 0
#define MODE_SVC 0x13 #define I_BIT 0x80
/* * use bad_save_user_regs for abort/prefetch/undef/swi ... * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling */
.macro bad_save_user_regs sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0-r12 ldr r2, _armboot_start sub r2, r2, #(CONFIG_STACKSIZE) sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) /* set base 2 words into abort stack */ sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) ldmia r2, {r2 - r3} @ get pc, cpsr add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
add r5, sp, #S_SP mov r1, lr stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr mov r0, sp .endm
.macro irq_save_user_regs sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0-r12 add r7, sp, #S_PC stmdb r7, {sp, lr}^ @ Calling SP, LR str lr, [r7, #0] @ Save calling PC mrs r6, spsr str r6, [r7, #4] @ Save CPSR str r0, [r7, #8] @ Save OLD_R0 mov r0, sp .endm
.macro irq_restore_user_regs ldmia sp, {r0 - lr}^ @ Calling r0 - lr mov r0, r0 ldr lr, [sp, #S_PC] @ Get PC add sp, sp, #S_FRAME_SIZE /* return & move spsr_svc into cpsr */ subs pc, lr, #4 .endm
.macro get_bad_stack ldr r13, _armboot_start @ setup our mode stack sub r13, r13, #(CONFIG_STACKSIZE) sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) /* reserve a couple spots in abort stack */ sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8)
str lr, [r13] @ save caller lr / spsr mrs lr, spsr str lr, [r13, #4]
mov r13, #MODE_SVC @ prepare SVC-Mode @ msr spsr_c, r13 msr spsr, r13 mov lr, pc movs pc, lr .endm
.macro get_irq_stack @ setup IRQ stack ldr sp, IRQ_STACK_START .endm
.macro get_fiq_stack @ setup FIQ stack ldr sp, FIQ_STACK_START .endm
/* * exception handlers */ .align 5 undefined_instruction: get_bad_stack bad_save_user_regs bl do_undefined_instruction
.align 5 software_interrupt: get_bad_stack bad_save_user_regs bl do_software_interrupt
.align 5 prefetch_abort: get_bad_stack bad_save_user_regs bl do_prefetch_abort
.align 5 data_abort: get_bad_stack bad_save_user_regs bl do_data_abort
.align 5 not_used: get_bad_stack bad_save_user_regs bl do_not_used
#ifdef CONFIG_USE_IRQ
.align 5 irq: get_irq_stack irq_save_user_regs bl do_irq irq_restore_user_regs
.align 5 fiq: get_fiq_stack /* someone ought to write a more effiction fiq_save_user_regs */ irq_save_user_regs bl do_fiq irq_restore_user_regs
#else
.align 5 irq: get_bad_stack bad_save_user_regs bl do_irq
.align 5 fiq: get_bad_stack bad_save_user_regs bl do_fiq
#endif
|