ARM_cpsr
ARM_ORIG_r0
为什么要给r0赋值?因此kernel不想修改sp的值,保持sp指向栈顶。
E:在内核栈上保存剩余的寄存器的值,根据代码,依次是r0,PC,CPSR和orig r0。执行到这里,内核栈的布局如下图所示:

R0,PC和CPSR来自IRQ mode的stack。实际上这段操作就是从irq stack就中断现场搬移到内核栈上。
F:内核栈上还有两个寄存器没有保持,分别是发生中断时候sp和lr这两个寄存器。这时候,r0指向了保存PC寄存器那个地址(add r0, sp, #S_PC),stmdb r0, {sp, lr}^中的“db”是decrement before,因此,将sp和lr压入stack中的剩余的两个位置。需要注意的是,我们保存的是发生中断那一刻(对于本节,这是当时user mode的sp和lr),指令中的“^”符号表示访问user mode的寄存器。
(2)核心处理
irq_handler的处理有两种配置。一种是配置了CONFIG_MULTI_IRQ_HANDLER。这种情况下,linux kernel允许run time设定irq handler。如果我们需要一个linux kernel image支持多个平台,这是就需要配置这个选项。另外一种是传统的linux的做法,irq_handler实际上就是arch_irq_handler_default,具体代码如下:
.macro irq_handler
#ifdef CONFIG_MULTI_IRQ_HANDLER
ldr r1, =handle_arch_irq
mov r0, sp--------设定传递给machine定义的handle_arch_irq的参数
adr lr, BSYM(9997f)----设定返回地址
ldr pc, [r1]
#else
arch_irq_handler_default
#endif
9997:
.endm
对于情况一,machine相关代码需要设定handle_arch_irq函数指针,这里的汇编指令只需要调用这个machine代码提供的irq handler即可(当然,要准备好参数传递和返回地址设定)。
情况二要稍微复杂一些(而且,看起来kernel中使用的越来越少),代码如下:
.macro arch_irq_handler_default
get_irqnr_preamble r6, lr
1: get_irqnr_and_base r0, r2, r6, lr
movne r1, sp
@
@ asm_do_IRQ 需要两个参数,一个是 irq number(保存在r0)
@ 另一个是 struct pt_regs *(保存在r1中)
adrne lr, BSYM(1b)-------返回地址设定为符号1,也就是说要不断的解析irq状态寄存器
的内容,得到IRQ number,直到所有的irq number处理完毕
bne asm_do_IRQ
.endm
这里的代码已经是和machine相关的代码了,我们这里只是简短描述一下。所谓machine相关也就是说和系统中的中断控制器相关了。get_irqnr_preamble是为中断处理做准备,有些平台根本不需要这个步骤,直接定义为空即可。get_irqnr_and_base 有四个参数,分别是:r0保存了本次解析的irq number,r2是irq状态寄存器的值,r6是irq controller的base address,lr是scratch register。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-76601-9.html
奠定中东军政格局
面对的不光是日本还有美国
弟弟