Kernel: Move IDT to Processor
This commit is contained in:
parent
f84df175ce
commit
76b0f80169
|
@ -12,7 +12,7 @@
|
||||||
#define ISR_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31)
|
#define ISR_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31)
|
||||||
#define IRQ_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31)
|
#define IRQ_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31)
|
||||||
|
|
||||||
namespace Kernel::IDT
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
struct Registers
|
struct Registers
|
||||||
|
@ -42,26 +42,6 @@ namespace Kernel::IDT
|
||||||
uint64_t rax;
|
uint64_t rax;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GateDescriptor
|
|
||||||
{
|
|
||||||
uint16_t offset1;
|
|
||||||
uint16_t selector;
|
|
||||||
uint8_t IST;
|
|
||||||
uint8_t flags;
|
|
||||||
uint16_t offset2;
|
|
||||||
uint32_t offset3;
|
|
||||||
uint32_t reserved;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
struct IDTR
|
|
||||||
{
|
|
||||||
uint16_t size;
|
|
||||||
uint64_t offset;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
static IDTR s_idtr;
|
|
||||||
static GateDescriptor* s_idt = nullptr;
|
|
||||||
|
|
||||||
#define X(num) 1 +
|
#define X(num) 1 +
|
||||||
static BAN::Array<Interruptable*, IRQ_LIST_X 0> s_interruptables;
|
static BAN::Array<Interruptable*, IRQ_LIST_X 0> s_interruptables;
|
||||||
#undef X
|
#undef X
|
||||||
|
@ -341,14 +321,9 @@ done:
|
||||||
ASSERT(Thread::current().state() != Thread::State::Terminated);
|
ASSERT(Thread::current().state() != Thread::State::Terminated);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flush_idt()
|
void IDT::register_interrupt_handler(uint8_t index, void (*handler)())
|
||||||
{
|
{
|
||||||
asm volatile("lidt %0"::"m"(s_idtr));
|
auto& descriptor = m_idt[index];
|
||||||
}
|
|
||||||
|
|
||||||
static void register_interrupt_handler(uint8_t index, void(*handler)())
|
|
||||||
{
|
|
||||||
GateDescriptor& descriptor = s_idt[index];
|
|
||||||
descriptor.offset1 = (uint16_t)((uint64_t)handler >> 0);
|
descriptor.offset1 = (uint16_t)((uint64_t)handler >> 0);
|
||||||
descriptor.offset2 = (uint16_t)((uint64_t)handler >> 16);
|
descriptor.offset2 = (uint16_t)((uint64_t)handler >> 16);
|
||||||
descriptor.offset3 = (uint32_t)((uint64_t)handler >> 32);
|
descriptor.offset3 = (uint32_t)((uint64_t)handler >> 32);
|
||||||
|
@ -358,13 +333,13 @@ done:
|
||||||
descriptor.flags = 0x8E;
|
descriptor.flags = 0x8E;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void register_syscall_handler(uint8_t index, void(*handler)())
|
void IDT::register_syscall_handler(uint8_t index, void (*handler)())
|
||||||
{
|
{
|
||||||
register_interrupt_handler(index, handler);
|
register_interrupt_handler(index, handler);
|
||||||
s_idt[index].flags = 0xEE;
|
m_idt[index].flags = 0xEE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_irq_handler(uint8_t irq, Interruptable* interruptable)
|
void IDT::register_irq_handler(uint8_t irq, Interruptable* interruptable)
|
||||||
{
|
{
|
||||||
if (irq > s_interruptables.size())
|
if (irq > s_interruptables.size())
|
||||||
Kernel::panic("Trying to assign handler for irq {} while only {} are supported", irq, s_interruptables.size());
|
Kernel::panic("Trying to assign handler for irq {} while only {} are supported", irq, s_interruptables.size());
|
||||||
|
@ -381,34 +356,39 @@ done:
|
||||||
|
|
||||||
extern "C" void syscall_asm();
|
extern "C" void syscall_asm();
|
||||||
|
|
||||||
void initialize()
|
IDT* IDT::create()
|
||||||
{
|
{
|
||||||
s_idt = (GateDescriptor*)kmalloc(0x100 * sizeof(GateDescriptor));
|
auto* idt = new IDT();
|
||||||
ASSERT(s_idt);
|
ASSERT(idt);
|
||||||
memset(s_idt, 0x00, 0x100 * sizeof(GateDescriptor));
|
|
||||||
|
|
||||||
s_idtr.offset = (uint64_t)s_idt;
|
memset(idt->m_idt.data(), 0x00, 0x100 * sizeof(GateDescriptor));
|
||||||
s_idtr.size = 0x100 * sizeof(GateDescriptor) - 1;
|
|
||||||
|
|
||||||
#define X(num) register_interrupt_handler(num, isr ## num);
|
#define X(num) idt->register_interrupt_handler(num, isr ## num);
|
||||||
ISR_LIST_X
|
ISR_LIST_X
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
#define X(num) register_interrupt_handler(IRQ_VECTOR_BASE + num, irq ## num);
|
// FIXME: distribute IRQs more evenly?
|
||||||
IRQ_LIST_X
|
#define X(num) idt->register_interrupt_handler(IRQ_VECTOR_BASE + num, irq ## num);
|
||||||
|
if (Processor::current_is_bsb())
|
||||||
|
{
|
||||||
|
IRQ_LIST_X
|
||||||
|
}
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
register_syscall_handler(0x80, syscall_asm);
|
idt->register_syscall_handler(0x80, syscall_asm);
|
||||||
|
|
||||||
flush_idt();
|
idt->flush();
|
||||||
|
|
||||||
|
return idt;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void force_triple_fault()
|
[[noreturn]] void IDT::force_triple_fault()
|
||||||
{
|
{
|
||||||
// load 0 sized IDT and trigger an interrupt to force triple fault
|
// load 0 sized IDT and trigger an interrupt to force triple fault
|
||||||
asm volatile("cli");
|
auto& processor = Processor::current();
|
||||||
s_idtr.size = 0;
|
processor.set_interrupt_state(InterruptState::Disabled);
|
||||||
flush_idt();
|
processor.idt().m_idtr.size = 0;
|
||||||
|
processor.idt().flush();
|
||||||
asm volatile("int $0x00");
|
asm volatile("int $0x00");
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,63 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Array.h>
|
||||||
|
#include <BAN/NoCopyMove.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
||||||
|
|
||||||
namespace Kernel::IDT
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
void initialize();
|
class Interruptable;
|
||||||
[[noreturn]] void force_triple_fault();
|
|
||||||
|
struct GateDescriptor
|
||||||
|
{
|
||||||
|
uint16_t offset1;
|
||||||
|
uint16_t selector;
|
||||||
|
uint8_t IST;
|
||||||
|
uint8_t flags;
|
||||||
|
uint16_t offset2;
|
||||||
|
uint32_t offset3;
|
||||||
|
uint32_t reserved;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct IDTR
|
||||||
|
{
|
||||||
|
uint16_t size;
|
||||||
|
uint64_t offset;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
class IDT
|
||||||
|
{
|
||||||
|
BAN_NON_COPYABLE(IDT);
|
||||||
|
BAN_NON_MOVABLE(IDT);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static IDT* create();
|
||||||
|
|
||||||
|
[[noreturn]] static void force_triple_fault();
|
||||||
|
|
||||||
|
void register_irq_handler(uint8_t irq, Interruptable* interruptable);
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDT() = default;
|
||||||
|
|
||||||
|
void register_interrupt_handler(uint8_t index, void (*handler)());
|
||||||
|
void register_syscall_handler(uint8_t index, void (*handler)());
|
||||||
|
|
||||||
|
void flush()
|
||||||
|
{
|
||||||
|
asm volatile("lidt %0" :: "m"(m_idtr) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BAN::Array<GateDescriptor, 0x100> m_idt;
|
||||||
|
IDTR m_idtr {
|
||||||
|
.size = m_idt.size() * sizeof(GateDescriptor) - 1,
|
||||||
|
.offset = reinterpret_cast<uint64_t>(m_idt.data())
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <kernel/Arch.h>
|
#include <kernel/Arch.h>
|
||||||
#include <kernel/GDT.h>
|
#include <kernel/GDT.h>
|
||||||
|
#include <kernel/IDT.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -60,6 +61,7 @@ namespace Kernel
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
GDT& gdt() { ASSERT(m_gdt); return *m_gdt; }
|
GDT& gdt() { ASSERT(m_gdt); return *m_gdt; }
|
||||||
|
IDT& idt() { ASSERT(m_idt); return *m_idt; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Processor() = default;
|
Processor() = default;
|
||||||
|
@ -70,6 +72,9 @@ namespace Kernel
|
||||||
|
|
||||||
m_gdt = other.m_gdt;
|
m_gdt = other.m_gdt;
|
||||||
other.m_gdt = nullptr;
|
other.m_gdt = nullptr;
|
||||||
|
|
||||||
|
m_idt = other.m_idt;
|
||||||
|
other.m_idt = nullptr;
|
||||||
}
|
}
|
||||||
~Processor();
|
~Processor();
|
||||||
|
|
||||||
|
@ -80,6 +85,7 @@ namespace Kernel
|
||||||
static constexpr size_t m_stack_size { 4096 };
|
static constexpr size_t m_stack_size { 4096 };
|
||||||
|
|
||||||
GDT* m_gdt { nullptr };
|
GDT* m_gdt { nullptr };
|
||||||
|
IDT* m_idt { nullptr };
|
||||||
|
|
||||||
friend class BAN::Vector<Processor>;
|
friend class BAN::Vector<Processor>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -48,6 +48,10 @@ namespace Kernel
|
||||||
ASSERT(m_gdt == nullptr);
|
ASSERT(m_gdt == nullptr);
|
||||||
m_gdt = GDT::create();
|
m_gdt = GDT::create();
|
||||||
ASSERT(m_gdt);
|
ASSERT(m_gdt);
|
||||||
|
|
||||||
|
ASSERT(m_idt == nullptr);
|
||||||
|
m_idt = IDT::create();
|
||||||
|
ASSERT(m_idt);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,9 +106,6 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
|
||||||
Processor::current().initialize();
|
Processor::current().initialize();
|
||||||
dprintln("BSP initialized");
|
dprintln("BSP initialized");
|
||||||
|
|
||||||
IDT::initialize();
|
|
||||||
dprintln("IDT initialized");
|
|
||||||
|
|
||||||
PageTable::initialize();
|
PageTable::initialize();
|
||||||
dprintln("PageTable initialized");
|
dprintln("PageTable initialized");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue