3、linux中断中(异常向量详解)
中断程序完成了从asm代码到C代码的传递,并且获得了引起中断的IRQ编号
中断向量表在arch/arm/kernel/entry_armv.S
中定义
代码被分为两部分:
第一部分是真正的向量跳转表,位于__vectors_start
和__vectors_end
之间;
第二部分是处理跳转的部分,位于__stubs_start
和__stubs_end
之间;
.globl __stubs_start
__stubs_start:
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)
vector_stub dabt, ABT_MODE, 8
.long __dabt_usr @ 0 (USR_26 / USR_32)
.long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
.long __dabt_invalid @ 2 (IRQ_26 / IRQ_32)
.long __dabt_svc @ 3 (SVC_26 / SVC_32)
vector_fiq:
disable_fiq
subs pc, lr, #4
......
.globl __stubs_end
__stubs_end:
.equ stubs_offset, __vectors_start + 0x200 - __stubs_start
.globl __vectors_start
__vectors_start:
ARM( swi SYS_ERROR0 )
THUMB( svc #0 )
THUMB( nop )
W(b) vector_und + stubs_offset
W(ldr) pc, .LCvswi + stubs_offset
W(b) vector_pabt + stubs_offset
W(b) vector_dabt + stubs_offset
W(b) vector_addrexcptn + stubs_offset
W(b) vector_irq + stubs_offset
W(b) vector_fiq + stubs_offset
.globl __vectors_end
__vectors_end:
中断向量表的使用:
1. 首先,在setup_arch
函数中,early_trap_init
被调用,其中完成了中断向量的拷贝和重定位工作。
void __init early_trap_init(void)
{
......
/*
* Copy the vectors, stubs and kuser helpers (in entry-armv.S)
* into the vector page, mapped at 0xffff0000, and ensure these
* are visible to the instruction stream.
*/
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
......
}
两个memcpy
会把__vectors_start
开始的代码拷贝到0xffff0000处,把__stubs_start
开始的代码拷贝到0xFFFF0000+0x200处,这样,异常中断到来时,CPU
就可以正确地跳转到相应中断向量入口并执行他们。
然后,
start_kernel
发出early_irq_init
调用,early_irq_init
属于与硬件和平台无关的通用逻辑层,它完成irq_desc
结构的内存申请,为它们其中某些字段填充默认值,完成后调用体系相关的arch_early_irq_init
函数完成进一步的初始化工作,不过ARM
体系没有实现arch_early_irq_init
。接着,
start_kernel
发出init_IRQ
调用,它会直接调用所属板子machine_desc
结构体中的init_irq
回调。machine_desc
通常在板子的特定代码中,使用MACHINE_START和MACHINE_END
宏进行定义。machine_desc->init_irq()
完成对中断控制器的初始化,为每个irq_desc
结构安装合适的流控handler
,为每个irq_desc
结构安装irq_chip
指针,使他指向正确的中断控制器所对应的irq_chip
结构的实例,同时,如果该平台中的中断线有多路复用(多个中断公用一个irq
中断线)的情况,还应该初始化irq_desc
中相应的字段和标志,以便实现中断控制器的级联。