From cbcc67fc316bc4da6eb28b2d560486e0a7349ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Wed, 6 Dec 2017 16:53:12 +0100 Subject: [PATCH] Quick and dirty IDT setup --- src/kernel/Makefile | 8 ++- src/kernel/boot/kmain.c | 11 ++++ src/kernel/interrupts/idt.c | 89 ++++++++++++++++++++++++++++++ src/kernel/interrupts/idt.tt | 31 +++++++++++ src/kernel/interrupts/isr.S.py | 32 +++++++++++ src/kernel/interrupts/isr_common.S | 50 +++++++++++++++++ 6 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 src/kernel/interrupts/idt.c create mode 100644 src/kernel/interrupts/idt.tt create mode 100644 src/kernel/interrupts/isr.S.py create mode 100644 src/kernel/interrupts/isr_common.S diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 111a704..2ef80ad 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -2,8 +2,8 @@ ifeq ($(MITTOS64),) $(error Unsupported environment! See README) endif -SRC := $(wildcard **/*.[cS]) -OBJ := $(patsubst %, %.o, $(basename $(SRC))) +SRC := $(wildcard **/*.[cS]*) +OBJ := $(patsubst %, %.o, $(basename $(basename $(SRC)))) CFLAGS ?= -Wall -Wextra -pedantic CFLAGS += -ffreestanding -mcmodel=large @@ -20,6 +20,9 @@ LDFLAGS := -n -nostdlib -lgcc -T Link.ld kernel: $(OBJ) $(LINK.c) $^ -o $@ +%.S: %.S.py + python $^ > $@ + # Automatically generate dependency files # Those keep track of which header files are used by which source files DEP := $(OBJ:.o=.d) @@ -39,6 +42,7 @@ clean: rm -rf $(OBJ) $(DEP) kernel .PHONY: install clean +.INTERMEDIATE: $(basename $(filter %.py, $(SRC))) # Include generated dependency files include $(DEP) diff --git a/src/kernel/boot/kmain.c b/src/kernel/boot/kmain.c index 3c0657e..aee6cbd 100644 --- a/src/kernel/boot/kmain.c +++ b/src/kernel/boot/kmain.c @@ -4,6 +4,8 @@ #include #include +void interrupt_init(); + void kmain(uint64_t multiboot_magic, void *multiboot_data) { serial_init(PORT_COM1); @@ -14,6 +16,15 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data) debug_info("Kernel was loaded with command line \"%s\", by <%s>\n", kernel_boot_data.commandline, kernel_boot_data.bootloader); + interrupt_init(); + + // Force a divide by zero exception + // ISR 0 + int a = 5, b = 0; + int c = a/b; + + debug("a: %d b:%d c:%d\n", a,b,c); + debug_ok("Boot \"Complete\"\n"); PANIC("Reached end of kernel main function\n"); diff --git a/src/kernel/interrupts/idt.c b/src/kernel/interrupts/idt.c new file mode 100644 index 0000000..7f034a6 --- /dev/null +++ b/src/kernel/interrupts/idt.c @@ -0,0 +1,89 @@ +#include +#include +#include + +struct int_gate_descriptor +{ + uint16_t base_l; + uint16_t cs; + uint8_t ist; + uint8_t flags; + uint16_t base_m; + uint32_t base_h; + uint32_t ignored; +} __attribute__((packed)); + +struct idtr +{ + uint16_t len; + struct int_gate_descriptor *addr; +} __attribute__((packed)); + +typedef struct +{ + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rsi; + uint64_t rdi; + uint64_t rbp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + + uint64_t int_no; + uint64_t err_code; + + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +} registers; + +void load_idt(struct idtr *); + +#define NUM_INTERRUPTS 256 + +struct int_gate_descriptor idt[NUM_INTERRUPTS]; +struct idtr idtr; + + +extern uintptr_t isr_table[]; + +void idt_set_gate(uint32_t num, uintptr_t vector, uint16_t cs, uint8_t ist, uint8_t flags) +{ + idt[num].base_l = vector & 0xFFFF; + idt[num].base_m = (vector >> 16) & 0xFFFF; + idt[num].base_h = (vector >> 32) & 0xFFFFFFFF; + idt[num].cs = cs; + idt[num].ist = ist; + idt[num].flags = flags; +} + +void interrupt_init() +{ + memset(idt, 0, sizeof(idt)); + + for(int i=0; i < NUM_INTERRUPTS; i++) + { + idt_set_gate(i, isr_table[i], 0x8, 0, 0x8E); + } + + idtr.addr = idt; + idtr.len = sizeof(idt)-1; + load_idt(&idtr); +} + +registers *int_handler(registers *r) +{ + (void)r; + debug("Interrupt %d\n", r->int_no); + for(;;); +} diff --git a/src/kernel/interrupts/idt.tt b/src/kernel/interrupts/idt.tt new file mode 100644 index 0000000..4cec586 --- /dev/null +++ b/src/kernel/interrupts/idt.tt @@ -0,0 +1,31 @@ +// vim: ft=c +#include +#include +#undef debug +#define debug(...) +#include "idt.c" + +uintptr_t isr_table[] ={}; +void load_idt(struct idtr *_) +{ + (void)_; +} + +TEST(idt_set_gate_correctly_sets_address_L) +{ + idt_set_gate(1, 0x1234567890ABCDEF, 0, 0, 0); + + ASSERT_EQ_INT(idt[1].base_l, 0xCDEF); +} +TEST(idt_set_gate_correctly_sets_address_M) +{ + idt_set_gate(1, 0x1234567890ABCDEF, 0, 0, 0); + + ASSERT_EQ_INT(idt[1].base_m, 0x90AB); +} +TEST(idt_set_gate_correctly_sets_address_H) +{ + idt_set_gate(1, 0x1234567890ABCDEF, 0, 0, 0); + + ASSERT_EQ_INT(idt[1].base_h, 0x12345678); +} diff --git a/src/kernel/interrupts/isr.S.py b/src/kernel/interrupts/isr.S.py new file mode 100644 index 0000000..46fe461 --- /dev/null +++ b/src/kernel/interrupts/isr.S.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +num_isr = 256 +pushes_error = [8, 10, 11, 12, 13, 14, 17] + +print ''' +.intel_syntax noprefix +.extern isr_common +''' + + +print '// Interrupt Service Routines' +for i in range(num_isr): + print '''isr{0}: + cli + {1} + push {0} + jmp isr_common + '''.format(i, + 'push 0' if i not in pushes_error else 'nop') + +print '' +print ''' +// Vector table + +.section .data +.global isr_table +isr_table:''' + +for i in range(num_isr): + print ' .quad isr{}'.format(i) diff --git a/src/kernel/interrupts/isr_common.S b/src/kernel/interrupts/isr_common.S new file mode 100644 index 0000000..4394d57 --- /dev/null +++ b/src/kernel/interrupts/isr_common.S @@ -0,0 +1,50 @@ +.intel_syntax noprefix + +.global load_idt +load_idt: + lidt [rdi] + ret + +.extern int_handler +.global isr_common +.global isr_return + +isr_common: + push r15 + push r14 + push r13 + push r12 + push r11 + push r10 + push r9 + push r8 + push rbp + push rdi + push rsi + push rdx + push rcx + push rbx + push rax + mov rdi, rsp + call int_handler + + mov rdi, rax +isr_return: + mov rsp, rdi + pop rax + pop rbx + pop rcx + pop rdx + pop rsi + pop rdi + pop rbp + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + add rsp, 0x10 + iretq