First draft of the interrupt handler system.
This commit is contained in:
parent
4e21175e8e
commit
cd4daaab7a
6 changed files with 136 additions and 38 deletions
11
prototypes/base/include/enums.hpp
Normal file
11
prototypes/base/include/enums.hpp
Normal 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; \
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "enums.hpp"
|
||||
|
||||
enum class SegmentAccess : uint8_t
|
||||
{
|
||||
|
@ -19,6 +20,8 @@ enum class SegmentAccess : uint8_t
|
|||
Present = (1<<7),
|
||||
};
|
||||
|
||||
ENUM_CLASS_OPERATORS(SegmentAccess)
|
||||
|
||||
enum class SegmentFlags : uint8_t
|
||||
{
|
||||
None = 0,
|
||||
|
@ -28,35 +31,7 @@ enum class SegmentFlags : uint8_t
|
|||
Use4KSize = (1<<3),
|
||||
};
|
||||
|
||||
static inline SegmentAccess operator | (SegmentAccess lhs, SegmentAccess rhs)
|
||||
{
|
||||
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;
|
||||
}
|
||||
ENUM_CLASS_OPERATORS(SegmentFlags)
|
||||
|
||||
struct SegmentDescriptor
|
||||
{
|
||||
|
|
71
prototypes/base/include/idt.hpp
Normal file
71
prototypes/base/include/idt.hpp
Normal 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();
|
||||
|
||||
};
|
|
@ -6,6 +6,7 @@
|
|||
#include "pointer.hpp"
|
||||
#include "multiboot.hpp"
|
||||
#include "gdt.hpp"
|
||||
#include "idt.hpp"
|
||||
#include "compat.h"
|
||||
|
||||
using namespace multiboot;
|
||||
|
@ -80,6 +81,11 @@ extern "C" void init(Structure const & data)
|
|||
<< (freeMemory >> 0) << "B, "
|
||||
<< (freeMemory >> 12) << "Pages\n";
|
||||
|
||||
IDT::initialize();
|
||||
|
||||
asm volatile("int $0x00");
|
||||
// asm volatile("cli");
|
||||
|
||||
/*
|
||||
for(int i = 0; i < 10; i++) {
|
||||
bool success;
|
||||
|
|
|
@ -13,31 +13,23 @@ SegmentDescriptor & GDT::descriptor(uint32_t index)
|
|||
|
||||
void GDT::initialize()
|
||||
{
|
||||
//Ein Nulldeskriptor (gdt[0] = 0)
|
||||
// Null descriptor
|
||||
GDT::descriptor(0) = SegmentDescriptor();
|
||||
|
||||
//Ein Codesegment für den Kernel (Present, Ring 0, Executable, 32 Bit; Basis 0, Limit 4 GiB)
|
||||
GDT::descriptor(1) = SegmentDescriptor(
|
||||
0x00000000,
|
||||
0xFFFFFFFF,
|
||||
SegmentAccess::Present | SegmentAccess::Executable | SegmentAccess::Segment | SegmentAccess::Ring0,
|
||||
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
|
||||
|
||||
//Ein Datensegment für den Kernel (Present, Ring 0, Non-Executable, 32 Bit; Basis 0, Limit 4 GiB)
|
||||
GDT::descriptor(2) = SegmentDescriptor(
|
||||
0x00000000,
|
||||
0xFFFFFFFF,
|
||||
SegmentAccess::Present | SegmentAccess::Writeable | SegmentAccess::Segment | SegmentAccess::Ring0,
|
||||
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
|
||||
|
||||
//Ein Codesegment für den Userspace (Present, Ring 3, Executable, 32 Bit; Basis 0, Limit 4 GiB)
|
||||
GDT::descriptor(3) = SegmentDescriptor(
|
||||
0x00000000,
|
||||
0xFFFFFFFF,
|
||||
SegmentAccess::Present | SegmentAccess::Executable | SegmentAccess::Segment | SegmentAccess::Ring3,
|
||||
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
|
||||
|
||||
//Ein Datensegment für den Userspace (Present, Ring 3, Non-Executable, 32 Bit; Basis 0, Limit 4 GiB)
|
||||
GDT::descriptor(4) = SegmentDescriptor(
|
||||
0x00000000,
|
||||
0xFFFFFFFF,
|
||||
|
|
43
prototypes/base/src/idt.cpp
Normal file
43
prototypes/base/src/idt.cpp
Normal 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));
|
||||
}
|
Loading…
Reference in a new issue