]> Joshua Wise's Git repositories - netwatch.git/blob - netwatch/traps.c
25a404c6a5fe58bf24275f8ab40c454ce8c5e6e5
[netwatch.git] / netwatch / traps.c
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 }
This page took 0.036127 seconds and 4 git commands to generate.