Interrupt support!
This commit is contained in:
parent
cd4daaab7a
commit
b3b0ac66fb
6 changed files with 144 additions and 17 deletions
|
@ -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
|
||||
|
|
25
prototypes/base/include/cpustate.hpp
Normal file
25
prototypes/base/include/cpustate.hpp
Normal 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.");
|
|
@ -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);
|
||||
|
|
38
prototypes/base/interrupt-list.inc
Normal file
38
prototypes/base/interrupt-list.inc
Normal 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)
|
56
prototypes/base/interrupts.S
Normal file
56
prototypes/base/interrupts.S
Normal 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
|
|
@ -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);
|
||||
}
|
Loading…
Reference in a new issue