xref: /haiku/src/system/kernel/arch/x86/arch_int.cpp (revision 97901ec593ec4dd50ac115c1c35a6d72f6e489a5)
1 /*
2  * Copyright 2010, Clemens Zeidler, haiku@clemens-zeidler.de.
3  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
4  * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de.
5  * Distributed under the terms of the MIT License.
6  *
7  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8  * Distributed under the terms of the NewOS License.
9  */
10 
11 
12 #include <cpu.h>
13 #include <int.h>
14 #include <kscheduler.h>
15 #include <ksyscalls.h>
16 #include <smp.h>
17 #include <team.h>
18 #include <thread.h>
19 #include <vm/vm.h>
20 #include <vm/vm_priv.h>
21 
22 #include <arch/cpu.h>
23 #include <arch/int.h>
24 #include <arch/smp.h>
25 #include <arch/user_debugger.h>
26 #include <arch/vm.h>
27 
28 #include <arch/x86/apic.h>
29 #include <arch/x86/descriptors.h>
30 #include <arch/x86/vm86.h>
31 
32 #include "interrupts.h"
33 #include "irq_routing_table.h"
34 
35 #include <ACPI.h>
36 #include <AutoDeleter.h>
37 #include <safemode.h>
38 #include <string.h>
39 #include <stdio.h>
40 
41 
42 //#define TRACE_ARCH_INT
43 #ifdef TRACE_ARCH_INT
44 #	define TRACE(x) dprintf x
45 #else
46 #	define TRACE(x) ;
47 #endif
48 
49 
50 // Definitions for the PIC 8259 controller
51 // (this is not a complete list, only what we're actually using)
52 
53 #define PIC_MASTER_CONTROL		0x20
54 #define PIC_MASTER_MASK			0x21
55 #define PIC_SLAVE_CONTROL		0xa0
56 #define PIC_SLAVE_MASK			0xa1
57 #define PIC_MASTER_INIT1		PIC_MASTER_CONTROL
58 #define PIC_MASTER_INIT2		PIC_MASTER_MASK
59 #define PIC_MASTER_INIT3		PIC_MASTER_MASK
60 #define PIC_MASTER_INIT4		PIC_MASTER_MASK
61 #define PIC_SLAVE_INIT1			PIC_SLAVE_CONTROL
62 #define PIC_SLAVE_INIT2			PIC_SLAVE_MASK
63 #define PIC_SLAVE_INIT3			PIC_SLAVE_MASK
64 #define PIC_SLAVE_INIT4			PIC_SLAVE_MASK
65 
66 // the edge/level trigger control registers
67 #define PIC_MASTER_TRIGGER_MODE	0x4d0
68 #define PIC_SLAVE_TRIGGER_MODE	0x4d1
69 
70 #define PIC_INIT1				0x10
71 #define PIC_INIT1_SEND_INIT4	0x01
72 #define PIC_INIT3_IR2_IS_SLAVE	0x04
73 #define PIC_INIT3_SLAVE_ID2		0x02
74 #define PIC_INIT4_x86_MODE		0x01
75 
76 #define PIC_CONTROL3			0x08
77 #define PIC_CONTROL3_READ_ISR	0x03
78 #define PIC_CONTROL3_READ_IRR	0x02
79 
80 #define PIC_NON_SPECIFIC_EOI	0x20
81 
82 #define PIC_SLAVE_INT_BASE		8
83 #define PIC_NUM_INTS			0x0f
84 
85 
86 // Definitions for a 82093AA IO APIC controller
87 #define IO_APIC_IDENTIFICATION				0x00
88 #define IO_APIC_VERSION						0x01
89 #define IO_APIC_ARBITRATION					0x02
90 #define IO_APIC_REDIRECTION_TABLE			0x10 // entry = base + 2 * index
91 
92 // Fields for the version register
93 #define IO_APIC_VERSION_SHIFT				0
94 #define IO_APIC_VERSION_MASK				0xff
95 #define IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT	16
96 #define IO_APIC_MAX_REDIRECTION_ENTRY_MASK	0xff
97 
98 // Fields of each redirection table entry
99 #define IO_APIC_DESTINATION_FIELD_SHIFT		56
100 #define IO_APIC_DESTINATION_FIELD_MASK		0x0f
101 #define IO_APIC_INTERRUPT_MASK_SHIFT		16
102 #define IO_APIC_INTERRUPT_MASKED			1
103 #define IO_APIC_INTERRUPT_UNMASKED			0
104 #define IO_APIC_TRIGGER_MODE_SHIFT			15
105 #define IO_APIC_TRIGGER_MODE_EDGE			0
106 #define IO_APIC_TRIGGER_MODE_LEVEL			1
107 #define IO_APIC_REMOTE_IRR_SHIFT			14
108 #define IO_APIC_PIN_POLARITY_SHIFT			13
109 #define IO_APIC_PIN_POLARITY_HIGH_ACTIVE	0
110 #define IO_APIC_PIN_POLARITY_LOW_ACTIVE		1
111 #define IO_APIC_DELIVERY_STATUS_SHIFT		12
112 #define IO_APIC_DELIVERY_STATUS_IDLE		0
113 #define IO_APIC_DELIVERY_STATUS_PENDING		1
114 #define IO_APIC_DESTINATION_MODE_SHIFT		11
115 #define IO_APIC_DESTINATION_MODE_PHYSICAL	0
116 #define IO_APIC_DESTINATION_MODE_LOGICAL	1
117 #define IO_APIC_DELIVERY_MODE_SHIFT			8
118 #define IO_APIC_DELIVERY_MODE_MASK			0x07
119 #define IO_APIC_DELIVERY_MODE_FIXED			0
120 #define IO_APIC_DELIVERY_MODE_LOWEST_PRIO	1
121 #define IO_APIC_DELIVERY_MODE_SMI			2
122 #define IO_APIC_DELIVERY_MODE_NMI			4
123 #define IO_APIC_DELIVERY_MODE_INIT			5
124 #define IO_APIC_DELIVERY_MODE_EXT_INT		7
125 #define IO_APIC_INTERRUPT_VECTOR_SHIFT		0
126 #define IO_APIC_INTERRUPT_VECTOR_MASK		0xff
127 
128 typedef struct ioapic_s {
129 	volatile uint32	io_register_select;
130 	uint32			reserved[3];
131 	volatile uint32	io_window_register;
132 } ioapic;
133 
134 static ioapic *sIOAPIC = NULL;
135 static uint32 sIOAPICMaxRedirectionEntry = 23;
136 
137 static uint32 sIRQToIOAPICPin[256];
138 
139 typedef struct interrupt_controller_s {
140 	const char *name;
141 	void	(*enable_io_interrupt)(int32 num);
142 	void	(*disable_io_interrupt)(int32 num);
143 	void	(*configure_io_interrupt)(int32 num, uint32 config);
144 	bool	(*is_spurious_interrupt)(int32 num);
145 	bool	(*end_of_interrupt)(int32 num);
146 } interrupt_controller;
147 
148 static const interrupt_controller *sCurrentPIC = NULL;
149 
150 static const char *kInterruptNames[] = {
151 	/*  0 */ "Divide Error Exception",
152 	/*  1 */ "Debug Exception",
153 	/*  2 */ "NMI Interrupt",
154 	/*  3 */ "Breakpoint Exception",
155 	/*  4 */ "Overflow Exception",
156 	/*  5 */ "BOUND Range Exceeded Exception",
157 	/*  6 */ "Invalid Opcode Exception",
158 	/*  7 */ "Device Not Available Exception",
159 	/*  8 */ "Double Fault Exception",
160 	/*  9 */ "Coprocessor Segment Overrun",
161 	/* 10 */ "Invalid TSS Exception",
162 	/* 11 */ "Segment Not Present",
163 	/* 12 */ "Stack Fault Exception",
164 	/* 13 */ "General Protection Exception",
165 	/* 14 */ "Page-Fault Exception",
166 	/* 15 */ "-",
167 	/* 16 */ "x87 FPU Floating-Point Error",
168 	/* 17 */ "Alignment Check Exception",
169 	/* 18 */ "Machine-Check Exception",
170 	/* 19 */ "SIMD Floating-Point Exception",
171 };
172 static const int kInterruptNameCount = 20;
173 
174 #define MAX_ARGS 16
175 
176 typedef struct {
177 	uint32 a, b;
178 } desc_table;
179 static desc_table* sIDTs[B_MAX_CPU_COUNT];
180 
181 static uint32 sLevelTriggeredInterrupts = 0;
182 	// binary mask: 1 level, 0 edge
183 
184 // table with functions handling respective interrupts
185 typedef void interrupt_handler_function(struct iframe* frame);
186 #define INTERRUPT_HANDLER_TABLE_SIZE 256
187 interrupt_handler_function* gInterruptHandlerTable[
188 	INTERRUPT_HANDLER_TABLE_SIZE];
189 
190 
191 /*!	Initializes a descriptor in an IDT.
192 */
193 static void
194 set_gate(desc_table *gate_addr, addr_t addr, int type, int dpl)
195 {
196 	unsigned int gate1; // first byte of gate desc
197 	unsigned int gate2; // second byte of gate desc
198 
199 	gate1 = (KERNEL_CODE_SEG << 16) | (0x0000ffff & addr);
200 	gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8);
201 
202 	gate_addr->a = gate1;
203 	gate_addr->b = gate2;
204 }
205 
206 
207 /*!	Initializes the descriptor for interrupt vector \a n in the IDT of the
208 	specified CPU to an interrupt-gate descriptor with the given procedure
209 	address.
210 	For CPUs other than the boot CPU it must not be called before
211 	arch_int_init_post_vm().
212 */
213 static void
214 set_interrupt_gate(int32 cpu, int n, void (*addr)())
215 {
216 	set_gate(&sIDTs[cpu][n], (addr_t)addr, 14, DPL_KERNEL);
217 }
218 
219 
220 /*!	Initializes the descriptor for interrupt vector \a n in the IDT of the
221 	specified CPU to an trap-gate descriptor with the given procedure address.
222 	For CPUs other than the boot CPU it must not be called before
223 	arch_int_init_post_vm().
224 */
225 static void
226 set_trap_gate(int32 cpu, int n, void (*addr)())
227 {
228 	set_gate(&sIDTs[cpu][n], (unsigned int)addr, 15, DPL_USER);
229 }
230 
231 
232 /*!	Initializes the descriptor for interrupt vector \a n in the IDT of CPU
233 	\a cpu to a task-gate descripter referring to the TSS segment identified
234 	by TSS segment selector \a segment.
235 	For CPUs other than the boot CPU it must not be called before
236 	arch_int_init_post_vm() (arch_cpu_init_post_vm() is fine).
237 */
238 void
239 x86_set_task_gate(int32 cpu, int32 n, int32 segment)
240 {
241 	sIDTs[cpu][n].a = (segment << 16);
242 	sIDTs[cpu][n].b = 0x8000 | (0 << 13) | (0x5 << 8); // present, dpl 0, type 5
243 }
244 
245 
246 /*!	Returns the virtual IDT address for CPU \a cpu. */
247 void*
248 x86_get_idt(int32 cpu)
249 {
250 	return sIDTs[cpu];
251 }
252 
253 
254 // #pragma mark - PIC
255 
256 
257 /*!	Tests if the interrupt in-service register of the responsible
258 	PIC is set for interrupts 7 and 15, and if that's not the case,
259 	it must assume it's a spurious interrupt.
260 */
261 static bool
262 pic_is_spurious_interrupt(int32 num)
263 {
264 	if (num != 7)
265 		return false;
266 
267 	// Note, detecting spurious interrupts on line 15 obviously doesn't
268 	// work correctly - and since those are extremely rare, anyway, we
269 	// just ignore them
270 
271 	out8(PIC_CONTROL3 | PIC_CONTROL3_READ_ISR, PIC_MASTER_CONTROL);
272 	int32 isr = in8(PIC_MASTER_CONTROL);
273 	out8(PIC_CONTROL3 | PIC_CONTROL3_READ_IRR, PIC_MASTER_CONTROL);
274 
275 	return (isr & 0x80) == 0;
276 }
277 
278 
279 /*!	Sends a non-specified EOI (end of interrupt) notice to the PIC in
280 	question (or both of them).
281 	This clears the PIC interrupt in-service bit.
282 */
283 static bool
284 pic_end_of_interrupt(int32 num)
285 {
286 	if (num < 0 || num > PIC_NUM_INTS)
287 		return false;
288 
289 	// PIC 8259 controlled interrupt
290 	if (num >= PIC_SLAVE_INT_BASE)
291 		out8(PIC_NON_SPECIFIC_EOI, PIC_SLAVE_CONTROL);
292 
293 	// we always need to acknowledge the master PIC
294 	out8(PIC_NON_SPECIFIC_EOI, PIC_MASTER_CONTROL);
295 	return true;
296 }
297 
298 
299 static void
300 pic_enable_io_interrupt(int32 num)
301 {
302 	// interrupt is specified "normalized"
303 	if (num < 0 || num > PIC_NUM_INTS)
304 		return;
305 
306 	// enable PIC 8259 controlled interrupt
307 
308 	TRACE(("pic_enable_io_interrupt: irq %ld\n", num));
309 
310 	if (num < PIC_SLAVE_INT_BASE)
311 		out8(in8(PIC_MASTER_MASK) & ~(1 << num), PIC_MASTER_MASK);
312 	else
313 		out8(in8(PIC_SLAVE_MASK) & ~(1 << (num - PIC_SLAVE_INT_BASE)), PIC_SLAVE_MASK);
314 }
315 
316 
317 static void
318 pic_disable_io_interrupt(int32 num)
319 {
320 	// interrupt is specified "normalized"
321 	// never disable slave pic line IRQ 2
322 	if (num < 0 || num > PIC_NUM_INTS || num == 2)
323 		return;
324 
325 	// disable PIC 8259 controlled interrupt
326 
327 	TRACE(("pic_disable_io_interrupt: irq %ld\n", num));
328 
329 	if (num < PIC_SLAVE_INT_BASE)
330 		out8(in8(PIC_MASTER_MASK) | (1 << num), PIC_MASTER_MASK);
331 	else
332 		out8(in8(PIC_SLAVE_MASK) | (1 << (num - PIC_SLAVE_INT_BASE)), PIC_SLAVE_MASK);
333 }
334 
335 
336 static void
337 pic_configure_io_interrupt(int32 num, uint32 config)
338 {
339 	uint8 value;
340 	int32 localBit;
341 	if (num < 0 || num > PIC_NUM_INTS || num == 2)
342 		return;
343 
344 	TRACE(("pic_configure_io_interrupt: irq %ld; config 0x%08lx\n", num, config));
345 
346 	if (num < PIC_SLAVE_INT_BASE) {
347 		value = in8(PIC_MASTER_TRIGGER_MODE);
348 		localBit = num;
349 	} else {
350 		value = in8(PIC_SLAVE_TRIGGER_MODE);
351 		localBit = num - PIC_SLAVE_INT_BASE;
352 	}
353 
354 	if (config & B_LEVEL_TRIGGERED)
355 		value |= 1 << localBit;
356 	else
357 		value &= ~(1 << localBit);
358 
359 	if (num < PIC_SLAVE_INT_BASE)
360 		out8(value, PIC_MASTER_TRIGGER_MODE);
361 	else
362 		out8(value, PIC_SLAVE_TRIGGER_MODE);
363 
364 	sLevelTriggeredInterrupts = in8(PIC_MASTER_TRIGGER_MODE)
365 		| (in8(PIC_SLAVE_TRIGGER_MODE) << 8);
366 }
367 
368 
369 static void
370 pic_init(void)
371 {
372 	static interrupt_controller picController = {
373 		"8259 PIC",
374 		&pic_enable_io_interrupt,
375 		&pic_disable_io_interrupt,
376 		&pic_configure_io_interrupt,
377 		&pic_is_spurious_interrupt,
378 		&pic_end_of_interrupt
379 	};
380 
381 	// Start initialization sequence for the master and slave PICs
382 	out8(PIC_INIT1 | PIC_INIT1_SEND_INIT4, PIC_MASTER_INIT1);
383 	out8(PIC_INIT1 | PIC_INIT1_SEND_INIT4, PIC_SLAVE_INIT1);
384 
385 	// Set start of interrupts to 0x20 for master, 0x28 for slave
386 	out8(ARCH_INTERRUPT_BASE, PIC_MASTER_INIT2);
387 	out8(ARCH_INTERRUPT_BASE + PIC_SLAVE_INT_BASE, PIC_SLAVE_INIT2);
388 
389 	// Specify cascading through interrupt 2
390 	out8(PIC_INIT3_IR2_IS_SLAVE, PIC_MASTER_INIT3);
391 	out8(PIC_INIT3_SLAVE_ID2, PIC_SLAVE_INIT3);
392 
393 	// Set both to operate in 8086 mode
394 	out8(PIC_INIT4_x86_MODE, PIC_MASTER_INIT4);
395 	out8(PIC_INIT4_x86_MODE, PIC_SLAVE_INIT4);
396 
397 	out8(0xfb, PIC_MASTER_MASK);	// Mask off all interrupts (except slave pic line IRQ 2).
398 	out8(0xff, PIC_SLAVE_MASK); 	// Mask off interrupts on the slave.
399 
400 	// determine which interrupts are level or edge triggered
401 
402 #if 0
403 	// should set everything possible to level triggered
404 	out8(0xf8, PIC_MASTER_TRIGGER_MODE);
405 	out8(0xde, PIC_SLAVE_TRIGGER_MODE);
406 #endif
407 
408 	sLevelTriggeredInterrupts = in8(PIC_MASTER_TRIGGER_MODE)
409 		| (in8(PIC_SLAVE_TRIGGER_MODE) << 8);
410 
411 	TRACE(("PIC level trigger mode: 0x%08lx\n", sLevelTriggeredInterrupts));
412 
413 	// make the pic controller the current one
414 	sCurrentPIC = &picController;
415 }
416 
417 
418 // #pragma mark - I/O APIC
419 
420 
421 static inline uint32
422 ioapic_read_32(uint8 registerSelect)
423 {
424 	sIOAPIC->io_register_select = registerSelect;
425 	return sIOAPIC->io_window_register;
426 }
427 
428 
429 static inline void
430 ioapic_write_32(uint8 registerSelect, uint32 value)
431 {
432 	sIOAPIC->io_register_select = registerSelect;
433 	sIOAPIC->io_window_register = value;
434 }
435 
436 
437 static inline uint64
438 ioapic_read_64(uint8 registerSelect)
439 {
440 	sIOAPIC->io_register_select = registerSelect + 1;
441 	uint64 result = sIOAPIC->io_window_register;
442 	result <<= 32;
443 	sIOAPIC->io_register_select = registerSelect;
444 	result |= sIOAPIC->io_window_register;
445 	return result;
446 }
447 
448 
449 static inline void
450 ioapic_write_64(uint8 registerSelect, uint64 value)
451 {
452 	sIOAPIC->io_register_select = registerSelect;
453 	sIOAPIC->io_window_register = (uint32)value;
454 	sIOAPIC->io_register_select = registerSelect + 1;
455 	sIOAPIC->io_window_register = (uint32)(value >> 32);
456 }
457 
458 
459 static bool
460 ioapic_is_spurious_interrupt(int32 num)
461 {
462 	// the spurious interrupt vector is initialized to the max value in smp
463 	return num == 0xff - ARCH_INTERRUPT_BASE;
464 }
465 
466 
467 static bool
468 ioapic_end_of_interrupt(int32 num)
469 {
470 	apic_end_of_interrupt();
471 	return true;
472 }
473 
474 
475 static void
476 ioapic_enable_io_interrupt(int32 num)
477 {
478 	int32 pin = sIRQToIOAPICPin[num];
479 	if (pin < 0 || pin > (int32)sIOAPICMaxRedirectionEntry)
480 		return;
481 
482 	TRACE(("ioapic_enable_io_interrupt: IRQ %ld -> pin %ld\n", num, pin));
483 
484 	uint64 entry = ioapic_read_64(IO_APIC_REDIRECTION_TABLE + pin * 2);
485 	entry &= ~(1 << IO_APIC_INTERRUPT_MASK_SHIFT);
486 	entry |= IO_APIC_INTERRUPT_UNMASKED << IO_APIC_INTERRUPT_MASK_SHIFT;
487 	ioapic_write_64(IO_APIC_REDIRECTION_TABLE + pin * 2, entry);
488 }
489 
490 
491 static void
492 ioapic_disable_io_interrupt(int32 num)
493 {
494 	int32 pin = sIRQToIOAPICPin[num];
495 	if (pin < 0 || pin > (int32)sIOAPICMaxRedirectionEntry)
496 		return;
497 
498 	TRACE(("ioapic_disable_io_interrupt: IRQ %ld -> pin %ld\n", num, pin));
499 
500 	uint64 entry = ioapic_read_64(IO_APIC_REDIRECTION_TABLE + pin * 2);
501 	entry &= ~(1 << IO_APIC_INTERRUPT_MASK_SHIFT);
502 	entry |= IO_APIC_INTERRUPT_MASKED << IO_APIC_INTERRUPT_MASK_SHIFT;
503 	ioapic_write_64(IO_APIC_REDIRECTION_TABLE + pin * 2, entry);
504 }
505 
506 
507 static void
508 ioapic_configure_io_interrupt(int32 num, uint32 config)
509 {
510 	int32 pin = sIRQToIOAPICPin[num];
511 	if (pin < 0 || pin > (int32)sIOAPICMaxRedirectionEntry)
512 		return;
513 
514 	TRACE(("ioapic_configure_io_interrupt: IRQ %ld -> pin %ld; config 0x%08lx\n",
515 		num, pin, config));
516 
517 	uint64 entry = ioapic_read_64(IO_APIC_REDIRECTION_TABLE + pin * 2);
518 	entry &= ~((1 << IO_APIC_TRIGGER_MODE_SHIFT)
519 		| (1 << IO_APIC_PIN_POLARITY_SHIFT)
520 		| (IO_APIC_INTERRUPT_VECTOR_MASK << IO_APIC_INTERRUPT_VECTOR_SHIFT));
521 
522 	if (config & B_LEVEL_TRIGGERED) {
523 		entry |= (IO_APIC_TRIGGER_MODE_LEVEL << IO_APIC_TRIGGER_MODE_SHIFT);
524 		sLevelTriggeredInterrupts |= (1 << num);
525 	} else {
526 		entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT);
527 		sLevelTriggeredInterrupts &= ~(1 << num);
528 	}
529 
530 	if (config & B_LOW_ACTIVE_POLARITY)
531 		entry |= (IO_APIC_PIN_POLARITY_LOW_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT);
532 	else
533 		entry |= (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT);
534 
535 	entry |= (num + ARCH_INTERRUPT_BASE) << IO_APIC_INTERRUPT_VECTOR_SHIFT;
536 	ioapic_write_64(IO_APIC_REDIRECTION_TABLE + pin * 2, entry);
537 }
538 
539 
540 static void
541 ioapic_map(kernel_args* args)
542 {
543 	if (args->arch_args.apic == NULL) {
544 		dprintf("no local apic available\n");
545 		return;
546 	}
547 
548 	if (args->arch_args.ioapic == NULL) {
549 		dprintf("no ioapic available, not using ioapics for interrupt routing\n");
550 		return;
551 	}
552 
553 	// map in the ioapic
554 	sIOAPIC = (ioapic *)args->arch_args.ioapic;
555 	if (vm_map_physical_memory(B_SYSTEM_TEAM, "ioapic", (void**)&sIOAPIC,
556 			B_EXACT_ADDRESS, B_PAGE_SIZE,
557 			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
558 			args->arch_args.ioapic_phys, true) < 0) {
559 		panic("mapping the ioapic failed");
560 		return;
561 	}
562 }
563 
564 
565 static void
566 ioapic_init(kernel_args* args)
567 {
568 	static const interrupt_controller ioapicController = {
569 		"82093AA IOAPIC",
570 		&ioapic_enable_io_interrupt,
571 		&ioapic_disable_io_interrupt,
572 		&ioapic_configure_io_interrupt,
573 		&ioapic_is_spurious_interrupt,
574 		&ioapic_end_of_interrupt
575 	};
576 
577 	if (sIOAPIC == NULL)
578 		return;
579 
580 	if (!get_safemode_boolean(B_SAFEMODE_DISABLE_IOAPIC, true)) {
581 		dprintf("ioapic explicitly disabled, not using ioapics for interrupt "
582 			"routing\n");
583 		return;
584 	}
585 
586 	uint32 version = ioapic_read_32(IO_APIC_VERSION);
587 	if (version == 0xffffffff) {
588 		dprintf("ioapic seems inaccessible, not using it\n");
589 		return;
590 	}
591 
592 	// load acpi module
593 	status_t status;
594 	acpi_module_info* acpiModule;
595 	status = get_module(B_ACPI_MODULE_NAME, (module_info**)&acpiModule);
596 	if (status != B_OK) {
597 		dprintf("acpi module not available, not configuring ioapic\n");
598 		return;
599 	}
600 	BPrivate::CObjectDeleter<const char, status_t>
601 		acpiModulePutter(B_ACPI_MODULE_NAME, put_module);
602 
603 	// load pci module
604 	pci_module_info* pciModule;
605 	status = get_module(B_PCI_MODULE_NAME, (module_info**)&pciModule);
606 	if (status != B_OK) {
607 		dprintf("could not load pci module, not configuring ioapic\n");
608 		return;
609 	}
610 	CObjectDeleter<const char, status_t> pciModulePutter(B_PCI_MODULE_NAME,
611 		put_module);
612 
613 	// TODO: here ACPI needs to be used to properly set up the PCI IRQ
614 	// routing.
615 
616 	IRQRoutingTable table;
617 	status = read_irq_routing_table(pciModule, acpiModule, &table);
618 	if (status != B_OK) {
619 		dprintf("reading IRQ routing table failed, no ioapic.\n");
620 		return;
621 	}
622 
623 	sLevelTriggeredInterrupts = 0;
624 	sIOAPICMaxRedirectionEntry
625 		= ((version >> IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT)
626 			& IO_APIC_MAX_REDIRECTION_ENTRY_MASK);
627 
628 	// use the boot CPU as the target for all interrupts
629 	uint64 targetAPIC = args->arch_args.cpu_apic_id[0];
630 
631 	// program the interrupt vectors of the ioapic
632 	for (uint32 i = 0; i <= sIOAPICMaxRedirectionEntry; i++) {
633 		// initialize everything to deliver to the boot CPU in physical mode
634 		// and masked until explicitly enabled through enable_io_interrupt()
635 		uint64 entry = (targetAPIC << IO_APIC_DESTINATION_FIELD_SHIFT)
636 			| (IO_APIC_INTERRUPT_MASKED << IO_APIC_INTERRUPT_MASK_SHIFT)
637 			| (IO_APIC_DESTINATION_MODE_PHYSICAL << IO_APIC_DESTINATION_MODE_SHIFT)
638 			| ((i + ARCH_INTERRUPT_BASE) << IO_APIC_INTERRUPT_VECTOR_SHIFT);
639 
640 		if (i == 0) {
641 			// make redirection entry 0 into an external interrupt
642 			entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT)
643 				| (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT)
644 				| (IO_APIC_DELIVERY_MODE_EXT_INT << IO_APIC_DELIVERY_MODE_SHIFT);
645 		} else if (i < 16) {
646 			// make 1-15 ISA interrupts
647 			entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT)
648 				| (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT)
649 				| (IO_APIC_DELIVERY_MODE_FIXED << IO_APIC_DELIVERY_MODE_SHIFT);
650 		} else {
651 			// and the rest are PCI interrupts
652 			entry |= (IO_APIC_TRIGGER_MODE_LEVEL << IO_APIC_TRIGGER_MODE_SHIFT)
653 				| (IO_APIC_PIN_POLARITY_LOW_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT)
654 				| (IO_APIC_DELIVERY_MODE_FIXED << IO_APIC_DELIVERY_MODE_SHIFT);
655 			sLevelTriggeredInterrupts |= (1 << i);
656 		}
657 
658 		ioapic_write_64(IO_APIC_REDIRECTION_TABLE + 2 * i, entry);
659 	}
660 
661 	// setup default 1:1 mapping
662 	for (uint32 i = 0; i < 256; i++)
663 		sIRQToIOAPICPin[i] = i;
664 
665 	// configure apic interrupts assume 1:1 mapping
666 	for (int i = 0; i < table.Count(); i++) {
667 		irq_routing_entry& entry = table.ElementAt(i);
668 		irq_descriptor irqDescriptor;
669 		read_current_irq(acpiModule, entry.source, &irqDescriptor);
670 		uint32 config = 0;
671 		config |= irqDescriptor.polarity;
672 		config |= irqDescriptor.interrupt_mode;
673 		ioapic_configure_io_interrupt(irqDescriptor.irq, config);
674 	}
675 
676 	// prefer the ioapic over the normal pic
677 	dprintf("using ioapic for interrupt routing\n");
678 	sCurrentPIC = &ioapicController;
679 }
680 
681 
682 // #pragma mark -
683 
684 
685 void
686 arch_int_enable_io_interrupt(int irq)
687 {
688 	sCurrentPIC->enable_io_interrupt(irq);
689 }
690 
691 
692 void
693 arch_int_disable_io_interrupt(int irq)
694 {
695 	sCurrentPIC->disable_io_interrupt(irq);
696 }
697 
698 
699 void
700 arch_int_configure_io_interrupt(int irq, uint32 config)
701 {
702 	sCurrentPIC->configure_io_interrupt(irq, config);
703 }
704 
705 
706 #undef arch_int_enable_interrupts
707 #undef arch_int_disable_interrupts
708 #undef arch_int_restore_interrupts
709 #undef arch_int_are_interrupts_enabled
710 
711 
712 void
713 arch_int_enable_interrupts(void)
714 {
715 	arch_int_enable_interrupts_inline();
716 }
717 
718 
719 int
720 arch_int_disable_interrupts(void)
721 {
722 	return arch_int_disable_interrupts_inline();
723 }
724 
725 
726 void
727 arch_int_restore_interrupts(int oldState)
728 {
729 	arch_int_restore_interrupts_inline(oldState);
730 }
731 
732 
733 bool
734 arch_int_are_interrupts_enabled(void)
735 {
736 	return arch_int_are_interrupts_enabled_inline();
737 }
738 
739 
740 static const char *
741 exception_name(int number, char *buffer, int32 bufferSize)
742 {
743 	if (number >= 0 && number < kInterruptNameCount)
744 		return kInterruptNames[number];
745 
746 	snprintf(buffer, bufferSize, "exception %d", number);
747 	return buffer;
748 }
749 
750 
751 static void
752 invalid_exception(struct iframe* frame)
753 {
754 	struct thread* thread = thread_get_current_thread();
755 	char name[32];
756 	panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n",
757 		frame->vector, exception_name(frame->vector, name, sizeof(name)),
758 		frame->eip, thread ? thread->id : -1);
759 }
760 
761 
762 static void
763 fatal_exception(struct iframe *frame)
764 {
765 	char name[32];
766 	panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n",
767 		exception_name(frame->vector, name, sizeof(name)), frame->error_code);
768 }
769 
770 
771 static void
772 unexpected_exception(struct iframe* frame)
773 {
774 	debug_exception_type type;
775 	int signal;
776 
777 	if (IFRAME_IS_VM86(frame)) {
778 		x86_vm86_return((struct vm86_iframe *)frame, (frame->vector == 13) ?
779 			B_OK : B_ERROR);
780 		// won't get here
781 	}
782 
783 	switch (frame->vector) {
784 		case 0:		// Divide Error Exception (#DE)
785 			type = B_DIVIDE_ERROR;
786 			signal = SIGFPE;
787 			break;
788 
789 		case 4:		// Overflow Exception (#OF)
790 			type = B_OVERFLOW_EXCEPTION;
791 			signal = SIGTRAP;
792 			break;
793 
794 		case 5:		// BOUND Range Exceeded Exception (#BR)
795 			type = B_BOUNDS_CHECK_EXCEPTION;
796 			signal = SIGTRAP;
797 			break;
798 
799 		case 6:		// Invalid Opcode Exception (#UD)
800 			type = B_INVALID_OPCODE_EXCEPTION;
801 			signal = SIGILL;
802 			break;
803 
804 		case 13: 	// General Protection Exception (#GP)
805 			type = B_GENERAL_PROTECTION_FAULT;
806 			signal = SIGILL;
807 			break;
808 
809 		case 16: 	// x87 FPU Floating-Point Error (#MF)
810 			type = B_FLOATING_POINT_EXCEPTION;
811 			signal = SIGFPE;
812 			break;
813 
814 		case 17: 	// Alignment Check Exception (#AC)
815 			type = B_ALIGNMENT_EXCEPTION;
816 			signal = SIGTRAP;
817 			break;
818 
819 		case 19: 	// SIMD Floating-Point Exception (#XF)
820 			type = B_FLOATING_POINT_EXCEPTION;
821 			signal = SIGFPE;
822 			break;
823 
824 		default:
825 			invalid_exception(frame);
826 			return;
827 	}
828 
829 	if (IFRAME_IS_USER(frame)) {
830 		struct sigaction action;
831 		struct thread* thread = thread_get_current_thread();
832 
833 		enable_interrupts();
834 
835 		// If the thread has a signal handler for the signal, we simply send it
836 		// the signal. Otherwise we notify the user debugger first.
837 		if (sigaction(signal, NULL, &action) == 0
838 			&& action.sa_handler != SIG_DFL
839 			&& action.sa_handler != SIG_IGN) {
840 			send_signal(thread->id, signal);
841 		} else if (user_debug_exception_occurred(type, signal))
842 			send_signal(team_get_current_team_id(), signal);
843 	} else {
844 		char name[32];
845 		panic("Unexpected exception \"%s\" occurred in kernel mode! "
846 			"Error code: 0x%lx\n",
847 			exception_name(frame->vector, name, sizeof(name)),
848 			frame->error_code);
849 	}
850 }
851 
852 
853 void
854 x86_double_fault_exception(struct iframe* frame)
855 {
856 	int cpu = x86_double_fault_get_cpu();
857 
858 	// The double fault iframe contains no useful information (as
859 	// per Intel's architecture spec). Thus we simply save the
860 	// information from the (unhandlable) exception which caused the
861 	// double in our iframe. This will result even in useful stack
862 	// traces. Only problem is that we trust that at least the
863 	// TSS is still accessible.
864 	struct tss *tss = &gCPU[cpu].arch.tss;
865 
866 	frame->cs = tss->cs;
867 	frame->es = tss->es;
868 	frame->ds = tss->ds;
869 	frame->fs = tss->fs;
870 	frame->gs = tss->gs;
871 	frame->eip = tss->eip;
872 	frame->ebp = tss->ebp;
873 	frame->esp = tss->esp;
874 	frame->eax = tss->eax;
875 	frame->ebx = tss->ebx;
876 	frame->ecx = tss->ecx;
877 	frame->edx = tss->edx;
878 	frame->esi = tss->esi;
879 	frame->edi = tss->edi;
880 	frame->flags = tss->eflags;
881 
882 	// Use a special handler for page faults which avoids the triple fault
883 	// pitfalls.
884 	set_interrupt_gate(cpu, 14, &trap14_double_fault);
885 
886 	debug_double_fault(cpu);
887 }
888 
889 
890 void
891 x86_page_fault_exception_double_fault(struct iframe* frame)
892 {
893 	uint32 cr2;
894 	asm("movl %%cr2, %0" : "=r" (cr2));
895 
896 	// Only if this CPU has a fault handler, we're allowed to be here.
897 	cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()];
898 	addr_t faultHandler = cpu.fault_handler;
899 	if (faultHandler != 0) {
900 		debug_set_page_fault_info(cr2, frame->eip,
901 			(frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0);
902 		frame->eip = faultHandler;
903 		frame->ebp = cpu.fault_handler_stack_pointer;
904 		return;
905 	}
906 
907 	// No fault handler. This is bad. Since we originally came from a double
908 	// fault, we don't try to reenter the kernel debugger. Instead we just
909 	// print the info we've got and enter an infinite loop.
910 	kprintf("Page fault in double fault debugger without fault handler! "
911 		"Touching address %p from eip %p. Entering infinite loop...\n",
912 		(void*)cr2, (void*)frame->eip);
913 
914 	while (true);
915 }
916 
917 
918 static void
919 page_fault_exception(struct iframe* frame)
920 {
921 	struct thread *thread = thread_get_current_thread();
922 	uint32 cr2;
923 	addr_t newip;
924 
925 	asm("movl %%cr2, %0" : "=r" (cr2));
926 
927 	if (debug_debugger_running()) {
928 		// If this CPU or this thread has a fault handler, we're allowed to be
929 		// here.
930 		if (thread != NULL) {
931 			cpu_ent* cpu = &gCPU[smp_get_current_cpu()];
932 			if (cpu->fault_handler != 0) {
933 				debug_set_page_fault_info(cr2, frame->eip,
934 					(frame->error_code & 0x2) != 0
935 						? DEBUG_PAGE_FAULT_WRITE : 0);
936 				frame->eip = cpu->fault_handler;
937 				frame->ebp = cpu->fault_handler_stack_pointer;
938 				return;
939 			}
940 
941 			if (thread->fault_handler != 0) {
942 				kprintf("ERROR: thread::fault_handler used in kernel "
943 					"debugger!\n");
944 				debug_set_page_fault_info(cr2, frame->eip,
945 					(frame->error_code & 0x2) != 0
946 						? DEBUG_PAGE_FAULT_WRITE : 0);
947 				frame->eip = thread->fault_handler;
948 				return;
949 			}
950 		}
951 
952 		// otherwise, not really
953 		panic("page fault in debugger without fault handler! Touching "
954 			"address %p from eip %p\n", (void *)cr2, (void *)frame->eip);
955 		return;
956 	} else if ((frame->flags & 0x200) == 0) {
957 		// interrupts disabled
958 
959 		// If a page fault handler is installed, we're allowed to be here.
960 		// TODO: Now we are generally allowing user_memcpy() with interrupts
961 		// disabled, which in most cases is a bug. We should add some thread
962 		// flag allowing to explicitly indicate that this handling is desired.
963 		if (thread && thread->fault_handler != 0) {
964 			if (frame->eip != thread->fault_handler) {
965 				frame->eip = thread->fault_handler;
966 				return;
967 			}
968 
969 			// The fault happened at the fault handler address. This is a
970 			// certain infinite loop.
971 			panic("page fault, interrupts disabled, fault handler loop. "
972 				"Touching address %p from eip %p\n", (void*)cr2,
973 				(void*)frame->eip);
974 		}
975 
976 		// If we are not running the kernel startup the page fault was not
977 		// allowed to happen and we must panic.
978 		panic("page fault, but interrupts were disabled. Touching address "
979 			"%p from eip %p\n", (void *)cr2, (void *)frame->eip);
980 		return;
981 	} else if (thread != NULL && thread->page_faults_allowed < 1) {
982 		panic("page fault not allowed at this place. Touching address "
983 			"%p from eip %p\n", (void *)cr2, (void *)frame->eip);
984 		return;
985 	}
986 
987 	enable_interrupts();
988 
989 	vm_page_fault(cr2, frame->eip,
990 		(frame->error_code & 0x2) != 0,	// write access
991 		(frame->error_code & 0x4) != 0,	// userland
992 		&newip);
993 	if (newip != 0) {
994 		// the page fault handler wants us to modify the iframe to set the
995 		// IP the cpu will return to to be this ip
996 		frame->eip = newip;
997 	}
998 }
999 
1000 
1001 static void
1002 hardware_interrupt(struct iframe* frame)
1003 {
1004 	int32 vector = frame->vector - ARCH_INTERRUPT_BASE;
1005 	bool levelTriggered = false;
1006 	struct thread* thread = thread_get_current_thread();
1007 
1008 	if (sCurrentPIC->is_spurious_interrupt(vector)) {
1009 		TRACE(("got spurious interrupt at vector %ld\n", vector));
1010 		return;
1011 	}
1012 
1013 	if (vector < 32)
1014 		levelTriggered = (sLevelTriggeredInterrupts & (1 << vector)) != 0;
1015 
1016 	if (!levelTriggered) {
1017 		// if it's not handled by the current pic then it's an apic generated
1018 		// interrupt like local interrupts, msi or ipi.
1019 		if (!sCurrentPIC->end_of_interrupt(vector))
1020 			apic_end_of_interrupt();
1021 	}
1022 
1023 	int_io_interrupt_handler(vector, levelTriggered);
1024 
1025 	if (levelTriggered) {
1026 		if (!sCurrentPIC->end_of_interrupt(vector))
1027 			apic_end_of_interrupt();
1028 	}
1029 
1030 	cpu_status state = disable_interrupts();
1031 	if (thread->cpu->invoke_scheduler) {
1032 		GRAB_THREAD_LOCK();
1033 		scheduler_reschedule();
1034 		RELEASE_THREAD_LOCK();
1035 		restore_interrupts(state);
1036 	} else if (thread->post_interrupt_callback != NULL) {
1037 		restore_interrupts(state);
1038 		void (*callback)(void*) = thread->post_interrupt_callback;
1039 		void* data = thread->post_interrupt_data;
1040 
1041 		thread->post_interrupt_callback = NULL;
1042 		thread->post_interrupt_data = NULL;
1043 
1044 		callback(data);
1045 	}
1046 }
1047 
1048 
1049 status_t
1050 arch_int_init(struct kernel_args *args)
1051 {
1052 	int i;
1053 	interrupt_handler_function** table;
1054 
1055 	// set the global sIDT variable
1056 	sIDTs[0] = (desc_table *)args->arch_args.vir_idt;
1057 
1058 	// setup the standard programmable interrupt controller
1059 	pic_init();
1060 
1061 	set_interrupt_gate(0, 0, &trap0);
1062 	set_interrupt_gate(0, 1, &trap1);
1063 	set_interrupt_gate(0, 2, &trap2);
1064 	set_trap_gate(0, 3, &trap3);
1065 	set_interrupt_gate(0, 4, &trap4);
1066 	set_interrupt_gate(0, 5, &trap5);
1067 	set_interrupt_gate(0, 6, &trap6);
1068 	set_interrupt_gate(0, 7, &trap7);
1069 	// trap8 (double fault) is set in arch_cpu.c
1070 	set_interrupt_gate(0, 9, &trap9);
1071 	set_interrupt_gate(0, 10, &trap10);
1072 	set_interrupt_gate(0, 11, &trap11);
1073 	set_interrupt_gate(0, 12, &trap12);
1074 	set_interrupt_gate(0, 13, &trap13);
1075 	set_interrupt_gate(0, 14, &trap14);
1076 //	set_interrupt_gate(0, 15, &trap15);
1077 	set_interrupt_gate(0, 16, &trap16);
1078 	set_interrupt_gate(0, 17, &trap17);
1079 	set_interrupt_gate(0, 18, &trap18);
1080 	set_interrupt_gate(0, 19, &trap19);
1081 
1082 	// legacy or ioapic interrupts
1083 	set_interrupt_gate(0, 32, &trap32);
1084 	set_interrupt_gate(0, 33, &trap33);
1085 	set_interrupt_gate(0, 34, &trap34);
1086 	set_interrupt_gate(0, 35, &trap35);
1087 	set_interrupt_gate(0, 36, &trap36);
1088 	set_interrupt_gate(0, 37, &trap37);
1089 	set_interrupt_gate(0, 38, &trap38);
1090 	set_interrupt_gate(0, 39, &trap39);
1091 	set_interrupt_gate(0, 40, &trap40);
1092 	set_interrupt_gate(0, 41, &trap41);
1093 	set_interrupt_gate(0, 42, &trap42);
1094 	set_interrupt_gate(0, 43, &trap43);
1095 	set_interrupt_gate(0, 44, &trap44);
1096 	set_interrupt_gate(0, 45, &trap45);
1097 	set_interrupt_gate(0, 46, &trap46);
1098 	set_interrupt_gate(0, 47, &trap47);
1099 
1100 	// additional ioapic interrupts
1101 	set_interrupt_gate(0, 48, &trap48);
1102 	set_interrupt_gate(0, 49, &trap49);
1103 	set_interrupt_gate(0, 50, &trap50);
1104 	set_interrupt_gate(0, 51, &trap51);
1105 	set_interrupt_gate(0, 52, &trap52);
1106 	set_interrupt_gate(0, 53, &trap53);
1107 	set_interrupt_gate(0, 54, &trap54);
1108 	set_interrupt_gate(0, 55, &trap55);
1109 
1110 	// configurable msi or msi-x interrupts
1111 	set_interrupt_gate(0, 56, &trap56);
1112 	set_interrupt_gate(0, 57, &trap57);
1113 	set_interrupt_gate(0, 58, &trap58);
1114 	set_interrupt_gate(0, 59, &trap59);
1115 	set_interrupt_gate(0, 60, &trap60);
1116 	set_interrupt_gate(0, 61, &trap61);
1117 	set_interrupt_gate(0, 62, &trap62);
1118 	set_interrupt_gate(0, 63, &trap63);
1119 	set_interrupt_gate(0, 64, &trap64);
1120 	set_interrupt_gate(0, 65, &trap65);
1121 	set_interrupt_gate(0, 66, &trap66);
1122 	set_interrupt_gate(0, 67, &trap67);
1123 	set_interrupt_gate(0, 68, &trap68);
1124 	set_interrupt_gate(0, 69, &trap69);
1125 	set_interrupt_gate(0, 70, &trap70);
1126 	set_interrupt_gate(0, 71, &trap71);
1127 	set_interrupt_gate(0, 72, &trap72);
1128 	set_interrupt_gate(0, 73, &trap73);
1129 	set_interrupt_gate(0, 74, &trap74);
1130 	set_interrupt_gate(0, 75, &trap75);
1131 	set_interrupt_gate(0, 76, &trap76);
1132 	set_interrupt_gate(0, 77, &trap77);
1133 	set_interrupt_gate(0, 78, &trap78);
1134 	set_interrupt_gate(0, 79, &trap79);
1135 	set_interrupt_gate(0, 80, &trap80);
1136 	set_interrupt_gate(0, 81, &trap81);
1137 	set_interrupt_gate(0, 82, &trap82);
1138 	set_interrupt_gate(0, 83, &trap83);
1139 	set_interrupt_gate(0, 84, &trap84);
1140 	set_interrupt_gate(0, 85, &trap85);
1141 	set_interrupt_gate(0, 86, &trap86);
1142 	set_interrupt_gate(0, 87, &trap87);
1143 	set_interrupt_gate(0, 88, &trap88);
1144 	set_interrupt_gate(0, 89, &trap89);
1145 	set_interrupt_gate(0, 90, &trap90);
1146 	set_interrupt_gate(0, 91, &trap91);
1147 	set_interrupt_gate(0, 92, &trap92);
1148 	set_interrupt_gate(0, 93, &trap93);
1149 	set_interrupt_gate(0, 94, &trap94);
1150 	set_interrupt_gate(0, 95, &trap95);
1151 	set_interrupt_gate(0, 96, &trap96);
1152 	set_interrupt_gate(0, 97, &trap97);
1153 
1154 	set_trap_gate(0, 98, &trap98);	// for performance testing only
1155 	set_trap_gate(0, 99, &trap99);	// syscall interrupt
1156 
1157 	// configurable msi or msi-x interrupts
1158 	set_interrupt_gate(0, 100, &trap100);
1159 	set_interrupt_gate(0, 101, &trap101);
1160 	set_interrupt_gate(0, 102, &trap102);
1161 	set_interrupt_gate(0, 103, &trap103);
1162 	set_interrupt_gate(0, 104, &trap104);
1163 	set_interrupt_gate(0, 105, &trap105);
1164 	set_interrupt_gate(0, 106, &trap106);
1165 	set_interrupt_gate(0, 107, &trap107);
1166 	set_interrupt_gate(0, 108, &trap108);
1167 	set_interrupt_gate(0, 109, &trap109);
1168 	set_interrupt_gate(0, 110, &trap110);
1169 	set_interrupt_gate(0, 111, &trap111);
1170 	set_interrupt_gate(0, 112, &trap112);
1171 	set_interrupt_gate(0, 113, &trap113);
1172 	set_interrupt_gate(0, 114, &trap114);
1173 	set_interrupt_gate(0, 115, &trap115);
1174 	set_interrupt_gate(0, 116, &trap116);
1175 	set_interrupt_gate(0, 117, &trap117);
1176 	set_interrupt_gate(0, 118, &trap118);
1177 	set_interrupt_gate(0, 119, &trap119);
1178 	set_interrupt_gate(0, 120, &trap120);
1179 	set_interrupt_gate(0, 121, &trap121);
1180 	set_interrupt_gate(0, 122, &trap122);
1181 	set_interrupt_gate(0, 123, &trap123);
1182 	set_interrupt_gate(0, 124, &trap124);
1183 	set_interrupt_gate(0, 125, &trap125);
1184 	set_interrupt_gate(0, 126, &trap126);
1185 	set_interrupt_gate(0, 127, &trap127);
1186 	set_interrupt_gate(0, 128, &trap128);
1187 	set_interrupt_gate(0, 129, &trap129);
1188 	set_interrupt_gate(0, 130, &trap130);
1189 	set_interrupt_gate(0, 131, &trap131);
1190 	set_interrupt_gate(0, 132, &trap132);
1191 	set_interrupt_gate(0, 133, &trap133);
1192 	set_interrupt_gate(0, 134, &trap134);
1193 	set_interrupt_gate(0, 135, &trap135);
1194 	set_interrupt_gate(0, 136, &trap136);
1195 	set_interrupt_gate(0, 137, &trap137);
1196 	set_interrupt_gate(0, 138, &trap138);
1197 	set_interrupt_gate(0, 139, &trap139);
1198 	set_interrupt_gate(0, 140, &trap140);
1199 	set_interrupt_gate(0, 141, &trap141);
1200 	set_interrupt_gate(0, 142, &trap142);
1201 	set_interrupt_gate(0, 143, &trap143);
1202 	set_interrupt_gate(0, 144, &trap144);
1203 	set_interrupt_gate(0, 145, &trap145);
1204 	set_interrupt_gate(0, 146, &trap146);
1205 	set_interrupt_gate(0, 147, &trap147);
1206 	set_interrupt_gate(0, 148, &trap148);
1207 	set_interrupt_gate(0, 149, &trap149);
1208 	set_interrupt_gate(0, 150, &trap150);
1209 	set_interrupt_gate(0, 151, &trap151);
1210 	set_interrupt_gate(0, 152, &trap152);
1211 	set_interrupt_gate(0, 153, &trap153);
1212 	set_interrupt_gate(0, 154, &trap154);
1213 	set_interrupt_gate(0, 155, &trap155);
1214 	set_interrupt_gate(0, 156, &trap156);
1215 	set_interrupt_gate(0, 157, &trap157);
1216 	set_interrupt_gate(0, 158, &trap158);
1217 	set_interrupt_gate(0, 159, &trap159);
1218 	set_interrupt_gate(0, 160, &trap160);
1219 	set_interrupt_gate(0, 161, &trap161);
1220 	set_interrupt_gate(0, 162, &trap162);
1221 	set_interrupt_gate(0, 163, &trap163);
1222 	set_interrupt_gate(0, 164, &trap164);
1223 	set_interrupt_gate(0, 165, &trap165);
1224 	set_interrupt_gate(0, 166, &trap166);
1225 	set_interrupt_gate(0, 167, &trap167);
1226 	set_interrupt_gate(0, 168, &trap168);
1227 	set_interrupt_gate(0, 169, &trap169);
1228 	set_interrupt_gate(0, 170, &trap170);
1229 	set_interrupt_gate(0, 171, &trap171);
1230 	set_interrupt_gate(0, 172, &trap172);
1231 	set_interrupt_gate(0, 173, &trap173);
1232 	set_interrupt_gate(0, 174, &trap174);
1233 	set_interrupt_gate(0, 175, &trap175);
1234 	set_interrupt_gate(0, 176, &trap176);
1235 	set_interrupt_gate(0, 177, &trap177);
1236 	set_interrupt_gate(0, 178, &trap178);
1237 	set_interrupt_gate(0, 179, &trap179);
1238 	set_interrupt_gate(0, 180, &trap180);
1239 	set_interrupt_gate(0, 181, &trap181);
1240 	set_interrupt_gate(0, 182, &trap182);
1241 	set_interrupt_gate(0, 183, &trap183);
1242 	set_interrupt_gate(0, 184, &trap184);
1243 	set_interrupt_gate(0, 185, &trap185);
1244 	set_interrupt_gate(0, 186, &trap186);
1245 	set_interrupt_gate(0, 187, &trap187);
1246 	set_interrupt_gate(0, 188, &trap188);
1247 	set_interrupt_gate(0, 189, &trap189);
1248 	set_interrupt_gate(0, 190, &trap190);
1249 	set_interrupt_gate(0, 191, &trap191);
1250 	set_interrupt_gate(0, 192, &trap192);
1251 	set_interrupt_gate(0, 193, &trap193);
1252 	set_interrupt_gate(0, 194, &trap194);
1253 	set_interrupt_gate(0, 195, &trap195);
1254 	set_interrupt_gate(0, 196, &trap196);
1255 	set_interrupt_gate(0, 197, &trap197);
1256 	set_interrupt_gate(0, 198, &trap198);
1257 	set_interrupt_gate(0, 199, &trap199);
1258 	set_interrupt_gate(0, 200, &trap200);
1259 	set_interrupt_gate(0, 201, &trap201);
1260 	set_interrupt_gate(0, 202, &trap202);
1261 	set_interrupt_gate(0, 203, &trap203);
1262 	set_interrupt_gate(0, 204, &trap204);
1263 	set_interrupt_gate(0, 205, &trap205);
1264 	set_interrupt_gate(0, 206, &trap206);
1265 	set_interrupt_gate(0, 207, &trap207);
1266 	set_interrupt_gate(0, 208, &trap208);
1267 	set_interrupt_gate(0, 209, &trap209);
1268 	set_interrupt_gate(0, 210, &trap210);
1269 	set_interrupt_gate(0, 211, &trap211);
1270 	set_interrupt_gate(0, 212, &trap212);
1271 	set_interrupt_gate(0, 213, &trap213);
1272 	set_interrupt_gate(0, 214, &trap214);
1273 	set_interrupt_gate(0, 215, &trap215);
1274 	set_interrupt_gate(0, 216, &trap216);
1275 	set_interrupt_gate(0, 217, &trap217);
1276 	set_interrupt_gate(0, 218, &trap218);
1277 	set_interrupt_gate(0, 219, &trap219);
1278 	set_interrupt_gate(0, 220, &trap220);
1279 	set_interrupt_gate(0, 221, &trap221);
1280 	set_interrupt_gate(0, 222, &trap222);
1281 	set_interrupt_gate(0, 223, &trap223);
1282 	set_interrupt_gate(0, 224, &trap224);
1283 	set_interrupt_gate(0, 225, &trap225);
1284 	set_interrupt_gate(0, 226, &trap226);
1285 	set_interrupt_gate(0, 227, &trap227);
1286 	set_interrupt_gate(0, 228, &trap228);
1287 	set_interrupt_gate(0, 229, &trap229);
1288 	set_interrupt_gate(0, 230, &trap230);
1289 	set_interrupt_gate(0, 231, &trap231);
1290 	set_interrupt_gate(0, 232, &trap232);
1291 	set_interrupt_gate(0, 233, &trap233);
1292 	set_interrupt_gate(0, 234, &trap234);
1293 	set_interrupt_gate(0, 235, &trap235);
1294 	set_interrupt_gate(0, 236, &trap236);
1295 	set_interrupt_gate(0, 237, &trap237);
1296 	set_interrupt_gate(0, 238, &trap238);
1297 	set_interrupt_gate(0, 239, &trap239);
1298 	set_interrupt_gate(0, 240, &trap240);
1299 	set_interrupt_gate(0, 241, &trap241);
1300 	set_interrupt_gate(0, 242, &trap242);
1301 	set_interrupt_gate(0, 243, &trap243);
1302 	set_interrupt_gate(0, 244, &trap244);
1303 	set_interrupt_gate(0, 245, &trap245);
1304 	set_interrupt_gate(0, 246, &trap246);
1305 	set_interrupt_gate(0, 247, &trap247);
1306 	set_interrupt_gate(0, 248, &trap248);
1307 	set_interrupt_gate(0, 249, &trap249);
1308 	set_interrupt_gate(0, 250, &trap250);
1309 
1310 	// smp / apic local interrupts
1311 	set_interrupt_gate(0, 251, &trap251);
1312 	set_interrupt_gate(0, 252, &trap252);
1313 	set_interrupt_gate(0, 253, &trap253);
1314 	set_interrupt_gate(0, 254, &trap254);
1315 	set_interrupt_gate(0, 255, &trap255);
1316 
1317 	// init interrupt handler table
1318 	table = gInterruptHandlerTable;
1319 
1320 	// defaults
1321 	for (i = 0; i < ARCH_INTERRUPT_BASE; i++)
1322 		table[i] = invalid_exception;
1323 	for (i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++)
1324 		table[i] = hardware_interrupt;
1325 
1326 	table[0] = unexpected_exception;	// Divide Error Exception (#DE)
1327 	table[1] = x86_handle_debug_exception; // Debug Exception (#DB)
1328 	table[2] = fatal_exception;			// NMI Interrupt
1329 	table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
1330 	table[4] = unexpected_exception;	// Overflow Exception (#OF)
1331 	table[5] = unexpected_exception;	// BOUND Range Exceeded Exception (#BR)
1332 	table[6] = unexpected_exception;	// Invalid Opcode Exception (#UD)
1333 	table[7] = fatal_exception;			// Device Not Available Exception (#NM)
1334 	table[8] = x86_double_fault_exception; // Double Fault Exception (#DF)
1335 	table[9] = fatal_exception;			// Coprocessor Segment Overrun
1336 	table[10] = fatal_exception;		// Invalid TSS Exception (#TS)
1337 	table[11] = fatal_exception;		// Segment Not Present (#NP)
1338 	table[12] = fatal_exception;		// Stack Fault Exception (#SS)
1339 	table[13] = unexpected_exception;	// General Protection Exception (#GP)
1340 	table[14] = page_fault_exception;	// Page-Fault Exception (#PF)
1341 	table[16] = unexpected_exception;	// x87 FPU Floating-Point Error (#MF)
1342 	table[17] = unexpected_exception;	// Alignment Check Exception (#AC)
1343 	table[18] = fatal_exception;		// Machine-Check Exception (#MC)
1344 	table[19] = unexpected_exception;	// SIMD Floating-Point Exception (#XF)
1345 
1346 	return B_OK;
1347 }
1348 
1349 
1350 status_t
1351 arch_int_init_post_vm(struct kernel_args *args)
1352 {
1353 	// Always init the local apic as it can be used for timers even if we
1354 	// don't end up using the io apic
1355 	apic_init(args);
1356 
1357 	// We need to map in the I/O APIC here, since we would lose the already
1358 	// wired mapping before arch_int_init_io() is called.
1359 	ioapic_map(args);
1360 
1361 	// create IDT area for the boot CPU
1362 	area_id area = create_area("idt", (void**)&sIDTs[0], B_EXACT_ADDRESS,
1363 		B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
1364 	if (area < 0)
1365 		return area;
1366 
1367 	// create IDTs for the off-boot CPU
1368 	size_t idtSize = 256 * 8;
1369 		// 256 8 bytes-sized descriptors
1370 	int32 cpuCount = smp_get_num_cpus();
1371 	if (cpuCount > 0) {
1372 		size_t areaSize = ROUNDUP(cpuCount * idtSize, B_PAGE_SIZE);
1373 		desc_table* idt;
1374 		area = create_area_etc(B_SYSTEM_TEAM, "idt", (void**)&idt,
1375 			B_ANY_KERNEL_ADDRESS, areaSize, B_CONTIGUOUS,
1376 			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 0, CREATE_AREA_DONT_WAIT);
1377 		if (area < 0)
1378 			return area;
1379 
1380 		for (int32 i = 1; i < cpuCount; i++) {
1381 			sIDTs[i] = idt;
1382 			memcpy(idt, sIDTs[0], idtSize);
1383 			idt += 256;
1384 			// The CPU's IDTR will be set in arch_cpu_init_percpu().
1385 		}
1386 	}
1387 
1388 	return area >= B_OK ? B_OK : area;
1389 }
1390 
1391 
1392 status_t
1393 arch_int_init_io(kernel_args* args)
1394 {
1395 	ioapic_init(args);
1396 	return B_OK;
1397 }
1398 
1399 
1400 status_t
1401 arch_int_init_post_device_manager(struct kernel_args *args)
1402 {
1403 	return B_OK;
1404 }
1405