misc: Handle CPU exceptions nicely
This commit is contained in:
parent
9e60b1da10
commit
94887a4533
@ -74,8 +74,7 @@ ifeq ($(TARGET), bios)
|
||||
-static \
|
||||
-fno-pie \
|
||||
-lgcc \
|
||||
-static-libgcc \
|
||||
-Wl,--gc-sections
|
||||
-static-libgcc
|
||||
endif
|
||||
|
||||
.PHONY: all clean builddir
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <pxe/pxe.h>
|
||||
#include <pxe/tftp.h>
|
||||
#include <drivers/disk.h>
|
||||
#include <sys/idt.h>
|
||||
|
||||
extern uint64_t stage3_build_id;
|
||||
|
||||
@ -74,6 +75,8 @@ void entry(uint8_t boot_drive, int boot_from) {
|
||||
if (!a20_enable())
|
||||
panic("Could not enable A20 line");
|
||||
|
||||
init_idt();
|
||||
|
||||
init_e820();
|
||||
init_memmap();
|
||||
|
||||
@ -90,7 +93,7 @@ void entry(uint8_t boot_drive, int boot_from) {
|
||||
);
|
||||
|
||||
if (!stage3_loaded)
|
||||
panic("Failed to load stage 3.\n");
|
||||
panic("Failed to load stage 3.");
|
||||
|
||||
__attribute__((noreturn))
|
||||
void (*stage3)(int boot_from) = (void *)stage3_addr;
|
||||
|
@ -83,7 +83,7 @@ bool efi_exit_boot_services(void) {
|
||||
status = uefi_call_wrapper(gBS->ExitBootServices, 2, efi_image_handle, mmap_key);
|
||||
|
||||
if (status)
|
||||
panic("efi: Failed to exit boot services\n");
|
||||
panic("efi: Failed to exit boot services");
|
||||
|
||||
asm volatile ("cli" ::: "memory");
|
||||
|
||||
|
@ -2,6 +2,9 @@ section .realmode
|
||||
|
||||
global rm_hcf
|
||||
rm_hcf:
|
||||
; Load BIOS IVT
|
||||
lidt [.rm_idt]
|
||||
|
||||
; Jump to real mode
|
||||
jmp 0x08:.bits16
|
||||
.bits16:
|
||||
@ -30,6 +33,9 @@ rm_hcf:
|
||||
jmp .hang
|
||||
bits 32
|
||||
|
||||
.rm_idt: dw 0x3ff
|
||||
dd 0
|
||||
|
||||
global rm_int
|
||||
rm_int:
|
||||
; Self-modifying code: int $int_no
|
||||
@ -47,6 +53,12 @@ rm_int:
|
||||
; Save GDT in case BIOS overwrites it
|
||||
sgdt [.gdt]
|
||||
|
||||
; Save IDT
|
||||
sidt [.idt]
|
||||
|
||||
; Load BIOS IVT
|
||||
lidt [.rm_idt]
|
||||
|
||||
; Save non-scratch GPRs
|
||||
push ebx
|
||||
push esi
|
||||
@ -116,7 +128,10 @@ rm_int:
|
||||
mov esp, dword [ss:.esp]
|
||||
|
||||
; Restore GDT
|
||||
lgdt [ss:.gdt]
|
||||
o32 lgdt [ss:.gdt]
|
||||
|
||||
; Restore IDT
|
||||
o32 lidt [ss:.idt]
|
||||
|
||||
; Jump back to pmode
|
||||
mov eax, cr0
|
||||
@ -146,3 +161,6 @@ align 16
|
||||
.out_regs: dd 0
|
||||
.in_regs: dd 0
|
||||
.gdt: dq 0
|
||||
.idt: dq 0
|
||||
.rm_idt: dw 0x3ff
|
||||
dd 0
|
||||
|
@ -26,6 +26,15 @@ _pit_sleep_and_quit_on_keypress:
|
||||
|
||||
mov dword [int_08_ticks_counter], 0
|
||||
|
||||
; Save GDT in case BIOS overwrites it
|
||||
sgdt [.gdt]
|
||||
|
||||
; Save IDT
|
||||
sidt [.idt]
|
||||
|
||||
; Load BIOS IVT
|
||||
lidt [.rm_idt]
|
||||
|
||||
; Save non-scratch GPRs
|
||||
push ebx
|
||||
push esi
|
||||
@ -81,6 +90,12 @@ _pit_sleep_and_quit_on_keypress:
|
||||
.done:
|
||||
cli
|
||||
|
||||
; Restore GDT
|
||||
o32 lgdt [ss:.gdt]
|
||||
|
||||
; Restore IDT
|
||||
o32 lidt [ss:.idt]
|
||||
|
||||
; Jump back to pmode
|
||||
mov ebx, cr0
|
||||
or bl, 1
|
||||
@ -115,3 +130,8 @@ _pit_sleep_and_quit_on_keypress:
|
||||
pop edx
|
||||
|
||||
ret
|
||||
|
||||
.gdt: dq 0
|
||||
.idt: dq 0
|
||||
.rm_idt: dw 0x3ff
|
||||
dd 0
|
||||
|
@ -28,6 +28,7 @@ SECTIONS
|
||||
*(.stage3_build_id*)
|
||||
full_map = .;
|
||||
limine_sys_size = .;
|
||||
getchar_internal = .;
|
||||
}
|
||||
|
||||
.bss : {
|
||||
|
47
stage23/sys/exceptions.s2.c
Normal file
47
stage23/sys/exceptions.s2.c
Normal file
@ -0,0 +1,47 @@
|
||||
#include <stdint.h>
|
||||
#include <lib/blib.h>
|
||||
#include <lib/trace.h>
|
||||
#include <lib/print.h>
|
||||
|
||||
#if defined (bios)
|
||||
|
||||
static const char *exception_names[] = {
|
||||
"Division by 0",
|
||||
"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",
|
||||
"???",
|
||||
"???",
|
||||
"???",
|
||||
"???",
|
||||
"???",
|
||||
"???",
|
||||
"???",
|
||||
"???",
|
||||
"???",
|
||||
"Security"
|
||||
};
|
||||
|
||||
void except(uint32_t exception, uint32_t error_code, uint32_t ebp, uint32_t eip) {
|
||||
(void)ebp;
|
||||
panic("%s at %x. Error code: %x", exception_names[exception], eip, error_code);
|
||||
}
|
||||
|
||||
#endif
|
@ -59,6 +59,9 @@ static struct gdt_desc gdt_descs[] = {
|
||||
}
|
||||
};
|
||||
|
||||
#if defined (bios)
|
||||
__attribute__((section(".realmode")))
|
||||
#endif
|
||||
struct gdtr gdt = {
|
||||
sizeof(gdt_descs) - 1,
|
||||
(uintptr_t)gdt_descs,
|
||||
|
27
stage23/sys/idt.h
Normal file
27
stage23/sys/idt.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __SYS__IDT_H__
|
||||
#define __SYS__IDT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined (bios)
|
||||
|
||||
struct idtr {
|
||||
uint16_t limit;
|
||||
uint32_t ptr;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct idt_entry {
|
||||
uint16_t offset_lo;
|
||||
uint16_t selector;
|
||||
uint8_t unused;
|
||||
uint8_t type_attr;
|
||||
uint16_t offset_hi;
|
||||
} __attribute__((packed));
|
||||
|
||||
extern struct idtr idt;
|
||||
|
||||
void init_idt(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
36
stage23/sys/idt.s2.c
Normal file
36
stage23/sys/idt.s2.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/idt.h>
|
||||
#include <lib/blib.h>
|
||||
|
||||
#if defined (bios)
|
||||
|
||||
__attribute__((section(".realmode")))
|
||||
static struct idt_entry idt_entries[32];
|
||||
|
||||
__attribute__((section(".realmode")))
|
||||
struct idtr idt = {
|
||||
sizeof(idt_entries) - 1,
|
||||
(uintptr_t)idt_entries
|
||||
};
|
||||
|
||||
static void register_interrupt_handler(size_t vec, void *handler, uint8_t type) {
|
||||
uint32_t p = (uint32_t)handler;
|
||||
|
||||
idt_entries[vec].offset_lo = (uint16_t)p;
|
||||
idt_entries[vec].selector = 0x18;
|
||||
idt_entries[vec].unused = 0;
|
||||
idt_entries[vec].type_attr = type;
|
||||
idt_entries[vec].offset_hi = (uint16_t)(p >> 16);
|
||||
}
|
||||
|
||||
extern void *exceptions[];
|
||||
|
||||
void init_idt(void) {
|
||||
for (size_t i = 0; i < SIZEOF_ARRAY(idt_entries); i++)
|
||||
register_interrupt_handler(i, exceptions[i], 0x8e);
|
||||
|
||||
asm volatile ("lidt %0" :: "m"(idt) : "memory");
|
||||
}
|
||||
|
||||
#endif
|
39
stage23/sys/int_thunks.s2.asm
Normal file
39
stage23/sys/int_thunks.s2.asm
Normal file
@ -0,0 +1,39 @@
|
||||
section .text
|
||||
|
||||
extern except
|
||||
|
||||
%macro raise_exception 1
|
||||
align 16
|
||||
raise_exception_%1:
|
||||
cld
|
||||
%if %1 == 8 || %1 == 10 || %1 == 11 || %1 == 12 || %1 == 13 || %1 == 14 || %1 == 17 || %1 == 30
|
||||
pop eax
|
||||
%else
|
||||
xor eax, eax
|
||||
%endif
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push eax
|
||||
push %1
|
||||
call except
|
||||
%endmacro
|
||||
|
||||
%assign i 0
|
||||
%rep 32
|
||||
raise_exception i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
section .rodata
|
||||
|
||||
%macro raise_exception_getaddr 1
|
||||
dd raise_exception_%1
|
||||
%endmacro
|
||||
|
||||
global exceptions
|
||||
exceptions:
|
||||
%assign i 0
|
||||
%rep 32
|
||||
raise_exception_getaddr i
|
||||
%assign i i+1
|
||||
%endrep
|
Loading…
Reference in New Issue
Block a user