From a6c1174b3fb598cd59c1668cfc4d4746ab688079 Mon Sep 17 00:00:00 2001 From: aqua Date: Fri, 1 Apr 2022 11:38:00 +0300 Subject: lidt --- arch/i686/include/gdt.h | 5 ----- arch/i686/include/idt.h | 18 ++++++++++++++++ arch/i686/include/sys/control.h | 9 ++++++++ arch/i686/lgdt.c | 8 +++++-- arch/i686/lidt.c | 46 +++++++++++++++++++++++++++++++++++++++++ arch/i686/meson.build | 7 +++++-- 6 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 arch/i686/include/idt.h create mode 100644 arch/i686/include/sys/control.h create mode 100644 arch/i686/lidt.c (limited to 'arch') 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 + +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 +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 +#include + +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)) -- cgit v1.2.1