首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

linux下X86架构IDT解析(4)

linux下X86架构IDT解析(4)

769


770

#ifdef CONFIG_X86_32771


set_system_trap_gate(SYSCALL_VECTOR, &system_call);772


set_bit(SYSCALL_VECTOR, used_vectors);773

#endif774


775


/*776


* Set the IDT descriptor to a fixed read-only location, so that

* the "sidt" instruction will not leak the location of the kernel, and
778


* to defend the IDT against arbitrary memory write vulnerabilities.
779


* It will be reloaded in cpu_init() */
780


__set_fixmap(FIX_RO_IDT, __pa_symbol(idt_table), PAGE_KERNEL_RO);781


idt_descr.address = fix_to_virt(FIX_RO_IDT);782


783


/*784


* Should be a barrier for any external CPU state:
785


*/
786


cpu_init();787


788


x86_init.irqs.trap_init();789


795

}
        3.对剩余表项的初始化由init_IRQ()完成。init_IRQ()通过调用native_init_IRQ()函数完成初始化。
void __init
native_init_IRQ(void)193

{194


int i;195


196


/* Execute any quirks before the call gates are initialised: */197


x86_init.irqs.pre_vector_init();198


199


apic_intr_init();200


201


/*202


* Cover the whole vector space, no vector can escape
203


* us. (some of these will be overridden and become
204


* 'special' SMP interrupts)
205


*/
206


i = FIRST_EXTERNAL_VECTOR;207


for_each_clear_bit_from(i, used_vectors, NR_VECTORS) {
/* IA32_SYSCALL_VECTOR could be used in trap_init already. */
209


set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);210


}211


212


if (!acpi_ioapic && !of_ioapic)213


setup_irq(2, &irq2);214


215

#ifdef CONFIG_X86_32216


irq_ctx_init(smp_processor_id());217

#endif218

}        可以看出调用set_intr_gate()将剩下的233项全部初始化为中断门。其中的NR_VECTOR为256,FIRST_EXTERNAL_VECTOR为0x20(也就是32),所以循环共进行224次,其中当要初始化的中断号等于SYSCALL_VECTOR(系统调用中断号)时,就跳过,所以也就是前面说的初始化剩下的223项。现在的关键是给这些中断的处理程序是什么?这又要说到interrupt数组了。该数组定义在arch/x86_64/kernel/i8259.c中:
        #define IRQ(x,y)
IRQ##x##y##_interrupt

        #define IRQLIST_16(x) \

        IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \

        IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \

        IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \

        IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
       

        /* for the irq vectors */

        static void (*interrupt[NR_VECTORS - FIRST_EXTERNAL_VECTOR])(void) = {

        IRQLIST_16(0x2), IRQLIST_16(0x3),

        IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),

        IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),

        IRQLIST_16(0xc), IRQLIST_16(0xd), IRQLIST_16(0xe), IRQLIST_16(0xf)

        };
        现在结合native_init_IRQ()分析一下。当进行第一次循环也就是i=0的时候,vector=32,所以set_intr_gate()的调用是:
        set_intr_gate(32,interrupt[0]);
        对应的是:

        IRQLIST_16(0x2)
        --->IRQ(0x2,0)
       
|--->IRQ0x20_interrupt()
        这样就将IRQ0x20_interrupt()设置为0x20中断的处理程序了。
        下来我们看看这些IRQn_interrupt()(n=0x20~0xff)是如何建立的。
        #define BUILD_IRQ(nr) \
        asmlinkage void IRQ_NAME(nr); \
        __asm__( \
        "\n.p2align\n" \
        "IRQ" #nr "_interrupt:\n\t" \
        "push $~(" #nr ") ; " \
        "jmp common_interrupt");
        common_interrupt是一个汇编标号,在它里面会调用do_IRQ()函数去处理中断。
继承事业,薪火相传
返回列表