中断之中断向量表IDT的初始化

本文详细介绍了中断向量表IDT的初始化过程,包括在trap_init中完成的系统保留中断向量初始化和在init_IRQ中进行的其他中断向量初始化。内容涉及到设置中断门、陷阱门、GDT、DPL等概念,并解析了相关函数和结构,如_set_gate、intr_init和interrupt数组的作用。
摘要由CSDN通过智能技术生成

中断的初始化是在哪里完成的呢?是在start_kernel()中:

512	trap_init();

535    /* init some links before init_ISA_irqs() */
536    early_irq_init();
537    init_IRQ(); //最终调用native_init_IRQ,由它来完成主要工作。



中断向量表的初始化分为两个部分:

(1)对0~19号和0x80号系统保留中断向量的初始化,在trap_init中完成

(2)对其它中断向量的初始化,在init_IRQ中完成。

我们首先来看对系统保留中断向量的初始化,这部分的初始化工作实在trap_init中完成的:

void __init trap_init(void)
{
	int i;

#ifdef CONFIG_EISA
	void __iomem *p = early_ioremap(0x0FFFD9, 4);

	if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
		EISA_bus = 1;
	early_iounmap(p, 4);
#endif

	set_intr_gate(0, ÷_error);
	set_intr_gate_ist(2, &nmi, NMI_STACK);
	/* int4 can be called from all */
	set_system_intr_gate(4, &overflow);
	set_intr_gate(5, &bounds);
	set_intr_gate(6, &invalid_op);
	set_intr_gate(7, &device_not_available);
#ifdef CONFIG_X86_32
	set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS);
#else
	set_intr_gate_ist(8, &double_fault, DOUBLEFAULT_STACK);
#endif
	set_intr_gate(9, &coprocessor_segment_overrun);
	set_intr_gate(10, &invalid_TSS);
	set_intr_gate(11, &segment_not_present);
	set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK);
	set_intr_gate(13, &general_protection);
	set_intr_gate(15, &spurious_interrupt_bug);
	set_intr_gate(16, &coprocessor_error);
	set_intr_gate(17, &alignment_check);
#ifdef CONFIG_X86_MCE
	set_intr_gate_ist(18, &machine_check, MCE_STACK);
#endif
	set_intr_gate(19, &simd_coprocessor_error);

	/* Reserve all the builtin and the syscall vector: */
	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
		set_bit(i, used_vectors);

#ifdef CONFIG_IA32_EMULATION
	set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
	set_bit(IA32_SYSCALL_VECTOR, used_vectors);
#endif

#ifdef CONFIG_X86_32
	set_system_trap_gate(SYSCALL_VECTOR, &system_call);
	set_bit(SYSCALL_VECTOR, used_vectors);
#endif

	/*
	 * Should be a barrier for any external CPU state:
	 */
	cpu_init();

	x86_init.irqs.trap_init();  //这个是什么意思呢?好像跟虚拟机有关,我们不用关注。
}

    程序中首先设置中断向量表的头19个陷阱门,这些中断向量表都是CPU保留用于异常处理的。 

接着,有这样的操作:

	/* Reserve all the builtin and the syscall vector: */
	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
		set_bit(i, used_vectors);

系统设置了一个位图used_vectors,来表示每个中断向量表的使用情况,FIRST_EXTERNAL_VECTOR = 20,可以看到,这里是将前20(0~19)个向量表项对应的位图设置为1,表示已经被占用了。

紧接着:

	set_system_trap_gate(SYSCALL_VECTOR, &system_call);
初始化系统调用向量。SYS_CALL_VECTOR = 0x80。这里有一个这样的问题,为什么用的是set_system_trap_gate,而不是像2.4那样用set_system_gate呢?我们可以将系统调用看成是trap,因为它同样要陷入内核空间,可以这样理解,当陷入陷阱时,EIP指向的是下一条指令,而当故障(fault)发生时,EIP指向当前指令,当异常发生时,EIP的指向是不固定的,因此想想系统调用后EIP的变化,它必然是属于陷阱范畴的。


接下来,看这样一个操作cpu_init()

/*
 * cpu_init() initializes state that is per-CPU. Some data is already
 * initialized (naturally) in the bootstrap process, such as the GDT
 * and IDT. We reloa
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值