我
们这里讨论ARM体系下的Linux中断处理的上下文切换部分的细节。我们只讨论底层汇编处理细节,不考虑上层。
首先,Linux的中断处理程序是经过搬移的,向量表和处理程序距离很近,这是在系统初始化的时候
就完成的。这个地方我们不做深入讨论。
Linux的向量表通过MMU安排在0xffff0000的位置,向量表如下:
.globl __vectors_start
__vectors_start:
swi SYS_ERROR0
b vector_und + stubs_offset
ldr pc, .LCvswi + stubs_offset
b vector_pabt + stubs_offset
b vector_dabt + stubs_offset
b vector_addrexcptn + stubs_offset
b vector_irq + stubs_offset
b vector_fiq + stubs_offset
其中stubs_offset定义为__vectors_start + 0x200 - __stubs_start。
这个__vectors_start就是刚才的这个向量表,而__stubs_start为中断处理程序的开始地址。
向量表在trap_init函数中建立,该函数在start_kernel中较后的位置被建立。
---------------------- --- __kuser_helper_end
/ \
| |
| | --- __kuser_helper_start -
| | |
------------------------ --- __stubs_end 0xe00
| | |
| | --- __stubs_start -
| | ^
| | |
------------------------ --- __vectos_end 0x200
| | |
| | vector 32字节 |
| | |
\ / |
---------------------- --- __vectors_start -
整个__stubs的代码如下:
.globl __stubs_start
__stubs_start:
/* 这些都是宏,IRQ_MODE等所有宏都在ptrace.h当中 */
vector_stub irq, IRQ_MODE, 4
.long __irq_usr @ 0 (USR_26 / USR_32)
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
.long __irq_invalid @ 2 (IRQ_26 / IRQ_32)
.long __irq_svc @ 3 (SVC_26 / SVC_32)
.long __irq_invalid @ 4
.long __irq_invalid @ 5
.long __irq_invalid @ 6
.long __irq_invalid @ 7
.long __irq_invalid @ 8
.long