From 736de137b8f391b3624ecd656a8f19f14b37f948 Mon Sep 17 00:00:00 2001 From: Baptiste Wicht Date: Tue, 10 Dec 2013 20:42:24 +0100 Subject: [PATCH] Start implementing ISRs --- kernel/Makefile | 7 +- kernel/include/interrupts.hpp | 1 + kernel/include/isrs.hpp | 48 ++++++ kernel/src/interrupts.cpp | 76 +++++++++ kernel/src/isrs.s | 283 ++++++++++++++++++++++++++++++++++ 5 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 kernel/include/isrs.hpp create mode 100644 kernel/src/isrs.s diff --git a/kernel/Makefile b/kernel/Makefile index c37a2b88..5b8522f1 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -10,7 +10,9 @@ KERNEL_FLAGS=$(CPP_FLAGS) $(THOR_FLAGS) KERNEL_LINK_FLAGS=-lgcc -T linker.ld $(CPP_FLAGS) KERNEL_CPP_FILES=$(wildcard src/*.cpp) -KERNEL_O_FILES=$(KERNEL_CPP_FILES:src/%.cpp=%.o) + +#TODO Generate also the o files coming from s files automatically, ignoring crti and crtn +KERNEL_O_FILES=$(KERNEL_CPP_FILES:src/%.cpp=%.o) isrs.o CRTBEGIN_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o) CRTEND_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtend.o) @@ -23,6 +25,9 @@ crti.o: src/crti.s crtn.o: src/crtn.s $(AS) -c src/crtn.s -o crtn.o +isrs.o: src/isrs.o + $(AS) -c src/isrs.s -o isrs.o + %.o : src/%.cpp $(CC) $(KERNEL_FLAGS) -c $< -o $@ diff --git a/kernel/include/interrupts.hpp b/kernel/include/interrupts.hpp index ceafa1b6..5dd953a3 100644 --- a/kernel/include/interrupts.hpp +++ b/kernel/include/interrupts.hpp @@ -11,6 +11,7 @@ namespace interrupt { void install_idt(); +void install_isrs(); } //end of interrupt namespace diff --git a/kernel/include/isrs.hpp b/kernel/include/isrs.hpp new file mode 100644 index 00000000..55c44814 --- /dev/null +++ b/kernel/include/isrs.hpp @@ -0,0 +1,48 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef ISRS_H +#define ISRS_H + +extern "C" { + +void _isr0(); +void _isr1(); +void _isr2(); +void _isr3(); +void _isr4(); +void _isr5(); +void _isr6(); +void _isr7(); +void _isr8(); +void _isr9(); +void _isr10(); +void _isr11(); +void _isr12(); +void _isr13(); +void _isr14(); +void _isr15(); +void _isr16(); +void _isr17(); +void _isr18(); +void _isr19(); +void _isr20(); +void _isr21(); +void _isr22(); +void _isr23(); +void _isr24(); +void _isr25(); +void _isr26(); +void _isr27(); +void _isr28(); +void _isr29(); +void _isr30(); +void _isr31(); + +} //end of extern "C" + +#endif diff --git a/kernel/src/interrupts.cpp b/kernel/src/interrupts.cpp index f5a02dc2..1d265956 100644 --- a/kernel/src/interrupts.cpp +++ b/kernel/src/interrupts.cpp @@ -7,6 +7,9 @@ #include "interrupts.hpp" #include "types.hpp" +#include "utils.hpp" +#include "isrs.hpp" +#include "console.hpp" namespace { @@ -27,13 +30,86 @@ struct idtr { idt_entry idt_64[64]; idtr idtr_64; +void idt_set_gate(size_t gate, void (*function)(void), uint16_t gdt_selector, uint16_t flags){ + auto& entry = idt_64[gate]; + + entry.segment_selector = gdt_selector; + entry.flags = flags; + entry.reserved = 0; + + auto function_address = reinterpret_cast(function); + entry.offset_low = function_address & 0xFFFF; + entry.offset_middle = (function_address >> 16) & 0xFFFF; + entry.offset_high= function_address >> 32; +} + } //end of anonymous namespace +struct regs { + uint64_t error_no; + uint64_t error_code; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +} __attribute__((packed)); + +extern "C" { + +void _fault_handler(regs* regs){ + k_printf("Exception (%d) occured\n", regs->error_no); + //TODO Complete that + while(true){}; +} + +} //end of extern "C" + void interrupt::install_idt(){ //Set the correct values inside IDTR idtr_64.limit = (64 * 16) - 1; idtr_64.base = &idt_64[0]; + //Clear the IDT + std::fill_n(reinterpret_cast(idt_64), 64 * 2, 0); + //Give the IDTR address to the CPU asm volatile("lidt [%0]" : : "m" (idtr_64)); } + +void interrupt::install_isrs(){ + //TODO The GDT Selector should be computed in a better way + + idt_set_gate(0, _isr0, 0x18, 0x8E); + idt_set_gate(1, _isr1, 0x18, 0x8E); + idt_set_gate(2, _isr2, 0x18, 0x8E); + idt_set_gate(3, _isr3, 0x18, 0x8E); + idt_set_gate(4, _isr4, 0x18, 0x8E); + idt_set_gate(5, _isr5, 0x18, 0x8E); + idt_set_gate(6, _isr6, 0x18, 0x8E); + idt_set_gate(7, _isr7, 0x18, 0x8E); + idt_set_gate(8, _isr8, 0x18, 0x8E); + idt_set_gate(9, _isr9, 0x18, 0x8E); + idt_set_gate(10, _isr10, 0x18, 0x8E); + idt_set_gate(11, _isr11, 0x18, 0x8E); + idt_set_gate(12, _isr12, 0x18, 0x8E); + idt_set_gate(13, _isr13, 0x18, 0x8E); + idt_set_gate(14, _isr14, 0x18, 0x8E); + idt_set_gate(15, _isr15, 0x18, 0x8E); + idt_set_gate(16, _isr16, 0x18, 0x8E); + idt_set_gate(17, _isr17, 0x18, 0x8E); + idt_set_gate(18, _isr18, 0x18, 0x8E); + idt_set_gate(19, _isr19, 0x18, 0x8E); + idt_set_gate(20, _isr20, 0x18, 0x8E); + idt_set_gate(21, _isr21, 0x18, 0x8E); + idt_set_gate(22, _isr22, 0x18, 0x8E); + idt_set_gate(23, _isr23, 0x18, 0x8E); + idt_set_gate(24, _isr24, 0x18, 0x8E); + idt_set_gate(25, _isr25, 0x18, 0x8E); + idt_set_gate(26, _isr26, 0x18, 0x8E); + idt_set_gate(27, _isr27, 0x18, 0x8E); + idt_set_gate(28, _isr28, 0x18, 0x8E); + idt_set_gate(29, _isr29, 0x18, 0x8E); + idt_set_gate(30, _isr30, 0x18, 0x8E); + idt_set_gate(31, _isr31, 0x18, 0x8E); +} diff --git a/kernel/src/isrs.s b/kernel/src/isrs.s new file mode 100644 index 00000000..599d122a --- /dev/null +++ b/kernel/src/isrs.s @@ -0,0 +1,283 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +.intel_syntax noprefix + +// The fault handler provided by the C++ kernel +//extern _fault_handler + +// Define the base ISRs + +.global _isr0 +.global _isr0 +.global _isr1 +.global _isr2 +.global _isr3 +.global _isr4 +.global _isr5 +.global _isr6 +.global _isr7 +.global _isr8 +.global _isr9 +.global _isr10 +.global _isr11 +.global _isr12 +.global _isr13 +.global _isr14 +.global _isr15 +.global _isr16 +.global _isr17 +.global _isr18 +.global _isr19 +.global _isr20 +.global _isr21 +.global _isr22 +.global _isr23 +.global _isr24 +.global _isr25 +.global _isr26 +.global _isr27 +.global _isr28 +.global _isr29 +.global _isr30 +.global _isr31 + +_isr0: + cli + push 0 // Dummy error code + push 0 + + jmp isr_common_handler + +_isr1: + cli + push 0 // Dummy error code + push 1 + + jmp isr_common_handler + +_isr2: + cli + push 0 // Dummy error code + push 2 + + jmp isr_common_handler + +_isr3: + cli + push 0 // Dummy error code + push 3 + + jmp isr_common_handler + +_isr4: + cli + push 0 // Dummy error code + push 4 + + jmp isr_common_handler + +_isr5: + cli + push 0 // Dummy error code + push 5 + + jmp isr_common_handler + +_isr6: + cli + push 0 // Dummy error code + push 6 + + jmp isr_common_handler + +_isr7: + cli + push 0 // Dummy error code + push 7 + + jmp isr_common_handler + +_isr8: + cli + push 8 + + jmp isr_common_handler + +_isr9: + cli + push 0 // Dummy error code + push 9 + + jmp isr_common_handler + +_isr10: + cli + push 10 + + jmp isr_common_handler + +_isr11: + cli + push 11 + + jmp isr_common_handler + +_isr12: + cli + push 12 + + jmp isr_common_handler + +_isr13: + cli + push 13 + + jmp isr_common_handler + +_isr14: + cli + push 14 + + jmp isr_common_handler + +_isr15: + cli + push 0 // Dummy error code + push 15 + + jmp isr_common_handler + +_isr16: + cli + push 0 // Dummy error code + push 16 + + jmp isr_common_handler + +_isr17: + cli + push 0 // Dummy error code + push 17 + + jmp isr_common_handler + +_isr18: + cli + push 0 // Dummy error code + push 18 + + jmp isr_common_handler + +_isr19: + cli + push 0 // Dummy error code + push 19 + + jmp isr_common_handler + +_isr20: + cli + push 0 // Dummy error code + push 20 + + jmp isr_common_handler + +_isr21: + cli + push 0 // Dummy error code + push 21 + + jmp isr_common_handler + +_isr22: + cli + push 0 // Dummy error code + push 22 + + jmp isr_common_handler + +_isr23: + cli + push 0 // Dummy error code + push 23 + + jmp isr_common_handler + +_isr24: + cli + push 0 // Dummy error code + push 24 + + jmp isr_common_handler + +_isr25: + cli + push 0 // Dummy error code + push 25 + + jmp isr_common_handler + +_isr26: + cli + push 0 // Dummy error code + push 26 + + jmp isr_common_handler + +_isr27: + cli + push 0 // Dummy error code + push 27 + + jmp isr_common_handler + +_isr28: + cli + push 0 // Dummy error code + push 28 + + jmp isr_common_handler + +_isr29: + cli + push 0 // Dummy error code + push 29 + + jmp isr_common_handler + +_isr30: + cli + push 0 // Dummy error code + push 30 + + jmp isr_common_handler + +_isr31: + cli + push 0 // Dummy error code + push 31 + + jmp isr_common_handler + +// Common handler + +isr_common_handler: + mov rax, rsp + push rax + + mov rax, _fault_handler + call rax + + // TODO At this point, it is absolutely not safe to return since most + // registers will get trashed the fault handler must hang + + add rsp, 2 // Cleans the pushed error code + + pop rax // Clean the pushed stack + + iret // iret will clean the other automatically pushed stuff