linux内核中断向量表,Linux内核中断之中断向量表IDT的初始化

本文详细解析了Linux内核中中断门(set_intr_gate)、系统中断门(set_system_intr_gate)、任务门(set_task_gate)及陷阱门(set_system_trap_gate)的设置过程。通过分析_set_gate函数及其内部实现细节,介绍了不同门类型之间的区别。

我们好像忘了很重要的东西:

(1)set_intr_gate

/*

* This needs to use 'idt_table' rather than 'idt', and

* thus use the _nonmapped_ version of the IDT, as the

* Pentium F0 0F bugfix can have resulted in the mapped

* IDT being write-protected.

*/

staticinlinevoidset_intr_gate(unsignedintn,void*addr)

{

BUG_ON((unsigned)n > 0xFF);

_set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);//设置中断门

}

(2)set_system_intr_gate

/*

* This routine sets up an interrupt gate at directory privilege level 3.

*/

staticinlinevoidset_system_intr_gate(unsignedintn,void*addr)

{

BUG_ON((unsigned)n > 0xFF);

_set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);//设置中断门

}

(3)set_task_gate

staticinlinevoidset_task_gate(unsignedintn, unsignedintgdt_entry)

{

BUG_ON((unsigned)n > 0xFF);

_set_gate(n, GATE_TASK, (void*)0, 0, 0, (gdt_entry<<3));//设置任务门

}

(4)set_system_trap_gate

staticinlinevoidset_system_trap_gate(unsignedintn,void*addr)

{

BUG_ON((unsigned)n > 0xFF);

_set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);//设置陷阱门

}

我们观察一下这几个函数,都是调用_set_gate,区别在于第二个和第四个参数。第二个参数对应于中断门或陷阱门格式中的D标志位加上类型位段;第四个参数对应于DPL。下面,我们来看一下_set_gate函数:

staticinlinevoid_set_gate(intgate, unsigned type,void*addr,

unsigned dpl, unsigned ist, unsigned seg)

{

gate_desc s;

pack_gate(&s, type, (unsignedlong)addr, dpl, ist, seg);

/*

* does not need to be atomic because it is only done once at

* setup time

*/

write_idt_entry(idt_table, gate, &s);

}

其第一个操作pack_gate():

staticinlinevoidpack_gate(gate_desc *gate, unsignedchartype,

unsignedlongbase, unsigned dpl, unsigned flags,

unsignedshortseg)

{

gate->a = (seg <

gate->b = (base & 0xffff0000) | (((0x80 | type | (dpl <

}

而wirte_idt_entry():

#define write_idt_entry(dt, entry, g)       native_write_idt_entry(dt, entry, g)

staticinlinevoidnative_write_idt_entry(gate_desc *idt,intentry,constgate_desc *gate)

{

memcpy(&idt[entry], gate,sizeof(*gate));

}

trap_init()中设置了一些为CPU保留专用的IDT表项以及系统调用所用的陷阱门以后,就进入init_IRQ()设置大量用于外设的通用中断门了:void__init init_IRQ(void)

{

inti;

/*

* We probably need a better place for this, but it works for

* now ...

*/

x86_add_irq_domains();

/*

* On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.

* If these IRQ's are handled by legacy interrupt-controllers like PIC,

* then this configuration will likely be static after the boot. If

* these IRQ's are handled by more mordern controllers like IO-APIC,

* then this vector space can be freed and re-used dynamically as the

* irq's migrate etc.

*/

for(i = 0; i nr_legacy_irqs; i++)

per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;

x86_init.irqs.intr_init();

}

这段内容在《情景分析》中有精彩的解释,但是我没有在3.0.4中找到合适的代码,不过想来应该是变化不大的,特别是基本的原理应该变化不大,因此就不费时讲解了。0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值