xref: /haiku/src/system/kernel/arch/x86/arch_int.cpp (revision 1294543de9ac0eff000eaea1b18368c36435d08e)
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 
674 		int32 num = entry.source_index;
675 		for (int a = 0; a < 16 && num == 0; a++) {
676 			if (irqDescriptor.irq >> i & 0x01) {
677 				num = a;
678 				break;
679 			}
680 		}
681 		ioapic_configure_io_interrupt(num, config);
682 	}
683 
684 	// prefer the ioapic over the normal pic
685 	dprintf("using ioapic for interrupt routing\n");
686 	sCurrentPIC = &ioapicController;
687 }
688 
689 
690 // #pragma mark -
691 
692 
693 void
694 arch_int_enable_io_interrupt(int irq)
695 {
696 	sCurrentPIC->enable_io_interrupt(irq);
697 }
698 
699 
700 void
701 arch_int_disable_io_interrupt(int irq)
702 {
703 	sCurrentPIC->disable_io_interrupt(irq);
704 }
705 
706 
707 void
708 arch_int_configure_io_interrupt(int irq, uint32 config)
709 {
710 	sCurrentPIC->configure_io_interrupt(irq, config);
711 }
712 
713 
714 #undef arch_int_enable_interrupts
715 #undef arch_int_disable_interrupts
716 #undef arch_int_restore_interrupts
717 #undef arch_int_are_interrupts_enabled
718 
719 
720 void
721 arch_int_enable_interrupts(void)
722 {
723 	arch_int_enable_interrupts_inline();
724 }
725 
726 
727 int
728 arch_int_disable_interrupts(void)
729 {
730 	return arch_int_disable_interrupts_inline();
731 }
732 
733 
734 void
735 arch_int_restore_interrupts(int oldState)
736 {
737 	arch_int_restore_interrupts_inline(oldState);
738 }
739 
740 
741 bool
742 arch_int_are_interrupts_enabled(void)
743 {
744 	return arch_int_are_interrupts_enabled_inline();
745 }
746 
747 
748 static const char *
749 exception_name(int number, char *buffer, int32 bufferSize)
750 {
751 	if (number >= 0 && number < kInterruptNameCount)
752 		return kInterruptNames[number];
753 
754 	snprintf(buffer, bufferSize, "exception %d", number);
755 	return buffer;
756 }
757 
758 
759 static void
760 invalid_exception(struct iframe* frame)
761 {
762 	struct thread* thread = thread_get_current_thread();
763 	char name[32];
764 	panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n",
765 		frame->vector, exception_name(frame->vector, name, sizeof(name)),
766 		frame->eip, thread ? thread->id : -1);
767 }
768 
769 
770 static void
771 fatal_exception(struct iframe *frame)
772 {
773 	char name[32];
774 	panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n",
775 		exception_name(frame->vector, name, sizeof(name)), frame->error_code);
776 }
777 
778 
779 static void
780 unexpected_exception(struct iframe* frame)
781 {
782 	debug_exception_type type;
783 	int signal;
784 
785 	if (IFRAME_IS_VM86(frame)) {
786 		x86_vm86_return((struct vm86_iframe *)frame, (frame->vector == 13) ?
787 			B_OK : B_ERROR);
788 		// won't get here
789 	}
790 
791 	switch (frame->vector) {
792 		case 0:		// Divide Error Exception (#DE)
793 			type = B_DIVIDE_ERROR;
794 			signal = SIGFPE;
795 			break;
796 
797 		case 4:		// Overflow Exception (#OF)
798 			type = B_OVERFLOW_EXCEPTION;
799 			signal = SIGTRAP;
800 			break;
801 
802 		case 5:		// BOUND Range Exceeded Exception (#BR)
803 			type = B_BOUNDS_CHECK_EXCEPTION;
804 			signal = SIGTRAP;
805 			break;
806 
807 		case 6:		// Invalid Opcode Exception (#UD)
808 			type = B_INVALID_OPCODE_EXCEPTION;
809 			signal = SIGILL;
810 			break;
811 
812 		case 13: 	// General Protection Exception (#GP)
813 			type = B_GENERAL_PROTECTION_FAULT;
814 			signal = SIGILL;
815 			break;
816 
817 		case 16: 	// x87 FPU Floating-Point Error (#MF)
818 			type = B_FLOATING_POINT_EXCEPTION;
819 			signal = SIGFPE;
820 			break;
821 
822 		case 17: 	// Alignment Check Exception (#AC)
823 			type = B_ALIGNMENT_EXCEPTION;
824 			signal = SIGTRAP;
825 			break;
826 
827 		case 19: 	// SIMD Floating-Point Exception (#XF)
828 			type = B_FLOATING_POINT_EXCEPTION;
829 			signal = SIGFPE;
830 			break;
831 
832 		default:
833 			invalid_exception(frame);
834 			return;
835 	}
836 
837 	if (IFRAME_IS_USER(frame)) {
838 		struct sigaction action;
839 		struct thread* thread = thread_get_current_thread();
840 
841 		enable_interrupts();
842 
843 		// If the thread has a signal handler for the signal, we simply send it
844 		// the signal. Otherwise we notify the user debugger first.
845 		if (sigaction(signal, NULL, &action) == 0
846 			&& action.sa_handler != SIG_DFL
847 			&& action.sa_handler != SIG_IGN) {
848 			send_signal(thread->id, signal);
849 		} else if (user_debug_exception_occurred(type, signal))
850 			send_signal(team_get_current_team_id(), signal);
851 	} else {
852 		char name[32];
853 		panic("Unexpected exception \"%s\" occurred in kernel mode! "
854 			"Error code: 0x%lx\n",
855 			exception_name(frame->vector, name, sizeof(name)),
856 			frame->error_code);
857 	}
858 }
859 
860 
861 void
862 x86_double_fault_exception(struct iframe* frame)
863 {
864 	int cpu = x86_double_fault_get_cpu();
865 
866 	// The double fault iframe contains no useful information (as
867 	// per Intel's architecture spec). Thus we simply save the
868 	// information from the (unhandlable) exception which caused the
869 	// double in our iframe. This will result even in useful stack
870 	// traces. Only problem is that we trust that at least the
871 	// TSS is still accessible.
872 	struct tss *tss = &gCPU[cpu].arch.tss;
873 
874 	frame->cs = tss->cs;
875 	frame->es = tss->es;
876 	frame->ds = tss->ds;
877 	frame->fs = tss->fs;
878 	frame->gs = tss->gs;
879 	frame->eip = tss->eip;
880 	frame->ebp = tss->ebp;
881 	frame->esp = tss->esp;
882 	frame->eax = tss->eax;
883 	frame->ebx = tss->ebx;
884 	frame->ecx = tss->ecx;
885 	frame->edx = tss->edx;
886 	frame->esi = tss->esi;
887 	frame->edi = tss->edi;
888 	frame->flags = tss->eflags;
889 
890 	// Use a special handler for page faults which avoids the triple fault
891 	// pitfalls.
892 	set_interrupt_gate(cpu, 14, &trap14_double_fault);
893 
894 	debug_double_fault(cpu);
895 }
896 
897 
898 void
899 x86_page_fault_exception_double_fault(struct iframe* frame)
900 {
901 	uint32 cr2;
902 	asm("movl %%cr2, %0" : "=r" (cr2));
903 
904 	// Only if this CPU has a fault handler, we're allowed to be here.
905 	cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()];
906 	addr_t faultHandler = cpu.fault_handler;
907 	if (faultHandler != 0) {
908 		debug_set_page_fault_info(cr2, frame->eip,
909 			(frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0);
910 		frame->eip = faultHandler;
911 		frame->ebp = cpu.fault_handler_stack_pointer;
912 		return;
913 	}
914 
915 	// No fault handler. This is bad. Since we originally came from a double
916 	// fault, we don't try to reenter the kernel debugger. Instead we just
917 	// print the info we've got and enter an infinite loop.
918 	kprintf("Page fault in double fault debugger without fault handler! "
919 		"Touching address %p from eip %p. Entering infinite loop...\n",
920 		(void*)cr2, (void*)frame->eip);
921 
922 	while (true);
923 }
924 
925 
926 static void
927 page_fault_exception(struct iframe* frame)
928 {
929 	struct thread *thread = thread_get_current_thread();
930 	uint32 cr2;
931 	addr_t newip;
932 
933 	asm("movl %%cr2, %0" : "=r" (cr2));
934 
935 	if (debug_debugger_running()) {
936 		// If this CPU or this thread has a fault handler, we're allowed to be
937 		// here.
938 		if (thread != NULL) {
939 			cpu_ent* cpu = &gCPU[smp_get_current_cpu()];
940 			if (cpu->fault_handler != 0) {
941 				debug_set_page_fault_info(cr2, frame->eip,
942 					(frame->error_code & 0x2) != 0
943 						? DEBUG_PAGE_FAULT_WRITE : 0);
944 				frame->eip = cpu->fault_handler;
945 				frame->ebp = cpu->fault_handler_stack_pointer;
946 				return;
947 			}
948 
949 			if (thread->fault_handler != 0) {
950 				kprintf("ERROR: thread::fault_handler used in kernel "
951 					"debugger!\n");
952 				debug_set_page_fault_info(cr2, frame->eip,
953 					(frame->error_code & 0x2) != 0
954 						? DEBUG_PAGE_FAULT_WRITE : 0);
955 				frame->eip = thread->fault_handler;
956 				return;
957 			}
958 		}
959 
960 		// otherwise, not really
961 		panic("page fault in debugger without fault handler! Touching "
962 			"address %p from eip %p\n", (void *)cr2, (void *)frame->eip);
963 		return;
964 	} else if ((frame->flags & 0x200) == 0) {
965 		// interrupts disabled
966 
967 		// If a page fault handler is installed, we're allowed to be here.
968 		// TODO: Now we are generally allowing user_memcpy() with interrupts
969 		// disabled, which in most cases is a bug. We should add some thread
970 		// flag allowing to explicitly indicate that this handling is desired.
971 		if (thread && thread->fault_handler != 0) {
972 			if (frame->eip != thread->fault_handler) {
973 				frame->eip = thread->fault_handler;
974 				return;
975 			}
976 
977 			// The fault happened at the fault handler address. This is a
978 			// certain infinite loop.
979 			panic("page fault, interrupts disabled, fault handler loop. "
980 				"Touching address %p from eip %p\n", (void*)cr2,
981 				(void*)frame->eip);
982 		}
983 
984 		// If we are not running the kernel startup the page fault was not
985 		// allowed to happen and we must panic.
986 		panic("page fault, but interrupts were disabled. Touching address "
987 			"%p from eip %p\n", (void *)cr2, (void *)frame->eip);
988 		return;
989 	} else if (thread != NULL && thread->page_faults_allowed < 1) {
990 		panic("page fault not allowed at this place. Touching address "
991 			"%p from eip %p\n", (void *)cr2, (void *)frame->eip);
992 		return;
993 	}
994 
995 	enable_interrupts();
996 
997 	vm_page_fault(cr2, frame->eip,
998 		(frame->error_code & 0x2) != 0,	// write access
999 		(frame->error_code & 0x4) != 0,	// userland
1000 		&newip);
1001 	if (newip != 0) {
1002 		// the page fault handler wants us to modify the iframe to set the
1003 		// IP the cpu will return to to be this ip
1004 		frame->eip = newip;
1005 	}
1006 }
1007 
1008 
1009 static void
1010 hardware_interrupt(struct iframe* frame)
1011 {
1012 	int32 vector = frame->vector - ARCH_INTERRUPT_BASE;
1013 	bool levelTriggered = false;
1014 	struct thread* thread = thread_get_current_thread();
1015 
1016 	if (sCurrentPIC->is_spurious_interrupt(vector)) {
1017 		TRACE(("got spurious interrupt at vector %ld\n", vector));
1018 		return;
1019 	}
1020 
1021 	if (vector < 32)
1022 		levelTriggered = (sLevelTriggeredInterrupts & (1 << vector)) != 0;
1023 
1024 	if (!levelTriggered) {
1025 		// if it's not handled by the current pic then it's an apic generated
1026 		// interrupt like local interrupts, msi or ipi.
1027 		if (!sCurrentPIC->end_of_interrupt(vector))
1028 			apic_end_of_interrupt();
1029 	}
1030 
1031 	int_io_interrupt_handler(vector, levelTriggered);
1032 
1033 	if (levelTriggered) {
1034 		if (!sCurrentPIC->end_of_interrupt(vector))
1035 			apic_end_of_interrupt();
1036 	}
1037 
1038 	cpu_status state = disable_interrupts();
1039 	if (thread->cpu->invoke_scheduler) {
1040 		GRAB_THREAD_LOCK();
1041 		scheduler_reschedule();
1042 		RELEASE_THREAD_LOCK();
1043 		restore_interrupts(state);
1044 	} else if (thread->post_interrupt_callback != NULL) {
1045 		restore_interrupts(state);
1046 		void (*callback)(void*) = thread->post_interrupt_callback;
1047 		void* data = thread->post_interrupt_data;
1048 
1049 		thread->post_interrupt_callback = NULL;
1050 		thread->post_interrupt_data = NULL;
1051 
1052 		callback(data);
1053 	}
1054 }
1055 
1056 
1057 status_t
1058 arch_int_init(struct kernel_args *args)
1059 {
1060 	int i;
1061 	interrupt_handler_function** table;
1062 
1063 	// set the global sIDT variable
1064 	sIDTs[0] = (desc_table *)args->arch_args.vir_idt;
1065 
1066 	// setup the standard programmable interrupt controller
1067 	pic_init();
1068 
1069 	set_interrupt_gate(0, 0, &trap0);
1070 	set_interrupt_gate(0, 1, &trap1);
1071 	set_interrupt_gate(0, 2, &trap2);
1072 	set_trap_gate(0, 3, &trap3);
1073 	set_interrupt_gate(0, 4, &trap4);
1074 	set_interrupt_gate(0, 5, &trap5);
1075 	set_interrupt_gate(0, 6, &trap6);
1076 	set_interrupt_gate(0, 7, &trap7);
1077 	// trap8 (double fault) is set in arch_cpu.c
1078 	set_interrupt_gate(0, 9, &trap9);
1079 	set_interrupt_gate(0, 10, &trap10);
1080 	set_interrupt_gate(0, 11, &trap11);
1081 	set_interrupt_gate(0, 12, &trap12);
1082 	set_interrupt_gate(0, 13, &trap13);
1083 	set_interrupt_gate(0, 14, &trap14);
1084 //	set_interrupt_gate(0, 15, &trap15);
1085 	set_interrupt_gate(0, 16, &trap16);
1086 	set_interrupt_gate(0, 17, &trap17);
1087 	set_interrupt_gate(0, 18, &trap18);
1088 	set_interrupt_gate(0, 19, &trap19);
1089 
1090 	// legacy or ioapic interrupts
1091 	set_interrupt_gate(0, 32, &trap32);
1092 	set_interrupt_gate(0, 33, &trap33);
1093 	set_interrupt_gate(0, 34, &trap34);
1094 	set_interrupt_gate(0, 35, &trap35);
1095 	set_interrupt_gate(0, 36, &trap36);
1096 	set_interrupt_gate(0, 37, &trap37);
1097 	set_interrupt_gate(0, 38, &trap38);
1098 	set_interrupt_gate(0, 39, &trap39);
1099 	set_interrupt_gate(0, 40, &trap40);
1100 	set_interrupt_gate(0, 41, &trap41);
1101 	set_interrupt_gate(0, 42, &trap42);
1102 	set_interrupt_gate(0, 43, &trap43);
1103 	set_interrupt_gate(0, 44, &trap44);
1104 	set_interrupt_gate(0, 45, &trap45);
1105 	set_interrupt_gate(0, 46, &trap46);
1106 	set_interrupt_gate(0, 47, &trap47);
1107 
1108 	// additional ioapic interrupts
1109 	set_interrupt_gate(0, 48, &trap48);
1110 	set_interrupt_gate(0, 49, &trap49);
1111 	set_interrupt_gate(0, 50, &trap50);
1112 	set_interrupt_gate(0, 51, &trap51);
1113 	set_interrupt_gate(0, 52, &trap52);
1114 	set_interrupt_gate(0, 53, &trap53);
1115 	set_interrupt_gate(0, 54, &trap54);
1116 	set_interrupt_gate(0, 55, &trap55);
1117 
1118 	// configurable msi or msi-x interrupts
1119 	set_interrupt_gate(0, 56, &trap56);
1120 	set_interrupt_gate(0, 57, &trap57);
1121 	set_interrupt_gate(0, 58, &trap58);
1122 	set_interrupt_gate(0, 59, &trap59);
1123 	set_interrupt_gate(0, 60, &trap60);
1124 	set_interrupt_gate(0, 61, &trap61);
1125 	set_interrupt_gate(0, 62, &trap62);
1126 	set_interrupt_gate(0, 63, &trap63);
1127 	set_interrupt_gate(0, 64, &trap64);
1128 	set_interrupt_gate(0, 65, &trap65);
1129 	set_interrupt_gate(0, 66, &trap66);
1130 	set_interrupt_gate(0, 67, &trap67);
1131 	set_interrupt_gate(0, 68, &trap68);
1132 	set_interrupt_gate(0, 69, &trap69);
1133 	set_interrupt_gate(0, 70, &trap70);
1134 	set_interrupt_gate(0, 71, &trap71);
1135 	set_interrupt_gate(0, 72, &trap72);
1136 	set_interrupt_gate(0, 73, &trap73);
1137 	set_interrupt_gate(0, 74, &trap74);
1138 	set_interrupt_gate(0, 75, &trap75);
1139 	set_interrupt_gate(0, 76, &trap76);
1140 	set_interrupt_gate(0, 77, &trap77);
1141 	set_interrupt_gate(0, 78, &trap78);
1142 	set_interrupt_gate(0, 79, &trap79);
1143 	set_interrupt_gate(0, 80, &trap80);
1144 	set_interrupt_gate(0, 81, &trap81);
1145 	set_interrupt_gate(0, 82, &trap82);
1146 	set_interrupt_gate(0, 83, &trap83);
1147 	set_interrupt_gate(0, 84, &trap84);
1148 	set_interrupt_gate(0, 85, &trap85);
1149 	set_interrupt_gate(0, 86, &trap86);
1150 	set_interrupt_gate(0, 87, &trap87);
1151 	set_interrupt_gate(0, 88, &trap88);
1152 	set_interrupt_gate(0, 89, &trap89);
1153 	set_interrupt_gate(0, 90, &trap90);
1154 	set_interrupt_gate(0, 91, &trap91);
1155 	set_interrupt_gate(0, 92, &trap92);
1156 	set_interrupt_gate(0, 93, &trap93);
1157 	set_interrupt_gate(0, 94, &trap94);
1158 	set_interrupt_gate(0, 95, &trap95);
1159 	set_interrupt_gate(0, 96, &trap96);
1160 	set_interrupt_gate(0, 97, &trap97);
1161 
1162 	set_trap_gate(0, 98, &trap98);	// for performance testing only
1163 	set_trap_gate(0, 99, &trap99);	// syscall interrupt
1164 
1165 	// configurable msi or msi-x interrupts
1166 	set_interrupt_gate(0, 100, &trap100);
1167 	set_interrupt_gate(0, 101, &trap101);
1168 	set_interrupt_gate(0, 102, &trap102);
1169 	set_interrupt_gate(0, 103, &trap103);
1170 	set_interrupt_gate(0, 104, &trap104);
1171 	set_interrupt_gate(0, 105, &trap105);
1172 	set_interrupt_gate(0, 106, &trap106);
1173 	set_interrupt_gate(0, 107, &trap107);
1174 	set_interrupt_gate(0, 108, &trap108);
1175 	set_interrupt_gate(0, 109, &trap109);
1176 	set_interrupt_gate(0, 110, &trap110);
1177 	set_interrupt_gate(0, 111, &trap111);
1178 	set_interrupt_gate(0, 112, &trap112);
1179 	set_interrupt_gate(0, 113, &trap113);
1180 	set_interrupt_gate(0, 114, &trap114);
1181 	set_interrupt_gate(0, 115, &trap115);
1182 	set_interrupt_gate(0, 116, &trap116);
1183 	set_interrupt_gate(0, 117, &trap117);
1184 	set_interrupt_gate(0, 118, &trap118);
1185 	set_interrupt_gate(0, 119, &trap119);
1186 	set_interrupt_gate(0, 120, &trap120);
1187 	set_interrupt_gate(0, 121, &trap121);
1188 	set_interrupt_gate(0, 122, &trap122);
1189 	set_interrupt_gate(0, 123, &trap123);
1190 	set_interrupt_gate(0, 124, &trap124);
1191 	set_interrupt_gate(0, 125, &trap125);
1192 	set_interrupt_gate(0, 126, &trap126);
1193 	set_interrupt_gate(0, 127, &trap127);
1194 	set_interrupt_gate(0, 128, &trap128);
1195 	set_interrupt_gate(0, 129, &trap129);
1196 	set_interrupt_gate(0, 130, &trap130);
1197 	set_interrupt_gate(0, 131, &trap131);
1198 	set_interrupt_gate(0, 132, &trap132);
1199 	set_interrupt_gate(0, 133, &trap133);
1200 	set_interrupt_gate(0, 134, &trap134);
1201 	set_interrupt_gate(0, 135, &trap135);
1202 	set_interrupt_gate(0, 136, &trap136);
1203 	set_interrupt_gate(0, 137, &trap137);
1204 	set_interrupt_gate(0, 138, &trap138);
1205 	set_interrupt_gate(0, 139, &trap139);
1206 	set_interrupt_gate(0, 140, &trap140);
1207 	set_interrupt_gate(0, 141, &trap141);
1208 	set_interrupt_gate(0, 142, &trap142);
1209 	set_interrupt_gate(0, 143, &trap143);
1210 	set_interrupt_gate(0, 144, &trap144);
1211 	set_interrupt_gate(0, 145, &trap145);
1212 	set_interrupt_gate(0, 146, &trap146);
1213 	set_interrupt_gate(0, 147, &trap147);
1214 	set_interrupt_gate(0, 148, &trap148);
1215 	set_interrupt_gate(0, 149, &trap149);
1216 	set_interrupt_gate(0, 150, &trap150);
1217 	set_interrupt_gate(0, 151, &trap151);
1218 	set_interrupt_gate(0, 152, &trap152);
1219 	set_interrupt_gate(0, 153, &trap153);
1220 	set_interrupt_gate(0, 154, &trap154);
1221 	set_interrupt_gate(0, 155, &trap155);
1222 	set_interrupt_gate(0, 156, &trap156);
1223 	set_interrupt_gate(0, 157, &trap157);
1224 	set_interrupt_gate(0, 158, &trap158);
1225 	set_interrupt_gate(0, 159, &trap159);
1226 	set_interrupt_gate(0, 160, &trap160);
1227 	set_interrupt_gate(0, 161, &trap161);
1228 	set_interrupt_gate(0, 162, &trap162);
1229 	set_interrupt_gate(0, 163, &trap163);
1230 	set_interrupt_gate(0, 164, &trap164);
1231 	set_interrupt_gate(0, 165, &trap165);
1232 	set_interrupt_gate(0, 166, &trap166);
1233 	set_interrupt_gate(0, 167, &trap167);
1234 	set_interrupt_gate(0, 168, &trap168);
1235 	set_interrupt_gate(0, 169, &trap169);
1236 	set_interrupt_gate(0, 170, &trap170);
1237 	set_interrupt_gate(0, 171, &trap171);
1238 	set_interrupt_gate(0, 172, &trap172);
1239 	set_interrupt_gate(0, 173, &trap173);
1240 	set_interrupt_gate(0, 174, &trap174);
1241 	set_interrupt_gate(0, 175, &trap175);
1242 	set_interrupt_gate(0, 176, &trap176);
1243 	set_interrupt_gate(0, 177, &trap177);
1244 	set_interrupt_gate(0, 178, &trap178);
1245 	set_interrupt_gate(0, 179, &trap179);
1246 	set_interrupt_gate(0, 180, &trap180);
1247 	set_interrupt_gate(0, 181, &trap181);
1248 	set_interrupt_gate(0, 182, &trap182);
1249 	set_interrupt_gate(0, 183, &trap183);
1250 	set_interrupt_gate(0, 184, &trap184);
1251 	set_interrupt_gate(0, 185, &trap185);
1252 	set_interrupt_gate(0, 186, &trap186);
1253 	set_interrupt_gate(0, 187, &trap187);
1254 	set_interrupt_gate(0, 188, &trap188);
1255 	set_interrupt_gate(0, 189, &trap189);
1256 	set_interrupt_gate(0, 190, &trap190);
1257 	set_interrupt_gate(0, 191, &trap191);
1258 	set_interrupt_gate(0, 192, &trap192);
1259 	set_interrupt_gate(0, 193, &trap193);
1260 	set_interrupt_gate(0, 194, &trap194);
1261 	set_interrupt_gate(0, 195, &trap195);
1262 	set_interrupt_gate(0, 196, &trap196);
1263 	set_interrupt_gate(0, 197, &trap197);
1264 	set_interrupt_gate(0, 198, &trap198);
1265 	set_interrupt_gate(0, 199, &trap199);
1266 	set_interrupt_gate(0, 200, &trap200);
1267 	set_interrupt_gate(0, 201, &trap201);
1268 	set_interrupt_gate(0, 202, &trap202);
1269 	set_interrupt_gate(0, 203, &trap203);
1270 	set_interrupt_gate(0, 204, &trap204);
1271 	set_interrupt_gate(0, 205, &trap205);
1272 	set_interrupt_gate(0, 206, &trap206);
1273 	set_interrupt_gate(0, 207, &trap207);
1274 	set_interrupt_gate(0, 208, &trap208);
1275 	set_interrupt_gate(0, 209, &trap209);
1276 	set_interrupt_gate(0, 210, &trap210);
1277 	set_interrupt_gate(0, 211, &trap211);
1278 	set_interrupt_gate(0, 212, &trap212);
1279 	set_interrupt_gate(0, 213, &trap213);
1280 	set_interrupt_gate(0, 214, &trap214);
1281 	set_interrupt_gate(0, 215, &trap215);
1282 	set_interrupt_gate(0, 216, &trap216);
1283 	set_interrupt_gate(0, 217, &trap217);
1284 	set_interrupt_gate(0, 218, &trap218);
1285 	set_interrupt_gate(0, 219, &trap219);
1286 	set_interrupt_gate(0, 220, &trap220);
1287 	set_interrupt_gate(0, 221, &trap221);
1288 	set_interrupt_gate(0, 222, &trap222);
1289 	set_interrupt_gate(0, 223, &trap223);
1290 	set_interrupt_gate(0, 224, &trap224);
1291 	set_interrupt_gate(0, 225, &trap225);
1292 	set_interrupt_gate(0, 226, &trap226);
1293 	set_interrupt_gate(0, 227, &trap227);
1294 	set_interrupt_gate(0, 228, &trap228);
1295 	set_interrupt_gate(0, 229, &trap229);
1296 	set_interrupt_gate(0, 230, &trap230);
1297 	set_interrupt_gate(0, 231, &trap231);
1298 	set_interrupt_gate(0, 232, &trap232);
1299 	set_interrupt_gate(0, 233, &trap233);
1300 	set_interrupt_gate(0, 234, &trap234);
1301 	set_interrupt_gate(0, 235, &trap235);
1302 	set_interrupt_gate(0, 236, &trap236);
1303 	set_interrupt_gate(0, 237, &trap237);
1304 	set_interrupt_gate(0, 238, &trap238);
1305 	set_interrupt_gate(0, 239, &trap239);
1306 	set_interrupt_gate(0, 240, &trap240);
1307 	set_interrupt_gate(0, 241, &trap241);
1308 	set_interrupt_gate(0, 242, &trap242);
1309 	set_interrupt_gate(0, 243, &trap243);
1310 	set_interrupt_gate(0, 244, &trap244);
1311 	set_interrupt_gate(0, 245, &trap245);
1312 	set_interrupt_gate(0, 246, &trap246);
1313 	set_interrupt_gate(0, 247, &trap247);
1314 	set_interrupt_gate(0, 248, &trap248);
1315 	set_interrupt_gate(0, 249, &trap249);
1316 	set_interrupt_gate(0, 250, &trap250);
1317 
1318 	// smp / apic local interrupts
1319 	set_interrupt_gate(0, 251, &trap251);
1320 	set_interrupt_gate(0, 252, &trap252);
1321 	set_interrupt_gate(0, 253, &trap253);
1322 	set_interrupt_gate(0, 254, &trap254);
1323 	set_interrupt_gate(0, 255, &trap255);
1324 
1325 	// init interrupt handler table
1326 	table = gInterruptHandlerTable;
1327 
1328 	// defaults
1329 	for (i = 0; i < ARCH_INTERRUPT_BASE; i++)
1330 		table[i] = invalid_exception;
1331 	for (i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++)
1332 		table[i] = hardware_interrupt;
1333 
1334 	table[0] = unexpected_exception;	// Divide Error Exception (#DE)
1335 	table[1] = x86_handle_debug_exception; // Debug Exception (#DB)
1336 	table[2] = fatal_exception;			// NMI Interrupt
1337 	table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
1338 	table[4] = unexpected_exception;	// Overflow Exception (#OF)
1339 	table[5] = unexpected_exception;	// BOUND Range Exceeded Exception (#BR)
1340 	table[6] = unexpected_exception;	// Invalid Opcode Exception (#UD)
1341 	table[7] = fatal_exception;			// Device Not Available Exception (#NM)
1342 	table[8] = x86_double_fault_exception; // Double Fault Exception (#DF)
1343 	table[9] = fatal_exception;			// Coprocessor Segment Overrun
1344 	table[10] = fatal_exception;		// Invalid TSS Exception (#TS)
1345 	table[11] = fatal_exception;		// Segment Not Present (#NP)
1346 	table[12] = fatal_exception;		// Stack Fault Exception (#SS)
1347 	table[13] = unexpected_exception;	// General Protection Exception (#GP)
1348 	table[14] = page_fault_exception;	// Page-Fault Exception (#PF)
1349 	table[16] = unexpected_exception;	// x87 FPU Floating-Point Error (#MF)
1350 	table[17] = unexpected_exception;	// Alignment Check Exception (#AC)
1351 	table[18] = fatal_exception;		// Machine-Check Exception (#MC)
1352 	table[19] = unexpected_exception;	// SIMD Floating-Point Exception (#XF)
1353 
1354 	return B_OK;
1355 }
1356 
1357 
1358 status_t
1359 arch_int_init_post_vm(struct kernel_args *args)
1360 {
1361 	// Always init the local apic as it can be used for timers even if we
1362 	// don't end up using the io apic
1363 	apic_init(args);
1364 
1365 	// We need to map in the I/O APIC here, since we would lose the already
1366 	// wired mapping before arch_int_init_io() is called.
1367 	ioapic_map(args);
1368 
1369 	// create IDT area for the boot CPU
1370 	area_id area = create_area("idt", (void**)&sIDTs[0], B_EXACT_ADDRESS,
1371 		B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
1372 	if (area < 0)
1373 		return area;
1374 
1375 	// create IDTs for the off-boot CPU
1376 	size_t idtSize = 256 * 8;
1377 		// 256 8 bytes-sized descriptors
1378 	int32 cpuCount = smp_get_num_cpus();
1379 	if (cpuCount > 0) {
1380 		size_t areaSize = ROUNDUP(cpuCount * idtSize, B_PAGE_SIZE);
1381 		desc_table* idt;
1382 		virtual_address_restrictions virtualRestrictions = {};
1383 		virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS;
1384 		physical_address_restrictions physicalRestrictions = {};
1385 		area = create_area_etc(B_SYSTEM_TEAM, "idt", areaSize, B_CONTIGUOUS,
1386 			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT,
1387 			&virtualRestrictions, &physicalRestrictions, (void**)&idt);
1388 		if (area < 0)
1389 			return area;
1390 
1391 		for (int32 i = 1; i < cpuCount; i++) {
1392 			sIDTs[i] = idt;
1393 			memcpy(idt, sIDTs[0], idtSize);
1394 			idt += 256;
1395 			// The CPU's IDTR will be set in arch_cpu_init_percpu().
1396 		}
1397 	}
1398 
1399 	return area >= B_OK ? B_OK : area;
1400 }
1401 
1402 
1403 status_t
1404 arch_int_init_io(kernel_args* args)
1405 {
1406 	ioapic_init(args);
1407 	return B_OK;
1408 }
1409 
1410 
1411 status_t
1412 arch_int_init_post_device_manager(struct kernel_args *args)
1413 {
1414 	return B_OK;
1415 }
1416