summaryrefslogtreecommitdiff
path: root/kernel/idt.c
blob: 3fdc3dc5f27a423da0072af2fef125d099653982 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "idt.h"

#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port));

#define isr_panic(num) void isr_ ## num(); \
asm( \
	".globl isr_" #num "\n" \
	"isr_" #num ":\n" \
	"push $" #num "\n" \
	"call panic\n" \
	"iret\n" \
)

char* panic_msg[] = {
	[0] = "Divide error.",
	[8] = "Double fault.",
	[14] = "Page fault."
};

isr_panic(0);
isr_panic(8);
isr_panic(14);

void panic(uint32_t num) {
	char* str = panic_msg[num];
	while(*str) {
		outb(0x3f8, *str++);
	}
	outb(0x3f8, '\r');
	outb(0x3f8, '\n');
	asm volatile(
		"cli\n"
		"hlt\n"
	);
	while(1);
}

idt_entry idt[] = {
	{.base_low = 1}, // Keep IDT in .data.
	[1 ... 255] = idt_entry_null
};

idt_ptr idtr = {
	.base = idt,
	.limit = sizeof(idt) - 1
};

void idt_set_gate(uint8_t num, uint32_t base, uint16_t segment, uint16_t flags) {
	idt[num].base_low = base & 0xffff;
	idt[num].base_high = base >> 16 & 0xffff;
	idt[num].segment = segment;
	idt[num].flags = flags;
}

void idt_init() {
	idt_set_gate(0, (uint32_t)isr_0, 0x08, 0x8e00);
	idt_set_gate(8, (uint32_t)isr_8, 0x08, 0x8e00);
	idt_set_gate(14, (uint32_t)isr_14, 0x08, 0x8e00);
	asm volatile(
		"lidt (%0)\n"
		: : "r" (&idtr)
	);
}