summaryrefslogtreecommitdiff
path: root/src/arch/amd64/cpu/idt.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-02-03 00:50:07 -0500
committerFreya Murphy <freya@freyacat.org>2024-02-03 00:53:58 -0500
commit90a6065691beee52bf5309916fba98f7580d27be (patch)
tree0b5375d20c189f62d394c473d371f7bf7f1d3fc5 /src/arch/amd64/cpu/idt.c
parentimproved debugger, refactored (diff)
downloadcorn-90a6065691beee52bf5309916fba98f7580d27be.tar.gz
corn-90a6065691beee52bf5309916fba98f7580d27be.tar.bz2
corn-90a6065691beee52bf5309916fba98f7580d27be.zip
refactor, new arch dirs, (wip) page alloc on write, hsv screen (convert to userspace later), other fixes
Diffstat (limited to 'src/arch/amd64/cpu/idt.c')
-rw-r--r--src/arch/amd64/cpu/idt.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/arch/amd64/cpu/idt.c b/src/arch/amd64/cpu/idt.c
new file mode 100644
index 0000000..053f614
--- /dev/null
+++ b/src/arch/amd64/cpu/idt.c
@@ -0,0 +1,160 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <lib.h>
+#include <panic.h>
+#include "idt.h"
+#include "debugger.h"
+#include "../paging.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));
+}
+
+// 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) {
+ switch (exception) {
+ case 0x01: // debug
+ debugger(state, DEBUG_DBG);
+ return;
+ case 0x03: // breakpoint
+ debugger(state, DEBUG_INT3);
+ return;
+ }
+
+ char custom[64];
+ *custom = '\0';
+
+ // page faults store the offending address in cr2
+ if (exception == 0x0E) {
+ strcat(custom, "\nPage fault address: 0x");
+ uint64_t cr2;
+ __asm__ volatile ("mov %%cr2, %0" : "=r"(cr2));
+ ultoa((size_t)cr2, custom + 23, 16);
+ }
+
+ panic_interrupt(
+ (void *)state->rip,
+ (void *)state->rbp,
+ "Exception %s\nError code 0x%lu%s",
+ EXCEPTIONS[exception],
+ code,
+ custom
+ );
+}
+
+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) {}