]>
Commit | Line | Data |
---|---|---|
1 | /* traps.c | |
2 | * Trap handling routines | |
3 | * NetWatch system management mode administration console | |
4 | * | |
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. | |
8 | * | |
9 | */ | |
10 | ||
11 | #include <output.h> | |
12 | #include <io.h> | |
13 | #include <paging.h> | |
14 | ||
15 | #include "traps.h" | |
16 | ||
17 | #define CS_SEGSEL 0x10 | |
18 | ||
19 | asm ( | |
20 | "fault_wrapper_common:\n" | |
21 | "push %eax\n" | |
22 | "mov %cr2, %eax\n" | |
23 | "push %eax\n" | |
24 | "push %esp\n" | |
25 | "call die\n" | |
26 | ); | |
27 | ||
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); | |
34 | ||
35 | #define FAULT_WRAPPER1(func_name, code) asm ( \ | |
36 | ".global " #func_name "_wrapper\n" \ | |
37 | #func_name "_wrapper:\n" \ | |
38 | "mov $0, %eax\n" \ | |
39 | "push %eax\n" \ | |
40 | "mov $" #code ", %eax\n" \ | |
41 | "jmp fault_wrapper_common\n" \ | |
42 | ); void func_name##_wrapper(void); | |
43 | ||
44 | #define WRAPPER_INSTALL(idt, idt4_value, func_name, int_number) { \ | |
45 | *(int *)((void *)idt + (8 * int_number)) = \ | |
46 | ((int)func_name##_wrapper & 0xFFFF) | \ | |
47 | (CS_SEGSEL << 16); \ | |
48 | *(int *)((void *)idt + (8 * int_number) + 4) = \ | |
49 | ((int)func_name##_wrapper & 0xFFFF0000) | idt4_value; \ | |
50 | } | |
51 | ||
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 | |
57 | * 7-0 Set to 0 | |
58 | */ | |
59 | #define TRAP 0x8F00 | |
60 | ||
61 | typedef struct trap_t { | |
62 | int cr2; | |
63 | int fault_code; | |
64 | int error_code; | |
65 | int eip; | |
66 | int cs; | |
67 | int eflags; | |
68 | } trap_t; | |
69 | ||
70 | static const char const * trapcodes[20] = { | |
71 | "Divide by Zero", | |
72 | "Debug Trap", | |
73 | "NMI", | |
74 | "Breakpoint Trap", | |
75 | "Overflow Trap", | |
76 | "Bound Range Fault", | |
77 | "Invalid Opcode", | |
78 | "Device Not Available", | |
79 | "Double Fault", | |
80 | "Coprocessor Overrun", | |
81 | "Invalid TSS", | |
82 | "Segmnet Not Present", | |
83 | "Stack Fault", | |
84 | "GPF", | |
85 | "Page Fault", | |
86 | "Reserved Trap", | |
87 | "x87 FPE Pending", | |
88 | "Alignment Check", | |
89 | "Machine Check", | |
90 | "SIMD FPE Fault" | |
91 | }; | |
92 | ||
93 | void die(struct trap_t * trap) { | |
94 | ||
95 | DBG(0x40 + trap->fault_code); | |
96 | ||
97 | if (trap->fault_code < 20) { | |
98 | outputf("---\n%s", trapcodes[trap->fault_code]); | |
99 | } else { | |
100 | outputf("---\nUNKNOWN FAULT"); | |
101 | } | |
102 | ||
103 | outputf("Error %08x %%eip %08x", trap->error_code, trap->eip); | |
104 | outputf("%%cr2 %08x %%eflags %08x", trap->cr2, trap->eflags); | |
105 | while(1) asm("hlt"); | |
106 | } | |
107 | ||
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); | |
127 | ||
128 | /* pseudo_descriptor and x86_gate structs from 15-410 basis code. */ | |
129 | ||
130 | struct x86_gate { | |
131 | unsigned int filler[2]; //64 bits, or 8 bytes. | |
132 | }; | |
133 | ||
134 | static struct x86_gate idt[64]; | |
135 | ||
136 | struct pseudo_descriptor { | |
137 | short pad; | |
138 | unsigned short limit; | |
139 | unsigned long linear_base; | |
140 | } __attribute__((packed)); | |
141 | ||
142 | void traps_install(void) { | |
143 | DBG(0xCA); | |
144 | int i; | |
145 | ||
146 | struct pseudo_descriptor pdesc; | |
147 | pdesc.limit = sizeof(idt) - 1; | |
148 | pdesc.linear_base = (int)&idt; //v2p(&idt); | |
149 | ||
150 | DBG(0xCB); | |
151 | ||
152 | for (i = 0; i < 32; i++) | |
153 | WRAPPER_INSTALL(idt, TRAP, fault_other, i); | |
154 | ||
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); | |
173 | ||
174 | DBG(0xCC); | |
175 | asm volatile("lidt %0" : : "m" (pdesc.limit)); | |
176 | DBG(0xCE); | |
177 | } |