2 * Trap handling routines
3 * NetWatch system management mode administration console
5 * Copyright (c) 2008 Jacob Potter and Joshua Wise. All rights reserved.
6 * This program is free software; you can redistribute and/or modify it under
7 * the terms found in the file LICENSE in the root of this source tree.
17 #define CS_SEGSEL 0x10
20 "fault_wrapper_common:\n"
28 #define FAULT_WRAPPER(func_name, code) asm ( \
29 ".global " #func_name "_wrapper\n" \
30 #func_name "_wrapper:\n" \
31 "mov $" #code ", %eax\n" \
32 "jmp fault_wrapper_common\n" \
33 ); void func_name##_wrapper(void);
35 #define FAULT_WRAPPER1(func_name, code) asm ( \
36 ".global " #func_name "_wrapper\n" \
37 #func_name "_wrapper:\n" \
40 "mov $" #code ", %eax\n" \
41 "jmp fault_wrapper_common\n" \
42 ); void func_name##_wrapper(void);
44 #define WRAPPER_INSTALL(idt, idt4_value, func_name, int_number) { \
45 *(int *)((void *)idt + (8 * int_number)) = \
46 ((int)func_name##_wrapper & 0xFFFF) | \
48 *(int *)((void *)idt + (8 * int_number) + 4) = \
49 ((int)func_name##_wrapper & 0xFFFF0000) | idt4_value; \
52 /* The 16 bits at offset 4 from the start of an interrupt gate are a
53 * bitfield, according to the Intel spec:
54 * 15 P - Segment Present - set to 1
55 * 14-13 DPL - Descriptor privilege level - set to 00, since we're always in ring 0
56 * 12-8 01111 for 32-bit trap gates, 01110 for 32-bit interrupt gates
61 typedef struct trap_t {
70 static const char const * trapcodes[20] = {
78 "Device Not Available",
80 "Coprocessor Overrun",
82 "Segmnet Not Present",
93 void die(struct trap_t * trap) {
95 DBG(0x40 + trap->fault_code);
97 if (trap->fault_code < 20) {
98 outputf("---\n%s", trapcodes[trap->fault_code]);
100 outputf("---\nUNKNOWN FAULT");
103 outputf("Error %08x %%eip %08x", trap->error_code, trap->eip);
104 outputf("%%cr2 %08x %%eflags %08x", trap->cr2, trap->eflags);
108 FAULT_WRAPPER1(fault_divide, 0);
109 FAULT_WRAPPER1(fault_db, 1);
110 FAULT_WRAPPER1(fault_nmi, 2);
111 FAULT_WRAPPER1(fault_3, 3);
112 FAULT_WRAPPER1(fault_overflow, 4);
113 FAULT_WRAPPER1(fault_oob, 5);
114 FAULT_WRAPPER1(fault_opcode, 6);
115 FAULT_WRAPPER1(fault_enofpu, 7);
116 FAULT_WRAPPER(double_fault, 8);
117 FAULT_WRAPPER1(fault_fpu, 9);
118 FAULT_WRAPPER(fault_invalid_tss, 10);
119 FAULT_WRAPPER(fault_noseg, 11);
120 FAULT_WRAPPER(fault_stack, 12);
121 FAULT_WRAPPER(fault_gp, 13);
122 FAULT_WRAPPER(fault_page, 14);
123 FAULT_WRAPPER1(fault_fpe, 16);
124 FAULT_WRAPPER(fault_ac, 17);
125 FAULT_WRAPPER1(fault_machine, 18);
126 FAULT_WRAPPER1(fault_other, 19);
128 /* pseudo_descriptor and x86_gate structs from 15-410 basis code. */
131 unsigned int filler[2]; //64 bits, or 8 bytes.
134 static struct x86_gate idt[64];
136 struct pseudo_descriptor {
138 unsigned short limit;
139 unsigned long linear_base;
140 } __attribute__((packed));
142 void traps_install(void) {
146 struct pseudo_descriptor pdesc;
147 pdesc.limit = sizeof(idt) - 1;
148 pdesc.linear_base = (int)&idt; //v2p(&idt);
152 for (i = 0; i < 32; i++)
153 WRAPPER_INSTALL(idt, TRAP, fault_other, i);
155 WRAPPER_INSTALL(idt, TRAP, fault_divide, T_DIVIDE_ERROR);
156 WRAPPER_INSTALL(idt, TRAP, fault_db, T_DEBUG);
157 WRAPPER_INSTALL(idt, TRAP, fault_nmi, T_NMI);
158 WRAPPER_INSTALL(idt, TRAP, fault_3, T_INT3);
159 WRAPPER_INSTALL(idt, TRAP, fault_overflow, T_OVERFLOW);
160 WRAPPER_INSTALL(idt, TRAP, fault_oob, T_OUT_OF_BOUNDS);
161 WRAPPER_INSTALL(idt, TRAP, fault_opcode, T_INVALID_OPCODE);
162 WRAPPER_INSTALL(idt, TRAP, fault_enofpu, T_NO_FPU);
163 WRAPPER_INSTALL(idt, TRAP, double_fault, T_DOUBLE_FAULT);
164 WRAPPER_INSTALL(idt, TRAP, fault_fpu, T_FPU_FAULT);
165 WRAPPER_INSTALL(idt, TRAP, fault_invalid_tss, T_INVALID_TSS);
166 WRAPPER_INSTALL(idt, TRAP, fault_noseg, T_SEGMENT_NOT_PRESENT);
167 WRAPPER_INSTALL(idt, TRAP, fault_stack, T_STACK_FAULT);
168 WRAPPER_INSTALL(idt, TRAP, fault_gp, T_GENERAL_PROTECTION);
169 WRAPPER_INSTALL(idt, TRAP, fault_page, T_PAGE_FAULT);
170 WRAPPER_INSTALL(idt, TRAP, fault_fpe, T_FLOATING_POINT_ERROR);
171 WRAPPER_INSTALL(idt, TRAP, fault_ac, T_ALIGNMENT_CHECK);
172 WRAPPER_INSTALL(idt, TRAP, fault_machine, T_MACHINE_CHECK);
175 asm volatile("lidt %0" : : "m" (pdesc.limit));