aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authoraqua <aqua@iserlohn-fortress.net>2022-04-01 11:38:00 +0300
committeraqua <aqua@iserlohn-fortress.net>2022-08-12 10:13:59 +0300
commita6c1174b3fb598cd59c1668cfc4d4746ab688079 (patch)
tree85e2c3e37ef0c9602c56873332b98311e655e6e5 /arch
parentInitial commit (diff)
downloadkernel-a6c1174b3fb598cd59c1668cfc4d4746ab688079.tar.xz
lidt
Diffstat (limited to 'arch')
-rw-r--r--arch/i686/include/gdt.h5
-rw-r--r--arch/i686/include/idt.h18
-rw-r--r--arch/i686/include/sys/control.h9
-rw-r--r--arch/i686/lgdt.c8
-rw-r--r--arch/i686/lidt.c46
-rw-r--r--arch/i686/meson.build7
6 files changed, 84 insertions, 9 deletions
diff --git a/arch/i686/include/gdt.h b/arch/i686/include/gdt.h
index 6badf84..9148c3d 100644
--- a/arch/i686/include/gdt.h
+++ b/arch/i686/include/gdt.h
@@ -47,11 +47,6 @@ _Static_assert(sizeof(struct SegmentDescriptor_t) == 8);
void SegmentDescriptor(struct SegmentDescriptor_t *self, unsigned base, unsigned limit, uint8_t access);
-struct __attribute__((packed)) Pointer {
- uint16_t limit;
- uint32_t base;
-};
-
void gdt_install();
enum SegmentIndex {
diff --git a/arch/i686/include/idt.h b/arch/i686/include/idt.h
new file mode 100644
index 0000000..22dc6de
--- /dev/null
+++ b/arch/i686/include/idt.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <stdint.h>
+
+struct interrupt_frame {
+ uint32_t ip;
+ uint32_t cs;
+ uint32_t flags;
+ uint32_t sp;
+ uint32_t ss;
+};
+
+void abort_handler(struct interrupt_frame *frame);
+void interrupt_handler(struct interrupt_frame *frame);
+void interrupt_handler_e(struct interrupt_frame *frame, uint32_t error);
+void syscall_handler(struct interrupt_frame *frame);
+
+void idt_install();
diff --git a/arch/i686/include/sys/control.h b/arch/i686/include/sys/control.h
new file mode 100644
index 0000000..a40a67f
--- /dev/null
+++ b/arch/i686/include/sys/control.h
@@ -0,0 +1,9 @@
+#pragma once
+
+static void
+abort()
+{
+ asm volatile(R"(cli
+h: hlt
+jmp h)");
+}
diff --git a/arch/i686/lgdt.c b/arch/i686/lgdt.c
index 2d35e8d..2be5d30 100644
--- a/arch/i686/lgdt.c
+++ b/arch/i686/lgdt.c
@@ -1,5 +1,10 @@
#include <gdt.h>
+struct __attribute__((packed)) Pointer {
+ uint16_t limit;
+ uint32_t base;
+};
+
static struct SegmentDescriptor_t segments[8] __attribute__((aligned(32)));
void
@@ -9,8 +14,7 @@ gdt_install()
SegmentDescriptor(&segments[2], 0, 0xffffffff, 0x9a); // ktext
SegmentDescriptor(&segments[3], 0, 0xffffffff, 0x92); // kdata
- struct Pointer ptr = {.limit = sizeof(segments) - 1, .base = (unsigned)&segments};
-
+ const struct Pointer ptr = {.limit = sizeof(segments) - 1, .base = (unsigned)&segments};
asm volatile("lgdt (%0)" : : "a"(&ptr));
// load the kernel data segment
diff --git a/arch/i686/lidt.c b/arch/i686/lidt.c
new file mode 100644
index 0000000..efbade3
--- /dev/null
+++ b/arch/i686/lidt.c
@@ -0,0 +1,46 @@
+#include <idt.h>
+#include <stdint.h>
+
+struct __attribute__((packed)) Pointer {
+ uint16_t limit;
+ uint32_t base;
+};
+
+enum Type {
+ Null = 0,
+ Intr = 0b10001110, // 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);
+
+void
+Gate(struct Gate_t *entry, void *f, uint16_t selector)
+{
+ uint32_t f_addr = (uint32_t)f;
+ entry->offset_15_0 = f_addr & 0xffff;
+ entry->offset_31_16 = (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()
+{
+ for (int i = 0; i <= 0x2f; ++i) Gate(&interrupt_table[i], &interrupt_handler, 0x10);
+ Gate(&interrupt_table[0x80], &abort_handler, 0x10);
+
+ const struct Pointer ptr = {.limit = sizeof(interrupt_table) - 1, .base = (unsigned)&interrupt_table};
+ asm volatile("lidt (%0)" : : "a"(&ptr));
+
+ asm volatile("sti");
+}
diff --git a/arch/i686/meson.build b/arch/i686/meson.build
index 25eebee..f6bed8e 100644
--- a/arch/i686/meson.build
+++ b/arch/i686/meson.build
@@ -1,6 +1,9 @@
arch = declare_dependency(
- sources: ['boot.S', 'init.s', 'gdt.c', 'lgdt.c'],
- include_directories: 'include'
+ sources: ['boot.S', 'init.s',
+ 'gdt.c', 'lgdt.c', 'lidt.c'
+ ],
+ include_directories: 'include',
+ compile_args: '-mgeneral-regs-only'
)
test('GDT', executable('gdt', ['test/gdt.c', 'gdt.c'], include_directories: 'include', native: true))