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
|
#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
|
||||||
{
|
{
|
||||||
|
|
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 "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;
|
||||||
|
|
|
@ -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, 32 Bit; Basis 0, Limit 4 GiB)
|
|
||||||
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, 32 Bit; Basis 0, Limit 4 GiB)
|
|
||||||
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, 32 Bit; Basis 0, Limit 4 GiB)
|
|
||||||
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, 32 Bit; Basis 0, Limit 4 GiB)
|
|
||||||
GDT::descriptor(4) = SegmentDescriptor(
|
GDT::descriptor(4) = SegmentDescriptor(
|
||||||
0x00000000,
|
0x00000000,
|
||||||
0xFFFFFFFF,
|
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