diff options
Diffstat (limited to 'src/kernel/traps.c')
-rw-r--r-- | src/kernel/traps.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/src/kernel/traps.c b/src/kernel/traps.c new file mode 100644 index 0000000..3629a13 --- /dev/null +++ b/src/kernel/traps.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * linux/kernel/traps.c | ||
3 | * | ||
4 | * (C) 1991 Linus Torvalds | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * 'Traps.c' handles hardware traps and faults after we have saved some | ||
9 | * state in 'asm.s'. Currently mostly a debugging-aid, will be extended | ||
10 | * to mainly kill the offending process (probably by giving it a signal, | ||
11 | * but possibly by killing it outright if necessary). | ||
12 | */ | ||
13 | #include <string.h> | ||
14 | |||
15 | #include <linux/head.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/segment.h> | ||
20 | #include <asm/io.h> | ||
21 | |||
22 | #define get_seg_byte(seg,addr) ({ \ | ||
23 | register char __res; \ | ||
24 | __asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ | ||
25 | :"=a" (__res):"0" (seg),"m" (*(addr))); \ | ||
26 | __res;}) | ||
27 | |||
28 | #define get_seg_long(seg,addr) ({ \ | ||
29 | register unsigned long __res; \ | ||
30 | __asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ | ||
31 | :"=a" (__res):"0" (seg),"m" (*(addr))); \ | ||
32 | __res;}) | ||
33 | |||
34 | #define _fs() ({ \ | ||
35 | register unsigned short __res; \ | ||
36 | __asm__("mov %%fs,%%ax":"=a" (__res):); \ | ||
37 | __res;}) | ||
38 | |||
39 | int do_exit(long code); | ||
40 | |||
41 | void page_exception(void); | ||
42 | |||
43 | void divide_error(void); | ||
44 | void debug(void); | ||
45 | void nmi(void); | ||
46 | void int3(void); | ||
47 | void overflow(void); | ||
48 | void bounds(void); | ||
49 | void invalid_op(void); | ||
50 | void device_not_available(void); | ||
51 | void double_fault(void); | ||
52 | void coprocessor_segment_overrun(void); | ||
53 | void invalid_TSS(void); | ||
54 | void segment_not_present(void); | ||
55 | void stack_segment(void); | ||
56 | void general_protection(void); | ||
57 | void page_fault(void); | ||
58 | void coprocessor_error(void); | ||
59 | void reserved(void); | ||
60 | void parallel_interrupt(void); | ||
61 | void irq13(void); | ||
62 | |||
63 | static void die(char * str,long esp_ptr,long nr) | ||
64 | { | ||
65 | long * esp = (long *) esp_ptr; | ||
66 | int i; | ||
67 | |||
68 | printk("%s: %04x\n\r",str,nr&0xffff); | ||
69 | printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n", | ||
70 | esp[1],esp[0],esp[2],esp[4],esp[3]); | ||
71 | printk("fs: %04x\n",_fs()); | ||
72 | printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17)); | ||
73 | if (esp[4] == 0x17) { | ||
74 | printk("Stack: "); | ||
75 | for (i=0;i<4;i++) | ||
76 | printk("%p ",get_seg_long(0x17,i+(long *)esp[3])); | ||
77 | printk("\n"); | ||
78 | } | ||
79 | str(i); | ||
80 | printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i); | ||
81 | for(i=0;i<10;i++) | ||
82 | printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0]))); | ||
83 | printk("\n\r"); | ||
84 | do_exit(11); /* play segment exception */ | ||
85 | } | ||
86 | |||
87 | void do_double_fault(long esp, long error_code) | ||
88 | { | ||
89 | die("double fault",esp,error_code); | ||
90 | } | ||
91 | |||
92 | void do_general_protection(long esp, long error_code) | ||
93 | { | ||
94 | die("general protection",esp,error_code); | ||
95 | } | ||
96 | |||
97 | void do_divide_error(long esp, long error_code) | ||
98 | { | ||
99 | die("divide error",esp,error_code); | ||
100 | } | ||
101 | |||
102 | void do_int3(long * esp, long error_code, | ||
103 | long fs,long es,long ds, | ||
104 | long ebp,long esi,long edi, | ||
105 | long edx,long ecx,long ebx,long eax) | ||
106 | { | ||
107 | int tr; | ||
108 | |||
109 | __asm__("str %%ax":"=a" (tr):"0" (0)); | ||
110 | printk("eax\t\tebx\t\tecx\t\tedx\n\r%8x\t%8x\t%8x\t%8x\n\r", | ||
111 | eax,ebx,ecx,edx); | ||
112 | printk("esi\t\tedi\t\tebp\t\tesp\n\r%8x\t%8x\t%8x\t%8x\n\r", | ||
113 | esi,edi,ebp,(long) esp); | ||
114 | printk("\n\rds\tes\tfs\ttr\n\r%4x\t%4x\t%4x\t%4x\n\r", | ||
115 | ds,es,fs,tr); | ||
116 | printk("EIP: %8x CS: %4x EFLAGS: %8x\n\r",esp[0],esp[1],esp[2]); | ||
117 | } | ||
118 | |||
119 | void do_nmi(long esp, long error_code) | ||
120 | { | ||
121 | die("nmi",esp,error_code); | ||
122 | } | ||
123 | |||
124 | void do_debug(long esp, long error_code) | ||
125 | { | ||
126 | die("debug",esp,error_code); | ||
127 | } | ||
128 | |||
129 | void do_overflow(long esp, long error_code) | ||
130 | { | ||
131 | die("overflow",esp,error_code); | ||
132 | } | ||
133 | |||
134 | void do_bounds(long esp, long error_code) | ||
135 | { | ||
136 | die("bounds",esp,error_code); | ||
137 | } | ||
138 | |||
139 | void do_invalid_op(long esp, long error_code) | ||
140 | { | ||
141 | die("invalid operand",esp,error_code); | ||
142 | } | ||
143 | |||
144 | void do_device_not_available(long esp, long error_code) | ||
145 | { | ||
146 | die("device not available",esp,error_code); | ||
147 | } | ||
148 | |||
149 | void do_coprocessor_segment_overrun(long esp, long error_code) | ||
150 | { | ||
151 | die("coprocessor segment overrun",esp,error_code); | ||
152 | } | ||
153 | |||
154 | void do_invalid_TSS(long esp,long error_code) | ||
155 | { | ||
156 | die("invalid TSS",esp,error_code); | ||
157 | } | ||
158 | |||
159 | void do_segment_not_present(long esp,long error_code) | ||
160 | { | ||
161 | die("segment not present",esp,error_code); | ||
162 | } | ||
163 | |||
164 | void do_stack_segment(long esp,long error_code) | ||
165 | { | ||
166 | die("stack segment",esp,error_code); | ||
167 | } | ||
168 | |||
169 | void do_coprocessor_error(long esp, long error_code) | ||
170 | { | ||
171 | if (last_task_used_math != current) | ||
172 | return; | ||
173 | die("coprocessor error",esp,error_code); | ||
174 | } | ||
175 | |||
176 | void do_reserved(long esp, long error_code) | ||
177 | { | ||
178 | die("reserved (15,17-47) error",esp,error_code); | ||
179 | } | ||
180 | |||
181 | void trap_init(void) | ||
182 | { | ||
183 | int i; | ||
184 | |||
185 | set_trap_gate(0,÷_error); | ||
186 | set_trap_gate(1,&debug); | ||
187 | set_trap_gate(2,&nmi); | ||
188 | set_system_gate(3,&int3); /* int3-5 can be called from all */ | ||
189 | set_system_gate(4,&overflow); | ||
190 | set_system_gate(5,&bounds); | ||
191 | set_trap_gate(6,&invalid_op); | ||
192 | set_trap_gate(7,&device_not_available); | ||
193 | set_trap_gate(8,&double_fault); | ||
194 | set_trap_gate(9,&coprocessor_segment_overrun); | ||
195 | set_trap_gate(10,&invalid_TSS); | ||
196 | set_trap_gate(11,&segment_not_present); | ||
197 | set_trap_gate(12,&stack_segment); | ||
198 | set_trap_gate(13,&general_protection); | ||
199 | set_trap_gate(14,&page_fault); | ||
200 | set_trap_gate(15,&reserved); | ||
201 | set_trap_gate(16,&coprocessor_error); | ||
202 | for (i=17;i<48;i++) | ||
203 | set_trap_gate(i,&reserved); | ||
204 | set_trap_gate(45,&irq13); | ||
205 | outb_p(inb_p(0x21)&0xfb,0x21); | ||
206 | outb(inb_p(0xA1)&0xdf,0xA1); | ||
207 | set_trap_gate(39,¶llel_interrupt); | ||
208 | } | ||