基于i386的Linux实现特点剖析——关于中断
来源:Linux-cn.com
作者:Webmaster
时间:2007-05-05
点击:
[ 收藏] [ 投稿]
三、Linux下中断管理的实现
1.中断向量表IDT的初始化
Linux内核在初始化阶段完成了对页式虚拟管理的初始化以后,便调用trap_init()和init_IRQ()两个函数进行中断机制的初始化。其中trap_init()主要是对一些系统保留的中断向量的初始化,而init_IRQ()则主要是用于外设的中断。
void _init trap_init(void)
{
#ifdef CONFIG_EISA
if (isa_readl(0x0FFFD9) ==
'E+('I'<<8)+('S'<<16)+('A'<<24))
EISA_bus = 1;
#endif
set_trap_gate(0,÷_error);
set_trap_gate(1,&debug);
set_intr_gate(2,&nmi);
set_system_gate(3,&int3); /*int3-5 can be called from all */
set_system_gate(4,&overflow);
set_system_gate(5,&bounds);
set_trap_gate(6,&invalid_op)
set_trap_gate(7,device_not_available);
set_trap_gate(8,&double_fault);
set_trap_gate(9,&coprocessor_segment_overrun);
set_trap_gate(10,&invalid_TSS);
set_trap_gate(11,&segment_not_present);
set_trap_gate(12,&stack_segment);
set_trap_gate(13,&general_protection);
set_trap_gate(14,&page_fault);
set_trap_gate(15,&spurious_interrupt_bug);
set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check);
set_trap_gate(18,&machine_check);
set_trap_gate(19,&simd_coprocessor_error);
set_system_gate(SYSCALL_VECTOR,&system_call);
/*
* default LDT is a single_entry callgate to lcall7 for iBCS
* and a callgate to lcall27 for Solaris/x86 binaries
*/
set_call_gate(&default_ldt[0],lcall7);
set_call_gate(&default_ldt[4],lcall27);
/*
_set_gate(a,12,3,addr);
//12 即1100b,类型码为100,即调用门
}
|
这些函数都调用同一个子程序_set_gate(),第一个参数用以设置中断描述符表idt_table中的第n项,第二个参数对应于门格式中的D位加类型位段,第三个参数是对应的DPL位段。
#define _set_gate(gate_addr,type,dpl,addr)
do {
int _d0,_d1;
_asm_ _volatile_("movw %%dx,%%ax
")
"movw %4,%%dx
"
"mov1 %%eax,%0
"
"mov1 %%edx,%1"
:"=m" (*((long * ) (gate_addr))),
"=m" (*(1+(long *)(gate_addr))),"=&a" (_d0),"=&d" (_d1)
:"i" ((short) (0x8000+(dpl<<13)+(type<<8))),
"3" ((char *) (addr)),"2" (_KERNEL_CS << 16));
}while(0)
|
在第一个“:”到第二个“:”之间为输出部,有四个约束输出,将有四个变量会被改变,分别为%0、%1、%2和%3相结合。其中%0和%1都是内存单元,分别和gate_addr、gate_addr+1结合,%2于局部变量_d0结合,存放在寄存器%%eax中;%3于局部变量_d1结合,存放在寄存器%%edx中。
第二个“:”之后的部分是输入部,输出部已经定义了%0-%3,输入部中的第一个变量为%4,而紧接着的第二、第三个变量分别等价于输出部的%3和%2。输入部中说明的个输入变量地值,包括%3和%2,都会在引用这些变量之前设置好。在执行指令部的代码之前,会先将%%eax设成(_KERNEL_CS<<16),把%%edx设为addr,%4变量设置为(0x8000+(dpl<<13)+type<<8),则%4变量对应于门结构中的第32-47位,其P位为1。
有表格
指令部第一条指令“movw %%dx,%%ax”,将%%dx的低16位移入%%ax的低16位,这样,在%%eax中,其高16位为_KERNEL_CS,而低16位为addr的低16位,形成了门结构中的第0-31位。
第二条指令“movx %4 ,%%dx”,将%4放入%%dx中,也就是将门结构中的第32-47位放在%%dx中,而对于%%edx而言,就对应着门结构中的高32位。
第三条指令“mov1 %%eax,%0”,将%%edx写入变量%0中,即*gate_addr。
第四条指令“mov1 %%eax,%1”将%%edx写入变量%1中,即*(gate_addr+1)。
将第三、第四条指令和起来看,就是将整个门结构的内容都写道*gate_addr中去了。
void _inti init_IRQ(void)
{
int i;
#ifndef CONFIG_X86_VISWS-APIC
init_ISA_irqs();
#else
init_VISWS_APIC_irqs();
#endif
/*
* Cover the whole vector space,no vector can escape
* us. (some of these will be overridden and become
* 'special' SMP interrupts)
*/
for (i=0;i< NR_IRQS;i++) {
int vector = FIRST_EXTERNAL_VECTOR + i;
if (vector != SYSCALL_VECTOR)
set_intr_gate(vector,interrupt[i]);
}
#ifdef CONFIG_SMP
/*
* IRQ0 must ve given a fixed assignment and initialized,
* because it's used before the I0-APIC is set up.
*/
set_intr-gate(FIRST_DEVICE_VECTOR,interrupt[0]);
/*
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
* IPI,driven by wakeup.
*/
set_intr_gate(RESCHEDULE_VECTOR,reschedule_interrupt);
/* IPI for generic function call */
set_intr_gate(CALL_FUCTION_VECTOR,call_funtion_interrupt);
#endif
#ifdef CONFIG_X86_LOCAL_APIC
/* IPI vectors for APIC spurious and error interrupts */
set_intr_gate(SPURIOUS_APIC_VECTOR,spurious_interrupt);
set_intr_gate(ERROR_APIC_VECTOR,error_interrupt);
#endif
/*
* Set the clock to HZ Hz, we already have a valid
* vector now;
*/
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB ,ch 0*/
outb_p(LATCH & 0xff,0x40); /* LSB */
outb(LATCH >> 8, 0x40); /* MSB */
#ifndef CONFIG_VISWS
setup_irq(2, &irq2)
#endif
/*
* External FPU? Set up irq13 if so,for
* original braindamaged IBM FERR coupling.
*/
if (boot_cpu_data.hard_math && !cpu_has_fpu)
setup_irq(13,&irq13);
如果您对本文有任何疑问或者建议,请到讨论区发表您的意见:
>>
论坛入口 <<
上一篇:基于i386的Linux实现特点剖析——基础的基础
下一篇:基于i386体系结构的Linux实现特点剖析——内存与进程
【文章评论】
【收藏本文】
【推荐好友】
【打印本文】
【我要投稿】 【论坛讨论】
更多相关文章
|
|
|