kernel: try some shit to get the compiler to put a backtrace
This commit is contained in:
parent
ca489e986a
commit
cfc9159ad9
7 changed files with 90 additions and 10 deletions
10
README.md
10
README.md
|
@ -3,11 +3,12 @@ The Soaplin kernel is a new Unix-like operating system kernel.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* x86_64 support (kinda)
|
* x86_64 support (kinda)
|
||||||
* Memory management (VMM/PMM)
|
* Memory management (VMM/PMM/VMA/kmalloc)
|
||||||
* Simple pre-emptive scheduler
|
* Simple pre-emptive scheduler
|
||||||
* Ring 3 (user mode) support
|
* Ring 3 (user mode) support
|
||||||
* ELF loader
|
* ELF loader
|
||||||
* ACPI
|
* ACPI
|
||||||
|
* Symetric Multiprocessing (It runs code, but the scheduler is running on 1 processor.)
|
||||||
|
|
||||||
## In the works
|
## In the works
|
||||||
* Virtual File System
|
* Virtual File System
|
||||||
|
@ -17,7 +18,7 @@ The Soaplin kernel is a new Unix-like operating system kernel.
|
||||||
* RTC support
|
* RTC support
|
||||||
* EXT2 driver
|
* EXT2 driver
|
||||||
* FAT32 driver
|
* FAT32 driver
|
||||||
* CPIO-based init ram disk
|
* TAR-based init ram disk
|
||||||
* Video driver for Bochs graphics adapter, and the VMware display adapter.
|
* Video driver for Bochs graphics adapter, and the VMware display adapter.
|
||||||
|
|
||||||
## Known bugs
|
## Known bugs
|
||||||
|
@ -26,12 +27,13 @@ The Soaplin kernel is a new Unix-like operating system kernel.
|
||||||
## Building
|
## Building
|
||||||
To build Soaplin, you must ensure you have these:
|
To build Soaplin, you must ensure you have these:
|
||||||
* The Netwide Assembler (nasm)
|
* The Netwide Assembler (nasm)
|
||||||
* A compiler (In the future, a custom toolchain would be built.)
|
* A compiler (both GCC & Clang works!) (In the future, a custom toolchain would be built.)
|
||||||
* A linker
|
* A linker (both GNU LD & LLVM linker works too!)
|
||||||
|
|
||||||
Clone the repo, and run "make" in it!
|
Clone the repo, and run "make" in it!
|
||||||
|
|
||||||
## Acknowledgements
|
## Acknowledgements
|
||||||
Thanks to all these people :heart:
|
Thanks to all these people :heart:
|
||||||
|
* Limine contributors: The Limine bootloader, used for kicking up Soaplin
|
||||||
* Kevin Alavik (kevinalavik): VMAs implementation
|
* Kevin Alavik (kevinalavik): VMAs implementation
|
||||||
* Astrido (asterd-og): IOAPIC/LAPIC (from ZanOS)
|
* Astrido (asterd-og): IOAPIC/LAPIC (from ZanOS)
|
|
@ -58,7 +58,9 @@ override CFLAGS += \
|
||||||
-fno-stack-check \
|
-fno-stack-check \
|
||||||
-fno-PIC \
|
-fno-PIC \
|
||||||
-ffunction-sections \
|
-ffunction-sections \
|
||||||
-fdata-sections
|
-fdata-sections \
|
||||||
|
-fno-omit-frame-pointer \
|
||||||
|
-fno-optimize-sibling-calls
|
||||||
|
|
||||||
# Internal C preprocessor flags that should not be changed by the user.
|
# Internal C preprocessor flags that should not be changed by the user.
|
||||||
override CPPFLAGS := \
|
override CPPFLAGS := \
|
||||||
|
|
|
@ -10,7 +10,7 @@ void __x86_64_syscall_init() {
|
||||||
wrmsr(IA32_EFER, efer);
|
wrmsr(IA32_EFER, efer);
|
||||||
uint64_t star = 0;
|
uint64_t star = 0;
|
||||||
star |= ((uint64_t)0x28 << 32); // kernel cs
|
star |= ((uint64_t)0x28 << 32); // kernel cs
|
||||||
star |= ((uint64_t)0x30 << 48); // user cs base (SYSCALL adds 16 for CS=0x38, 24 for SS=0x40)
|
star |= ((uint64_t)0x30 << 48); // user cs base (SYSCALL adds 16 for CS=0x40, 24 for SS=0x38)
|
||||||
wrmsr(IA32_STAR, star);
|
wrmsr(IA32_STAR, star);
|
||||||
wrmsr(IA32_LSTAR, (uint64_t)syscall_entry);
|
wrmsr(IA32_LSTAR, (uint64_t)syscall_entry);
|
||||||
wrmsr(IA32_CSTAR, 0x0);
|
wrmsr(IA32_CSTAR, 0x0);
|
||||||
|
|
|
@ -57,7 +57,11 @@ struct flanterm_context *ft_ctx;
|
||||||
|
|
||||||
char kstack[8192];
|
char kstack[8192];
|
||||||
|
|
||||||
void kmain(void) {
|
void test3() { *((uint8_t*)0x0) = (uint8_t)0xFF; }
|
||||||
|
void test2() { test3();}
|
||||||
|
void test1() { test2(); }
|
||||||
|
|
||||||
|
void __kmain(void) {
|
||||||
if (framebuffer_request.response != NULL) {
|
if (framebuffer_request.response != NULL) {
|
||||||
|
|
||||||
struct limine_framebuffer *framebuffer =
|
struct limine_framebuffer *framebuffer =
|
||||||
|
@ -97,6 +101,7 @@ void kmain(void) {
|
||||||
|
|
||||||
syscall_init();
|
syscall_init();
|
||||||
sched_init();
|
sched_init();
|
||||||
|
test1();
|
||||||
|
|
||||||
// vfs_init();
|
// vfs_init();
|
||||||
|
|
||||||
|
@ -105,6 +110,7 @@ void kmain(void) {
|
||||||
|
|
||||||
program_t *p = elf_load(module_request.response->modules[0]->address, 1);
|
program_t *p = elf_load(module_request.response->modules[0]->address, 1);
|
||||||
|
|
||||||
|
|
||||||
sched_process *proc =
|
sched_process *proc =
|
||||||
sched_create("Test", p->entry, p->pm, SCHED_USER_PROCESS);
|
sched_create("Test", p->entry, p->pm, SCHED_USER_PROCESS);
|
||||||
|
|
||||||
|
@ -112,6 +118,5 @@ void kmain(void) {
|
||||||
|
|
||||||
pit_enable();
|
pit_enable();
|
||||||
while (1)
|
while (1)
|
||||||
;
|
;;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
10
kernel/src/premain.asm
Normal file
10
kernel/src/premain.asm
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
bits 64
|
||||||
|
section .text
|
||||||
|
global kmain
|
||||||
|
extern __kmain
|
||||||
|
extern kstack
|
||||||
|
|
||||||
|
kmain:
|
||||||
|
mov rsp, kstack+0x2000 ; supposons 16 KiB de stack
|
||||||
|
xor rbp, rbp ; Set %ebp to NULL
|
||||||
|
call __kmain
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "sys/errhnd/panic.h"
|
||||||
#include "arch/x86_64/idt.h"
|
#include "arch/x86_64/idt.h"
|
||||||
#include "lib/spinlock.h"
|
#include "lib/spinlock.h"
|
||||||
#include <mm/memop.h>
|
#include <mm/memop.h>
|
||||||
|
@ -59,7 +60,9 @@ static void __panic_display_page_fault(registers_t *regs) {
|
||||||
uint64_t cr2;
|
uint64_t cr2;
|
||||||
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||||
|
|
||||||
log("Page Fault Details:\n");
|
log("-- PAGE FAULT DETAILS --\n");
|
||||||
|
log("This appears to be a page fault.\n");
|
||||||
|
log("\n");
|
||||||
log("Faulting Address (CR2): 0x%lx\n", cr2);
|
log("Faulting Address (CR2): 0x%lx\n", cr2);
|
||||||
log("Error Code: %d\n", regs->err_code);
|
log("Error Code: %d\n", regs->err_code);
|
||||||
log("Flags:\n");
|
log("Flags:\n");
|
||||||
|
@ -83,6 +86,7 @@ static void __panic_display_page_fault(registers_t *regs) {
|
||||||
|
|
||||||
if (regs->err_code & (1 << 4))
|
if (regs->err_code & (1 << 4))
|
||||||
log(" - Instruction Fetch\n");
|
log(" - Instruction Fetch\n");
|
||||||
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __panic_display_regs(registers_t *regs) {
|
static void __panic_display_regs(registers_t *regs) {
|
||||||
|
@ -96,11 +100,60 @@ static void __panic_display_regs(registers_t *regs) {
|
||||||
regs->rip, regs->cs, regs->ss, regs->rflags, regs->int_no,
|
regs->rip, regs->cs, regs->ss, regs->rflags, regs->int_no,
|
||||||
regs->err_code);
|
regs->err_code);
|
||||||
log("RSP: %p\n", regs->rsp);
|
log("RSP: %p\n", regs->rsp);
|
||||||
|
log("\n");
|
||||||
|
|
||||||
if (regs->int_no == 14) // If it's a page fault
|
if (regs->int_no == 14) // If it's a page fault
|
||||||
__panic_display_page_fault(regs);
|
__panic_display_page_fault(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __panic_display_bt(registers_t *regs) {
|
||||||
|
if (regs->cs == 0x43 || regs->cs == 0x3B) {
|
||||||
|
log("The backtrace can't be dumped from a userspace process.\n");
|
||||||
|
return; // Don't try to backtrace userspace
|
||||||
|
}
|
||||||
|
|
||||||
|
log("-- BACKTRACE --\n");
|
||||||
|
|
||||||
|
// First print the current instruction pointer from the interrupt frame
|
||||||
|
if (regs->rip) {
|
||||||
|
log("* %p (current)\n", regs->rip);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t *frame = (uint64_t*)regs->rbp;
|
||||||
|
if (!frame || (uint64_t)frame < 0xffffffff80000000) {
|
||||||
|
log("No further stack frames available\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frame format in x86_64:
|
||||||
|
// [rbp] -> previous rbp
|
||||||
|
// [rbp+8] -> return address
|
||||||
|
int depth = 0;
|
||||||
|
while (frame && depth < 16) { // Limit depth to avoid infinite loops
|
||||||
|
// Validate both frame and return address pointers
|
||||||
|
uint64_t *ret_addr_ptr = frame + 1;
|
||||||
|
if ((uint64_t)ret_addr_ptr < 0xffffffff80000000) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ret_addr = *ret_addr_ptr;
|
||||||
|
if (ret_addr < 0xffffffff80000000 || ret_addr > 0xfffffffffffff000) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
log("* %p\n", ret_addr);
|
||||||
|
|
||||||
|
uint64_t next_rbp = *frame;
|
||||||
|
if (next_rbp < 0xffffffff80000000 || next_rbp > 0xfffffffffffff000) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame = (uint64_t*)next_rbp;
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
void __panic_display_ascii_art() {
|
void __panic_display_ascii_art() {
|
||||||
log(" _ __ _ ___ _ \n");
|
log(" _ __ _ ___ _ \n");
|
||||||
log("| |/ /___ _ _ _ _ ___| | | _ \\__ _ _ _ (_)__ \n");
|
log("| |/ /___ _ _ _ _ ___| | | _ \\__ _ _ _ (_)__ \n");
|
||||||
|
@ -145,6 +198,8 @@ void panic_ctx(char *msg, registers_t *regs) {
|
||||||
else
|
else
|
||||||
log("No register context provided.\n");
|
log("No register context provided.\n");
|
||||||
|
|
||||||
|
__panic_display_bt(regs);
|
||||||
|
|
||||||
log("System halted: Please restart your computer manually.\n");
|
log("System halted: Please restart your computer manually.\n");
|
||||||
|
|
||||||
asm("cli");
|
asm("cli");
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "arch/x86_64/idt.h"
|
#include "arch/x86_64/idt.h"
|
||||||
|
|
||||||
|
typedef struct __panic_backtrace {
|
||||||
|
struct Idt_StackFrame* rbp;
|
||||||
|
uint64_t rip;
|
||||||
|
} __attribute__((packed)) panic_backtrace_t;
|
||||||
|
|
||||||
void panic(char *msg);
|
void panic(char *msg);
|
||||||
void panic_ctx(char *msg, registers_t *regs);
|
void panic_ctx(char *msg, registers_t *regs);
|
Loading…
Add table
Add a link
Reference in a new issue