xref: /haiku/src/system/kernel/arch/x86/32/descriptors.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
1 /*
2  * Copyright 2013, Paweł Dziepak, pdziepak@quarnos.org.
3  * Copyright 2008-2011, Michael Lotz, mmlr@mlotz.ch.
4  * Copyright 2010, Clemens Zeidler, haiku@clemens-zeidler.de.
5  * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
6  * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de.
7  * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
8  * Distributed under the terms of the MIT License.
9  *
10  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
11  * Distributed under the terms of the NewOS License.
12  */
13 
14 
15 #include <arch/x86/descriptors.h>
16 
17 #include <stdio.h>
18 
19 #include <boot/kernel_args.h>
20 #include <cpu.h>
21 #include <int.h>
22 #include <tls.h>
23 #include <vm/vm.h>
24 #include <vm/vm_priv.h>
25 
26 #include <arch/int.h>
27 #include <arch/user_debugger.h>
28 
29 #include "interrupts.h"
30 
31 
32 #define IDT_GATES_COUNT	256
33 
34 
35 typedef interrupt_descriptor interrupt_descriptor_table[IDT_GATES_COUNT];
36 
37 global_descriptor_table gGDTs[SMP_MAX_CPUS];
38 static interrupt_descriptor_table sIDTs[SMP_MAX_CPUS];
39 
40 // table with functions handling respective interrupts
41 typedef void interrupt_handler_function(struct iframe* frame);
42 
43 static const uint32 kInterruptHandlerTableSize = IDT_GATES_COUNT;
44 interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize];
45 
46 
47 /*!	Initializes a descriptor in an IDT.
48 */
49 static void
50 set_gate(interrupt_descriptor *gate_addr, addr_t addr, int type, int dpl)
51 {
52 	unsigned int gate1; // first byte of gate desc
53 	unsigned int gate2; // second byte of gate desc
54 
55 	gate1 = (KERNEL_CODE_SELECTOR << 16) | (0x0000ffff & addr);
56 	gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8);
57 
58 	gate_addr->a = gate1;
59 	gate_addr->b = gate2;
60 }
61 
62 
63 /*!	Initializes the descriptor for interrupt vector \a n in the IDT of the
64 	specified CPU to an interrupt-gate descriptor with the given procedure
65 	address.
66 	For CPUs other than the boot CPU it must not be called before
67 	arch_int_init_post_vm().
68 */
69 static void
70 set_interrupt_gate(int32 cpu, int n, void (*addr)())
71 {
72 	set_gate(&sIDTs[cpu][n], (addr_t)addr, 14, DPL_KERNEL);
73 }
74 
75 
76 /*!	Initializes the descriptor for interrupt vector \a n in the IDT of the
77 	specified CPU to an trap-gate descriptor with the given procedure address.
78 	For CPUs other than the boot CPU it must not be called before
79 	arch_int_init_post_vm().
80 */
81 static void
82 set_trap_gate(int32 cpu, int n, void (*addr)())
83 {
84 	set_gate(&sIDTs[cpu][n], (unsigned int)addr, 15, DPL_USER);
85 }
86 
87 
88 /*!	Initializes the descriptor for interrupt vector \a n in the IDT of CPU
89 	\a cpu to a task-gate descripter referring to the TSS segment identified
90 	by TSS segment selector \a segment.
91 	For CPUs other than the boot CPU it must not be called before
92 	arch_int_init_post_vm() (arch_cpu_init_post_vm() is fine).
93 */
94 static void
95 set_task_gate(int32 cpu, int32 n, int32 segment)
96 {
97 	sIDTs[cpu][n].a = (segment << 16);
98 	sIDTs[cpu][n].b = 0x8000 | (0 << 13) | (0x5 << 8); // present, dpl 0, type 5
99 }
100 
101 
102 static inline void
103 load_tss()
104 {
105 	uint16 segment = (TSS_SEGMENT << 3) | DPL_KERNEL;
106 	asm("ltr %w0" : : "r" (segment));
107 }
108 
109 
110 static inline void
111 load_gdt(int cpu)
112 {
113 	struct {
114 		uint16	limit;
115 		void*	address;
116 	} _PACKED gdtDescriptor = {
117 		GDT_SEGMENT_COUNT * sizeof(segment_descriptor) - 1,
118 		gGDTs[cpu]
119 	};
120 
121 	asm volatile("lgdt %0" : : "m" (gdtDescriptor));
122 }
123 
124 
125 static inline void
126 load_idt(int cpu)
127 {
128 	struct {
129 		uint16	limit;
130 		void*	address;
131 	} _PACKED idtDescriptor = {
132 		IDT_GATES_COUNT * sizeof(interrupt_descriptor) - 1,
133 		&sIDTs[cpu]
134 	};
135 
136 	asm volatile("lidt %0" : : "m" (idtDescriptor));
137 }
138 
139 
140 //	#pragma mark - Double fault handling
141 
142 
143 void
144 x86_double_fault_exception(struct iframe* frame)
145 {
146 	int cpu = x86_double_fault_get_cpu();
147 
148 	// The double fault iframe contains no useful information (as
149 	// per Intel's architecture spec). Thus we simply save the
150 	// information from the (unhandlable) exception which caused the
151 	// double in our iframe. This will result even in useful stack
152 	// traces. Only problem is that we trust that at least the
153 	// TSS is still accessible.
154 	struct tss *tss = &gCPU[cpu].arch.tss;
155 
156 	frame->cs = tss->cs;
157 	frame->es = tss->es;
158 	frame->ds = tss->ds;
159 	frame->fs = tss->fs;
160 	frame->gs = tss->gs;
161 	frame->ip = tss->eip;
162 	frame->bp = tss->ebp;
163 	frame->sp = tss->esp;
164 	frame->ax = tss->eax;
165 	frame->bx = tss->ebx;
166 	frame->cx = tss->ecx;
167 	frame->dx = tss->edx;
168 	frame->si = tss->esi;
169 	frame->di = tss->edi;
170 	frame->flags = tss->eflags;
171 
172 	// Use a special handler for page faults which avoids the triple fault
173 	// pitfalls.
174 	set_interrupt_gate(cpu, 14, &trap14_double_fault);
175 
176 	debug_double_fault(cpu);
177 }
178 
179 
180 void
181 x86_page_fault_exception_double_fault(struct iframe* frame)
182 {
183 	addr_t cr2 = x86_read_cr2();
184 
185 	// Only if this CPU has a fault handler, we're allowed to be here.
186 	cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()];
187 	addr_t faultHandler = cpu.fault_handler;
188 	if (faultHandler != 0) {
189 		debug_set_page_fault_info(cr2, frame->ip,
190 			(frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0);
191 		frame->ip = faultHandler;
192 		frame->bp = cpu.fault_handler_stack_pointer;
193 		return;
194 	}
195 
196 	// No fault handler. This is bad. Since we originally came from a double
197 	// fault, we don't try to reenter the kernel debugger. Instead we just
198 	// print the info we've got and enter an infinite loop.
199 	kprintf("Page fault in double fault debugger without fault handler! "
200 		"Touching address %p from eip %p. Entering infinite loop...\n",
201 		(void*)cr2, (void*)frame->ip);
202 
203 	while (true);
204 }
205 
206 
207 static void
208 init_double_fault(int cpuNum)
209 {
210 	// set up the double fault TSS
211 	struct tss* tss = &gCPU[cpuNum].arch.double_fault_tss;
212 
213 	memset(tss, 0, sizeof(struct tss));
214 	size_t stackSize;
215 	tss->sp0 = (addr_t)x86_get_double_fault_stack(cpuNum, &stackSize);
216 	tss->sp0 += stackSize;
217 	tss->ss0 = KERNEL_DATA_SELECTOR;
218 	tss->cr3 = x86_read_cr3();
219 		// copy the current cr3 to the double fault cr3
220 	tss->eip = (uint32)&double_fault;
221 	tss->es = KERNEL_DATA_SELECTOR;
222 	tss->cs = KERNEL_CODE_SELECTOR;
223 	tss->ss = KERNEL_DATA_SELECTOR;
224 	tss->esp = tss->sp0;
225 	tss->ds = KERNEL_DATA_SELECTOR;
226 	tss->fs = KERNEL_DATA_SELECTOR;
227 	tss->gs = KERNEL_DATA_SELECTOR;
228 	tss->ldt_seg_selector = 0;
229 	tss->io_map_base = sizeof(struct tss);
230 
231 	// add TSS descriptor for this new TSS
232 	set_tss_descriptor(&gGDTs[cpuNum][DOUBLE_FAULT_TSS_SEGMENT], (addr_t)tss,
233 		sizeof(struct tss));
234 
235 	set_task_gate(cpuNum, 8, DOUBLE_FAULT_TSS_SEGMENT << 3);
236 }
237 
238 
239 static void
240 init_gdt_percpu(kernel_args* args, int cpu)
241 {
242 	STATIC_ASSERT(GDT_SEGMENT_COUNT <= 8192);
243 
244 	segment_descriptor* gdt = get_gdt(cpu);
245 
246 	clear_segment_descriptor(&gdt[0]);
247 
248 	set_segment_descriptor(&gdt[KERNEL_CODE_SEGMENT], 0, addr_t(-1),
249 		DT_CODE_READABLE, DPL_KERNEL);
250 	set_segment_descriptor(&gdt[KERNEL_DATA_SEGMENT], 0, addr_t(-1),
251 		DT_DATA_WRITEABLE, DPL_KERNEL);
252 
253 	set_segment_descriptor(&gdt[USER_CODE_SEGMENT], 0, addr_t(-1),
254 		DT_CODE_READABLE, DPL_USER);
255 	set_segment_descriptor(&gdt[USER_DATA_SEGMENT], 0, addr_t(-1),
256 		DT_DATA_WRITEABLE, DPL_USER);
257 
258 	// initialize the regular and double fault tss stored in the per-cpu
259 	// structure
260 	memset(&gCPU[cpu].arch.tss, 0, sizeof(struct tss));
261 	gCPU[cpu].arch.tss.ss0 = (KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL;
262 	gCPU[cpu].arch.tss.io_map_base = sizeof(struct tss);
263 
264 	// add TSS descriptor for this new TSS
265 	set_tss_descriptor(&gdt[TSS_SEGMENT], (addr_t)&gCPU[cpu].arch.tss,
266 		sizeof(struct tss));
267 
268 	// initialize the double fault tss
269 	init_double_fault(cpu);
270 
271 	set_segment_descriptor(&gdt[KERNEL_TLS_SEGMENT],
272 		(addr_t)&gCPU[cpu].arch.kernel_tls, sizeof(void*), DT_DATA_WRITEABLE,
273 		DPL_KERNEL);
274 	set_segment_descriptor(&gdt[USER_TLS_SEGMENT], 0, TLS_SIZE,
275 		DT_DATA_WRITEABLE, DPL_USER);
276 
277 	load_gdt(cpu);
278 
279 	load_tss();
280 
281 	// set kernel TLS segment
282 	asm volatile("movw %w0, %%gs" : : "r" (KERNEL_TLS_SEGMENT << 3));
283 }
284 
285 
286 static void
287 init_idt_percpu(kernel_args* args, int cpu)
288 {
289 	set_interrupt_gate(cpu, 0, &trap0);
290 	set_interrupt_gate(cpu, 1, &trap1);
291 	set_interrupt_gate(cpu, 2, &trap2);
292 	set_trap_gate(cpu, 3, &trap3);
293 	set_interrupt_gate(cpu, 4, &trap4);
294 	set_interrupt_gate(cpu, 5, &trap5);
295 	set_interrupt_gate(cpu, 6, &trap6);
296 	set_interrupt_gate(cpu, 7, &trap7);
297 	// trap8 (double fault) is set in init_double_fault().
298 	set_interrupt_gate(cpu, 9, &trap9);
299 	set_interrupt_gate(cpu, 10, &trap10);
300 	set_interrupt_gate(cpu, 11, &trap11);
301 	set_interrupt_gate(cpu, 12, &trap12);
302 	set_interrupt_gate(cpu, 13, &trap13);
303 	set_interrupt_gate(cpu, 14, &trap14);
304 	//set_interrupt_gate(cpu, 15, &trap15);
305 	set_interrupt_gate(cpu, 16, &trap16);
306 	set_interrupt_gate(cpu, 17, &trap17);
307 	set_interrupt_gate(cpu, 18, &trap18);
308 	set_interrupt_gate(cpu, 19, &trap19);
309 
310 	// legacy or ioapic interrupts
311 	set_interrupt_gate(cpu, 32, &trap32);
312 	set_interrupt_gate(cpu, 33, &trap33);
313 	set_interrupt_gate(cpu, 34, &trap34);
314 	set_interrupt_gate(cpu, 35, &trap35);
315 	set_interrupt_gate(cpu, 36, &trap36);
316 	set_interrupt_gate(cpu, 37, &trap37);
317 	set_interrupt_gate(cpu, 38, &trap38);
318 	set_interrupt_gate(cpu, 39, &trap39);
319 	set_interrupt_gate(cpu, 40, &trap40);
320 	set_interrupt_gate(cpu, 41, &trap41);
321 	set_interrupt_gate(cpu, 42, &trap42);
322 	set_interrupt_gate(cpu, 43, &trap43);
323 	set_interrupt_gate(cpu, 44, &trap44);
324 	set_interrupt_gate(cpu, 45, &trap45);
325 	set_interrupt_gate(cpu, 46, &trap46);
326 	set_interrupt_gate(cpu, 47, &trap47);
327 
328 	// additional ioapic interrupts
329 	set_interrupt_gate(cpu, 48, &trap48);
330 	set_interrupt_gate(cpu, 49, &trap49);
331 	set_interrupt_gate(cpu, 50, &trap50);
332 	set_interrupt_gate(cpu, 51, &trap51);
333 	set_interrupt_gate(cpu, 52, &trap52);
334 	set_interrupt_gate(cpu, 53, &trap53);
335 	set_interrupt_gate(cpu, 54, &trap54);
336 	set_interrupt_gate(cpu, 55, &trap55);
337 
338 	// configurable msi or msi-x interrupts
339 	set_interrupt_gate(cpu, 56, &trap56);
340 	set_interrupt_gate(cpu, 57, &trap57);
341 	set_interrupt_gate(cpu, 58, &trap58);
342 	set_interrupt_gate(cpu, 59, &trap59);
343 	set_interrupt_gate(cpu, 60, &trap60);
344 	set_interrupt_gate(cpu, 61, &trap61);
345 	set_interrupt_gate(cpu, 62, &trap62);
346 	set_interrupt_gate(cpu, 63, &trap63);
347 	set_interrupt_gate(cpu, 64, &trap64);
348 	set_interrupt_gate(cpu, 65, &trap65);
349 	set_interrupt_gate(cpu, 66, &trap66);
350 	set_interrupt_gate(cpu, 67, &trap67);
351 	set_interrupt_gate(cpu, 68, &trap68);
352 	set_interrupt_gate(cpu, 69, &trap69);
353 	set_interrupt_gate(cpu, 70, &trap70);
354 	set_interrupt_gate(cpu, 71, &trap71);
355 	set_interrupt_gate(cpu, 72, &trap72);
356 	set_interrupt_gate(cpu, 73, &trap73);
357 	set_interrupt_gate(cpu, 74, &trap74);
358 	set_interrupt_gate(cpu, 75, &trap75);
359 	set_interrupt_gate(cpu, 76, &trap76);
360 	set_interrupt_gate(cpu, 77, &trap77);
361 	set_interrupt_gate(cpu, 78, &trap78);
362 	set_interrupt_gate(cpu, 79, &trap79);
363 	set_interrupt_gate(cpu, 80, &trap80);
364 	set_interrupt_gate(cpu, 81, &trap81);
365 	set_interrupt_gate(cpu, 82, &trap82);
366 	set_interrupt_gate(cpu, 83, &trap83);
367 	set_interrupt_gate(cpu, 84, &trap84);
368 	set_interrupt_gate(cpu, 85, &trap85);
369 	set_interrupt_gate(cpu, 86, &trap86);
370 	set_interrupt_gate(cpu, 87, &trap87);
371 	set_interrupt_gate(cpu, 88, &trap88);
372 	set_interrupt_gate(cpu, 89, &trap89);
373 	set_interrupt_gate(cpu, 90, &trap90);
374 	set_interrupt_gate(cpu, 91, &trap91);
375 	set_interrupt_gate(cpu, 92, &trap92);
376 	set_interrupt_gate(cpu, 93, &trap93);
377 	set_interrupt_gate(cpu, 94, &trap94);
378 	set_interrupt_gate(cpu, 95, &trap95);
379 	set_interrupt_gate(cpu, 96, &trap96);
380 	set_interrupt_gate(cpu, 97, &trap97);
381 
382 	set_trap_gate(cpu, 98, &trap98);	// for performance testing only
383 	set_trap_gate(cpu, 99, &trap99);	// syscall interrupt
384 
385 	// configurable msi or msi-x interrupts
386 	set_interrupt_gate(cpu, 100, &trap100);
387 	set_interrupt_gate(cpu, 101, &trap101);
388 	set_interrupt_gate(cpu, 102, &trap102);
389 	set_interrupt_gate(cpu, 103, &trap103);
390 	set_interrupt_gate(cpu, 104, &trap104);
391 	set_interrupt_gate(cpu, 105, &trap105);
392 	set_interrupt_gate(cpu, 106, &trap106);
393 	set_interrupt_gate(cpu, 107, &trap107);
394 	set_interrupt_gate(cpu, 108, &trap108);
395 	set_interrupt_gate(cpu, 109, &trap109);
396 	set_interrupt_gate(cpu, 110, &trap110);
397 	set_interrupt_gate(cpu, 111, &trap111);
398 	set_interrupt_gate(cpu, 112, &trap112);
399 	set_interrupt_gate(cpu, 113, &trap113);
400 	set_interrupt_gate(cpu, 114, &trap114);
401 	set_interrupt_gate(cpu, 115, &trap115);
402 	set_interrupt_gate(cpu, 116, &trap116);
403 	set_interrupt_gate(cpu, 117, &trap117);
404 	set_interrupt_gate(cpu, 118, &trap118);
405 	set_interrupt_gate(cpu, 119, &trap119);
406 	set_interrupt_gate(cpu, 120, &trap120);
407 	set_interrupt_gate(cpu, 121, &trap121);
408 	set_interrupt_gate(cpu, 122, &trap122);
409 	set_interrupt_gate(cpu, 123, &trap123);
410 	set_interrupt_gate(cpu, 124, &trap124);
411 	set_interrupt_gate(cpu, 125, &trap125);
412 	set_interrupt_gate(cpu, 126, &trap126);
413 	set_interrupt_gate(cpu, 127, &trap127);
414 	set_interrupt_gate(cpu, 128, &trap128);
415 	set_interrupt_gate(cpu, 129, &trap129);
416 	set_interrupt_gate(cpu, 130, &trap130);
417 	set_interrupt_gate(cpu, 131, &trap131);
418 	set_interrupt_gate(cpu, 132, &trap132);
419 	set_interrupt_gate(cpu, 133, &trap133);
420 	set_interrupt_gate(cpu, 134, &trap134);
421 	set_interrupt_gate(cpu, 135, &trap135);
422 	set_interrupt_gate(cpu, 136, &trap136);
423 	set_interrupt_gate(cpu, 137, &trap137);
424 	set_interrupt_gate(cpu, 138, &trap138);
425 	set_interrupt_gate(cpu, 139, &trap139);
426 	set_interrupt_gate(cpu, 140, &trap140);
427 	set_interrupt_gate(cpu, 141, &trap141);
428 	set_interrupt_gate(cpu, 142, &trap142);
429 	set_interrupt_gate(cpu, 143, &trap143);
430 	set_interrupt_gate(cpu, 144, &trap144);
431 	set_interrupt_gate(cpu, 145, &trap145);
432 	set_interrupt_gate(cpu, 146, &trap146);
433 	set_interrupt_gate(cpu, 147, &trap147);
434 	set_interrupt_gate(cpu, 148, &trap148);
435 	set_interrupt_gate(cpu, 149, &trap149);
436 	set_interrupt_gate(cpu, 150, &trap150);
437 	set_interrupt_gate(cpu, 151, &trap151);
438 	set_interrupt_gate(cpu, 152, &trap152);
439 	set_interrupt_gate(cpu, 153, &trap153);
440 	set_interrupt_gate(cpu, 154, &trap154);
441 	set_interrupt_gate(cpu, 155, &trap155);
442 	set_interrupt_gate(cpu, 156, &trap156);
443 	set_interrupt_gate(cpu, 157, &trap157);
444 	set_interrupt_gate(cpu, 158, &trap158);
445 	set_interrupt_gate(cpu, 159, &trap159);
446 	set_interrupt_gate(cpu, 160, &trap160);
447 	set_interrupt_gate(cpu, 161, &trap161);
448 	set_interrupt_gate(cpu, 162, &trap162);
449 	set_interrupt_gate(cpu, 163, &trap163);
450 	set_interrupt_gate(cpu, 164, &trap164);
451 	set_interrupt_gate(cpu, 165, &trap165);
452 	set_interrupt_gate(cpu, 166, &trap166);
453 	set_interrupt_gate(cpu, 167, &trap167);
454 	set_interrupt_gate(cpu, 168, &trap168);
455 	set_interrupt_gate(cpu, 169, &trap169);
456 	set_interrupt_gate(cpu, 170, &trap170);
457 	set_interrupt_gate(cpu, 171, &trap171);
458 	set_interrupt_gate(cpu, 172, &trap172);
459 	set_interrupt_gate(cpu, 173, &trap173);
460 	set_interrupt_gate(cpu, 174, &trap174);
461 	set_interrupt_gate(cpu, 175, &trap175);
462 	set_interrupt_gate(cpu, 176, &trap176);
463 	set_interrupt_gate(cpu, 177, &trap177);
464 	set_interrupt_gate(cpu, 178, &trap178);
465 	set_interrupt_gate(cpu, 179, &trap179);
466 	set_interrupt_gate(cpu, 180, &trap180);
467 	set_interrupt_gate(cpu, 181, &trap181);
468 	set_interrupt_gate(cpu, 182, &trap182);
469 	set_interrupt_gate(cpu, 183, &trap183);
470 	set_interrupt_gate(cpu, 184, &trap184);
471 	set_interrupt_gate(cpu, 185, &trap185);
472 	set_interrupt_gate(cpu, 186, &trap186);
473 	set_interrupt_gate(cpu, 187, &trap187);
474 	set_interrupt_gate(cpu, 188, &trap188);
475 	set_interrupt_gate(cpu, 189, &trap189);
476 	set_interrupt_gate(cpu, 190, &trap190);
477 	set_interrupt_gate(cpu, 191, &trap191);
478 	set_interrupt_gate(cpu, 192, &trap192);
479 	set_interrupt_gate(cpu, 193, &trap193);
480 	set_interrupt_gate(cpu, 194, &trap194);
481 	set_interrupt_gate(cpu, 195, &trap195);
482 	set_interrupt_gate(cpu, 196, &trap196);
483 	set_interrupt_gate(cpu, 197, &trap197);
484 	set_interrupt_gate(cpu, 198, &trap198);
485 	set_interrupt_gate(cpu, 199, &trap199);
486 	set_interrupt_gate(cpu, 200, &trap200);
487 	set_interrupt_gate(cpu, 201, &trap201);
488 	set_interrupt_gate(cpu, 202, &trap202);
489 	set_interrupt_gate(cpu, 203, &trap203);
490 	set_interrupt_gate(cpu, 204, &trap204);
491 	set_interrupt_gate(cpu, 205, &trap205);
492 	set_interrupt_gate(cpu, 206, &trap206);
493 	set_interrupt_gate(cpu, 207, &trap207);
494 	set_interrupt_gate(cpu, 208, &trap208);
495 	set_interrupt_gate(cpu, 209, &trap209);
496 	set_interrupt_gate(cpu, 210, &trap210);
497 	set_interrupt_gate(cpu, 211, &trap211);
498 	set_interrupt_gate(cpu, 212, &trap212);
499 	set_interrupt_gate(cpu, 213, &trap213);
500 	set_interrupt_gate(cpu, 214, &trap214);
501 	set_interrupt_gate(cpu, 215, &trap215);
502 	set_interrupt_gate(cpu, 216, &trap216);
503 	set_interrupt_gate(cpu, 217, &trap217);
504 	set_interrupt_gate(cpu, 218, &trap218);
505 	set_interrupt_gate(cpu, 219, &trap219);
506 	set_interrupt_gate(cpu, 220, &trap220);
507 	set_interrupt_gate(cpu, 221, &trap221);
508 	set_interrupt_gate(cpu, 222, &trap222);
509 	set_interrupt_gate(cpu, 223, &trap223);
510 	set_interrupt_gate(cpu, 224, &trap224);
511 	set_interrupt_gate(cpu, 225, &trap225);
512 	set_interrupt_gate(cpu, 226, &trap226);
513 	set_interrupt_gate(cpu, 227, &trap227);
514 	set_interrupt_gate(cpu, 228, &trap228);
515 	set_interrupt_gate(cpu, 229, &trap229);
516 	set_interrupt_gate(cpu, 230, &trap230);
517 	set_interrupt_gate(cpu, 231, &trap231);
518 	set_interrupt_gate(cpu, 232, &trap232);
519 	set_interrupt_gate(cpu, 233, &trap233);
520 	set_interrupt_gate(cpu, 234, &trap234);
521 	set_interrupt_gate(cpu, 235, &trap235);
522 	set_interrupt_gate(cpu, 236, &trap236);
523 	set_interrupt_gate(cpu, 237, &trap237);
524 	set_interrupt_gate(cpu, 238, &trap238);
525 	set_interrupt_gate(cpu, 239, &trap239);
526 	set_interrupt_gate(cpu, 240, &trap240);
527 	set_interrupt_gate(cpu, 241, &trap241);
528 	set_interrupt_gate(cpu, 242, &trap242);
529 	set_interrupt_gate(cpu, 243, &trap243);
530 	set_interrupt_gate(cpu, 244, &trap244);
531 	set_interrupt_gate(cpu, 245, &trap245);
532 	set_interrupt_gate(cpu, 246, &trap246);
533 	set_interrupt_gate(cpu, 247, &trap247);
534 	set_interrupt_gate(cpu, 248, &trap248);
535 	set_interrupt_gate(cpu, 249, &trap249);
536 	set_interrupt_gate(cpu, 250, &trap250);
537 
538 	// smp / apic local interrupts
539 	set_interrupt_gate(cpu, 251, &trap251);
540 	set_interrupt_gate(cpu, 252, &trap252);
541 	set_interrupt_gate(cpu, 253, &trap253);
542 	set_interrupt_gate(cpu, 254, &trap254);
543 	set_interrupt_gate(cpu, 255, &trap255);
544 
545 	load_idt(cpu);
546 }
547 
548 
549 //	#pragma mark -
550 
551 
552 void
553 x86_descriptors_preboot_init_percpu(kernel_args* args, int cpu)
554 {
555 	init_idt_percpu(args, cpu);
556 	init_gdt_percpu(args, cpu);
557 }
558 
559 
560 void
561 x86_descriptors_init(kernel_args* args)
562 {
563 	reserve_io_interrupt_vectors(2, 98, INTERRUPT_TYPE_SYSCALL);
564 
565 	// init interrupt handler table
566 	interrupt_handler_function** table = gInterruptHandlerTable;
567 
568 	// defaults
569 	uint32 i;
570 	for (i = 0; i < ARCH_INTERRUPT_BASE; i++)
571 		table[i] = x86_invalid_exception;
572 	for (i = ARCH_INTERRUPT_BASE; i < kInterruptHandlerTableSize; i++)
573 		table[i] = x86_hardware_interrupt;
574 
575 	table[0] = x86_unexpected_exception;	// Divide Error Exception (#DE)
576 	table[1] = x86_handle_debug_exception;	// Debug Exception (#DB)
577 	table[2] = x86_fatal_exception;			// NMI Interrupt
578 	table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
579 	table[4] = x86_unexpected_exception;	// Overflow Exception (#OF)
580 	table[5] = x86_unexpected_exception;	// BOUND Range Exceeded Exception (#BR)
581 	table[6] = x86_unexpected_exception;	// Invalid Opcode Exception (#UD)
582 	table[7] = x86_fatal_exception;			// Device Not Available Exception (#NM)
583 	table[8] = x86_double_fault_exception;	// Double Fault Exception (#DF)
584 	table[9] = x86_fatal_exception;			// Coprocessor Segment Overrun
585 	table[10] = x86_fatal_exception;		// Invalid TSS Exception (#TS)
586 	table[11] = x86_fatal_exception;		// Segment Not Present (#NP)
587 	table[12] = x86_fatal_exception;		// Stack Fault Exception (#SS)
588 	table[13] = x86_unexpected_exception;	// General Protection Exception (#GP)
589 	table[14] = x86_page_fault_exception;	// Page-Fault Exception (#PF)
590 	table[16] = x86_unexpected_exception;	// x87 FPU Floating-Point Error (#MF)
591 	table[17] = x86_unexpected_exception;	// Alignment Check Exception (#AC)
592 	table[18] = x86_fatal_exception;		// Machine-Check Exception (#MC)
593 	table[19] = x86_unexpected_exception;	// SIMD Floating-Point Exception (#XF)
594 }
595 
596