ARM Linux 中断向量表建立流程
在看Linux内核对arm中的中断的初始化的时候,就一直对0xffff0000的地址有点怀疑,果然在网上发现这个地址不是随便写的,当我看到arm的协处理器进行控制,中断向量表的地址的时候,真的是哭笑不得啊!!
有人肯定会问?v位是什么时候设置的呢?其实仔细的朋友就知道在head.S中,在创建完页表的时候,如add pc,r10,#PROCINFO_INITFUNC
别急,r10保存在前面设置的procinfo的地址,但是很多人就觉得PROCINFO_INITFUNC的宏定义就不知道在哪找了,在include/asm/asm-offset.h中有定义。
这些搞懂了,首先必须将中断向量表拷贝到0xffff0000的地址上去,把中断处理函数也拷贝到0xffff0200的地址上去,那么在中断向量表进行跳转的时候,如b vector_irq+stubs_offset,但是stubs_offset的偏移怎么设置呢?如果用b vector_irq的话,它就会跳转到原先的中断处理函数中去,因为它也拷贝到了0xffff0200的地址上去,所以将__vector_start-_stubs_start+0x200的话就转移到拷贝后的地址上去执行了。
很多人应该会有点疑问吧,vector_irq好像找不到,别急,细心点,就在宏定义.macro vector_stubs,name,mode,correction中对各种处理函数有定义,所以很快就将中断向量表创建好了。
Linux Version : 2.6.29
1. start_kernel-->setup_arch-->early_trap_init
1: memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
2: memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
3: memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
对于第一行:
__vectors_start 和 __vectors_end 定义在 arch/arm/kernel/entry-armv.S , 它们之间保存了中断向量表。
1: .globl __vectors_start
2: __vectors_start:
3: swi SYS_ERROR0
4: b vector_und + stubs_offset
5: ldr pc, .LCvswi + stubs_offset
6: b vector_pabt + stubs_offset
7: b vector_dabt + stubs_offset
8: b vector_addrexcptn + stubs_offset
9: b vector_irq + stubs_offset
10: b vector_fiq + stubs_offset
11:
12: .globl __vectors_end
13: __vectors_end:
vectors 的地址为CONFIG_VECTORS_BASE , 在.config中定义为0xffff0000
所以 第1行就是把中断向量表拷贝到0xffff0000
对于第二行:
vector_stub是一个带参数的宏,第一个是name,第二个是arm excepiton mode,第三个是为了得到返回地址,lr需要减去的偏移
1: .macro vector_stub, name, mode, correction=0
2: .align 5
3:
4: vector_/name:
5: .if /correction
6: sub lr, lr, #/correction @得到正确的返回地址
7: .endif
8:
9: @
10: @ Save r0, lr_(parent PC) and spsr_
11: @ (parent CPSR)
12: @
13: stmia sp, {r0, lr} @ save r0, lr
14: mrs lr, spsr
15: str lr, [sp, #8] @ save spsr
16:
17: @
18: @ Prepare for SVC32 mode. IRQs remain disabled.
19: @
20: mrs r0, cpsr
21: eor r0, r0, #(/mode ^ SVC_MODE) @把cpsr内容与(mode^SVC_mode)异或,即r0里为SVC_MODE
22: msr spsr_cxsf, r0 @把r0的值写入整个spsr寄存器(cxsf表示要往哪个字节写入)
23:
24: @
25: @ the branch table must immediately follow this code
26: @
27: and lr, lr, #0x0f @lr为spsr_的值,此语句取到进入异常前的mode
28: mov r0, sp @
29: ldr lr, [pc, lr, lsl #2] @lr=pc+mode*4,其中pc为紧接着30的指令,即vector_stub后的第一条指令
30: movs pc, lr @ movs会把spsr的值赋给cpsr,所以branch to handler in SVC mode
31: ENDPROC(vector_/name)
32: .endm
ARMLinux中断向量 相关文章:
- ARM Linux中断向量表搬移设计过程(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)