Add idt module and set up IDT

This commit is contained in:
Josh Holtrop 2022-09-04 22:25:46 -04:00
parent b72c69ef1c
commit bc7fd3f2fc
3 changed files with 111 additions and 4 deletions

View File

@ -14,10 +14,10 @@ struct gdt
} }
static assert(gdtr_t.sizeof == 10u); static assert(gdtr_t.sizeof == 10u);
private enum size_t SELECTOR_NULL = 0x00u; public enum size_t SELECTOR_NULL = 0x00u;
private enum size_t SELECTOR_KERNEL_CODE = 0x08u; public enum size_t SELECTOR_KERNEL_CODE = 0x08u;
private enum size_t SELECTOR_KERNEL_DATA = 0x10u; public enum size_t SELECTOR_KERNEL_DATA = 0x10u;
private enum size_t SELECTOR_COUNT = 3u; public enum size_t SELECTOR_COUNT = 3u;
static __gshared ulong[SELECTOR_COUNT] gdt; static __gshared ulong[SELECTOR_COUNT] gdt;
static __gshared gdtr_t gdtr; static __gshared gdtr_t gdtr;

View File

@ -14,6 +14,7 @@ import hulk.hurl;
import hulk.hippo; import hulk.hippo;
import hulk.pci; import hulk.pci;
import hulk.gdt; import hulk.gdt;
import hulk.idt;
import hos.cpu; import hos.cpu;
extern extern(C) __gshared ubyte _hulk_total_size; extern extern(C) __gshared ubyte _hulk_total_size;
@ -35,6 +36,7 @@ void hulk_start()
{ {
cli(); cli();
gdt.initialize(); gdt.initialize();
idt.initialize();
fb.initialize(cast(uint *)HULK_VIRTUAL_FRAMEBUFFER_ADDRESS, hulk_header.bootinfo.fb.width, hulk_header.bootinfo.fb.height, hulk_header.bootinfo.fb.stride); fb.initialize(cast(uint *)HULK_VIRTUAL_FRAMEBUFFER_ADDRESS, hulk_header.bootinfo.fb.width, hulk_header.bootinfo.fb.height, hulk_header.bootinfo.fb.stride);
console.initialize(); console.initialize();
console.clear(); console.clear();

105
src/hulk/idt.d Normal file
View File

@ -0,0 +1,105 @@
/**
* IDT (Interrupt Descriptor Table) functionality.
*/
module hulk.idt;
import hulk.gdt;
import ldc.llvmasm;
import hulk.fb;
import hulk.console;
import hulk.klog;
struct idt
{
struct idtr_t
{
ushort limit;
align(2) ulong offset;
}
static assert(idtr_t.sizeof == 10u);
alias descriptor_t = ulong[2];
static __gshared align(0x10) descriptor_t[256] idt;
static assert(idt.sizeof == (256u * 16u));
static __gshared idtr_t idtr;
public static void initialize()
{
set_isrs();
idtr.limit = idt.sizeof - 1u;
idtr.offset = cast(ulong)&idt;
lidt(&idtr);
}
private static void lidt(idtr_t * idtr)
{
__asm("lidt $0", "*m", idtr);
}
private static bool isr_has_error_code(size_t isr)
{
return (isr == 8) ||
((10 <= isr) && (isr <= 14)) ||
(isr == 17) ||
(isr == 21) ||
(isr == 29) ||
(isr == 30);
}
private static bool isr_is_trap(size_t isr)
{
return (isr < 32u) && (isr != 2u);
}
private static void set_isrs()
{
ulong isr_address;
static foreach(isr; 0 .. 256)
{
mixin("isr_address = __asm!ulong(`
movabs $$1f, %rax
jmp 2f
1:
pushq %rdi
pushq %rsi
pushq %rax
mov $$", isr, ", %rdi
" ~ (isr_has_error_code(isr) ? "mov 0x18(%rsp), %rsi" : "") ~ "
movabs $$isr, %rax
callq *%rax
popq %rax
popq %rsi
popq %rdi
" ~ (isr_has_error_code(isr) ? "add $$8, %rsp" : "") ~ "
iretq
2:`, `={rax}`);");
mixin("set_descriptor(", isr, ", 0u, " ~
(isr_is_trap(isr) ? "true" : "false") ~ ", isr_address);");
}
}
private static void set_descriptor(size_t index, ulong dpl, bool trap, ulong offset)
{
idt[index][0] =
0x0000_8E_00_0000_0000u |
((offset & 0xFFFF_0000u) << 32u) |
(dpl << 45u) |
((trap ? 1uL : 0uL) << 40u) |
(gdt.SELECTOR_KERNEL_CODE << 16u) |
(offset & 0xFFFFu);
idt[index][1] = offset >> 32u;
}
}
public extern(C) void isr(ulong vector, ulong arg)
{
console.initialize();
fb.clear(0xFF8000u);
klog.writefln("ISR %u, 0x%x", vector, arg);
__asm("cli", "");
for (;;)
{
__asm("hlt", "");
}
}