mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-25 23:10:32 +00:00
ZealBooter: Add minimal IDT and exception handling
This commit is contained in:
parent
f0c751e962
commit
674daa42a4
4 changed files with 233 additions and 0 deletions
163
zealbooter/idt.c
Normal file
163
zealbooter/idt.c
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <idt.h>
|
||||||
|
#include <print.h>
|
||||||
|
|
||||||
|
struct cpu_ctx {
|
||||||
|
uint64_t ds;
|
||||||
|
uint64_t es;
|
||||||
|
uint64_t rax;
|
||||||
|
uint64_t rbx;
|
||||||
|
uint64_t rcx;
|
||||||
|
uint64_t rdx;
|
||||||
|
uint64_t rsi;
|
||||||
|
uint64_t rdi;
|
||||||
|
uint64_t rbp;
|
||||||
|
uint64_t r8;
|
||||||
|
uint64_t r9;
|
||||||
|
uint64_t r10;
|
||||||
|
uint64_t r11;
|
||||||
|
uint64_t r12;
|
||||||
|
uint64_t r13;
|
||||||
|
uint64_t r14;
|
||||||
|
uint64_t r15;
|
||||||
|
uint64_t err;
|
||||||
|
uint64_t rip;
|
||||||
|
uint64_t cs;
|
||||||
|
uint64_t rflags;
|
||||||
|
uint64_t rsp;
|
||||||
|
uint64_t ss;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct idt_entry {
|
||||||
|
uint16_t offset_low;
|
||||||
|
uint16_t selector;
|
||||||
|
uint8_t ist;
|
||||||
|
uint8_t flags;
|
||||||
|
uint16_t offset_mid;
|
||||||
|
uint32_t offset_hi;
|
||||||
|
uint32_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct idtr {
|
||||||
|
uint16_t limit;
|
||||||
|
uint64_t base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
static struct idt_entry idt[256];
|
||||||
|
|
||||||
|
void *isr[256];
|
||||||
|
|
||||||
|
static void register_handler(uint8_t vector, void *handler, uint8_t flags) {
|
||||||
|
uint64_t handler_int = (uint64_t)handler;
|
||||||
|
|
||||||
|
idt[vector] = (struct idt_entry){
|
||||||
|
.offset_low = (uint16_t)handler_int,
|
||||||
|
.selector = 0x28,
|
||||||
|
.ist = 0,
|
||||||
|
.flags = flags,
|
||||||
|
.offset_mid = (uint16_t)(handler_int >> 16),
|
||||||
|
.offset_hi = (uint32_t)(handler_int >> 32),
|
||||||
|
.reserved = 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void *isr_thunks[];
|
||||||
|
|
||||||
|
static const char *exceptions[] = {
|
||||||
|
"Division exception",
|
||||||
|
"Debug",
|
||||||
|
"NMI",
|
||||||
|
"Breakpoint",
|
||||||
|
"Overflow",
|
||||||
|
"Bound range exceeded",
|
||||||
|
"Invalid opcode",
|
||||||
|
"Device not available",
|
||||||
|
"Double fault",
|
||||||
|
"???",
|
||||||
|
"Invalid TSS",
|
||||||
|
"Segment not present",
|
||||||
|
"Stack-segment fault",
|
||||||
|
"General protection fault",
|
||||||
|
"Page fault",
|
||||||
|
"???",
|
||||||
|
"x87 exception",
|
||||||
|
"Alignment check",
|
||||||
|
"Machine check",
|
||||||
|
"SIMD exception",
|
||||||
|
"Virtualisation"
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint64_t read_cr0(void) {
|
||||||
|
uint64_t ret;
|
||||||
|
asm volatile ("mov %%cr0, %0" : "=r"(ret) :: "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t read_cr2(void) {
|
||||||
|
uint64_t ret;
|
||||||
|
asm volatile ("mov %%cr2, %0" : "=r"(ret) :: "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t read_cr3(void) {
|
||||||
|
uint64_t ret;
|
||||||
|
asm volatile ("mov %%cr3, %0" : "=r"(ret) :: "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t read_cr4(void) {
|
||||||
|
uint64_t ret;
|
||||||
|
asm volatile ("mov %%cr4, %0" : "=r"(ret) :: "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exception_handler(uint8_t vector, struct cpu_ctx *ctx) {
|
||||||
|
printf("Exception %s triggered\n\n", exceptions[vector]);
|
||||||
|
|
||||||
|
printf(" RAX=%016lx RBX=%016lx\n"
|
||||||
|
" RCX=%016lx RDX=%016lx\n"
|
||||||
|
" RSI=%016lx RDI=%016lx\n"
|
||||||
|
" RBP=%016lx RSP=%016lx\n"
|
||||||
|
" R08=%016lx R09=%016lx\n"
|
||||||
|
" R10=%016lx R11=%016lx\n"
|
||||||
|
" R12=%016lx R13=%016lx\n"
|
||||||
|
" R14=%016lx R15=%016lx\n"
|
||||||
|
" RIP=%016lx RFLAGS=%08lx\n"
|
||||||
|
" CS=%04lx DS=%04lx ES=%04lx SS=%04lx\n"
|
||||||
|
" CR0=%016lx CR2=%016lx\n"
|
||||||
|
" CR3=%016lx CR4=%016lx\n"
|
||||||
|
" ERR=%016lx",
|
||||||
|
ctx->rax, ctx->rbx, ctx->rcx, ctx->rdx,
|
||||||
|
ctx->rsi, ctx->rdi, ctx->rbp, ctx->rsp,
|
||||||
|
ctx->r8, ctx->r9, ctx->r10, ctx->r11,
|
||||||
|
ctx->r12, ctx->r13, ctx->r14, ctx->r15,
|
||||||
|
ctx->rip, ctx->rflags,
|
||||||
|
ctx->cs, ctx->ds, ctx->es, ctx->ss,
|
||||||
|
read_cr0(), read_cr2(),
|
||||||
|
read_cr3(), read_cr4(),
|
||||||
|
ctx->err);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
asm ("hlt");
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_init(void) {
|
||||||
|
for (size_t i = 0; i < 256; i++) {
|
||||||
|
register_handler(i, isr_thunks[i], 0x8e);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(exceptions) / sizeof(exceptions[0]); i++) {
|
||||||
|
isr[i] = exception_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct idtr idtr = {
|
||||||
|
.limit = sizeof(idt) - 1,
|
||||||
|
.base = (uint64_t)idt
|
||||||
|
};
|
||||||
|
|
||||||
|
asm volatile ("lidt %0" :: "m"(idtr) : "memory");
|
||||||
|
}
|
6
zealbooter/idt.h
Normal file
6
zealbooter/idt.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef _IDT_H
|
||||||
|
#define _IDT_H
|
||||||
|
|
||||||
|
void idt_init(void);
|
||||||
|
|
||||||
|
#endif
|
61
zealbooter/int_thunks.S
Normal file
61
zealbooter/int_thunks.S
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
.altmacro
|
||||||
|
|
||||||
|
.macro THUNK num
|
||||||
|
interrupt_thunk_\num:
|
||||||
|
.if \num != 8 && \num != 10 && \num != 11 && \num != 12 && \num != 13 && \num != 14 && \num != 17 && \num != 30
|
||||||
|
push $0
|
||||||
|
.endif
|
||||||
|
|
||||||
|
push %r15
|
||||||
|
push %r14
|
||||||
|
push %r13
|
||||||
|
push %r12
|
||||||
|
push %r11
|
||||||
|
push %r10
|
||||||
|
push %r9
|
||||||
|
push %r8
|
||||||
|
push %rbp
|
||||||
|
push %rdi
|
||||||
|
push %rsi
|
||||||
|
push %rdx
|
||||||
|
push %rcx
|
||||||
|
push %rbx
|
||||||
|
push %rax
|
||||||
|
mov %es, %eax
|
||||||
|
push %rax
|
||||||
|
mov %ds, %eax
|
||||||
|
push %rax
|
||||||
|
|
||||||
|
cld
|
||||||
|
|
||||||
|
mov $\num, %rdi
|
||||||
|
mov $(\num * 8), %rax
|
||||||
|
lea isr(%rip), %rbx
|
||||||
|
add %rax, %rbx
|
||||||
|
mov %rsp, %rsi
|
||||||
|
call *(%rbx)
|
||||||
|
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro THUNKADDR num
|
||||||
|
.quad interrupt_thunk_\num
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
|
.global isr_thunks
|
||||||
|
.align 8
|
||||||
|
isr_thunks:
|
||||||
|
.set i,0
|
||||||
|
.rept 256
|
||||||
|
THUNKADDR %i
|
||||||
|
.set i,i+1
|
||||||
|
.endr
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
.set i,0
|
||||||
|
.rept 256
|
||||||
|
THUNK %i
|
||||||
|
.set i,i+1
|
||||||
|
.endr
|
|
@ -2,6 +2,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
|
#include <idt.h>
|
||||||
|
|
||||||
static volatile struct limine_module_request module_request = {
|
static volatile struct limine_module_request module_request = {
|
||||||
.id = LIMINE_MODULE_REQUEST,
|
.id = LIMINE_MODULE_REQUEST,
|
||||||
|
@ -152,6 +153,8 @@ void _start(void) {
|
||||||
printf("ZealBooter prekernel\n");
|
printf("ZealBooter prekernel\n");
|
||||||
printf("____________________\n\n");
|
printf("____________________\n\n");
|
||||||
|
|
||||||
|
idt_init();
|
||||||
|
|
||||||
struct limine_file *module_kernel = module_request.response->modules[0];
|
struct limine_file *module_kernel = module_request.response->modules[0];
|
||||||
struct CKernel *kernel = module_kernel->address;
|
struct CKernel *kernel = module_kernel->address;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue