ia64/xen-unstable

view extras/mini-os/traps.c @ 795:3a4eb84cc402

bitkeeper revision 1.485 (3f81b19fL5Y4lVlRaEpJI9r_IZlDcw)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/rn212/xeno.mini
into labyrinth.cl.cam.ac.uk:/auto/anfs/scratch/labyrinth/iap10/xeno-clone/xeno.bk
author iap10@labyrinth.cl.cam.ac.uk
date Mon Oct 06 18:17:03 2003 +0000 (2003-10-06)
parents 34473973889b
children 71f9c171157e
line source
2 #include <os.h>
3 #include <hypervisor.h>
4 #include <mm.h>
5 #include <lib.h>
7 /*
8 * These are assembler stubs in entry.S.
9 * They are the actual entry points for virtual exceptions.
10 */
11 void divide_error(void);
12 void debug(void);
13 void int3(void);
14 void overflow(void);
15 void bounds(void);
16 void invalid_op(void);
17 void device_not_available(void);
18 void double_fault(void);
19 void coprocessor_segment_overrun(void);
20 void invalid_TSS(void);
21 void segment_not_present(void);
22 void stack_segment(void);
23 void general_protection(void);
24 void page_fault(void);
25 void coprocessor_error(void);
26 void simd_coprocessor_error(void);
27 void alignment_check(void);
28 void spurious_interrupt_bug(void);
29 void machine_check(void);
32 extern void do_exit(void);
34 int kstack_depth_to_print = 24;
35 #define THREAD_SIZE (2*PAGE_SIZE)
37 static inline int kernel_text_address(unsigned long addr)
38 {
39 return ( (addr >> 20) > 0x800 && (addr >> 20) < 0x804 );
40 }
42 void show_trace(unsigned long * stack)
43 {
44 int i;
45 unsigned long addr;
47 if (!stack)
48 stack = (unsigned long*)&stack;
50 printk("Call Trace: ");
51 i = 1;
52 while (((long) stack & (4095)) != 0) {
53 addr = *stack++;
54 if (kernel_text_address(addr)) {
55 printf("0x%lx", addr);
56 i++;
57 }
58 }
59 printk("\n");
60 }
62 void show_stack(unsigned long * esp)
63 {
64 unsigned long *stack;
65 int i;
67 if(esp==NULL)
68 esp=(unsigned long*)&esp;
70 stack = esp;
71 for(i=0; i < kstack_depth_to_print; i++) {
72 if (((long) stack & (THREAD_SIZE-1)) == 0)
73 break;
74 printk("%08lx ", *stack++);
75 }
76 printk("\n");
77 show_trace(esp);
78 }
80 void dump_regs(struct pt_regs *regs)
81 {
82 int in_kernel = 1;
83 unsigned long esp;
84 unsigned short ss;
86 esp = (unsigned long) (&regs->esp);
87 ss = __KERNEL_DS;
88 if (regs->xcs & 2) {
89 in_kernel = 0;
90 esp = regs->esp;
91 ss = regs->xss & 0xffff;
92 }
93 printf("EIP: %04x:[<%08lx>]\n",
94 0xffff & regs->xcs, regs->eip);
95 printf("EFLAGS: %08lx\n",regs->eflags);
96 printf("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
97 regs->eax, regs->ebx, regs->ecx, regs->edx);
98 printf("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
99 regs->esi, regs->edi, regs->ebp, esp);
100 printf("ds: %04x es: %04x ss: %04x\n",
101 regs->xds & 0xffff, regs->xes & 0xffff, ss);
102 printf("\n");
103 }
106 static inline void dump_code(unsigned eip)
107 {
108 unsigned *ptr = (unsigned *)eip;
109 int x;
111 printk("Bytes at eip:\n");
112 for (x = -4; x < 5; x++)
113 printf("%x", ptr[x]);
114 }
117 /*
118 * C handlers here have their parameter-list constructed by the
119 * assembler stubs above. Each one gets a pointer to a list
120 * of register values (to be restored at end of exception).
121 * Some will also receive an error code -- this is the code that
122 * was generated by the processor for the underlying real exception.
123 *
124 * Note that the page-fault exception is special. It also receives
125 * the faulting linear address. Normally this would be found in
126 * register CR2, but that is not accessible in a virtualised OS.
127 */
129 static void inline do_trap(int trapnr, char *str,
130 struct pt_regs * regs, long error_code)
131 {
132 printk("FATAL: Unhandled Trap (see mini-os:traps.c)");
133 printf("%d %s", trapnr, str);
134 dump_regs(regs);
135 show_trace((void *)regs->esp);
136 dump_code(regs->eip);
138 do_exit();
139 }
141 #define DO_ERROR(trapnr, str, name) \
142 void do_##name(struct pt_regs * regs, long error_code) \
143 { \
144 do_trap(trapnr, str, regs, error_code); \
145 }
147 #define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr) \
148 void do_##name(struct pt_regs * regs, long error_code) \
149 { \
150 do_trap(trapnr, str, regs, error_code); \
151 }
153 DO_ERROR_INFO( 0, "divide error", divide_error, FPE_INTDIV, regs->eip)
154 DO_ERROR( 3, "int3", int3)
155 DO_ERROR( 4, "overflow", overflow)
156 DO_ERROR( 5, "bounds", bounds)
157 DO_ERROR_INFO( 6, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
158 DO_ERROR( 7, "device not available", device_not_available)
159 DO_ERROR( 8, "double fault", double_fault)
160 DO_ERROR( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
161 DO_ERROR(10, "invalid TSS", invalid_TSS)
162 DO_ERROR(11, "segment not present", segment_not_present)
163 DO_ERROR(12, "stack segment", stack_segment)
164 DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0)
165 DO_ERROR(18, "machine check", machine_check)
167 void do_page_fault(struct pt_regs * regs, long error_code,
168 unsigned long address)
169 {
170 printk("Page fault\n");
171 printk("Address: 0x%lx", address);
172 printk("Error Code: 0x%lx", error_code);
173 printk("eip: \t 0x%lx", regs->eip);
174 do_exit();
175 }
177 void do_general_protection(struct pt_regs * regs, long error_code)
178 {
180 HYPERVISOR_shared_info->events_mask = 0;
181 printk("GPF\n");
182 printk("Error Code: 0x%lx", error_code);
183 dump_regs(regs);
184 dump_code(regs->eip);
185 do_exit();
186 }
189 void do_debug(struct pt_regs * regs, long error_code)
190 {
191 printk("Debug exception\n");
192 #define TF_MASK 0x100
193 regs->eflags &= ~TF_MASK;
194 dump_regs(regs);
195 do_exit();
196 }
200 void do_coprocessor_error(struct pt_regs * regs, long error_code)
201 {
202 printk("Copro error\n");
203 dump_regs(regs);
204 dump_code(regs->eip);
205 do_exit();
206 }
208 void simd_math_error(void *eip)
209 {
210 printk("SIMD error\n");
211 }
213 void do_simd_coprocessor_error(struct pt_regs * regs,
214 long error_code)
215 {
216 printk("SIMD copro error\n");
217 }
219 void do_spurious_interrupt_bug(struct pt_regs * regs,
220 long error_code)
221 {
222 }
224 /*
225 * Submit a virtual IDT to teh hypervisor. This consists of tuples
226 * (interrupt vector, privilege ring, CS:EIP of handler).
227 * The 'privilege ring' field specifies the least-privileged ring that
228 * can trap to that vector using a software-interrupt instruction (INT).
229 */
230 static trap_info_t trap_table[] = {
231 { 0, 0, __KERNEL_CS, (unsigned long)divide_error },
232 { 1, 0, __KERNEL_CS, (unsigned long)debug },
233 { 3, 3, __KERNEL_CS, (unsigned long)int3 },
234 { 4, 3, __KERNEL_CS, (unsigned long)overflow },
235 { 5, 3, __KERNEL_CS, (unsigned long)bounds },
236 { 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
237 { 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
238 { 8, 0, __KERNEL_CS, (unsigned long)double_fault },
239 { 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
240 { 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
241 { 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
242 { 12, 0, __KERNEL_CS, (unsigned long)stack_segment },
243 { 13, 0, __KERNEL_CS, (unsigned long)general_protection },
244 { 14, 0, __KERNEL_CS, (unsigned long)page_fault },
245 { 15, 0, __KERNEL_CS, (unsigned long)spurious_interrupt_bug },
246 { 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error },
247 { 17, 0, __KERNEL_CS, (unsigned long)alignment_check },
248 { 18, 0, __KERNEL_CS, (unsigned long)machine_check },
249 { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error },
250 { 0, 0, 0, 0 }
251 };
255 void trap_init(void)
256 {
257 HYPERVISOR_set_trap_table(trap_table);
258 }