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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
#include <stdint.h>
#include <stddef.h>
#include <lib.h>
#include "idt.h"
#include "backtrace.h"
#include "debugger.h"
#include "../paging.h"
#include "../bindings.h"
#include "../drivers/pic.h"
#define IDT_SIZE 256
struct idt_entry {
uint16_t isr_low; // low 16 bits of isr
uint16_t kernel_cs; // kernel segment selector
uint8_t ist; // interrupt stack table
uint8_t flags; // gate type, privilege level, present bit
uint16_t isr_mid; // middle 16 bits of isr
uint32_t isr_high; // high 32 bits of isr
uint32_t reserved;
} __attribute__((packed));
struct idtr {
uint16_t size;
uint64_t address;
} __attribute__((packed));
// interrupt gate
#define GATE_64BIT_INT 0x0E
// trap gate
#define GATE_64BIT_TRAP 0x0F
// privilege ring allowed to call interrupt
#define RING0 0x00
#define RING1 0x20
#define RING2 0x40
#define RING3 0x60
// interrupt is present in IDT
#define PRESENT 0x80
__attribute__((aligned(0x10)))
static struct idt_entry idt[256];
static struct idtr idtr;
// from idt.S
extern void *isr_stub_table[];
// initialize and load the IDT
void idt_init(void) {
// initialize idtr
idtr.address = (uint64_t)&idt;
idtr.size = (uint16_t)sizeof(struct idt_entry) * IDT_SIZE - 1;
// initialize idt
for (size_t vector = 0; vector < IDT_SIZE; vector++) {
struct idt_entry *entry = &idt[vector];
uint64_t isr = (uint64_t)isr_stub_table[vector];
// interrupts before 0x20 are for cpu exceptions
uint8_t gate_type = (vector < 0x20) ? GATE_64BIT_TRAP : GATE_64BIT_INT;
entry->kernel_cs = 0x08; // offset of 1 into GDT
entry->ist = 0;
entry->flags = PRESENT | RING0 | gate_type;
entry->isr_low = isr & 0xffff;
entry->isr_mid = (isr >> 16) & 0xffff;
entry->isr_high = (isr >> 32) & 0xffffffff;
entry->reserved = 0;
}
__asm__ volatile ("lidt %0" : : "m"(idtr));
}
#define EX_DEBUG 0x01
#define EX_BREAKPOINT 0x03
#define EX_PAGE_FAULT 0x0e
// Intel manual vol 3 ch 6.3.1
char *EXCEPTIONS[] = {
"Division Error",
"Debug",
"NMI",
"Breakpoint",
"Overflow",
"BOUND Range Exceeded",
"Invalid Opcode",
"Device Not Available",
"Double Fault",
"Coprocessor Segment Overrun",
"Invalid TSS",
"Segment Not Present",
"Stack-Segment Fault",
"General Protection Fault",
"Page Fault",
"Reserved",
"x87 Floating-Point Error",
"Alignment Check",
"Machine Check",
"SIMD Floaing-Point Exception",
"Virtualization Exception",
"Control Protection Exception",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Hypervisor Injection Exception",
"VMM Communication Exception",
"Security Exception",
"Reserved",
};
void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *state) {
uint64_t cr2;
switch (exception) {
case EX_DEBUG: // debug
debugger(state, DEBUG_DBG);
return;
case EX_BREAKPOINT: // breakpoint
debugger(state, DEBUG_INT3);
return;
case EX_PAGE_FAULT:
// page faults store the offending address in cr2
__asm__ volatile ("mov %%cr2, %0" : "=r"(cr2));
if (!kload_page((void *)cr2))
return;
}
kputs("\n\n!!! EXCEPTION !!!\n");
kprintf("0x%02lX %s\n", exception, EXCEPTIONS[exception]);
kprintf("Error code 0x%lX\n", code);
if (exception == EX_PAGE_FAULT) {
kprintf("Page fault address: 0x%lX\n", cr2);
}
kputs("\n");
log_backtrace_ex((void *)state->rip, (void *)state->rbp);
while (1) {
halt();
}
}
void idt_pic_eoi(uint8_t exception) {
pic_eoi(exception - PIC_REMAP_OFFSET);
}
int counter = 0;
void idt_pic_timer(void) {
// print a message once we know the timer works
// but avoid spamming the logs
if (counter == 3) {
//kputs("pic timer!\n");
}
if (counter <= 3) {
counter++;
}
}
void idt_pic_keyboard(void) {}
void idt_pic_mouse(void) {}
|