summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrimill <trimill@trimillxyz.org>2024-01-29 16:25:39 -0500
committertrimill <trimill@trimillxyz.org>2024-01-29 16:29:04 -0500
commit57260801943108d063aa1adbfafe838c3eddd0de (patch)
treeffa531eced442600c514fd13035c3c40c2f08112
parentpanic (diff)
downloadcorn-57260801943108d063aa1adbfafe838c3eddd0de.tar.gz
corn-57260801943108d063aa1adbfafe838c3eddd0de.tar.bz2
corn-57260801943108d063aa1adbfafe838c3eddd0de.zip
add interrupts (not yet fully working)
-rw-r--r--src/arch/amd64/boot.S2
-rw-r--r--src/arch/amd64/idt.S92
-rw-r--r--src/arch/amd64/idt.c118
-rw-r--r--src/arch/amd64/idt.h3
-rw-r--r--src/arch/amd64/shim.c4
5 files changed, 216 insertions, 3 deletions
diff --git a/src/arch/amd64/boot.S b/src/arch/amd64/boot.S
index 6482d79..483f0f0 100644
--- a/src/arch/amd64/boot.S
+++ b/src/arch/amd64/boot.S
@@ -117,7 +117,6 @@ start:
;push ebx ; Call our function to set up basic paging
;call amd64_shim
-
mov eax, cr4 ; Enable the PAE bit
or eax, 1 << 5
mov cr4, eax
@@ -139,6 +138,7 @@ code64:
pop rdi
call amd64_shim
mov rdi, rax
+ sti
call kmain
cli
halt:
diff --git a/src/arch/amd64/idt.S b/src/arch/amd64/idt.S
new file mode 100644
index 0000000..43f4fd2
--- /dev/null
+++ b/src/arch/amd64/idt.S
@@ -0,0 +1,92 @@
+extern idt_exception_handler
+global isr_stub_table
+
+; call the exception handler with the interrupt number
+; args: interrupt number
+%macro ISRException 1
+align 8
+isr_stub_%+%1:
+ cld
+ mov rdi, %1
+ mov rsi, 0
+ call idt_exception_handler
+ iretq
+%endmacro
+
+; call the exception handler with the interrupt number
+; these exceptions also put an error code on the stack
+; args: interrupt number
+%macro ISRExceptionCode 1
+align 8
+isr_stub_%+%1:
+ cld
+ mov rdi, %1
+ pop rsi
+ call idt_exception_handler
+ iretq
+%endmacro
+
+; do nothing
+; args: interrupt number
+%macro ISRIgnore 1
+align 8
+isr_stub_%+%1:
+ iretq
+%endmacro
+
+; isr stubs
+section .text
+bits 64
+
+ISRException 0
+ISRException 1
+ISRException 2
+ISRException 3
+ISRException 4
+ISRException 5
+ISRException 6
+ISRException 7
+ISRExceptionCode 8
+ISRException 9
+ISRExceptionCode 10
+ISRExceptionCode 11
+ISRExceptionCode 12
+ISRExceptionCode 13
+ISRExceptionCode 14
+ISRException 15
+ISRException 16
+ISRExceptionCode 17
+ISRException 18
+ISRException 19
+ISRException 20
+ISRExceptionCode 21
+ISRException 22
+ISRException 23
+ISRException 24
+ISRException 25
+ISRException 26
+ISRException 27
+ISRException 28
+ISRExceptionCode 29
+ISRExceptionCode 30
+ISRException 31
+
+%assign i 32
+
+; ignore other interrupts
+%rep 0x100 - i
+ ISRIgnore i
+ %assign i i+1
+%endrep
+
+; isr stub table
+section .rodata
+bits 64
+align 16
+
+isr_stub_table:
+%assign i 0
+%rep 256
+ dq isr_stub_%+i
+%assign i i+1
+%endrep
diff --git a/src/arch/amd64/idt.c b/src/arch/amd64/idt.c
new file mode 100644
index 0000000..5445560
--- /dev/null
+++ b/src/arch/amd64/idt.c
@@ -0,0 +1,118 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <panic.h>
+#include <lib.h>
+#include <serial.h>
+
+#include "idt.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;
+ void *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 = &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;
+ entry->reserved = 0;
+ }
+
+ __asm__ volatile ("lidt %0" : : "m"(idtr));
+}
+
+
+// Intel manual vol 3 ch 6.3.1
+char *EXCEPTIONS[] = {
+ "Exception 0x00 Divide Error",
+ "Exception 0x01 Debug Exception",
+ "Exception 0x02 NMI Interrupt",
+ "Exception 0x03 Breakpoint",
+ "Exception 0x04 Overflow",
+ "Exception 0x05 BOUND Range Exceeded",
+ "Exception 0x06 Invalid Opcode",
+ "Exception 0x07 Device Not Available",
+ "Exception 0x08 Double Fault",
+ "Exception 0x09 Coprocessor Segment Overrun",
+ "Exception 0x0A Invalid TSS",
+ "Exception 0x0B Segment Not Present",
+ "Exception 0x0C Stack-Segment Fault",
+ "Exception 0x0D General Protection",
+ "Exception 0x0E Page Fault",
+ "Exception 0x0F Reserved",
+ "Exception 0x10 x87 FPU Floating-Point Error",
+ "Exception 0x11 Alignment Check",
+ "Exception 0x12 Machine Check",
+ "Exception 0x13 SIMD Floaing-Point Exception",
+ "Exception 0x14 Virtualization Exception",
+ "Exception 0x15 Control Protection Exception",
+ "Exception 0x16 Reserved",
+ "Exception 0x17 Reserved",
+ "Exception 0x18 Reserved",
+ "Exception 0x19 Reserved",
+ "Exception 0x1A Reserved",
+ "Exception 0x1B Reserved",
+ "Exception 0x1C Reserved",
+ "Exception 0x1D Reserved",
+ "Exception 0x1E Reserved",
+ "Exception 0x1F Reserved",
+};
+
+void idt_exception_handler(uint64_t exception, uint64_t code) {
+ // TODO don't just panic
+ char buf[80];
+ char *end = strcpy(buf, EXCEPTIONS[exception]);
+ end = strcpy(end, "\nError code 0x");
+ ltoa(code, end, 16);
+ panic(buf);
+}
+
diff --git a/src/arch/amd64/idt.h b/src/arch/amd64/idt.h
new file mode 100644
index 0000000..5627657
--- /dev/null
+++ b/src/arch/amd64/idt.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void idt_init();
diff --git a/src/arch/amd64/shim.c b/src/arch/amd64/shim.c
index 4afa6d2..5639aab 100644
--- a/src/arch/amd64/shim.c
+++ b/src/arch/amd64/shim.c
@@ -6,13 +6,13 @@
#include "paging.h"
#include "mboot.h"
-
+#include "idt.h"
static struct boot_info boot_info;
-// entry point for amd64
void* amd64_shim(void *mboot_data_ptr) {
serial_init();
paging_init();
+ idt_init();
kmap_page(mboot_data_ptr, mboot_data_ptr, F_WRITEABLE);