标题:
linux下X86架构IDT解析(4)
[打印本页]
作者:
yuyang911220
时间:
2015-7-30 18:57
标题:
linux下X86架构IDT解析(4)
769
770
#ifdef CONFIG_X86_32
771
set_system_trap_gate
(
SYSCALL_VECTOR
, &
system_call
);
772
set_bit
(
SYSCALL_VECTOR
,
used_vectors
);
773
#endif
774
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_32
216
irq_ctx_init
(
smp_processor_id
());
217
#endif
218
}
可以看出调用
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()函数去处理中断。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0