feat: idt
This commit is contained in:
parent
65a0eb1cda
commit
880638202f
|
@ -4,6 +4,10 @@
|
||||||
|
|
||||||
Res hal_setup(void);
|
Res hal_setup(void);
|
||||||
|
|
||||||
|
/* --- Structs ------------------------------------------------------------ */
|
||||||
|
|
||||||
|
typedef struct _HalRegs HalRegs;
|
||||||
|
|
||||||
/* --- Assembly function --------------------------------------------------- */
|
/* --- Assembly function --------------------------------------------------- */
|
||||||
|
|
||||||
void hal_disable_interrupts(void);
|
void hal_disable_interrupts(void);
|
||||||
|
@ -16,4 +20,4 @@ void hal_panic(void);
|
||||||
|
|
||||||
/* --- I/O ---------------------------------------------------------------- */
|
/* --- I/O ---------------------------------------------------------------- */
|
||||||
|
|
||||||
Stream hal_dbg_stream(void);
|
Stream hal_dbg_stream(void);
|
||||||
|
|
8
src/kernel/archs/x86_64/asm.h
Normal file
8
src/kernel/archs/x86_64/asm.h
Normal 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))
|
112
src/kernel/archs/x86_64/handler.c
Normal file
112
src/kernel/archs/x86_64/handler.c
Normal 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;
|
||||||
|
}
|
|
@ -15,8 +15,99 @@ gdt_flush:
|
||||||
push %rdi
|
push %rdi
|
||||||
lretq
|
lretq
|
||||||
|
|
||||||
|
|
||||||
tss_flush:
|
tss_flush:
|
||||||
mov $0x28, %ax
|
mov $0x28, %ax
|
||||||
ltr %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
|
ret
|
37
src/kernel/archs/x86_64/idt.c
Normal file
37
src/kernel/archs/x86_64/idt.c
Normal 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");
|
||||||
|
}
|
41
src/kernel/archs/x86_64/idt.h
Normal file
41
src/kernel/archs/x86_64/idt.h
Normal 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);
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "e9.h"
|
#include "e9.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
|
#include "idt.h"
|
||||||
|
|
||||||
Stream hal_dbg_stream(void)
|
Stream hal_dbg_stream(void)
|
||||||
{
|
{
|
||||||
|
@ -15,5 +16,6 @@ Stream hal_dbg_stream(void)
|
||||||
Res hal_setup(void)
|
Res hal_setup(void)
|
||||||
{
|
{
|
||||||
gdt_init();
|
gdt_init();
|
||||||
|
idt_init();
|
||||||
return ok$();
|
return ok$();
|
||||||
}
|
}
|
31
src/kernel/archs/x86_64/regs.h
Normal file
31
src/kernel/archs/x86_64/regs.h
Normal 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;
|
||||||
|
};
|
|
@ -5,6 +5,7 @@ _Noreturn int _start()
|
||||||
{
|
{
|
||||||
log$("Hello, world!");
|
log$("Hello, world!");
|
||||||
hal_setup();
|
hal_setup();
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
;
|
;
|
||||||
}
|
}
|
Loading…
Reference in a new issue