一. 中断描述符表
在实模式下,CPU 把中从 0 开始到 1K 的空间作为一个中断向量表,每个表项占 4 个字节,两个字节的段地址和两个字节的偏移量组成,这样就可以找到处理程序的入口地址。
但在保护模式下,中断向量表的表项由8个字节组成。也叫中断描述表,其中的每个表项叫做门描述符
门类型主要分为:
1.中断门(110) : 中断门包含了一个或异常处理程序所在段的符和偏移量。当控制权通过中断门进入中断控制程序时,处理器清IF标志关闭中断,避免了嵌套中断的发生。
中断门的请求特权级为0因此用户太的进程不能访问中断,所用的中断处理程序都由中断门激活,并全部限制在内核态
2.陷阱门(111):与中断门类似,唯一的区别是控制权通过陷阱门进入处理程序时IF 位不变,即不关闭中断。
3.系统门:linux内核特别设置的,用来让用户态进程,访问Intel 的陷阱门。DPL为3.
在保护模式下。中断描述符表可以放在内存的任何位置。CPU 设计了一个中断描述符表寄存器,用来存中断描述符表在内存中的位置。
中断描述表寄存器是一个48 位的寄存器,低 16 位用来保存中断描述符表的大小,高 32 位用来存放中断描述符表的基址。
二。初始化:
init/main.c
- 536 asmlinkage void __init start_kernel(void){
- ...
- 592 trap_init();
- ...
- }
start_kernel() 函数在linux内核启动后做一些初始化的工作,而 trap_init() 函数主要完成中断的初始化。
arch/x86/kernel/traps.c
- #define SYSCALL_VECTOR 0x80
- ...
- 891 void __init trap_init(void){
- ...
- 954 set_system_trap_gate(SYSCALL_VECTOR, &system_call);
- 955 set_bit(SYSCALL_VECTOR, used_vectors);
- ...
- }
通过函数 set_system_trap_gate() 来实现插入一个
arch/x86/include/asm/desc.h
- 365 static inline void set_system_trap_gate(unsigned int n, void *addr)
- 366 {
- 367 BUG_ON((unsigned)n > 0xFF);
- 368 _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
- 369 }
n : 0x80 门号。表示在IDT的第n个表项插入一个系统门GATE_TRAP : 0xF 表示32位陷阱门
addr:偏移量,表示异常处理程序的地址addr
第四个参数0x3: 表示特权级为3
BUG_ON():
arch/mips/include/asm/bug.h
- 21 static inline void __BUG_ON(unsigned long condition)
- 22 {
- 23 if (__builtin_constant_p(condition)) {
- 24 if (condition)
- 25 BUG();
- 26 else
- 27 return;
- 28 }
- 29 __asm__ __volatile__("tne $0, %0, %1" : : "r" (condition), "i" (BRK_BUG));
- 30 }
- 31
- 32 #define BUG_ON(C) __BUG_ON((unsigned long)(C))
BUG_ON((unsigned)n > 0xFF)是用来判断 n是不是大于255
阅读(1579) | 评论(0) | 转发(0) |