Files
banan-os/kernel/include/kernel/IDT.h
Bananymous 35c97e2ff8 Kernel: optimize yielding
Doing a yield no longer raises a software interrupt. Instead it just
saves all the callee saved registers, ip, sp and return value. Because
yield is only called in the kernel, it can just restore registers and
jump to the target address. There is never a need to use iret :)
2026-01-11 01:31:09 +02:00

92 lines
1.8 KiB
C++

#pragma once
#include <BAN/Array.h>
#include <BAN/NoCopyMove.h>
#include <kernel/Arch.h>
#include <kernel/Interruptable.h>
#include <stdint.h>
namespace Kernel
{
// IDT entries
// 0x00->0x1F (32): ISR
// 0x20->0x7F (96): PIC/IOAPIC
// 0x80->0xEF (112): MSI
// 0xF0->0xFE (15): internal
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
constexpr uint8_t IRQ_MSI_BASE = 0x80;
constexpr uint8_t IRQ_MSI_END = 0xF0;
#if ARCH(i686)
constexpr uint8_t IRQ_SYSCALL = 0xF0;
#endif
constexpr uint8_t IRQ_IPI = 0xF1;
constexpr uint8_t IRQ_TIMER = 0xF2;
#if ARCH(x86_64)
struct GateDescriptor
{
uint16_t offset0;
uint16_t selector;
uint8_t IST;
uint8_t flags;
uint16_t offset1;
uint32_t offset2;
uint32_t reserved;
};
static_assert(sizeof(GateDescriptor) == 16);
#elif ARCH(i686)
struct GateDescriptor
{
uint16_t offset0;
uint16_t selector;
uint8_t reserved;
uint8_t flags;
uint16_t offset1;
};
static_assert(sizeof(GateDescriptor) == 8);
#else
#error
#endif
struct IDTR
{
uint16_t size;
uintptr_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);
void load()
{
asm volatile("lidt %0" :: "m"(m_idtr) : "memory");
}
private:
IDT() = default;
void register_interrupt_handler(uint8_t index, void (*handler)(), uint8_t ist = 0);
void register_syscall_handler(uint8_t index, void (*handler)());
private:
BAN::Array<GateDescriptor, 0x100> m_idt;
IDTR m_idtr {
.size = static_cast<uint16_t>(m_idt.size() * sizeof(GateDescriptor) - 1),
.offset = reinterpret_cast<uintptr_t>(m_idt.data())
};
};
}