]>
Commit | Line | Data |
---|---|---|
ed22a699 JP |
1 | #include <output.h> |
2 | #include <io.h> | |
3 | #include <paging.h> | |
4 | ||
5 | #include "traps.h" | |
6 | ||
7285933f | 7 | #define CS_SEGSEL 0x8 |
ed22a699 JP |
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; | |
ea82a4d1 | 89 | } __attribute__((packed)); |
ed22a699 JP |
90 | |
91 | void traps_install(void) { | |
92 | ||
93 | struct pseudo_descriptor pdesc; | |
94 | pdesc.limit = sizeof(idt) - 1; | |
923ea2c2 | 95 | pdesc.linear_base = v2p(&idt); |
ed22a699 JP |
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 | } |