1 
2 #include <stdbool.h>
3 #include <stdint.h>
4 
5 #include <sys/kconfig.h>
6 #include <sys/kassert.h>
7 #include <sys/kdebug.h>
8 #include <sys/kmem.h>
9 #include <sys/ktime.h>
10 #include <sys/spinlock.h>
11 #include <sys/irq.h>
12 #include <sys/syscall.h>
13 #include <sys/mp.h>
14 
15 #include <machine/amd64.h>
16 #include <machine/lapic.h>
17 #include <machine/trap.h>
18 #include <machine/mp.h>
19 
20 #include <sys/thread.h>
21 
22 extern uint64_t trap_table[T_MAX];
23 extern void trap_pop(TrapFrame *tf);
24 extern void Debug_Breakpoint(TrapFrame *tf);
25 extern void Debug_HaltIPI(TrapFrame *tf);
26 extern void KTimer_Process();
27 
28 static InteruptGate64 idt[256];
29 static PseudoDescriptor idtdesc;
30 static uint64_t intStats[256];
31 
32 void
Trap_Init()33 Trap_Init()
34 {
35     int i;
36 
37     kprintf("Initializing IDT... ");
38 
39     for (i = 0; i < T_MAX; i++) {
40         idt[i].pc_low = trap_table[i] & 0x0000ffff;
41         idt[i].pc_mid = (trap_table[i] >> 16) & 0x0000ffff;
42         idt[i].pc_high = trap_table[i] >> 32;
43 
44         idt[i].cs = 0x0008;
45         idt[i].type = 0x8E;
46 
47         idt[i].ist = 0x00;
48         idt[i]._unused1 = 0x00000000;
49     }
50 
51     for (; i < 256; i++) {
52         idt[i].pc_low = trap_table[63] & 0x0000ffff;
53         idt[i].pc_mid = (trap_table[63] >> 16) & 0x0000ffff;
54         idt[i].pc_high = trap_table[63] >> 32;
55 
56         idt[i].cs = 0x0008;
57         idt[i].type = 0x8E;
58 
59         idt[i].ist = 0;
60         idt[i]._unused1 = 0;
61     }
62 
63     // Double fault handler
64     idt[T_NMI].ist = 0x01;
65     idt[T_DF].ist = 0x01;
66     idt[T_GP].ist = 0x01;
67     idt[T_NP].ist = 0x01;
68     idt[T_SS].ist = 0x01;
69 
70     // Enable Breakpoint and Syscall from Userspace
71     idt[T_DB].type = 0xEE;
72     idt[T_BP].type = 0xEE;
73     idt[T_SYSCALL].type = 0xEE;
74 
75     idtdesc.off = (uint64_t)&idt;
76     idtdesc.lim = sizeof(idt) - 1;
77 
78     lidt(&idtdesc);
79 
80     // Zero out interrupt stats
81     for (i = 0; i < 256; i++) {
82 	intStats[i] = 0;
83     }
84 
85     kprintf("Done!\n");
86 }
87 
88 void
Trap_InitAP()89 Trap_InitAP()
90 {
91     lidt(&idtdesc);
92 }
93 
94 void
Trap_Dump(TrapFrame * tf)95 Trap_Dump(TrapFrame *tf)
96 {
97     kprintf("CPU %d\n", CPU());
98     kprintf("Interrupt %d Error Code: %016llx\n",
99             tf->vector, tf->errcode);
100     kprintf("cr0: %016llx cr2: %016llx\n",
101             read_cr0(), read_cr2());
102     kprintf("cr3: %016llx cr4: %016llx\n",
103             read_cr3(), read_cr4());
104     kprintf("dr0: %016llx dr1: %016llx dr2: %016llx\n",
105             read_dr0(), read_dr1(), read_dr2());
106     kprintf("dr3: %016llx dr6: %016llx dr7: %016llx\n",
107             read_dr3(), read_dr6(), read_dr7());
108     kprintf("rip: %04x:%016llx rsp: %04x:%016llx\n",
109             tf->cs, tf->rip, tf->ss, tf->rsp);
110     kprintf("rflags: %016llx ds: %04x es: %04x fs: %04x gs: %04x\n",
111             tf->rflags, read_ds(), read_es(), read_fs(), read_gs());
112     kprintf("rax: %016llx rbx: %016llx rcx: %016llx\n",
113             tf->rax, tf->rbx, tf->rcx);
114     kprintf("rdx: %016llx rsi: %016llx rdi: %016llx\n",
115             tf->rdx, tf->rsi, tf->rdi);
116     kprintf("rbp: %016llx r8:  %016llx r9:  %016llx\n",
117             tf->rbp, tf->r8, tf->r9);
118     kprintf("r10: %016llx r11: %016llx r12: %016llx\n",
119             tf->r10, tf->r11, tf->r12);
120     kprintf("r13: %016llx r14: %016llx r15: %016llx\n",
121             tf->r13, tf->r14, tf->r15);
122 }
123 
124 void
Trap_StackDump(TrapFrame * tf)125 Trap_StackDump(TrapFrame *tf)
126 {
127     uint64_t rsp;
128     uint64_t *data;
129 
130     // XXX: This should use safe copy
131     for (rsp = tf->rsp; (rsp & 0xFFF) != 0; rsp += 8) {
132 	data = (uint64_t *)rsp;
133 	kprintf("%016llx: %016llx\n", rsp, *data);
134     }
135 }
136 
137 extern int copy_unsafe(void *to, void *from, uintptr_t len);
138 extern void copy_unsafe_done(void);
139 extern void copy_unsafe_fault(void);
140 
141 extern int copystr_unsafe(void *to, void *from, uintptr_t len);
142 extern void copystr_unsafe_done(void);
143 extern void copystr_unsafe_fault(void);
144 
145 void
trap_entry(TrapFrame * tf)146 trap_entry(TrapFrame *tf)
147 {
148     // XXX: USE ATOMIC!
149     intStats[tf->vector]++;
150 
151     // Debug NMI
152     if (tf->vector == T_NMI) {
153 	Critical_Enter();
154 	kprintf("Kernel Fault: Vector %d\n", tf->vector);
155 	Trap_Dump(tf);
156 	Debug_Breakpoint(tf);
157 	return;
158     }
159 
160     // Kernel
161     if (tf->cs == SEL_KCS)
162     {
163 	// Kernel Debugger
164 	if (tf->vector == T_BP || tf->vector == T_DE) {
165 	    Debug_Breakpoint(tf);
166 	    return;
167 	}
168 
169 	// User IO
170 	if ((tf->vector == T_PF) &&
171 	    (tf->rip >= (uint64_t)&copy_unsafe) &&
172 	    (tf->rip <= (uint64_t)&copy_unsafe_done)) {
173 	    kprintf("Faulted in copy_unsafe\n");
174 	    tf->rip = (uint64_t)&copy_unsafe_fault;
175 	    return;
176 	}
177 
178 	// User IO
179 	if ((tf->vector == T_PF) &&
180 	    (tf->rip >= (uint64_t)&copystr_unsafe) &&
181 	    (tf->rip <= (uint64_t)&copystr_unsafe_done)) {
182 	    kprintf("Faulted in copystr_unsafe\n");
183 	    tf->rip = (uint64_t)&copystr_unsafe_fault;
184 	    return;
185 	}
186 
187 	// Halt on kernel errors
188 	if (tf->vector <= T_CPU_LAST)
189 	{
190 	    Critical_Enter();
191 	    kprintf("Kernel Fault: Vector %d\n", tf->vector);
192 	    Trap_Dump(tf);
193 	    Debug_Breakpoint(tf);
194 	    while (1)
195 		hlt();
196 	}
197     }
198 
199     // User space exceptions
200     switch (tf->vector)
201     {
202 	case T_DE:
203 	    kprintf("Divide by Zero\n");
204 	    return;
205 	case T_DB:
206 	case T_BP:
207 	case T_UD: {
208 	    kprintf("Userlevel breakpoint\n");
209 	    Debug_Breakpoint(tf);
210 	    return;
211 	}
212 	case T_PF: {
213 	    Trap_Dump(tf);
214 	    Trap_StackDump(tf);
215 	    Debug_Breakpoint(tf);
216 	}
217 	case T_SYSCALL: {
218 	    VLOG(syscall, "Syscall %016llx\n", tf->rdi);
219 	    tf->rax = Syscall_Entry(tf->rdi, tf->rsi, tf->rdx, tf->rcx, tf->r8, tf->r9);
220 	    VLOG(syscall, "Return %016llx\n", tf->rax);
221 	    return;
222 	}
223     }
224 
225     // IRQs
226     if (tf->vector >= T_IRQ_BASE && tf->vector <= T_IRQ_MAX)
227     {
228 	LAPIC_SendEOI();
229 	IRQ_Handler(tf->vector - T_IRQ_BASE);
230 	if (tf->vector == T_IRQ_TIMER) {
231 	    KTimer_Process();
232 	    Sched_Scheduler();
233 	}
234 
235         return;
236     }
237 
238     // Debug IPI
239     if (tf->vector == T_DEBUGIPI) {
240 	Debug_HaltIPI(tf);
241 	LAPIC_SendEOI();
242     }
243 
244     // Cross calls
245     if (tf->vector == T_CROSSCALL)
246     {
247 	MP_CrossCallTrap();
248 	LAPIC_SendEOI();
249 	return;
250     }
251 
252     // LAPIC Special Vectors
253     if (tf->vector == T_IRQ_SPURIOUS)
254     {
255 	kprintf("Spurious Interrupt!\n");
256 	return;
257     }
258     if (tf->vector == T_IRQ_ERROR)
259     {
260 	kprintf("LAPIC Error!\n");
261 	while (1)
262 	    hlt();
263     }
264     if (tf->vector == T_IRQ_THERMAL)
265     {
266 	kprintf("Thermal Error!\n");
267 	while (1)
268 	    hlt();
269     }
270 
271     kprintf("Unhandled Interrupt 0x%x!\n", tf->vector);
272     Trap_Dump(tf);
273     while (1)
274 	hlt();
275 }
276 
277 static void
Debug_Traps(int argc,const char * argv[])278 Debug_Traps(int argc, const char *argv[])
279 {
280     int i;
281 
282     kprintf("Trap    Interrupts    Trap    Interrupts\n");
283     for (i = 0; i < T_MAX / 2; i++)
284     {
285 	kprintf("%-4d    %-12d  %-4d    %-12d\n",
286 		i, intStats[i],
287 		T_MAX / 2 + i, intStats[T_MAX / 2 + i]);
288     }
289 }
290 
291 REGISTER_DBGCMD(traps, "Print trap statistics", Debug_Traps);
292 
293