| Interrupt, Trap, and System Gates | |||||||||
| Linux uses a slightly different breakdown and terminology from Intel | |||||||||
| when classifying the interrupt descriptors included in the Interrupt Descriptor Table: | |||||||||
| Interrupt gate | |||||||||
| An Intel interrupt gate that cannot be accessed by a User Mode process | |||||||||
| (the gate's DPL field is equal to 0). All Linux interrupt handlers are activated by means of | |||||||||
| interrupt gates , and all are restricted to Kernel Mode. | |||||||||
| System gate | |||||||||
| An Intel trap gate that can be accessed by a User Mode process (the gate's DPL field is equal to 3). | |||||||||
| The three Linux exception handlers associated with the vectors 4, 5, and 128 are activated | |||||||||
| by means of system gates , so the three assembly language instructions into , bound , | |||||||||
| and int $0x80 can be issued in User Mode. | |||||||||
| System interrupt gate | |||||||||
| An Intel interrupt gate that can be accessed by a User Mode process (the gate's DPL field is equal to 3). | |||||||||
| The exception handler associated with the vector 3 is activated by means of a system interrupt gate, | |||||||||
| so the assembly language instruction int3 can be issued in User Mode. | |||||||||
| Trap gate | |||||||||
| An Intel trap gate that cannot be accessed by a User Mode process (the gate's DPL field is equal to 0). | |||||||||
| Most Linux exception handlers are activated by means of trap gates | |||||||||
| Task gate | |||||||||
| An Intel task gate that cannot be accessed by a User Mode process (the gate's DPL field is equal to 0). | |||||||||
| The Linux handler for the "Double fault " exception is activated by means of a task gate. | |||||||||
| The following architecture-dependent functions are used to insert gates in the IDT | |||||||||
| set_intr_gate(n,addr) | //Inserts an interrupt gate in the n th IDT entry | ||||||||
| set_system_gate(n,addr) | |||||||||
| set_system_intr_gate(n,addr) | |||||||||
| set_trap_gate(n,addr) | |||||||||
| set_task_gate(n,gdt) | |||||||||
| //i386/kernel/traps.c | |||||||||
| static void __init set_system_gate(unsigned int n, void *addr) | |||||||||
| { | |||||||||
| _set_gate(idt_table+n,15,3,addr,__KERNEL_CS); | |||||||||
| } | |||||||||
| #define _set_gate(gate_addr,type,dpl,addr,seg) / | |||||||||
| do { / | |||||||||
| int __d0, __d1; / | |||||||||
| __asm__ __volatile__ ("movw %%dx,%%ax/n/t" / | |||||||||
| movw %4,%%dx/n/t / | |||||||||
| movl %%eax,%0/n/t / | |||||||||
| movl %%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" ((seg) << 16)); / | |||||||||
| } while (0) | |||||||||
| The IDT is initialized and used by the BIOS routines while the computer still operates in Real Mode. | |||||||||
| Once Linux takes over, however, the IDT is moved to another area of RAM | |||||||||
| and initialized a second time, because Linux does not use any BIOS routine | |||||||||
| //i386/kernel/head.s | |||||||||
| /* | |||||||||
| * setup_idt | |||||||||
| * | |||||||||
| * sets up a idt with 256 entries pointing to | |||||||||
| * ignore_int, interrupt gates. It doesn't actually load | |||||||||
| * idt - that can be done only after paging has been enabled | |||||||||
| * and the kernel moved to PAGE_OFFSET. Interrupts | |||||||||
| * are enabled elsewhere, when we can be relatively | |||||||||
| * sure everything is ok. | |||||||||
| */ | |||||||||
| setup_idt: | |||||||||
| lea ignore_int,%edx | |||||||||
| movl $(__KERNEL_CS << 16),%eax | |||||||||
| movw %dx,%ax | /* selector = 0x0010 = cs */ | ||||||||
| movw $0x8E00,%dx | /* interrupt gate - dpl=0, present */ | ||||||||
| lea idt_table,%edi | |||||||||
| mov $256,%ecx | |||||||||
| rp_sidt: | |||||||||
| movl %eax,(%edi) | |||||||||
| movl %edx,4(%edi) | |||||||||
| addl $8,%edi | |||||||||
| dec %ecx | |||||||||
| jne rp_sidt | |||||||||
| ret | |||||||||
| /* This is the default interrupt "handler" :-) */ | |||||||||
| int_msg: | |||||||||
| .asciz "Unknown interrupt/n" | |||||||||
| ALIGN | |||||||||
| ignore_int: | |||||||||
| cld | |||||||||
| pushl %eax | |||||||||
| pushl %ecx | |||||||||
| pushl %edx | |||||||||
| pushl %es | |||||||||
| pushl %ds | |||||||||
| movl $(__KERNEL_DS),%eax | |||||||||
| movl %eax,%ds | |||||||||
| movl %eax,%es | |||||||||
| pushl $int_msg | |||||||||
| call printk | |||||||||
| popl %eax | |||||||||
| popl %ds | |||||||||
| popl %es | |||||||||
| popl %edx | |||||||||
| popl %ecx | |||||||||
| popl %eax | |||||||||
| iret | |||||||||
| The ignore_int( ) handler should never be executed. The occurrence of "Unknown interrupt" | |||||||||
| messages on the console or in the log files denotes either a hardware problem | |||||||||
| (an I/O device is issuing unforeseen interrupts) or a kernel problem | |||||||||
| (an interrupt or exception is not being handled properly). | |||||||||
Understanding the linux kernel-ch4-Initializing the Interrupt Descriptor Table
最新推荐文章于 2026-08-18 22:02:00 发布
本文探讨了Linux中对Intel中断描述符表(IDT)的不同分类及实现方式,包括中断门、系统门、系统中断门、陷阱门和任务门等,并介绍了与之相关的体系结构依赖函数。

1532

被折叠的 条评论
为什么被折叠?



