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