feat: idt

This commit is contained in:
Jordan ⌨️ 2023-12-10 23:29:10 +01:00
parent 65a0eb1cda
commit 880638202f
9 changed files with 329 additions and 2 deletions

View file

@ -4,6 +4,10 @@
Res hal_setup(void);
/* --- Structs ------------------------------------------------------------ */
typedef struct _HalRegs HalRegs;
/* --- Assembly function --------------------------------------------------- */
void hal_disable_interrupts(void);

View file

@ -0,0 +1,8 @@
#pragma once
#define asm_read_cr(n, reg) asm volatile("mov %%cr" #n ", %0" \
: "=r"(reg))
#define asm_write_cr(n, reg) asm volatile("mov %0, %%cr" #n \
: \
: "r"(reg))

View file

@ -0,0 +1,112 @@
#include <dbg/log.h>
#include <hal.h>
#include <sync/spinlock.h>
#include "asm.h"
#include "regs.h"
enum
{
IRQ0 = 32,
};
static Spinlock lock = SPINLOCK_INIT;
static char *exception_messages[32] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Detected Overflow",
"Out Of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad Tss",
"Segment Not Present",
"StackFault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point Exception",
"Virtualization Exception",
"Control Protection Exception",
"Reserved",
"Hypervisor Injection Exception",
"VMM Communication Exception",
"Security Exception",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
};
static void dump_backtrace(uintptr_t rbp)
{
struct _StackFrame
{
struct _StackFrame *rbp;
uint64_t rip;
} *stackframe = (void *)rbp;
for (;;)
{
if (stackframe->rip == 0)
{
break;
}
print$(" * %p\n", stackframe->rip);
stackframe = stackframe->rbp;
}
}
static void kpanic(HalRegs const regs[static 1])
{
spinlock_acquire(&lock);
uint64_t cr0, cr2, cr3, cr4;
asm_read_cr(0, cr0);
asm_read_cr(2, cr2);
asm_read_cr(3, cr3);
asm_read_cr(4, cr4);
print$("\n!!! ---------------------------------------------------------------------------------------------------\n\n");
print$(" KERNEL PANIC\n");
print$(" %s was raised\n\n", exception_messages[regs->intno]);
print$(" Registers:\n");
print$(" interrupt: %x, err: %x \n", regs->intno, regs->err);
print$(" RAX %p RBX %p RCX %p RDX %p\n", regs->rax, regs->rbx, regs->rcx, regs->rdx);
print$(" RSI %p RDI %p RBP %p RSP %p\n", regs->rsi, regs->rdi, regs->rbp, regs->rsp);
print$(" R8 %p R9 %p R10 %p R11 %p\n", regs->r8, regs->r9, regs->r10, regs->r11);
print$(" R12 %p R13 %p R14 %p R15 %p\n", regs->r12, regs->r13, regs->r14, regs->r15);
print$(" CR0 %p CR2 %p CR3 %p CR4 %p\n", cr0, cr2, cr3, cr4);
print$(" CS %p SS %p FLG %p\n", regs->cs, regs->ss, regs->rflags);
print$(" RIP \033[7m%p\033[0m\n\n", regs->rip);
print$(" Backtrace:\n");
dump_backtrace(regs->rbp);
print$("--------------------------------------------------------------------------------------------------- !!!\n\n");
spinlock_release(&lock);
}
uintptr_t interrupt_handler(uintptr_t rsp)
{
HalRegs *regs = (HalRegs *)rsp;
if (regs->intno < IRQ0)
{
kpanic(regs);
for (;;)
{
hal_disable_interrupts();
hal_pause();
}
}
return rsp;
}

View file

@ -15,8 +15,99 @@ gdt_flush:
push %rdi
lretq
tss_flush:
mov $0x28, %ax
ltr %ax
ret
.altmacro
.globl idt_flush
.globl __interrupts_vector
.extern interrupt_handler
.macro INTERRUPT_NAME intno
.quad __interrupt\intno
.endm
.macro INTERRUPT_ERR intno
__interrupt\intno:
pushq $\intno
jmp __interrupt_common
.endm
.macro INTERRUPT_NOERR intno
__interrupt\intno:
pushq $0
pushq $\intno
jmp __interrupt_common
.endm
.macro __pusha
push %rax
push %rbx
push %rcx
push %rdx
push %rsi
push %rdi
push %rbp
push %r8
push %r9
push %r10
push %r11
push %r12
push %r13
push %r14
push %r15
.endm
.macro __popa
pop %r15
pop %r14
pop %r13
pop %r12
pop %r11
pop %r10
pop %r9
pop %r8
pop %rbp
pop %rdi
pop %rsi
pop %rdx
pop %rcx
pop %rbx
pop %rax
.endm
__interrupt_common:
cld
__pusha
movq %rsp, %rdi
call interrupt_handler
movq %rax, %rsp
__popa
add $16, %rsp
iretq
.set i,0
.rept 48
.if i != 8 && i != 10 && i != 11 && i != 12 && i != 13 && i != 14 && i != 17 && i != 30
INTERRUPT_NOERR %i
.else
INTERRUPT_ERR %i
.endif
.set i,i+1
.endr
.align 8
__interrupts_vector:
.set i,0
.rept 48
INTERRUPT_NAME %i
.set i,i+1
.endr
idt_flush:
lidt (%rdi)
ret

View file

@ -0,0 +1,37 @@
#include <dbg/log.h>
#include "gdt.h"
#include "idt.h"
static Idt idt;
static IdtDescriptor idt_desc = {
.size = sizeof(idt) - 1,
.offset = (uintptr_t)&idt,
};
static void idt_init_entry(IdtEntry *self, uint64_t base, uint8_t type)
{
self->offset_low = base & 0xFFFF;
self->offset_mid = (base >> 16) & 0xFFFF;
self->offset_high = (base >> 32) & 0xFFFFFFFF;
self->ist = 0;
self->selector = GDT_KERNEL_CODE * 8;
self->type_attr = IDT_INT_PRESENT | type;
self->zero = 0;
}
uintptr_t idt_descriptor(void)
{
return (uintptr_t)&idt_desc;
}
void idt_init(void)
{
for (size_t i = 0; i < IDT_ENTRY_COUNT; i++)
{
idt_init_entry(&idt.entries[i], __interrupts_vector[i], IDT_INT_GATE);
}
idt_flush(idt_descriptor());
log$("IDT lodaded");
}

View file

@ -0,0 +1,41 @@
#pragma once
#include <stdint.h>
#define IDT_ENTRY_COUNT (256)
enum
{
IDT_INT_PRESENT = (1 << 7),
IDT_INT_GATE = (0xe),
};
typedef struct [[gnu::packed]]
{
uint16_t size;
uintptr_t offset;
} IdtDescriptor;
typedef struct packed
{
uint16_t offset_low;
uint16_t selector;
uint8_t ist;
uint8_t type_attr;
uint16_t offset_mid;
uint32_t offset_high;
uint32_t zero;
} IdtEntry;
typedef struct [[gnu::packed]]
{
IdtEntry entries[IDT_ENTRY_COUNT];
} Idt;
void idt_init(void);
uintptr_t idt_descriptor(void);
extern uintptr_t __interrupts_vector[];
extern void idt_flush(uintptr_t);

View file

@ -4,6 +4,7 @@
#include "e9.h"
#include "gdt.h"
#include "idt.h"
Stream hal_dbg_stream(void)
{
@ -15,5 +16,6 @@ Stream hal_dbg_stream(void)
Res hal_setup(void)
{
gdt_init();
idt_init();
return ok$();
}

View file

@ -0,0 +1,31 @@
#pragma once
#include <stdint.h>
struct [[gnu::packed]] _HalRegs
{
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rbp;
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t rbx;
uint64_t rax;
uint64_t intno;
uint64_t err;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
};

View file

@ -5,6 +5,7 @@ _Noreturn int _start()
{
log$("Hello, world!");
hal_setup();
for (;;)
;
}