硬件
When an IRQ is detected, the following actions are performed:
R14_irq = address of next instruction to be executed + 4
SPSR_irq = CPSR
CPSR[ 4 : 0 ] = 0 b10010
CPSR[ 5 ] = 0
CPSR[ 7 ] = 1
CPSR[ 8 ] = 1
CPSR[ 9 ] = CP15_reg1_EEbit
if high vectors configured then
PC = 0xFFFF0018
else
PC = 0x00000018
软件建议
To return after servicing the interrupt, use:
SUBS PC, R14, #4
软件
ldr pc, _irq
_irq: . word irq
. globl IRQ_STACK_START_IN
IRQ_STACK_START_IN:
. word 0x0badc0de
irq:
get_bad_stack
-- -- irq mode
ldr r13, IRQ_STACK_START_IN @ setup our mode stack
str lr, [ r13] @ save caller lr in position 0 of saved stack
mrs lr, spsr @ get the spsr
str lr, [ r13, #4 ] @ save spsr in position 1 of saved stack
mov r13, #0x13 @ prepare SVC- Mode
@ msr spsr_c, r13
msr spsr, r13 @ switch modes, make sure moves will execute
-- -- - Supervisor mode
mov lr, pc @ capture return pc
movs pc, lr @ jump to next instruction & switch modes.
bad_save_user_regs
. macro bad_save_user_regs
@ carve out a frame on current user stack
sub sp, sp, #72
stmia sp, { r0 - r12} @ Save user registers ( now in svc mode) r0- r12
ldr r2, IRQ_STACK_START_IN
@ get values for "aborted" pc and cpsr ( into parm regs)
ldmia r2, { r2 - r3}
add r0, sp, #72 @ grab pointer to old stack
add r5, sp, #52
mov r1, lr
stmia r5, { r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
mov r0, sp @ save current stack into r0 ( param register )
. endm
bl do_irq
struct pt_regs {
long uregs[ 18 ] ;
} ;
#define ARM_cpsr uregs[16]
#define ARM_pc uregs[15]
#define ARM_lr uregs[14]
#define ARM_sp uregs[13]
#define ARM_ip uregs[12]
#define ARM_fp uregs[11]
#define ARM_r10 uregs[10]
#define ARM_r9 uregs[9]
#define ARM_r8 uregs[8]
#define ARM_r7 uregs[7]
#define ARM_r6 uregs[6]
#define ARM_r5 uregs[5]
#define ARM_r4 uregs[4]
#define ARM_r3 uregs[3]
#define ARM_r2 uregs[2]
#define ARM_r1 uregs[1]
#define ARM_r0 uregs[0]
#define ARM_ORIG_r0 uregs[17]
void do_irq ( struct pt_regs * pt_regs)
{
efi_restore_gd ( ) ;
printf ( "interrupt request\n" ) ;
fixup_pc ( pt_regs, - 8 ) ;
uint32_t pc = ( ( ( ( regs) -> uregs[ 15 ] ) & ~ 0 ) ) + offset;
regs-> uregs[ 15 ] = pc | ( regs-> uregs[ 15 ] & 0 ) ;
show_regs ( pt_regs) ;
show_efi_loaded_images ( pt_regs) ;
bad_mode ( ) ;
panic ( "Resetting CPU ...\n" ) ;
reset_cpu ( 0 ) ;
}