From b3b0ac66fb134e5c9815d873625e65864c3d70cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Thu, 5 May 2016 17:06:11 +0200 Subject: [PATCH] Interrupt support! --- prototypes/base/Makefile | 4 +- prototypes/base/include/cpustate.hpp | 25 +++++++++++++ prototypes/base/include/idt.hpp | 3 ++ prototypes/base/interrupt-list.inc | 38 +++++++++++++++++++ prototypes/base/interrupts.S | 56 ++++++++++++++++++++++++++++ prototypes/base/src/idt.cpp | 35 +++++++++-------- 6 files changed, 144 insertions(+), 17 deletions(-) create mode 100644 prototypes/base/include/cpustate.hpp create mode 100644 prototypes/base/interrupt-list.inc create mode 100644 prototypes/base/interrupts.S diff --git a/prototypes/base/Makefile b/prototypes/base/Makefile index 08ef646..8aaff01 100644 --- a/prototypes/base/Makefile +++ b/prototypes/base/Makefile @@ -4,7 +4,9 @@ CC=gcc CXX=g++ LD=ld -FLAGS = -ffreestanding -m32 -Werror -Wall -iquote include -O3 +IDT_DISPATCH = _ZN3IDT8dispatchEP8CpuState + +FLAGS = -DIDT_DISPATCH=$(IDT_DISPATCH) -ffreestanding -m32 -Werror -Wall -iquote include -O3 ASFLAGS = $(FLAGS) CFLAGS = $(FLAGS) CXXFLAGS = $(FLAGS) -std=c++14 -fno-rtti -fno-exceptions -fno-leading-underscore -fno-use-cxa-atexit -nostdlib -fno-builtin diff --git a/prototypes/base/include/cpustate.hpp b/prototypes/base/include/cpustate.hpp new file mode 100644 index 0000000..9f1a822 --- /dev/null +++ b/prototypes/base/include/cpustate.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +struct CpuState +{ + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + + uint32_t intr; + uint32_t error; + + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; +}; + +static_assert(sizeof(CpuState) == 56, "CpuState must be 56 bytes large."); \ No newline at end of file diff --git a/prototypes/base/include/idt.hpp b/prototypes/base/include/idt.hpp index 015b1ba..a32d48b 100644 --- a/prototypes/base/include/idt.hpp +++ b/prototypes/base/include/idt.hpp @@ -2,6 +2,7 @@ #include #include "enums.hpp" +#include "cpustate.hpp" enum class InterruptFlags : uint8_t { @@ -62,6 +63,8 @@ public: private: static InterruptDescriptor descriptors[length]; IDT() = delete; + + static void dispatch(CpuState *cpu); public: static InterruptDescriptor & descriptor(uint32_t idx); diff --git a/prototypes/base/interrupt-list.inc b/prototypes/base/interrupt-list.inc new file mode 100644 index 0000000..819cad4 --- /dev/null +++ b/prototypes/base/interrupt-list.inc @@ -0,0 +1,38 @@ +ISR(0) +ISR(1) +ISR(2) +ISR(3) +ISR(4) +ISR(5) +ISR(6) +ISR(7) +ISR_ERR(8) +ISR(9) +ISR_ERR(10) +ISR_ERR(11) +ISR_ERR(12) +ISR_ERR(13) +ISR_ERR(14) +ISR(15) +ISR(16) +ISR_ERR(17) +ISR(18) + +ISR(32) +ISR(33) +ISR(34) +ISR(35) +ISR(36) +ISR(37) +ISR(38) +ISR(39) +ISR(40) +ISR(41) +ISR(42) +ISR(43) +ISR(44) +ISR(45) +ISR(46) +ISR(47) + +ISR(48) \ No newline at end of file diff --git a/prototypes/base/interrupts.S b/prototypes/base/interrupts.S new file mode 100644 index 0000000..1b582e3 --- /dev/null +++ b/prototypes/base/interrupts.S @@ -0,0 +1,56 @@ + +.macro isr_stub nr +.global isr_\nr +isr_\nr: + pushl $0 + pushl $\nr + jmp isr_handler +.endm + +.macro isr_stub_with_err nr +.global isr_\nr +isr_\nr: + pushl $\nr + jmp isr_handler +.endm + +#define ISR(num) isr_stub num +#define ISR_ERR(num) isr_stub_with_err num +#include "interrupt-list.inc" +#undef ISR +#undef ISR_ERR + +#if !defined(IDT_DISPATCH) + #error "IDT_DISPATCH must be defined!" +#endif + +.extern IDT_DISPATCH + +isr_handler: + // Store CPU State + push %ebp + push %edi + push %esi + push %edx + push %ecx + push %ebx + push %eax + + // Calls interrupt handler with CPU state as argument + push %esp + call IDT_DISPATCH + add $4, %esp + + // Restore CPU State + pop %eax + pop %ebx + pop %ecx + pop %edx + pop %esi + pop %edi + pop %ebp + + // Remove error code and interrupt number + add $8, %esp + + iret \ No newline at end of file diff --git a/prototypes/base/src/idt.cpp b/prototypes/base/src/idt.cpp index 30a8f19..14963a7 100644 --- a/prototypes/base/src/idt.cpp +++ b/prototypes/base/src/idt.cpp @@ -1,7 +1,12 @@ #include "idt.hpp" - #include "console.hpp" +#define ISR(num) extern "C" void isr_##num(); +#define ISR_ERR(num) ISR(num) +#include "../interrupt-list.inc" +#undef ISR +#undef ISR_ERR + static InterruptDescriptor invalid; InterruptDescriptor IDT::descriptors[length]; @@ -13,24 +18,16 @@ InterruptDescriptor & IDT::descriptor(uint32_t idx) return IDT::descriptors[idx]; } -static void trap() -{ - Console::main << "trapped!"; - while(true); -} - void IDT::initialize() { - IDT::descriptor(0) = InterruptDescriptor( - uint32_t(&trap), // offset - 0x08, // segment +#define ISR(num) IDT::descriptor(num) = InterruptDescriptor( \ + uint32_t(&isr_##num), \ + 0x08, \ InterruptFlags::Interrupt | InterruptFlags::Use32Bit | InterruptFlags::Ring0 | InterruptFlags::Present); - - IDT::descriptor(1) = InterruptDescriptor( - uint32_t(&trap), // offset - 0x08, // segment - InterruptFlags::Interrupt | InterruptFlags::Use32Bit | InterruptFlags::Ring0 | InterruptFlags::Present); - +#define ISR_ERR(num) ISR(num) +#include "../interrupt-list.inc" +#undef ISR +#undef ISR_ERR struct { uint16_t limit; @@ -40,4 +37,10 @@ void IDT::initialize() .pointer = IDT::descriptors, }; asm volatile("lidt %0" : : "m" (idtp)); +} + +void IDT::dispatch(CpuState *cpu) +{ + Console::main << "Ermahgerd, Interrupts!"; + while(true); } \ No newline at end of file