本篇主要分析IDT的初始化流程。
IDT简介
IDT——interrupt description table,用来描述中断异常向量,表中的每一个entry对应一个向量。
IDT entry:
每个entry为8bytes,有以下关键bit:
16~31:code segment selector
0~15 & 46-64:segment offset (根据以上两项可确定中断处理函数的地址)
Type:区分中断门、陷阱门、任务门等
DPL:Descriptor Privilege Level, 访问特权级
P:该描述符是否在内存中
desc_struct :
kernel中描述IDT entry的数据结构为
87 typedef struct desc_struct gate_desc;
14 /*
15 * FIXME: Accessing the desc_struct through its fields is more elegant,
16 * and should be the one valid thing to do. However, a lot of open code
17 * still touches the a and b accessors, and doing this allow us to do it
18 * incrementally. We keep the signature as a struct, rather than an union,
19 * so we can get rid of it transparently in the future -- glommer
20 */
21 /* 8 byte segment descriptor */
22 struct desc_struct {
23 union {
24 struct {
25 unsigned int a;
26 unsigned int b;
27 };
28 struct {
29 u16 limit0;
30 u16 base0;
31 unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
32 unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
33 };
34 };
35 } __attribute__((packed));
idt_table:
kernel中描述IDT:
77 /* Must be page-aligned because the real IDT is used in a fixmap. */
78 gate_desc idt_table[NR_VECTORS] __page_aligned_bss;
初始化IDT
setup_once:
第一次初始化,通过汇编形式,这里应该是设置特权级别和code segment?对汇编就不做太多研究了。
470 /*
471 * setup_once
472 *
473 * The setup work we only want to run on the BSP.
474 *
475 * Warning: %esi is live across this function.
476 */
477 __INIT
478 setup_once:
479 /*
480 * Set up a idt with 256 interrupt gates that push zero if there
481 * is no error code and then jump to early_idt_handler_common.
482 * It doesn't actually load the idt - that needs to be done on
483 * each CPU. Interrupts are enabled elsewhere, when we can be
484 * relatively sure everything is ok.
485 */
486
487 movl $idt_table,%edi
488 movl $early_idt_handler_array,%eax
489 movl $NUM_EXCEPTION_VECTORS,%ecx
490 1:
491 movl %eax,(%edi)
492 movl %eax,4(%edi)
493 /* interrupt gate, dpl=0, present */
494 movl $(0x8E000000 + __KERNEL_CS),2(%edi)
495 addl $EARLY_IDT_HANDLER_SIZE,%eax
496 addl $8,%edi
497 loop 1b
498
499 movl $256 - NUM_EXCEPTION_VECTORS,%ecx
500 movl $ignore_int,%edx
501 movl $(__KERNEL_CS << 16),%eax
502 movw %dx,%ax /* selector = 0x0010 = cs */
503 movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
504 2:
505 movl %eax,(%edi)
506 movl %edx,4(%edi)
507 addl $8,%edi
508 loop 2b
early_trap_init:
第二次初始化,通过early_trap_init和trap_init初始化IDT中kernel保留的vector,比如前32个vector和system call(0x80)等。系统保留的向量和set_intr_gate等分析见附录。