headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / kernel / arch / x86 / 32 / descriptors.cpp
blob94a3f16b7ce7e96112d7328daa6d075b9098b92e
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.
10 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
11 * Distributed under the terms of the NewOS License.
15 #include <arch/x86/descriptors.h>
17 #include <stdio.h>
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>
26 #include <arch/int.h>
27 #include <arch/user_debugger.h>
29 #include "interrupts.h"
32 #define IDT_GATES_COUNT 256
35 typedef interrupt_descriptor interrupt_descriptor_table[IDT_GATES_COUNT];
37 global_descriptor_table gGDTs[SMP_MAX_CPUS];
38 static interrupt_descriptor_table sIDTs[SMP_MAX_CPUS];
40 // table with functions handling respective interrupts
41 typedef void interrupt_handler_function(struct iframe* frame);
43 static const uint32 kInterruptHandlerTableSize = IDT_GATES_COUNT;
44 interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize];
47 /*! Initializes a descriptor in an IDT.
49 static void
50 set_gate(interrupt_descriptor *gate_addr, addr_t addr, int type, int dpl)
52 unsigned int gate1; // first byte of gate desc
53 unsigned int gate2; // second byte of gate desc
55 gate1 = (KERNEL_CODE_SELECTOR << 16) | (0x0000ffff & addr);
56 gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8);
58 gate_addr->a = gate1;
59 gate_addr->b = gate2;
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().
69 static void
70 set_interrupt_gate(int32 cpu, int n, void (*addr)())
72 set_gate(&sIDTs[cpu][n], (addr_t)addr, 14, DPL_KERNEL);
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().
81 static void
82 set_trap_gate(int32 cpu, int n, void (*addr)())
84 set_gate(&sIDTs[cpu][n], (unsigned int)addr, 15, DPL_USER);
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).
94 static void
95 set_task_gate(int32 cpu, int32 n, int32 segment)
97 sIDTs[cpu][n].a = (segment << 16);
98 sIDTs[cpu][n].b = 0x8000 | (0 << 13) | (0x5 << 8); // present, dpl 0, type 5
102 static inline void
103 load_tss()
105 uint16 segment = (TSS_SEGMENT << 3) | DPL_KERNEL;
106 asm("ltr %w0" : : "r" (segment));
110 static inline void
111 load_gdt(int cpu)
113 struct {
114 uint16 limit;
115 void* address;
116 } _PACKED gdtDescriptor = {
117 GDT_SEGMENT_COUNT * sizeof(segment_descriptor) - 1,
118 gGDTs[cpu]
121 asm volatile("lgdt %0" : : "m" (gdtDescriptor));
125 static inline void
126 load_idt(int cpu)
128 struct {
129 uint16 limit;
130 void* address;
131 } _PACKED idtDescriptor = {
132 IDT_GATES_COUNT * sizeof(interrupt_descriptor) - 1,
133 &sIDTs[cpu]
136 asm volatile("lidt %0" : : "m" (idtDescriptor));
140 // #pragma mark - Double fault handling
143 void
144 x86_double_fault_exception(struct iframe* frame)
146 int cpu = x86_double_fault_get_cpu();
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;
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;
172 // Use a special handler for page faults which avoids the triple fault
173 // pitfalls.
174 set_interrupt_gate(cpu, 14, &trap14_double_fault);
176 debug_double_fault(cpu);
180 void
181 x86_page_fault_exception_double_fault(struct iframe* frame)
183 addr_t cr2 = x86_read_cr2();
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;
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);
203 while (true);
207 static void
208 init_double_fault(int cpuNum)
210 // set up the double fault TSS
211 struct tss* tss = &gCPU[cpuNum].arch.double_fault_tss;
213 memset(tss, 0, sizeof(struct tss));
214 size_t stackSize = 0;
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);
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));
235 set_task_gate(cpuNum, 8, DOUBLE_FAULT_TSS_SEGMENT << 3);
239 static void
240 init_gdt_percpu(kernel_args* args, int cpu)
242 STATIC_ASSERT(GDT_SEGMENT_COUNT <= 8192);
244 segment_descriptor* gdt = get_gdt(cpu);
246 clear_segment_descriptor(&gdt[0]);
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);
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);
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);
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));
268 // initialize the double fault tss
269 init_double_fault(cpu);
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);
277 load_gdt(cpu);
279 load_tss();
281 // set kernel TLS segment
282 asm volatile("movw %w0, %%gs" : : "r" (KERNEL_TLS_SEGMENT << 3));
286 static void
287 init_idt_percpu(kernel_args* args, int cpu)
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);
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);
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);
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);
382 set_trap_gate(cpu, 98, &trap98); // for performance testing only
383 set_trap_gate(cpu, 99, &trap99); // syscall interrupt
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);
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);
545 load_idt(cpu);
549 // #pragma mark -
552 void
553 x86_descriptors_preboot_init_percpu(kernel_args* args, int cpu)
555 init_idt_percpu(args, cpu);
556 init_gdt_percpu(args, cpu);
560 void
561 x86_descriptors_init(kernel_args* args)
563 reserve_io_interrupt_vectors(2, 98, INTERRUPT_TYPE_SYSCALL);
565 // init interrupt handler table
566 interrupt_handler_function** table = gInterruptHandlerTable;
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;
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)