First draft of the interrupt handler system.

This commit is contained in:
Felix Queißner 2016-05-05 15:59:48 +02:00
parent 4e21175e8e
commit cd4daaab7a
6 changed files with 136 additions and 38 deletions

View file

@ -0,0 +1,11 @@
#pragma once
#define ENUM_CLASS_OPERATORS(type) static inline type operator | (type lhs, type rhs) { \
return static_cast<type>(static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs)); \
} \
static inline type operator & (type lhs, type rhs) { \
return static_cast<type>(static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs)); \
} \
static inline bool operator * (type lhs, type rhs) { \
return (static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs)) != 0; \
}

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <inttypes.h> #include <inttypes.h>
#include "enums.hpp"
enum class SegmentAccess : uint8_t enum class SegmentAccess : uint8_t
{ {
@ -19,6 +20,8 @@ enum class SegmentAccess : uint8_t
Present = (1<<7), Present = (1<<7),
}; };
ENUM_CLASS_OPERATORS(SegmentAccess)
enum class SegmentFlags : uint8_t enum class SegmentFlags : uint8_t
{ {
None = 0, None = 0,
@ -28,35 +31,7 @@ enum class SegmentFlags : uint8_t
Use4KSize = (1<<3), Use4KSize = (1<<3),
}; };
static inline SegmentAccess operator | (SegmentAccess lhs, SegmentAccess rhs) ENUM_CLASS_OPERATORS(SegmentFlags)
{
return static_cast<SegmentAccess>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
}
static inline SegmentAccess operator & (SegmentAccess lhs, SegmentAccess rhs)
{
return static_cast<SegmentAccess>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
}
static inline bool operator * (SegmentAccess lhs, SegmentAccess rhs)
{
return (static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs)) != 0;
}
static inline SegmentFlags operator | (SegmentFlags lhs, SegmentFlags rhs)
{
return static_cast<SegmentFlags>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
}
static inline SegmentFlags operator & (SegmentFlags lhs, SegmentFlags rhs)
{
return static_cast<SegmentFlags>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
}
static inline bool operator * (SegmentFlags lhs, SegmentFlags rhs)
{
return (static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs)) != 0;
}
struct SegmentDescriptor struct SegmentDescriptor
{ {

View file

@ -0,0 +1,71 @@
#pragma once
#include <inttypes.h>
#include "enums.hpp"
enum class InterruptFlags : uint8_t
{
None = 0x00,
Interrupt = 0x06,
TrapGate = 0x07,
TaskGate = 0x05,
Use32Bit = 0x08,
Ring0 = 0x00,
Ring1 = 0x20,
Ring2 = 0x40,
Ring3 = 0x60,
Present = 0x80,
};
ENUM_CLASS_OPERATORS(InterruptFlags)
struct InterruptDescriptor
{
uint16_t offset0;
uint16_t selector;
uint8_t zero;
InterruptFlags flags;
uint16_t offset1;
InterruptDescriptor() :
offset0(0), selector(0), zero(0), flags(InterruptFlags::None), offset1(0)
{
}
InterruptDescriptor(uint32_t offset, uint32_t selector, InterruptFlags flags) :
offset0(0), selector(selector), zero(0), flags(flags), offset1(0)
{
this->setOffset(offset);
}
uint32_t offset() const
{
return this->offset0 | (this->offset1 << 16);
}
void setOffset(uint32_t offset)
{
this->offset0 = (offset & 0x0000FFFF) >> 0;
this->offset1 = (offset & 0xFFFF0000) >> 16;
}
} __attribute__((packed));
static_assert(sizeof(InterruptDescriptor) == 8, "InterruptDescriptor must be 8 byte large.");
class IDT
{
public:
static const uint32_t length = 256;
private:
static InterruptDescriptor descriptors[length];
IDT() = delete;
public:
static InterruptDescriptor & descriptor(uint32_t idx);
static void initialize();
};

View file

@ -6,6 +6,7 @@
#include "pointer.hpp" #include "pointer.hpp"
#include "multiboot.hpp" #include "multiboot.hpp"
#include "gdt.hpp" #include "gdt.hpp"
#include "idt.hpp"
#include "compat.h" #include "compat.h"
using namespace multiboot; using namespace multiboot;
@ -80,6 +81,11 @@ extern "C" void init(Structure const & data)
<< (freeMemory >> 0) << "B, " << (freeMemory >> 0) << "B, "
<< (freeMemory >> 12) << "Pages\n"; << (freeMemory >> 12) << "Pages\n";
IDT::initialize();
asm volatile("int $0x00");
// asm volatile("cli");
/* /*
for(int i = 0; i < 10; i++) { for(int i = 0; i < 10; i++) {
bool success; bool success;

View file

@ -13,31 +13,23 @@ SegmentDescriptor & GDT::descriptor(uint32_t index)
void GDT::initialize() void GDT::initialize()
{ {
//Ein Nulldeskriptor (gdt[0] = 0) // Null descriptor
GDT::descriptor(0) = SegmentDescriptor(); GDT::descriptor(0) = SegmentDescriptor();
//Ein Codesegment für den Kernel (Present, Ring 0, Executable, 32Bit; Basis 0, Limit 4GiB)
GDT::descriptor(1) = SegmentDescriptor( GDT::descriptor(1) = SegmentDescriptor(
0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF,
SegmentAccess::Present | SegmentAccess::Executable | SegmentAccess::Segment | SegmentAccess::Ring0, SegmentAccess::Present | SegmentAccess::Executable | SegmentAccess::Segment | SegmentAccess::Ring0,
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit); SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
//Ein Datensegment für den Kernel (Present, Ring 0, Non-Executable, 32Bit; Basis 0, Limit 4GiB)
GDT::descriptor(2) = SegmentDescriptor( GDT::descriptor(2) = SegmentDescriptor(
0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF,
SegmentAccess::Present | SegmentAccess::Writeable | SegmentAccess::Segment | SegmentAccess::Ring0, SegmentAccess::Present | SegmentAccess::Writeable | SegmentAccess::Segment | SegmentAccess::Ring0,
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit); SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
//Ein Codesegment für den Userspace (Present, Ring 3, Executable, 32Bit; Basis 0, Limit 4GiB)
GDT::descriptor(3) = SegmentDescriptor( GDT::descriptor(3) = SegmentDescriptor(
0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF,
SegmentAccess::Present | SegmentAccess::Executable | SegmentAccess::Segment | SegmentAccess::Ring3, SegmentAccess::Present | SegmentAccess::Executable | SegmentAccess::Segment | SegmentAccess::Ring3,
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit); SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
//Ein Datensegment für den Userspace (Present, Ring 3, Non-Executable, 32Bit; Basis 0, Limit 4GiB)
GDT::descriptor(4) = SegmentDescriptor( GDT::descriptor(4) = SegmentDescriptor(
0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF,

View file

@ -0,0 +1,43 @@
#include "idt.hpp"
#include "console.hpp"
static InterruptDescriptor invalid;
InterruptDescriptor IDT::descriptors[length];
InterruptDescriptor & IDT::descriptor(uint32_t idx)
{
if(idx >= IDT::length) {
return invalid;
}
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
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);
struct {
uint16_t limit;
void* pointer;
} __attribute__((packed)) idtp = {
.limit = IDT::length * sizeof(InterruptDescriptor) - 1,
.pointer = IDT::descriptors,
};
asm volatile("lidt %0" : : "m" (idtp));
}