]> Joshua Wise's Git repositories - netwatch.git/blob - netwatch/traps.c
Avoid suffering from wrong CS_SEGSEL syndrome.
[netwatch.git] / netwatch / traps.c
1 #include <output.h>
2 #include <io.h>
3 #include <paging.h>
4
5 #include "traps.h"
6
7 #define CS_SEGSEL       0x8
8
9 #define FAULT_WRAPPER(func_name)        asm (           \
10         ".global " #func_name "_wrapper\n"              \
11         #func_name "_wrapper:\n"                        \
12         "mov %cr2, %eax\n"                              \
13         "push %eax\n"                                   \
14         "push %esp\n"                                   \
15         "call " #func_name "\n"                         \
16 ); void func_name##_wrapper(void);
17
18 #define WRAPPER_INSTALL(idt, idt4_value, func_name, int_number) {       \
19         *(int *)((void *)idt + (8 * int_number)) =      \
20                 ((int)func_name##_wrapper & 0xFFFF) |   \
21                 (CS_SEGSEL << 16);              \
22         *(int *)((void *)idt + (8 * int_number) + 4) =  \
23                 ((int)func_name##_wrapper & 0xFFFF0000) | idt4_value; \
24 }
25
26 /* The 16 bits at offset 4 from the start of an interrupt gate are a
27  * bitfield, according to the Intel spec:
28  * 15           P - Segment Present - set to 1
29  * 14-13        DPL - Descriptor privilege level - set to 11 for trap/int, 00 for IPI
30  * 12-8         01111 for 32-bit trap gates, 01110 for 32-bit interrupt gates
31  * 7-0          Set to 0
32  * Trap:      binary 11101111 0000000, hex EF00.
33  * Interrupt: binary 11101110 0000000, hex EE00.
34  */
35 #define TRAP            0xEF00
36 #define INTERRUPT       0xEE00
37
38 typedef struct trap_t {
39         int cr2;
40         int error_code;
41         int eip;
42         int cs;
43         int eflags;
44         int esp;
45         int ss;
46 } trap_t;
47
48 void die(struct trap_t * trap) {
49         outputf("Error %08x %%eip %08x", trap->error_code, trap->eip);
50         outputf("%%esp %08x %%eflags %08x", trap->esp, trap->eflags);
51         while(1) asm("hlt");
52 }
53
54 void fault_gp(struct trap_t * trap) {
55         outputf("GENERAL PROTECTION FAULT");
56         die(trap);
57 }
58
59 void fault_page(struct trap_t * trap) {
60         outputf("PAGE FAULT: %08x", trap->cr2);
61         die(trap);
62 }
63 void fault_divide(struct trap_t * trap) {
64         outputf("DIVISION FAULT");
65         die(trap);
66 }
67 void double_fault(struct trap_t * trap) {
68         outputf("DOUBLE FAULT");
69         die(trap);
70 }
71
72 FAULT_WRAPPER(fault_gp);
73 FAULT_WRAPPER(fault_page);
74 FAULT_WRAPPER(fault_divide);
75 FAULT_WRAPPER(double_fault);
76
77 /* pseudo_descriptor and x86_gate structs from 15-410 basis code. */
78
79 struct x86_gate {
80 unsigned int filler[2]; //64 bits; or 8 bytes.
81 };
82
83 static struct x86_gate idt[64];
84
85 struct pseudo_descriptor {
86         short pad;
87         unsigned short limit;
88         unsigned long linear_base;
89 } __attribute__((packed));
90
91 void traps_install(void) {
92
93         struct pseudo_descriptor pdesc;
94         pdesc.limit = sizeof(idt) - 1;
95         pdesc.linear_base = v2p(&idt);
96
97         WRAPPER_INSTALL(idt, TRAP, fault_divide, T_DIVIDE_ERROR);
98         WRAPPER_INSTALL(idt, TRAP, fault_gp, T_GENERAL_PROTECTION);
99         WRAPPER_INSTALL(idt, TRAP, fault_page, T_PAGE_FAULT);
100         WRAPPER_INSTALL(idt, TRAP, double_fault, T_DOUBLE_FAULT);
101
102         outb(0x80, 0xCC);
103         asm volatile("lidt %0" : : "m" (pdesc.limit));
104         outb(0x80, 0xCD);
105 }
This page took 0.028144 seconds and 4 git commands to generate.