Chinaunix首页 | 论坛 | 博客
  • 博客访问: 568011
  • 博文数量: 99
  • 博客积分: 3976
  • 博客等级: 中校
  • 技术积分: 1041
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-15 15:48
文章分类
文章存档

2009年(1)

2008年(5)

2007年(31)

2006年(58)

2005年(4)

分类:

2007-03-08 11:45:30

知识难免有些遗漏,有经验的前辈看到请指点,我会尽量记下
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高,所以就没有办法通过.


阅读(1799) | 评论(0) | 转发(0) |
0

上一篇:socket例子实现

下一篇:昨天重装系统了!

给主人留下些什么吧!~~