14f419b51SAlex Smith/*
2611376feSPawel Dziepak * Copyright 2013, Pawe�� Dziepak, pdziepak@quarnos.org.
34f419b51SAlex Smith * Copyright 2008-2011, Michael Lotz, mmlr@mlotz.ch.
44f419b51SAlex Smith * Copyright 2010, Clemens Zeidler, haiku@clemens-zeidler.de.
54f419b51SAlex Smith * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
64f419b51SAlex Smith * Copyright 2002-2010, Axel D��rfler, axeld@pinc-software.de.
7d2a1be1cSAlex Smith * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
84f419b51SAlex Smith * Distributed under the terms of the MIT License.
94f419b51SAlex Smith *
10d2a1be1cSAlex Smith * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
114f419b51SAlex Smith * Distributed under the terms of the NewOS License.
124f419b51SAlex Smith */
134f419b51SAlex Smith
14d2a1be1cSAlex Smith
15d2a1be1cSAlex Smith#include <arch/x86/descriptors.h>
166497f6b1SAlex Smith
176497f6b1SAlex Smith#include <stdio.h>
184f419b51SAlex Smith
19d2a1be1cSAlex Smith#include <boot/kernel_args.h>
204f419b51SAlex Smith#include <cpu.h>
2186f0f139SRene Gollent#include <int.h>
22d2a1be1cSAlex Smith#include <tls.h>
234f419b51SAlex Smith#include <vm/vm.h>
244f419b51SAlex Smith#include <vm/vm_priv.h>
254f419b51SAlex Smith
264f419b51SAlex Smith#include <arch/int.h>
274f419b51SAlex Smith#include <arch/user_debugger.h>
284f419b51SAlex Smith
294f419b51SAlex Smith#include "interrupts.h"
304f419b51SAlex Smith
314f419b51SAlex Smith
32611376feSPawel Dziepak#define IDT_GATES_COUNT	256
33611376feSPawel Dziepak
34611376feSPawel Dziepak
35611376feSPawel Dziepaktypedef interrupt_descriptor interrupt_descriptor_table[IDT_GATES_COUNT];
36611376feSPawel Dziepak
37611376feSPawel Dziepakglobal_descriptor_table gGDTs[SMP_MAX_CPUS];
38611376feSPawel Dziepakstatic interrupt_descriptor_table sIDTs[SMP_MAX_CPUS];
394f419b51SAlex Smith
404f419b51SAlex Smith// table with functions handling respective interrupts
414f419b51SAlex Smithtypedef void interrupt_handler_function(struct iframe* frame);
424f419b51SAlex Smith
43611376feSPawel Dziepakstatic const uint32 kInterruptHandlerTableSize = IDT_GATES_COUNT;
44d2a1be1cSAlex Smithinterrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize];
45d2a1be1cSAlex Smith
464f419b51SAlex Smith
474f419b51SAlex Smith/*!	Initializes a descriptor in an IDT.
484f419b51SAlex Smith*/
494f419b51SAlex Smithstatic void
5076a1175dSAlex Smithset_gate(interrupt_descriptor *gate_addr, addr_t addr, int type, int dpl)
514f419b51SAlex Smith{
524f419b51SAlex Smith	unsigned int gate1; // first byte of gate desc
534f419b51SAlex Smith	unsigned int gate2; // second byte of gate desc
544f419b51SAlex Smith
55611376feSPawel Dziepak	gate1 = (KERNEL_CODE_SELECTOR << 16) | (0x0000ffff & addr);
564f419b51SAlex Smith	gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8);
574f419b51SAlex Smith
584f419b51SAlex Smith	gate_addr->a = gate1;
594f419b51SAlex Smith	gate_addr->b = gate2;
604f419b51SAlex Smith}
614f419b51SAlex Smith
624f419b51SAlex Smith
634f419b51SAlex Smith/*!	Initializes the descriptor for interrupt vector \a n in the IDT of the
644f419b51SAlex Smith	specified CPU to an interrupt-gate descriptor with the given procedure
654f419b51SAlex Smith	address.
664f419b51SAlex Smith	For CPUs other than the boot CPU it must not be called before
674f419b51SAlex Smith	arch_int_init_post_vm().
684f419b51SAlex Smith*/
694f419b51SAlex Smithstatic void
704f419b51SAlex Smithset_interrupt_gate(int32 cpu, int n, void (*addr)())
714f419b51SAlex Smith{
724f419b51SAlex Smith	set_gate(&sIDTs[cpu][n], (addr_t)addr, 14, DPL_KERNEL);
734f419b51SAlex Smith}
744f419b51SAlex Smith
754f419b51SAlex Smith
764f419b51SAlex Smith/*!	Initializes the descriptor for interrupt vector \a n in the IDT of the
774f419b51SAlex Smith	specified CPU to an trap-gate descriptor with the given procedure address.
784f419b51SAlex Smith	For CPUs other than the boot CPU it must not be called before
794f419b51SAlex Smith	arch_int_init_post_vm().
804f419b51SAlex Smith*/
814f419b51SAlex Smithstatic void
824f419b51SAlex Smithset_trap_gate(int32 cpu, int n, void (*addr)())
834f419b51SAlex Smith{
844f419b51SAlex Smith	set_gate(&sIDTs[cpu][n], (unsigned int)addr, 15, DPL_USER);
854f419b51SAlex Smith}
864f419b51SAlex Smith
874f419b51SAlex Smith
884f419b51SAlex Smith/*!	Initializes the descriptor for interrupt vector \a n in the IDT of CPU
894f419b51SAlex Smith	\a cpu to a task-gate descripter referring to the TSS segment identified
904f419b51SAlex Smith	by TSS segment selector \a segment.
914f419b51SAlex Smith	For CPUs other than the boot CPU it must not be called before
924f419b51SAlex Smith	arch_int_init_post_vm() (arch_cpu_init_post_vm() is fine).
934f419b51SAlex Smith*/
94d2a1be1cSAlex Smithstatic void
95d2a1be1cSAlex Smithset_task_gate(int32 cpu, int32 n, int32 segment)
964f419b51SAlex Smith{
974f419b51SAlex Smith	sIDTs[cpu][n].a = (segment << 16);
984f419b51SAlex Smith	sIDTs[cpu][n].b = 0x8000 | (0 << 13) | (0x5 << 8); // present, dpl 0, type 5
994f419b51SAlex Smith}
1004f419b51SAlex Smith
1014f419b51SAlex Smith
102527da4caSPawel Dziepakstatic inline void
103611376feSPawel Dziepakload_tss()
1044f419b51SAlex Smith{
105527da4caSPawel Dziepak	uint16 segment = (TSS_SEGMENT << 3) | DPL_KERNEL;
106527da4caSPawel Dziepak	asm("ltr %w0" : : "r" (segment));
107527da4caSPawel Dziepak}
108527da4caSPawel Dziepak
109527da4caSPawel Dziepak
110527da4caSPawel Dziepakstatic inline void
111527da4caSPawel Dziepakload_gdt(int cpu)
112527da4caSPawel Dziepak{
113527da4caSPawel Dziepak	struct {
114527da4caSPawel Dziepak		uint16	limit;
115527da4caSPawel Dziepak		void*	address;
116527da4caSPawel Dziepak	} _PACKED gdtDescriptor = {
117527da4caSPawel Dziepak		GDT_SEGMENT_COUNT * sizeof(segment_descriptor) - 1,
118527da4caSPawel Dziepak		gGDTs[cpu]
119527da4caSPawel Dziepak	};
120527da4caSPawel Dziepak
121527da4caSPawel Dziepak	asm volatile("lgdt %0" : : "m" (gdtDescriptor));
122527da4caSPawel Dziepak}
123527da4caSPawel Dziepak
124527da4caSPawel Dziepak
125527da4caSPawel Dziepakstatic inline void
126527da4caSPawel Dziepakload_idt(int cpu)
127527da4caSPawel Dziepak{
128527da4caSPawel Dziepak	struct {
129527da4caSPawel Dziepak		uint16	limit;
130527da4caSPawel Dziepak		void*	address;
131527da4caSPawel Dziepak	} _PACKED idtDescriptor = {
132527da4caSPawel Dziepak		IDT_GATES_COUNT * sizeof(interrupt_descriptor) - 1,
133527da4caSPawel Dziepak		&sIDTs[cpu]
134527da4caSPawel Dziepak	};
135527da4caSPawel Dziepak
136527da4caSPawel Dziepak	asm volatile("lidt %0" : : "m" (idtDescriptor));
1374f419b51SAlex Smith}
1384f419b51SAlex Smith
1394f419b51SAlex Smith
140d2a1be1cSAlex Smith//	#pragma mark - Double fault handling
1414f419b51SAlex Smith
1424f419b51SAlex Smith
1434f419b51SAlex Smithvoid
1444f419b51SAlex Smithx86_double_fault_exception(struct iframe* frame)
1454f419b51SAlex Smith{
1464f419b51SAlex Smith	int cpu = x86_double_fault_get_cpu();
1474f419b51SAlex Smith
1484f419b51SAlex Smith	// The double fault iframe contains no useful information (as
1494f419b51SAlex Smith	// per Intel's architecture spec). Thus we simply save the
1504f419b51SAlex Smith	// information from the (unhandlable) exception which caused the
1514f419b51SAlex Smith	// double in our iframe. This will result even in useful stack
1524f419b51SAlex Smith	// traces. Only problem is that we trust that at least the
1534f419b51SAlex Smith	// TSS is still accessible.
1544f419b51SAlex Smith	struct tss *tss = &gCPU[cpu].arch.tss;
1554f419b51SAlex Smith
1564f419b51SAlex Smith	frame->cs = tss->cs;
1574f419b51SAlex Smith	frame->es = tss->es;
1584f419b51SAlex Smith	frame->ds = tss->ds;
1594f419b51SAlex Smith	frame->fs = tss->fs;
1604f419b51SAlex Smith	frame->gs = tss->gs;
161b5c9d24aSAlex Smith	frame->ip = tss->eip;
162b5c9d24aSAlex Smith	frame->bp = tss->ebp;
163b5c9d24aSAlex Smith	frame->sp = tss->esp;
164b5c9d24aSAlex Smith	frame->ax = tss->eax;
165b5c9d24aSAlex Smith	frame->bx = tss->ebx;
166b5c9d24aSAlex Smith	frame->cx = tss->ecx;
167b5c9d24aSAlex Smith	frame->dx = tss->edx;
168b5c9d24aSAlex Smith	frame->si = tss->esi;
169b5c9d24aSAlex Smith	frame->di = tss->edi;
1704f419b51SAlex Smith	frame->flags = tss->eflags;
1714f419b51SAlex Smith
1724f419b51SAlex Smith	// Use a special handler for page faults which avoids the triple fault
1734f419b51SAlex Smith	// pitfalls.
1744f419b51SAlex Smith	set_interrupt_gate(cpu, 14, &trap14_double_fault);
1754f419b51SAlex Smith
1764f419b51SAlex Smith	debug_double_fault(cpu);
1774f419b51SAlex Smith}
1784f419b51SAlex Smith
1794f419b51SAlex Smith
1804f419b51SAlex Smithvoid
1814f419b51SAlex Smithx86_page_fault_exception_double_fault(struct iframe* frame)
1824f419b51SAlex Smith{
1834e8fbfb2SAlex Smith	addr_t cr2 = x86_read_cr2();
1844f419b51SAlex Smith
1854f419b51SAlex Smith	// Only if this CPU has a fault handler, we're allowed to be here.
1864f419b51SAlex Smith	cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()];
1874f419b51SAlex Smith	addr_t faultHandler = cpu.fault_handler;
1884f419b51SAlex Smith	if (faultHandler != 0) {
189b5c9d24aSAlex Smith		debug_set_page_fault_info(cr2, frame->ip,
1904f419b51SAlex Smith			(frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0);
191b5c9d24aSAlex Smith		frame->ip = faultHandler;
192b5c9d24aSAlex Smith		frame->bp = cpu.fault_handler_stack_pointer;
1934f419b51SAlex Smith		return;
1944f419b51SAlex Smith	}
1954f419b51SAlex Smith
1964f419b51SAlex Smith	// No fault handler. This is bad. Since we originally came from a double
1974f419b51SAlex Smith	// fault, we don't try to reenter the kernel debugger. Instead we just
1984f419b51SAlex Smith	// print the info we've got and enter an infinite loop.
1994f419b51SAlex Smith	kprintf("Page fault in double fault debugger without fault handler! "
2004f419b51SAlex Smith		"Touching address %p from eip %p. Entering infinite loop...\n",
201b5c9d24aSAlex Smith		(void*)cr2, (void*)frame->ip);
2024f419b51SAlex Smith
2034f419b51SAlex Smith	while (true);
2044f419b51SAlex Smith}
2054f419b51SAlex Smith
2064f419b51SAlex Smith
207d2a1be1cSAlex Smithstatic void
208d2a1be1cSAlex Smithinit_double_fault(int cpuNum)
209d2a1be1cSAlex Smith{
210d2a1be1cSAlex Smith	// set up the double fault TSS
211d2a1be1cSAlex Smith	struct tss* tss = &gCPU[cpuNum].arch.double_fault_tss;
212d2a1be1cSAlex Smith
213d2a1be1cSAlex Smith	memset(tss, 0, sizeof(struct tss));
214527da4caSPawel Dziepak	size_t stackSize = 0;
215527da4caSPawel Dziepak	//tss->sp0 = (addr_t)x86_get_double_fault_stack(cpuNum, &stackSize);
216d2a1be1cSAlex Smith	tss->sp0 += stackSize;
217611376feSPawel Dziepak	tss->ss0 = KERNEL_DATA_SELECTOR;
218d2a1be1cSAlex Smith	tss->cr3 = x86_read_cr3();
219d2a1be1cSAlex Smith		// copy the current cr3 to the double fault cr3
220d2a1be1cSAlex Smith	tss->eip = (uint32)&double_fault;
221611376feSPawel Dziepak	tss->es = KERNEL_DATA_SELECTOR;
222611376feSPawel Dziepak	tss->cs = KERNEL_CODE_SELECTOR;
223611376feSPawel Dziepak	tss->ss = KERNEL_DATA_SELECTOR;
224d2a1be1cSAlex Smith	tss->esp = tss->sp0;
225611376feSPawel Dziepak	tss->ds = KERNEL_DATA_SELECTOR;
226611376feSPawel Dziepak	tss->fs = KERNEL_DATA_SELECTOR;
227611376feSPawel Dziepak	tss->gs = KERNEL_DATA_SELECTOR;
228d2a1be1cSAlex Smith	tss->ldt_seg_selector = 0;
229d2a1be1cSAlex Smith	tss->io_map_base = sizeof(struct tss);
230d2a1be1cSAlex Smith
231d2a1be1cSAlex Smith	// add TSS descriptor for this new TSS
232611376feSPawel Dziepak	set_tss_descriptor(&gGDTs[cpuNum][DOUBLE_FAULT_TSS_SEGMENT], (addr_t)tss,
233611376feSPawel Dziepak		sizeof(struct tss));
234d2a1be1cSAlex Smith
235611376feSPawel Dziepak	set_task_gate(cpuNum, 8, DOUBLE_FAULT_TSS_SEGMENT << 3);
236d2a1be1cSAlex Smith}
237d2a1be1cSAlex Smith
238d2a1be1cSAlex Smith
239611376feSPawel Dziepakstatic void
240611376feSPawel Dziepakinit_gdt_percpu(kernel_args* args, int cpu)
2414f419b51SAlex Smith{
242611376feSPawel Dziepak	STATIC_ASSERT(GDT_SEGMENT_COUNT <= 8192);
243611376feSPawel Dziepak
244611376feSPawel Dziepak	segment_descriptor* gdt = get_gdt(cpu);
245611376feSPawel Dziepak
246611376feSPawel Dziepak	clear_segment_descriptor(&gdt[0]);
247611376feSPawel Dziepak
248611376feSPawel Dziepak	set_segment_descriptor(&gdt[KERNEL_CODE_SEGMENT], 0, addr_t(-1),
249611376feSPawel Dziepak		DT_CODE_READABLE, DPL_KERNEL);
250611376feSPawel Dziepak	set_segment_descriptor(&gdt[KERNEL_DATA_SEGMENT], 0, addr_t(-1),
251611376feSPawel Dziepak		DT_DATA_WRITEABLE, DPL_KERNEL);
252611376feSPawel Dziepak
253611376feSPawel Dziepak	set_segment_descriptor(&gdt[USER_CODE_SEGMENT], 0, addr_t(-1),
254611376feSPawel Dziepak		DT_CODE_READABLE, DPL_USER);
255611376feSPawel Dziepak	set_segment_descriptor(&gdt[USER_DATA_SEGMENT], 0, addr_t(-1),
256611376feSPawel Dziepak		DT_DATA_WRITEABLE, DPL_USER);
257611376feSPawel Dziepak
258611376feSPawel Dziepak	// initialize the regular and double fault tss stored in the per-cpu
259611376feSPawel Dziepak	// structure
260611376feSPawel Dziepak	memset(&gCPU[cpu].arch.tss, 0, sizeof(struct tss));
261611376feSPawel Dziepak	gCPU[cpu].arch.tss.ss0 = (KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL;
262611376feSPawel Dziepak	gCPU[cpu].arch.tss.io_map_base = sizeof(struct tss);
263611376feSPawel Dziepak
264611376feSPawel Dziepak	// add TSS descriptor for this new TSS
265611376feSPawel Dziepak	set_tss_descriptor(&gdt[TSS_SEGMENT], (addr_t)&gCPU[cpu].arch.tss,
266611376feSPawel Dziepak		sizeof(struct tss));
267611376feSPawel Dziepak
268611376feSPawel Dziepak	// initialize the double fault tss
269611376feSPawel Dziepak	init_double_fault(cpu);
270611376feSPawel Dziepak
271611376feSPawel Dziepak	set_segment_descriptor(&gdt[KERNEL_TLS_SEGMENT],
272611376feSPawel Dziepak		(addr_t)&gCPU[cpu].arch.kernel_tls, sizeof(void*), DT_DATA_WRITEABLE,
273611376feSPawel Dziepak		DPL_KERNEL);
274611376feSPawel Dziepak	set_segment_descriptor(&gdt[USER_TLS_SEGMENT], 0, TLS_SIZE,
275611376feSPawel Dziepak		DT_DATA_WRITEABLE, DPL_USER);
276611376feSPawel Dziepak
277611376feSPawel Dziepak	load_gdt(cpu);
278611376feSPawel Dziepak
279611376feSPawel Dziepak	load_tss();
280611376feSPawel Dziepak
281611376feSPawel Dziepak	// set kernel TLS segment
282527da4caSPawel Dziepak	asm volatile("movw %w0, %%gs" : : "r" (KERNEL_TLS_SEGMENT << 3));
283611376feSPawel Dziepak}
284611376feSPawel Dziepak
285611376feSPawel Dziepak
286611376feSPawel Dziepakstatic void
287611376feSPawel Dziepakinit_idt_percpu(kernel_args* args, int cpu)
288611376feSPawel Dziepak{
289611376feSPawel Dziepak	set_interrupt_gate(cpu, 0, &trap0);
290611376feSPawel Dziepak	set_interrupt_gate(cpu, 1, &trap1);
291611376feSPawel Dziepak	set_interrupt_gate(cpu, 2, &trap2);
292611376feSPawel Dziepak	set_trap_gate(cpu, 3, &trap3);
293611376feSPawel Dziepak	set_interrupt_gate(cpu, 4, &trap4);
294611376feSPawel Dziepak	set_interrupt_gate(cpu, 5, &trap5);
295611376feSPawel Dziepak	set_interrupt_gate(cpu, 6, &trap6);
296611376feSPawel Dziepak	set_interrupt_gate(cpu, 7, &trap7);
297d2a1be1cSAlex Smith	// trap8 (double fault) is set in init_double_fault().
298611376feSPawel Dziepak	set_interrupt_gate(cpu, 9, &trap9);
299611376feSPawel Dziepak	set_interrupt_gate(cpu, 10, &trap10);
300611376feSPawel Dziepak	set_interrupt_gate(cpu, 11, &trap11);
301611376feSPawel Dziepak	set_interrupt_gate(cpu, 12, &trap12);
302611376feSPawel Dziepak	set_interrupt_gate(cpu, 13, &trap13);
303611376feSPawel Dziepak	set_interrupt_gate(cpu, 14, &trap14);
304611376feSPawel Dziepak	//set_interrupt_gate(cpu, 15, &trap15);
305611376feSPawel Dziepak	set_interrupt_gate(cpu, 16, &trap16);
306611376feSPawel Dziepak	set_interrupt_gate(cpu, 17, &trap17);
307611376feSPawel Dziepak	set_interrupt_gate(cpu, 18, &trap18);
308611376feSPawel Dziepak	set_interrupt_gate(cpu, 19, &trap19);
3094f419b51SAlex Smith
3104f419b51SAlex Smith	// legacy or ioapic interrupts
311611376feSPawel Dziepak	set_interrupt_gate(cpu, 32, &trap32);
312611376feSPawel Dziepak	set_interrupt_gate(cpu, 33, &trap33);
313611376feSPawel Dziepak	set_interrupt_gate(cpu, 34, &trap34);
314611376feSPawel Dziepak	set_interrupt_gate(cpu, 35, &trap35);
315611376feSPawel Dziepak	set_interrupt_gate(cpu, 36, &trap36);
316611376feSPawel Dziepak	set_interrupt_gate(cpu, 37, &trap37);
317611376feSPawel Dziepak	set_interrupt_gate(cpu, 38, &trap38);
318611376feSPawel Dziepak	set_interrupt_gate(cpu, 39, &trap39);
319611376feSPawel Dziepak	set_interrupt_gate(cpu, 40, &trap40);
320611376feSPawel Dziepak	set_interrupt_gate(cpu, 41, &trap41);
321611376feSPawel Dziepak	set_interrupt_gate(cpu, 42, &trap42);
322611376feSPawel Dziepak	set_interrupt_gate(cpu, 43, &trap43);
323611376feSPawel Dziepak	set_interrupt_gate(cpu, 44, &trap44);
324611376feSPawel Dziepak	set_interrupt_gate(cpu, 45, &trap45);
325611376feSPawel Dziepak	set_interrupt_gate(cpu, 46, &trap46);
326611376feSPawel Dziepak	set_interrupt_gate(cpu, 47, &trap47);
3274f419b51SAlex Smith
3284f419b51SAlex Smith	// additional ioapic interrupts
329611376feSPawel Dziepak	set_interrupt_gate(cpu, 48, &trap48);
330611376feSPawel Dziepak	set_interrupt_gate(cpu, 49, &trap49);
331611376feSPawel Dziepak	set_interrupt_gate(cpu, 50, &trap50);
332611376feSPawel Dziepak	set_interrupt_gate(cpu, 51, &trap51);
333611376feSPawel Dziepak	set_interrupt_gate(cpu, 52, &trap52);
334611376feSPawel Dziepak	set_interrupt_gate(cpu, 53, &trap53);
335611376feSPawel Dziepak	set_interrupt_gate(cpu, 54, &trap54);
336611376feSPawel Dziepak	set_interrupt_gate(cpu, 55, &trap55);
3374f419b51SAlex Smith
3384f419b51SAlex Smith	// configurable msi or msi-x interrupts
339611376feSPawel Dziepak	set_interrupt_gate(cpu, 56, &trap56);
340611376feSPawel Dziepak	set_interrupt_gate(cpu, 57, &trap57);
341611376feSPawel Dziepak	set_interrupt_gate(cpu, 58, &trap58);
342611376feSPawel Dziepak	set_interrupt_gate(cpu, 59, &trap59);
343611376feSPawel Dziepak	set_interrupt_gate(cpu, 60, &trap60);
344611376feSPawel Dziepak	set_interrupt_gate(cpu, 61, &trap61);
345611376feSPawel Dziepak	set_interrupt_gate(cpu, 62, &trap62);
346611376feSPawel Dziepak	set_interrupt_gate(cpu, 63, &trap63);
347611376feSPawel Dziepak	set_interrupt_gate(cpu, 64, &trap64);
348611376feSPawel Dziepak	set_interrupt_gate(cpu, 65, &trap65);
349611376feSPawel Dziepak	set_interrupt_gate(cpu, 66, &trap66);
350611376feSPawel Dziepak	set_interrupt_gate(cpu, 67, &trap67);
351611376feSPawel Dziepak	set_interrupt_gate(cpu, 68, &trap68);
352611376feSPawel Dziepak	set_interrupt_gate(cpu, 69, &trap69);
353611376feSPawel Dziepak	set_interrupt_gate(cpu, 70, &trap70);
354611376feSPawel Dziepak	set_interrupt_gate(cpu, 71, &trap71);
355611376feSPawel Dziepak	set_interrupt_gate(cpu, 72, &trap72);
356611376feSPawel Dziepak	set_interrupt_gate(cpu, 73, &trap73);
357611376feSPawel Dziepak	set_interrupt_gate(cpu, 74, &trap74);
358611376feSPawel Dziepak	set_interrupt_gate(cpu, 75, &trap75);
359611376feSPawel Dziepak	set_interrupt_gate(cpu, 76, &trap76);
360611376feSPawel Dziepak	set_interrupt_gate(cpu, 77, &trap77);
361611376feSPawel Dziepak	set_interrupt_gate(cpu, 78, &trap78);
362611376feSPawel Dziepak	set_interrupt_gate(cpu, 79, &trap79);
363611376feSPawel Dziepak	set_interrupt_gate(cpu, 80, &trap80);
364611376feSPawel Dziepak	set_interrupt_gate(cpu, 81, &trap81);
365611376feSPawel Dziepak	set_interrupt_gate(cpu, 82, &trap82);
366611376feSPawel Dziepak	set_interrupt_gate(cpu, 83, &trap83);
367611376feSPawel Dziepak	set_interrupt_gate(cpu, 84, &trap84);
368611376feSPawel Dziepak	set_interrupt_gate(cpu, 85, &trap85);
369611376feSPawel Dziepak	set_interrupt_gate(cpu, 86, &trap86);
370611376feSPawel Dziepak	set_interrupt_gate(cpu, 87, &trap87);
371611376feSPawel Dziepak	set_interrupt_gate(cpu, 88, &trap88);
372611376feSPawel Dziepak	set_interrupt_gate(cpu, 89, &trap89);
373611376feSPawel Dziepak	set_interrupt_gate(cpu, 90, &trap90);
374611376feSPawel Dziepak	set_interrupt_gate(cpu, 91, &trap91);
375611376feSPawel Dziepak	set_interrupt_gate(cpu, 92, &trap92);
376611376feSPawel Dziepak	set_interrupt_gate(cpu, 93, &trap93);
377611376feSPawel Dziepak	set_interrupt_gate(cpu, 94, &trap94);
378611376feSPawel Dziepak	set_interrupt_gate(cpu, 95, &trap95);
379611376feSPawel Dziepak	set_interrupt_gate(cpu, 96, &trap96);
380611376feSPawel Dziepak	set_interrupt_gate(cpu, 97, &trap97);
381611376feSPawel Dziepak
382611376feSPawel Dziepak	set_trap_gate(cpu, 98, &trap98);	// for performance testing only
383611376feSPawel Dziepak	set_trap_gate(cpu, 99, &trap99);	// syscall interrupt
3844f419b51SAlex Smith
3854f419b51SAlex Smith	// configurable msi or msi-x interrupts
386611376feSPawel Dziepak	set_interrupt_gate(cpu, 100, &trap100);
387611376feSPawel Dziepak	set_interrupt_gate(cpu, 101, &trap101);
388611376feSPawel Dziepak	set_interrupt_gate(cpu, 102, &trap102);
389611376feSPawel Dziepak	set_interrupt_gate(cpu, 103, &trap103);
390611376feSPawel Dziepak	set_interrupt_gate(cpu, 104, &trap104);
391611376feSPawel Dziepak	set_interrupt_gate(cpu, 105, &trap105);
392611376feSPawel Dziepak	set_interrupt_gate(cpu, 106, &trap106);
393611376feSPawel Dziepak	set_interrupt_gate(cpu, 107, &trap107);
394611376feSPawel Dziepak	set_interrupt_gate(cpu, 108, &trap108);
395611376feSPawel Dziepak	set_interrupt_gate(cpu, 109, &trap109);
396611376feSPawel Dziepak	set_interrupt_gate(cpu, 110, &trap110);
397611376feSPawel Dziepak	set_interrupt_gate(cpu, 111, &trap111);
398611376feSPawel Dziepak	set_interrupt_gate(cpu, 112, &trap112);
399611376feSPawel Dziepak	set_interrupt_gate(cpu, 113, &trap113);
400611376feSPawel Dziepak	set_interrupt_gate(cpu, 114, &trap114);
401611376feSPawel Dziepak	set_interrupt_gate(cpu, 115, &trap115);
402611376feSPawel Dziepak	set_interrupt_gate(cpu, 116, &trap116);
403611376feSPawel Dziepak	set_interrupt_gate(cpu, 117, &trap117);
404611376feSPawel Dziepak	set_interrupt_gate(cpu, 118, &trap118);
405611376feSPawel Dziepak	set_interrupt_gate(cpu, 119, &trap119);
406611376feSPawel Dziepak	set_interrupt_gate(cpu, 120, &trap120);
407611376feSPawel Dziepak	set_interrupt_gate(cpu, 121, &trap121);
408611376feSPawel Dziepak	set_interrupt_gate(cpu, 122, &trap122);
409611376feSPawel Dziepak	set_interrupt_gate(cpu, 123, &trap123);
410611376feSPawel Dziepak	set_interrupt_gate(cpu, 124, &trap124);
411611376feSPawel Dziepak	set_interrupt_gate(cpu, 125, &trap125);
412611376feSPawel Dziepak	set_interrupt_gate(cpu, 126, &trap126);
413611376feSPawel Dziepak	set_interrupt_gate(cpu, 127, &trap127);
414611376feSPawel Dziepak	set_interrupt_gate(cpu, 128, &trap128);
415611376feSPawel Dziepak	set_interrupt_gate(cpu, 129, &trap129);
416611376feSPawel Dziepak	set_interrupt_gate(cpu, 130, &trap130);
417611376feSPawel Dziepak	set_interrupt_gate(cpu, 131, &trap131);
418611376feSPawel Dziepak	set_interrupt_gate(cpu, 132, &trap132);
419611376feSPawel Dziepak	set_interrupt_gate(cpu, 133, &trap133);
420611376feSPawel Dziepak	set_interrupt_gate(cpu, 134, &trap134);
421611376feSPawel Dziepak	set_interrupt_gate(cpu, 135, &trap135);
422611376feSPawel Dziepak	set_interrupt_gate(cpu, 136, &trap136);
423611376feSPawel Dziepak	set_interrupt_gate(cpu, 137, &trap137);
424611376feSPawel Dziepak	set_interrupt_gate(cpu, 138, &trap138);
425611376feSPawel Dziepak	set_interrupt_gate(cpu, 139, &trap139);
426611376feSPawel Dziepak	set_interrupt_gate(cpu, 140, &trap140);
427611376feSPawel Dziepak	set_interrupt_gate(cpu, 141, &trap141);
428611376feSPawel Dziepak	set_interrupt_gate(cpu, 142, &trap142);
429611376feSPawel Dziepak	set_interrupt_gate(cpu, 143, &trap143);
430611376feSPawel Dziepak	set_interrupt_gate(cpu, 144, &trap144);
431611376feSPawel Dziepak	set_interrupt_gate(cpu, 145, &trap145);
432611376feSPawel Dziepak	set_interrupt_gate(cpu, 146, &trap146);
433611376feSPawel Dziepak	set_interrupt_gate(cpu, 147, &trap147);
434611376feSPawel Dziepak	set_interrupt_gate(cpu, 148, &trap148);
435611376feSPawel Dziepak	set_interrupt_gate(cpu, 149, &trap149);
436611376feSPawel Dziepak	set_interrupt_gate(cpu, 150, &trap150);
437611376feSPawel Dziepak	set_interrupt_gate(cpu, 151, &trap151);
438611376feSPawel Dziepak	set_interrupt_gate(cpu, 152, &trap152);
439611376feSPawel Dziepak	set_interrupt_gate(cpu, 153, &trap153);
440611376feSPawel Dziepak	set_interrupt_gate(cpu, 154, &trap154);
441611376feSPawel Dziepak	set_interrupt_gate(cpu, 155, &trap155);
442611376feSPawel Dziepak	set_interrupt_gate(cpu, 156, &trap156);
443611376feSPawel Dziepak	set_interrupt_gate(cpu, 157, &trap157);
444611376feSPawel Dziepak	set_interrupt_gate(cpu, 158, &trap158);
445611376feSPawel Dziepak	set_interrupt_gate(cpu, 159, &trap159);
446611376feSPawel Dziepak	set_interrupt_gate(cpu, 160, &trap160);
447611376feSPawel Dziepak	set_interrupt_gate(cpu, 161, &trap161);
448611376feSPawel Dziepak	set_interrupt_gate(cpu, 162, &trap162);
449611376feSPawel Dziepak	set_interrupt_gate(cpu, 163, &trap163);
450611376feSPawel Dziepak	set_interrupt_gate(cpu, 164, &trap164);
451611376feSPawel Dziepak	set_interrupt_gate(cpu, 165, &trap165);
452611376feSPawel Dziepak	set_interrupt_gate(cpu, 166, &trap166);
453611376feSPawel Dziepak	set_interrupt_gate(cpu, 167, &trap167);
454611376feSPawel Dziepak	set_interrupt_gate(cpu, 168, &trap168);
455611376feSPawel Dziepak	set_interrupt_gate(cpu, 169, &trap169);
456611376feSPawel Dziepak	set_interrupt_gate(cpu, 170, &trap170);
457611376feSPawel Dziepak	set_interrupt_gate(cpu, 171, &trap171);
458611376feSPawel Dziepak	set_interrupt_gate(cpu, 172, &trap172);
459611376feSPawel Dziepak	set_interrupt_gate(cpu, 173, &trap173);
460611376feSPawel Dziepak	set_interrupt_gate(cpu, 174, &trap174);
461611376feSPawel Dziepak	set_interrupt_gate(cpu, 175, &trap175);
462611376feSPawel Dziepak	set_interrupt_gate(cpu, 176, &trap176);
463611376feSPawel Dziepak	set_interrupt_gate(cpu, 177, &trap177);
464611376feSPawel Dziepak	set_interrupt_gate(cpu, 178, &trap178);
465611376feSPawel Dziepak	set_interrupt_gate(cpu, 179, &trap179);
466611376feSPawel Dziepak	set_interrupt_gate(cpu, 180, &trap180);
467611376feSPawel Dziepak	set_interrupt_gate(cpu, 181, &trap181);
468611376feSPawel Dziepak	set_interrupt_gate(cpu, 182, &trap182);
469611376feSPawel Dziepak	set_interrupt_gate(cpu, 183, &trap183);
470611376feSPawel Dziepak	set_interrupt_gate(cpu, 184, &trap184);
471611376feSPawel Dziepak	set_interrupt_gate(cpu, 185, &trap185);
472611376feSPawel Dziepak	set_interrupt_gate(cpu, 186, &trap186);
473611376feSPawel Dziepak	set_interrupt_gate(cpu, 187, &trap187);
474611376feSPawel Dziepak	set_interrupt_gate(cpu, 188, &trap188);
475611376feSPawel Dziepak	set_interrupt_gate(cpu, 189, &trap189);
476611376feSPawel Dziepak	set_interrupt_gate(cpu, 190, &trap190);
477611376feSPawel Dziepak	set_interrupt_gate(cpu, 191, &trap191);
478611376feSPawel Dziepak	set_interrupt_gate(cpu, 192, &trap192);
479611376feSPawel Dziepak	set_interrupt_gate(cpu, 193, &trap193);
480611376feSPawel Dziepak	set_interrupt_gate(cpu, 194, &trap194);
481611376feSPawel Dziepak	set_interrupt_gate(cpu, 195, &trap195);
482611376feSPawel Dziepak	set_interrupt_gate(cpu, 196, &trap196);
483611376feSPawel Dziepak	set_interrupt_gate(cpu, 197, &trap197);
484611376feSPawel Dziepak	set_interrupt_gate(cpu, 198, &trap198);
485611376feSPawel Dziepak	set_interrupt_gate(cpu, 199, &trap199);
486611376feSPawel Dziepak	set_interrupt_gate(cpu, 200, &trap200);
487611376feSPawel Dziepak	set_interrupt_gate(cpu, 201, &trap201);
488611376feSPawel Dziepak	set_interrupt_gate(cpu, 202, &trap202);
489611376feSPawel Dziepak	set_interrupt_gate(cpu, 203, &trap203);
490611376feSPawel Dziepak	set_interrupt_gate(cpu, 204, &trap204);
491611376feSPawel Dziepak	set_interrupt_gate(cpu, 205, &trap205);
492611376feSPawel Dziepak	set_interrupt_gate(cpu, 206, &trap206);
493611376feSPawel Dziepak	set_interrupt_gate(cpu, 207, &trap207);
494611376feSPawel Dziepak	set_interrupt_gate(cpu, 208, &trap208);
495611376feSPawel Dziepak	set_interrupt_gate(cpu, 209, &trap209);
496611376feSPawel Dziepak	set_interrupt_gate(cpu, 210, &trap210);
497611376feSPawel Dziepak	set_interrupt_gate(cpu, 211, &trap211);
498611376feSPawel Dziepak	set_interrupt_gate(cpu, 212, &trap212);
499611376feSPawel Dziepak	set_interrupt_gate(cpu, 213, &trap213);
500611376feSPawel Dziepak	set_interrupt_gate(cpu, 214, &trap214);
501611376feSPawel Dziepak	set_interrupt_gate(cpu, 215, &trap215);
502611376feSPawel Dziepak	set_interrupt_gate(cpu, 216, &trap216);
503611376feSPawel Dziepak	set_interrupt_gate(cpu, 217, &trap217);
504611376feSPawel Dziepak	set_interrupt_gate(cpu, 218, &trap218);
505611376feSPawel Dziepak	set_interrupt_gate(cpu, 219, &trap219);
506611376feSPawel Dziepak	set_interrupt_gate(cpu, 220, &trap220);
507611376feSPawel Dziepak	set_interrupt_gate(cpu, 221, &trap221);
508611376feSPawel Dziepak	set_interrupt_gate(cpu, 222, &trap222);
509611376feSPawel Dziepak	set_interrupt_gate(cpu, 223, &trap223);
510611376feSPawel Dziepak	set_interrupt_gate(cpu, 224, &trap224);
511611376feSPawel Dziepak	set_interrupt_gate(cpu, 225, &trap225);
512611376feSPawel Dziepak	set_interrupt_gate(cpu, 226, &trap226);
513611376feSPawel Dziepak	set_interrupt_gate(cpu, 227, &trap227);
514611376feSPawel Dziepak	set_interrupt_gate(cpu, 228, &trap228);
515611376feSPawel Dziepak	set_interrupt_gate(cpu, 229, &trap229);
516611376feSPawel Dziepak	set_interrupt_gate(cpu, 230, &trap230);
517611376feSPawel Dziepak	set_interrupt_gate(cpu, 231, &trap231);
518611376feSPawel Dziepak	set_interrupt_gate(cpu, 232, &trap232);
519611376feSPawel Dziepak	set_interrupt_gate(cpu, 233, &trap233);
520611376feSPawel Dziepak	set_interrupt_gate(cpu, 234, &trap234);
521611376feSPawel Dziepak	set_interrupt_gate(cpu, 235, &trap235);
522611376feSPawel Dziepak	set_interrupt_gate(cpu, 236, &trap236);
523611376feSPawel Dziepak	set_interrupt_gate(cpu, 237, &trap237);
524611376feSPawel Dziepak	set_interrupt_gate(cpu, 238, &trap238);
525611376feSPawel Dziepak	set_interrupt_gate(cpu, 239, &trap239);
526611376feSPawel Dziepak	set_interrupt_gate(cpu, 240, &trap240);
527611376feSPawel Dziepak	set_interrupt_gate(cpu, 241, &trap241);
528611376feSPawel Dziepak	set_interrupt_gate(cpu, 242, &trap242);
529611376feSPawel Dziepak	set_interrupt_gate(cpu, 243, &trap243);
530611376feSPawel Dziepak	set_interrupt_gate(cpu, 244, &trap244);
531611376feSPawel Dziepak	set_interrupt_gate(cpu, 245, &trap245);
532611376feSPawel Dziepak	set_interrupt_gate(cpu, 246, &trap246);
533611376feSPawel Dziepak	set_interrupt_gate(cpu, 247, &trap247);
534611376feSPawel Dziepak	set_interrupt_gate(cpu, 248, &trap248);
535611376feSPawel Dziepak	set_interrupt_gate(cpu, 249, &trap249);
536611376feSPawel Dziepak	set_interrupt_gate(cpu, 250, &trap250);
5374f419b51SAlex Smith
5384f419b51SAlex Smith	// smp / apic local interrupts
539611376feSPawel Dziepak	set_interrupt_gate(cpu, 251, &trap251);
540611376feSPawel Dziepak	set_interrupt_gate(cpu, 252, &trap252);
541611376feSPawel Dziepak	set_interrupt_gate(cpu, 253, &trap253);
542611376feSPawel Dziepak	set_interrupt_gate(cpu, 254, &trap254);
543611376feSPawel Dziepak	set_interrupt_gate(cpu, 255, &trap255);
544611376feSPawel Dziepak
545611376feSPawel Dziepak	load_idt(cpu);
546611376feSPawel Dziepak}
547611376feSPawel Dziepak
548611376feSPawel Dziepak
549611376feSPawel Dziepak//	#pragma mark -
550611376feSPawel Dziepak
551611376feSPawel Dziepak
552611376feSPawel Dziepakvoid
553611376feSPawel Dziepakx86_descriptors_preboot_init_percpu(kernel_args* args, int cpu)
554611376feSPawel Dziepak{
555611376feSPawel Dziepak	init_idt_percpu(args, cpu);
556611376feSPawel Dziepak	init_gdt_percpu(args, cpu);
557611376feSPawel Dziepak}
558611376feSPawel Dziepak
559611376feSPawel Dziepak
560611376feSPawel Dziepakvoid
561611376feSPawel Dziepakx86_descriptors_init(kernel_args* args)
562611376feSPawel Dziepak{
563611376feSPawel Dziepak	reserve_io_interrupt_vectors(2, 98, INTERRUPT_TYPE_SYSCALL);
5644f419b51SAlex Smith
5654f419b51SAlex Smith	// init interrupt handler table
566611376feSPawel Dziepak	interrupt_handler_function** table = gInterruptHandlerTable;
5674f419b51SAlex Smith
5684f419b51SAlex Smith	// defaults
569611376feSPawel Dziepak	uint32 i;
5704f419b51SAlex Smith	for (i = 0; i < ARCH_INTERRUPT_BASE; i++)
5716497f6b1SAlex Smith		table[i] = x86_invalid_exception;
572d2a1be1cSAlex Smith	for (i = ARCH_INTERRUPT_BASE; i < kInterruptHandlerTableSize; i++)
5736497f6b1SAlex Smith		table[i] = x86_hardware_interrupt;
5744f419b51SAlex Smith
5756497f6b1SAlex Smith	table[0] = x86_unexpected_exception;	// Divide Error Exception (#DE)
5766497f6b1SAlex Smith	table[1] = x86_handle_debug_exception;	// Debug Exception (#DB)
5776497f6b1SAlex Smith	table[2] = x86_fatal_exception;			// NMI Interrupt
5784f419b51SAlex Smith	table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
5796497f6b1SAlex Smith	table[4] = x86_unexpected_exception;	// Overflow Exception (#OF)
5806497f6b1SAlex Smith	table[5] = x86_unexpected_exception;	// BOUND Range Exceeded Exception (#BR)
5816497f6b1SAlex Smith	table[6] = x86_unexpected_exception;	// Invalid Opcode Exception (#UD)
5826497f6b1SAlex Smith	table[7] = x86_fatal_exception;			// Device Not Available Exception (#NM)
5836497f6b1SAlex Smith	table[8] = x86_double_fault_exception;	// Double Fault Exception (#DF)
5846497f6b1SAlex Smith	table[9] = x86_fatal_exception;			// Coprocessor Segment Overrun
5856497f6b1SAlex Smith	table[10] = x86_fatal_exception;		// Invalid TSS Exception (#TS)
5866497f6b1SAlex Smith	table[11] = x86_fatal_exception;		// Segment Not Present (#NP)
5876497f6b1SAlex Smith	table[12] = x86_fatal_exception;		// Stack Fault Exception (#SS)
5886497f6b1SAlex Smith	table[13] = x86_unexpected_exception;	// General Protection Exception (#GP)
5895670b0a8SAlex Smith	table[14] = x86_page_fault_exception;	// Page-Fault Exception (#PF)
5906497f6b1SAlex Smith	table[16] = x86_unexpected_exception;	// x87 FPU Floating-Point Error (#MF)
5916497f6b1SAlex Smith	table[17] = x86_unexpected_exception;	// Alignment Check Exception (#AC)
5926497f6b1SAlex Smith	table[18] = x86_fatal_exception;		// Machine-Check Exception (#MC)
5936497f6b1SAlex Smith	table[19] = x86_unexpected_exception;	// SIMD Floating-Point Exception (#XF)
594d2a1be1cSAlex Smith}
5954f419b51SAlex Smith
596