知识难免有些遗漏,有经验的前辈看到请指点,我会尽量记下
Linux/arch/i386/kernel/traps.c
代码在中得到
关于中断向量表:
初始化函数实现:
1119 void __init trap_init(void)
1120 {
1121 #ifdef CONFIG_EISA
1122 void __iomem *p = ioremap(0x0FFFD9, 4);
1123 if (readl(p) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) {
1124 EISA_bus = 1;
1125 }
1126 iounmap(p);
1127 #endif
1128
1129 #ifdef CONFIG_X86_LOCAL_APIC
1130 init_apic_mappings();
1131 #endif
1132
1133 set_trap_gate(0,÷_error);
1134 set_intr_gate(1,&debug);
1135 set_intr_gate(2,&nmi);
1136 set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
1137 set_system_gate(4,&overflow);
1138 set_trap_gate(5,&bounds);
1139 set_trap_gate(6,&invalid_op);
1140 set_trap_gate(7,&device_not_available);
1141 set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
1142 set_trap_gate(9,&coprocessor_segment_overrun);
1143 set_trap_gate(10,&invalid_TSS);
1144 set_trap_gate(11,&segment_not_present);
1145 set_trap_gate(12,&stack_segment);
1146 set_trap_gate(13,&general_protection);
1147 set_intr_gate(14,&page_fault);
1148 set_trap_gate(15,&spurious_interrupt_bug);
1149 set_trap_gate(16,&coprocessor_error);
1150 set_trap_gate(17,&alignment_check);
1151 #ifdef CONFIG_X86_MCE
1152 set_trap_gate(18,&machine_check);
1153 #endif
1154 set_trap_gate(19,&simd_coprocessor_error);
1155
1156 if (cpu_has_fxsr) {
1157 /*
1158
* Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
1159
* Generates a compile-time "error: zero width for bit-field" if
1160
* the alignment is wrong.
1161 */
1162 struct fxsrAlignAssert {
1163
int _:!(offsetof(struct task_struct,
1164
thread.i387.fxsave) & 15);
1165 };
1166
1167
printk(KERN_INFO "Enabling fast FPU save and restore... ");
1168 set_in_cr4(X86_CR4_OSFXSR);
1169 printk("done.\n");
1170 }
1171 if (cpu_has_xmm) {
1172
printk(KERN_INFO "Enabling unmasked SIMD FPU exception "
1173
"support... ");
1174
set_in_cr4(X86_CR4_OSXMMEXCPT);
1175 printk("done.\n");
1176 }
1177
1178 set_system_gate(SYSCALL_VECTOR,&system_call);
1179
1180 /*
1181 * Should be a barrier for any external CPU state.
1182 */
1183 cpu_init();
1184
1185 trap_init_hook();
1186 }
1187 从代码中看到中断向量表设置了20个,行1178
set_system_gate(SYSCALL_VECTOR,&system_call);是设置系统调用中断号,Linux下的是int
0x80,SYSCALL_VECTOR就是)0x80,这个宏定义在Linux/include/asm-i386/mach-
default/irq_vectors.h中:
31 #define SYSCALL_VECTOR 0x80
接下来说说前19个中断:
1,2,14号是中断门,3,4是系统调用,8号是任务,其他是trap门,这些的实现代码如下:
1085 * This needs to use 'idt_table' rather than 'idt', and
1086 * thus use the _nonmapped_ version of the IDT, as the
1087 * Pentium F0 0F bugfix can have resulted in the mapped
1088 * IDT being write-protected.
1089 */
1090 void set_intr_gate(unsigned int n, void *addr)
1091 {
1092 _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS);
1093 }
1094
1095 /*
1096 * This routine sets up an interrupt gate at directory privilege level 3.
1097 */
1098 static inline void set_system_intr_gate(unsigned int n, void *addr)
1099 {
1100 _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS);
1101 }
1102
1103 static void __init set_trap_gate(unsigned int n, void *addr)
1104 {
1105 _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS);
1106 }
1107
1108 static void __init set_system_gate(unsigned int n, void *addr)
1109 {
1110 _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS);
1111 }
1112
1113 static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
1114 {
1115 _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
1116 }
其中使用了一些宏:
52 #define DESCTYPE_TASK 0x85 /* present, system, DPL-0, task gate */
53 #define DESCTYPE_INT 0x8e /* present, system, DPL-0, interrupt gate */
54 #define DESCTYPE_TRAP 0x8f /* present, system, DPL-0, trap gate */
55 #define DESCTYPE_DPL3 0x60 /* DPL-3 */
_set_gate函数如下:
115 static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
116 {
117 __u32 a, b;
118 pack_gate(&a, &b, (unsigned long)addr, seg, type, 0);
119 write_idt_entry(idt_table, gate, a, b);
120 }
从函数实现中可以看出_set_gate中第一个参数是设置中断号,第二个参数是设置中断类型,第三个参数是调用地址,第四个参数是地址段.
地址段分为__KERNEL_CS,__KERNEL_DS,__USER_CS,_USER_DS,相关值来设置段寄存器的Index,TI,RPL三
个位.根据设置的类型来判断DPL,也就是判断级别,也就是说明了只有当外部中断或者CPU异常时中断门的DPL是忽略不计的,所以能穿过该中断,如果用
户在用户空间,也就是level3时,想用int 2是不可以的.因为level比kernel空间int的level高,所以就没有办法通过.
阅读(1835) | 评论(0) | 转发(0) |