aboutsummaryrefslogtreecommitdiff
path: root/arch/i386/lidt.c
diff options
context:
space:
mode:
authoraqua <aqua@iserlohn-fortress.net>2024-03-08 17:24:49 +0200
committeraqua <aqua@iserlohn-fortress.net>2024-03-08 22:00:07 +0200
commit20b97ea7c0dbbdc13800e12ff5c86c00c4a342ec (patch)
tree473281e5fc8b256827ce1a678573444e1aa5f669 /arch/i386/lidt.c
parentGenerate src/conf.h (diff)
downloadkernel-20b97ea7c0dbbdc13800e12ff5c86c00c4a342ec.tar.xz
Bazel build
Diffstat (limited to 'arch/i386/lidt.c')
-rw-r--r--arch/i386/lidt.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/i386/lidt.c b/arch/i386/lidt.c
new file mode 100644
index 0000000..86567f8
--- /dev/null
+++ b/arch/i386/lidt.c
@@ -0,0 +1,55 @@
+#include "idt.h"
+#include <stdint.h>
+
+struct __attribute__((packed)) Pointer {
+ uint16_t limit;
+ uint32_t base;
+};
+
+enum Type {
+ Null = 0,
+ Intr = 0x8e /* 1000 1110 32-bit interrupt */
+};
+
+struct __attribute__((packed)) Gate_t {
+ uint16_t offset_15_0; /* segment offset low */
+ uint16_t selector; /* code segment selector */
+ uint8_t __unused; /* unused in protected mode */
+ uint8_t type; /* interrupt type */
+ uint16_t offset_31_16; /* segment offset high */
+};
+/* _Static_assert(sizeof(struct Gate_t) == 8, "interrupt gate size"); */
+
+void
+Gate(struct Gate_t *entry, void (*f)(struct interrupt_frame *), uint16_t selector)
+{
+ uint32_t f_addr = (uint32_t)f;
+ entry->offset_15_0 = f_addr & 0xffff;
+ entry->offset_31_16 = (uint16_t)(f_addr >> 16) & 0xffff;
+ entry->selector = selector;
+ entry->__unused = 0;
+ entry->type = Intr;
+}
+
+static struct Gate_t interrupt_table[256] __attribute((aligned(4096)));
+
+void
+idt_install()
+{
+ int i;
+ const struct Pointer ptr = {sizeof(interrupt_table) - 1, (unsigned)&interrupt_table};
+
+ /* exceptions 0x00~0x13 */
+ for (i = 0; i <= 0x13; ++i) Gate(&interrupt_table[i], &abort_handler, 0x10);
+
+ /* irq 0x20~0x2f */
+ for (i = 0x22; i <= 0x2f; ++i) Gate(&interrupt_table[i], &abort_handler, 0x10);
+ Gate(&interrupt_table[0x20], &irq0x00, 0x10);
+ Gate(&interrupt_table[0x21], &irq0x01, 0x10);
+ Gate(&interrupt_table[0x2c], &irq0x0c, 0x10);
+
+ /* syscall 0x80 */
+ Gate(&interrupt_table[0x80], &syscall_handler, 0x10);
+
+ __asm__("lidt (%0)" : : "a"(&ptr));
+}