Interrupt support!

This commit is contained in:
Felix Queißner 2016-05-05 17:06:11 +02:00
parent cd4daaab7a
commit b3b0ac66fb
6 changed files with 144 additions and 17 deletions

View file

@ -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

View file

@ -0,0 +1,25 @@
#pragma once
#include <inttypes.h>
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.");

View file

@ -2,6 +2,7 @@
#include <inttypes.h>
#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);

View file

@ -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)

View file

@ -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

View file

@ -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);
}