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 */
/*
* �ڳ���asm.s�б�����һЩ״̬��������������Ӳ��������ϡ�Ŀǰ��Ҫ���ڵ���Ŀ�ģ�
* �Ժ���չ����ɱ�����Ľ��̣���Ҫ��ͨ������һ���źţ��������ҪҲ��ֱ��ɱ������
*/
13 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ڴ���ַ���������Ƕ�뺯����
14
15 #include <linux/head.h> // headͷ�ļ��������˶��������ļṹ���ͼ���ѡ���������
16 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct����ʼ����0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
17 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
18 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
19 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
20 #include <asm/io.h> // ����/���ͷ�ļ�������Ӳ���˿�����/���������䡣
21
// ������䶨��������Ƕ��ʽ������亯�����й�Ƕ��ʽ���Ļ�������������б����˵����
// ��Բ������ס�������䣨�������е���䣩������Ϊ����ʽʹ�ã���������__res�������ֵ��
// ��23�ж�����һ���Ĵ�������__res���ñ�������������һ���Ĵ����У��Ա��ڿ��ٷ��ʺͲ�����
// �����ָ���Ĵ���������eax������ô���ǿ��Ѹþ�д�ɡ�register char __res asm("ax");����
// ȡ��seg�е�ַaddr����һ���ֽڡ�
// ������seg - ��ѡ�����addr - ����ָ����ַ��
// �����%0 - eax (__res)�����룺%1 - eax (seg)��%2 - �ڴ��ַ (*(addr))��
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
// ȡ��seg�е�ַaddr����һ�����֣�4�ֽڣ���
// ������seg - ��ѡ�����addr - ����ָ����ַ��
// �����%0 - eax (__res)�����룺%1 - eax (seg)��%2 - �ڴ��ַ (*(addr))��
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
// ȡfs�μĴ�����ֵ��ѡ�������
// �����%0 - eax (__res)��
34 #define _fs() ({ \
35 register unsigned short __res; \
36 __asm__("mov %%fs,%%ax":"=a" (__res):); \
37 __res;})
38
// ���¶�����һЩ����ԭ�͡�
39 void page_exception(void); // ҳ�쳣��ʵ����page_fault��mm/page.s��14����
40
41 void divide_error(void); // int0��kernel/asm.s��20����
42 void debug(void); // int1��kernel/asm.s��54����
43 void nmi(void); // int2��kernel/asm.s��58����
44 void int3(void); // int3��kernel/asm.s��62����
45 void overflow(void); // int4��kernel/asm.s��66����
46 void bounds(void); // int5��kernel/asm.s��70����
47 void invalid_op(void); // int6��kernel/asm.s��74����
48 void device_not_available(void); // int7��kernel/sys_call.s��158����
49 void double_fault(void); // int8��kernel/asm.s��98����
50 void coprocessor_segment_overrun(void); // int9��kernel/asm.s��78����
51 void invalid_TSS(void); // int10��kernel/asm.s��132����
52 void segment_not_present(void); // int11��kernel/asm.s��136����
53 void stack_segment(void); // int12��kernel/asm.s��140����
54 void general_protection(void); // int13��kernel/asm.s��144����
55 void page_fault(void); // int14��mm/page.s��14����
56 void coprocessor_error(void); // int16��kernel/sys_call.s��140����
57 void reserved(void); // int15��kernel/asm.s��82����
58 void parallel_interrupt(void); // int39��kernel/sys_call.s��295����
59 void irq13(void); // int45 Э�������жϴ�����kernel/asm.s��86����
60 void alignment_check(void); // int46��kernel/asm.s��148����
61
// ���ӳ���������ӡ�����жϵ����ơ������š����ó����EIP��EFLAGS��ESP��fs�μĴ���ֵ��
// �εĻ�ַ���εij��ȡ����̺�pid������š�10�ֽ�ָ���롣�����ջ���û����ݶΣ���
// ��ӡ16�ֽڵĶ�ջ���ݡ���Щ��Ϣ�����ڳ�����ԡ�
62 static void die(char * str,long esp_ptr,long nr)
63 {
64 long * esp = (long *) esp_ptr;
65 int i;
66
67 printk("%s: %04x\n\r",str,nr&0xffff);
// ���д�ӡ�����ʾ��ǰ���ý��̵�CS:EIP��EFLAGS��SS:ESP��ֵ����������!δ�ҵ�����Դ����֪������esp[0]
// ��Ϊͼ�е�esp0λ�á�������ǰ�����ֿ�����Ϊ��
// (1) EIP:\t%04x:%p\n -- esp[1]�Ƕ�ѡ�����cs����esp[0]��eip
// (2) EFLAGS:\t%p -- esp[2]��eflags
// (3) ESP:\t%04x:%p\n -- esp[4]��ԭss��esp[3]��ԭesp
68 printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n",
69 esp[1],esp[0],esp[2],esp[4],esp[3]);
70 printk("fs: %04x\n",_fs());
71 printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17));
72 if (esp[4] == 0x17) { // ��ԭssֵΪ0x17���û�ջ������ӡ��
73 printk("Stack: "); // �û�ջ�е�4������ֵ��16�ֽڣ���
74 for (i=0;i<4;i++)
75 printk("%p ",get_seg_long(0x17,i+(long *)esp[3]));
76 printk("\n");
77 }
78 str(i); // ȡ��ǰ�������������ţ�include/linux/sched.h��210�У���
79 printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i); // ���̺ţ�����š�
80 for(i=0;i<10;i++)
81 printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0])));
82 printk("\n\r");
83 do_exit(11); /* play segment exception */
84 }
85
// ������Щ��do_��ͷ�ĺ�����asm.s�ж�Ӧ�жϴ���������õ�C������
86 void do_double_fault(long esp, long error_code)
87 {
88 die("double fault",esp,error_code);
89 }
90
91 void do_general_protection(long esp, long error_code)
92 {
93 die("general protection",esp,error_code);
94 }
95
96 void do_alignment_check(long esp, long error_code)
97 {
98 die("alignment check",esp,error_code);
99 }
100
101 void do_divide_error(long esp, long error_code)
102 {
103 die("divide error",esp,error_code);
104 }
105
// �����ǽ����жϺ�˳��ѹ���ջ�ļĴ���ֵ���μ�asm.s�����24--35�С�
106 void do_int3(long * esp, long error_code,
107 long fs,long es,long ds,
108 long ebp,long esi,long edi,
109 long edx,long ecx,long ebx,long eax)
110 {
111 int tr;
112
113 __asm__("str %%ax":"=a" (tr):"" (0)); // ȡ����Ĵ���ֵ��tr��
114 printk("eax\t\tebx\t\tecx\t\tedx\n\r%8x\t%8x\t%8x\t%8x\n\r",
115 eax,ebx,ecx,edx);
116 printk("esi\t\tedi\t\tebp\t\tesp\n\r%8x\t%8x\t%8x\t%8x\n\r",
117 esi,edi,ebp,(long) esp);
118 printk("\n\rds\tes\tfs\ttr\n\r%4x\t%4x\t%4x\t%4x\n\r",
119 ds,es,fs,tr);
120 printk("EIP: %8x CS: %4x EFLAGS: %8x\n\r",esp[0],esp[1],esp[2]);
121 }
122
123 void do_nmi(long esp, long error_code)
124 {
125 die("nmi",esp,error_code);
126 }
127
128 void do_debug(long esp, long error_code)
129 {
130 die("debug",esp,error_code);
131 }
132
133 void do_overflow(long esp, long error_code)
134 {
135 die("overflow",esp,error_code);
136 }
137
138 void do_bounds(long esp, long error_code)
139 {
140 die("bounds",esp,error_code);
141 }
142
143 void do_invalid_op(long esp, long error_code)
144 {
145 die("invalid operand",esp,error_code);
146 }
147
148 void do_device_not_available(long esp, long error_code)
149 {
150 die("device not available",esp,error_code);
151 }
152
153 void do_coprocessor_segment_overrun(long esp, long error_code)
154 {
155 die("coprocessor segment overrun",esp,error_code);
156 }
157
158 void do_invalid_TSS(long esp,long error_code)
159 {
160 die("invalid TSS",esp,error_code);
161 }
162
163 void do_segment_not_present(long esp,long error_code)
164 {
165 die("segment not present",esp,error_code);
166 }
167
168 void do_stack_segment(long esp,long error_code)
169 {
170 die("stack segment",esp,error_code);
171 }
172
173 void do_coprocessor_error(long esp, long error_code)
174 {
175 if (last_task_used_math != current)
176 return;
177 die("coprocessor error",esp,error_code);
178 }
179
180 void do_reserved(long esp, long error_code)
181 {
182 die("reserved (15,17-47) error",esp,error_code);
183 }
184
// �������쳣�����壩�жϳ����ʼ���ӳ����������ǵ��жϵ����ţ��ж���������
// set_trap_gate()��set_system_gate()��ʹ�����ж���������IDT�е������ţ�Trap Gate����
// ����֮�����Ҫ��������ǰ�����õ���Ȩ��Ϊ0��������3����˶ϵ������ж�int3������ж�
// overflow �ͱ߽�����ж� bounds �������κγ�����á� ��������������Ƕ��ʽ�������
// �μ�include/asm/system.h����36�С�39�С�
185 void trap_init(void)
186 {
187 int i;
188
189 set_trap_gate(0,÷_error); // ���ó������������ж�����ֵ��������ͬ��
190 set_trap_gate(1,&debug);
191 set_trap_gate(2,&nmi);
192 set_system_gate(3,&int3); /* int3-5 can be called from all */
193 set_system_gate(4,&overflow); /* int3-5 ���Ա����г���ִ�� */
194 set_system_gate(5,&bounds);
195 set_trap_gate(6,&invalid_op);
196 set_trap_gate(7,&device_not_available);
197 set_trap_gate(8,&double_fault);
198 set_trap_gate(9,&coprocessor_segment_overrun);
199 set_trap_gate(10,&invalid_TSS);
200 set_trap_gate(11,&segment_not_present);
201 set_trap_gate(12,&stack_segment);
202 set_trap_gate(13,&general_protection);
203 set_trap_gate(14,&page_fault);
204 set_trap_gate(15,&reserved);
205 set_trap_gate(16,&coprocessor_error);
206 set_trap_gate(17,&alignment_check);
// �����int17-47���������Ⱦ�����Ϊreserved���Ժ��Ӳ����ʼ��ʱ�����������Լ��������š�
207 for (i=18;i<48;i++)
208 set_trap_gate(i,&reserved);
// ����Э�������ж�0x2d��45����������������������������ж��������ò��п��ж���������
209 set_trap_gate(45,&irq13);
210 outb_p(inb_p(0x21)&0xfb,0x21); // ����8259A��оƬ��IRQ2�ж�����
211 outb(inb_p(0xA1)&0xdf,0xA1); // ����8259A��оƬ��IRQ13�ж�����
212 set_trap_gate(39,¶llel_interrupt); // ���ò��п�1���ж�0x27��������������
213 }
214