中断系统的初始化时由start_kernel调用setup_arch进行平台体系(处理器芯片)相关的初始化,然后复制中断向量表到内存中并对irq进行初始化:
/* init/main.c */
asmlinkage void __init start_kernel(void)
{
……
[1]setup_arch(&command_line);
……
[2]trap_init();
……
[3]init_IRQ();
……
}
代码[1]:进入setup_arch()函数中并调用了early_irq_init()函数代码[2]:复制中断向量表到内存地址CONFIG_VECTORS_BASE
代码[3]: init_IRQ对irq进行初始化时,又调用了init_arch_irq对于具体平台体系的中断进行初始化。而init_arch_irq是在start_kernel里调用setup_arch函数设定的
1.分析setch_arch()函数中调用的early_irq_init()函数:
void __init setup_arch(char **cmdline_p)
{#ifdef CONFIG_MULTI_IRQ_HANDLER
handle_arch_irq = mdesc->handle_irq;
#endif
......
early_trap_init();
if (mdesc->init_early)
mdesc->init_early();
}
---------------------------------------------------分割线
int __init early_irq_init(void)
{
struct irq_desc *desc;
int count;
int i;
init_irq_default_affinity();
printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
desc = irq_desc;
count = ARRAY_SIZE(irq_desc);
for (i = 0; i < count; i++) {
desc[i].irq = i;
alloc_desc_masks(&desc[i], 0, true);
init_desc_masks(&desc[i]);
desc[i].kstat_irqs = kstat_irqs_all[i];
}
return arch_early_irq_init();
}
该函数主要工作即为初始化用于管理中断的irq_desc[NR_IRQS]数组的每个元素,它主要设置数组中每一个成员的中断号,使得数组中每一个元素的kstat_irqs字段(irq stats per cpu),指向定义的二维数组中的对应的行。alloc_desc_masks(&desc[i], 0, true)和init_desc_masks(&desc[i])函数在非SMP平台上为空函数。arch_early_irq_init()在主要用于x86平台和PPC平台,其他平台上为空函数。
2. trap_init()拷贝中断向量表到高地址,并让cpu发生中断时在高端寻址
调用trap_init()前,先列出相关的中断向量表:
/*_ arch/arm/kernel/entry-armv.S */中断向量表
_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
.globl __vectors_end
__vectors_end:
2.1进行中断向量表的拷贝:
/* linux/arch/arm/kernel/traps.c */
void __init trap_init(void)
{
unsigned long vectors = CONFIG_