Add stack frame to panic

This commit is contained in:
ssimnb 2026-02-01 14:55:30 +01:00
parent b337e5193b
commit cfcb806ebf
16 changed files with 169 additions and 103 deletions

View file

@ -20,7 +20,8 @@ CFLAGS += -Wall \
-I src/include \
-O0 \
-ggdb3 \
-g
-g \
#-fno-omit-frame-pointer
CDEBUG = -g
LDFLAGS += -m elf_x86_64 \
-nostdlib \
@ -78,14 +79,12 @@ all:
$(AS) src/scheduler/sched.asm -o $(BUILD_DIR)/sched_asm.o $(NASMFLAGS)
# link everything to an elf
$(LD) -o $(BUILD_DIR)/SFB25.elf $(BUILD_DIR)/*.o $(LDFLAGS)
$(LD) -o $(BUILD_DIR)/Neobbo.elf $(BUILD_DIR)/*.o $(LDFLAGS)
# Create a directory which will be our ISO root.
mkdir -p iso_root
# Copy the relevant files over.
cp -v $(BUILD_DIR)/SFB25.elf limine.conf limine/limine-bios.sys \
cp -v $(BUILD_DIR)/Neobbo.elf limine.conf limine/limine-bios.sys \
limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/
# Create the EFI boot tree and copy Limine's EFI executables over.
mkdir -p iso_root/EFI/BOOT

View file

@ -126,10 +126,14 @@ void ap_apic_init(){
}
void apic_timer_handler(){
//kprintf("hii\n");
lapic_write_reg(LAPIC_EOI_REG, 0);
if(get_cpu_struct_initialized()){
get_cpu_struct()->lapic_timer_ticks++;
}
}
void apic_send_ipi(uint8_t dest_field, uint8_t dest_shorthand, uint8_t trigger, uint8_t level, uint8_t status, uint8_t destination, uint8_t delivery_mode, uint8_t vector){

View file

@ -2,6 +2,8 @@ default rel
extern interrupt_handler
global next_frame
extern idtr
global s_isr0
@ -328,3 +330,7 @@ s_load_idt:
sti
ret
next_frame:
mov rax, [rdi]
ret

View file

@ -1,5 +1,6 @@
#include "idt.h"
#include "error.h"
#include "smp.h"
#include "timer.h"
#include <kprint.h>
#include <lock.h>
@ -200,15 +201,30 @@ char *exception_messages[] =
"Reserved"
};
extern void *next_frame(void *addr);
void interrupt_handler(interrupt_frame *r){
if(r->int_no < 32){
kprintf("\nOh no! Received interrupt {d}, '{s}'. Below is the provided stack frame{n}{n}", r->int_no, exception_messages[r->int_no]);
kprintf("\nOh no! Received interrupt {d}, '{s}'. Below is the provided stack frame\n\n", r->int_no, exception_messages[r->int_no]);
if(r->err != 0){
kprintf("error code 0x{xn}", r->err);
kprintf("rax 0x{x} | rbx 0x{x} | rcx 0x{x} | rdx 0x{xn}", r->rax, r->rbx, r->rcx, r->rdx);
kprintf("rdi 0x{x} | rsi 0x{x} | rbp 0x{xn}", r->rdi, r->rsi, r->rbp);
kprintf("r8 0x{x} | r9 0x{x} | r10 0x{x} | r11 0x{x} | r12 0x{x} | r13 0x{x} | r14 0x{x} | r15 0x{xn}", r->r8, r->r9, r->r10, r->r11, r->r12, r->r13, r->r14, r->r15);
kprintf("rip 0x{x} | cs 0x{x} | ss 0x{x} | rsp 0x{x} | rflags 0x{xn}", r->rip, r->cs, r->ss, r->rsp, r->rflags);
}
kprintf("rax 0x{x} | rbx 0x{x} | rcx 0x{x} | rdx 0x{x}\n", r->rax, r->rbx, r->rcx, r->rdx);
kprintf("rdi 0x{x} | rsi 0x{x} | rbp 0x{x}\n", r->rdi, r->rsi, r->rbp);
kprintf("r8 0x{x} | r9 0x{x} | r10 0x{x} | r11 0x{x} | r12 0x{x} | r13 0x{x} | r14 0x{x} | r15 0x{x}\n", r->r8, r->r9, r->r10, r->r11, r->r12, r->r13, r->r14, r->r15);
kprintf("rip 0x{x} | cs 0x{x} | ss 0x{x} | rsp 0x{x} | rflags 0x{x}\n", r->rip, r->cs, r->ss, r->rsp, r->rflags);
kprintf("\nStack frame:\n");
struct stack_frame *f = __builtin_frame_address(0);
int i = 0;
while(f != NULL && i < 10){
kprintf("{d}: 0x{x}\n", i, f->rip);
f = (stack_frame *)f->rbp;
i++;
}
kkill();
for(;;);
}
@ -220,6 +236,12 @@ void interrupt_handler(interrupt_frame *r){
if(r->int_no == 69){
apic_timer_handler();
}
if(r->int_no == 69 && get_cpu_struct_initialized()
&& get_cpu_struct()->scheduler_initialized){
enter_scheduler();
}
if(r->int_no == 70){
for(;;){
asm("cli;hlt");

View file

@ -23,6 +23,11 @@ typedef struct interrupt_frame {
uint64_t rip, cs, rflags, rsp, ss;
} __attribute((packed)) interrupt_frame;
typedef struct stack_frame {
struct stack_frame *rbp;
uint64_t rip;
}__attribute((packed)) stack_frame;
typedef struct irq_t {
void *base;
bool in_use;

View file

@ -65,6 +65,8 @@ void ap_init(struct limine_smp_info *smp_info){
memset(cpu_struct, 0, sizeof(cpu_state));
cpu_struct->lapic_id = smp_info->lapic_id;
cpu_struct->scheduler_context = (context*)kmalloc(sizeof(context));
wrmsr(KERNELGSBASE, (uint64_t)cpu_struct);
wrmsr(GSBASE, (uint64_t)cpu_struct);
@ -100,6 +102,8 @@ void smp_init(){
cpu_state *cpu_struct = (cpu_state*)kmalloc(sizeof(cpu_state));
cpu_struct->lapic_id = smp_response->cpus[0]->lapic_id;
cpu_struct->scheduler_context = (context*)kmalloc(sizeof(context));
wrmsr(KERNELGSBASE, (uint64_t)cpu_struct);
wrmsr(GSBASE, (uint64_t)cpu_struct);

View file

@ -13,8 +13,9 @@ typedef struct cpu_state {
proc process_list[PROC_MAX];
proc *current_process;
uint16_t process_count;
context scheduler_context;
}__attribute((packed))cpu_state;
context *scheduler_context;
bool scheduler_initialized;
}cpu_state;
void smp_init();
cpu_state *get_cpu_struct();

View file

@ -51,7 +51,7 @@ atomic_flag printf_lock = ATOMIC_FLAG_INIT;
int kprintf(const char *format_string, ...){
extern struct flanterm_context *ft_ctx;
//acquire_spinlock(&printf_lock);
acquire_spinlock(&printf_lock);
int state = NORMAL;
va_list a_list;
va_start(a_list, format_string);
@ -114,7 +114,7 @@ int kprintf(const char *format_string, ...){
}
va_end(a_list);
//free_spinlock(&printf_lock);
free_spinlock(&printf_lock);
return 0;
}

View file

@ -84,6 +84,7 @@ void _start(void){
serial_init();
krand_init();
set_gdt();
set_idt();
@ -98,7 +99,6 @@ void _start(void){
klog("pmm", "Setting up the PMM");
pmm_init();
klog("vmm", "Setting up the page tables");
vmm_init();
@ -109,7 +109,6 @@ void _start(void){
klog("smp", "Starting APs");
smp_init();
klog("pci", "Getting le pci");
pci_init();

View file

@ -2,6 +2,7 @@
#include <stddef.h>
#include <kprint.h>
#include <kmath.h>
#include <string.h>
struct ma_kcache *kmalloc_caches[14] = {0};
// Create various sizes of caches to be used by kmalloc
@ -26,7 +27,7 @@ size_t sizes[14] = {16, 32, 64, 128, 256, 512, 1024, 4096, 8192, 32768, 65536, 1
void *kmalloc(size_t size){
if(size > 1048576){
klog(__func__, "Attempted to allocate {d} bytes, more than max size (1M)");
klog(__func__, "Attempted to allocate more than max size (1M)");
return NULL;
}
@ -46,6 +47,15 @@ void *kmalloc(size_t size){
}
void *kzalloc(size_t size){
void *addr = kmalloc(size);
if(addr == NULL){
return NULL;
}
memset(addr, 0, size);
return addr;
}
kstatus kfree(void *addr){
return ma_cache_dealloc(addr);
}

View file

@ -1,7 +1,9 @@
#include "error.h"
#include <stddef.h>
#include <stdint.h>
void _kmalloc_init(void);
void *kmalloc(uint64_t size);
void *kmalloc(size_t size);
void *kzalloc(size_t size);
kstatus kfree(void *addr);

View file

@ -113,6 +113,8 @@ kstatus _ma_alloc_slab(struct ma_kcache *kcache){
}
}
//asm("int $1");
if(kcache->slabs_free == NULL){
kcache->slabs_free = slab_structure;
}else{
@ -127,8 +129,10 @@ kstatus _ma_alloc_slab(struct ma_kcache *kcache){
return KERNEL_STATUS_SUCCESS;
}
// fix this complicated POS
void _ma_move_slab(struct ma_slab *slab, enum SLAB_STATE newstate){
struct ma_kcache *cache = slab->cache;
struct ma_slab *sb = 0;
switch (newstate) {
@ -199,6 +203,10 @@ void _ma_move_slab(struct ma_slab *slab, enum SLAB_STATE newstate){
}
free_common:
slab->next = NULL;
slab->prev = NULL;
// Preserve the linkage
if(sb->prev != NULL){
if(sb->next != NULL){
@ -216,6 +224,10 @@ void _ma_move_slab(struct ma_slab *slab, enum SLAB_STATE newstate){
return;
partial_common:
slab->next = NULL;
slab->prev = NULL;
if(sb->prev != NULL){
if(sb->next != NULL){
sb->next->prev = sb->prev;
@ -232,6 +244,9 @@ void _ma_move_slab(struct ma_slab *slab, enum SLAB_STATE newstate){
return;
used_common:
slab->next = NULL;
slab->prev = NULL;
if(sb->prev != NULL){
if(sb->next != NULL){
sb->next->prev = sb->prev;

View file

@ -12,7 +12,7 @@ struct ma_bufctl {
struct ma_bufctl *next;
size_t *startaddr;
};
// ADD COLORING
struct ma_slab {
struct ma_kcache *cache;

View file

@ -3,59 +3,40 @@ global switch_context
global get_context
global restore_stack
; switch_context(struct context *old, struct context *new)
; switch_context(struct context **old, *struct context new)
; ^RDI ^RSI
switch_context:
pop r8 ; Fetch RIP from stack
; Save callee-saved registers to the old struct
mov [rdi + 0x00], rbx
mov [rdi + 0x08], rsp
mov [rdi + 0x10], rbp
mov [rdi + 0x18], r12
mov [rdi + 0x20], r13
mov [rdi + 0x28], r14
mov [rdi + 0x30], r15
mov [rdi + 0x38], r8
; Load the new context
mov rbx, [rsi + 0x00]
mov rsp, [rsi + 0x08]
mov rbp, [rsi + 0x10]
mov r12, [rsi + 0x18]
mov r13, [rsi + 0x20]
mov r14, [rsi + 0x28]
mov r15, [rsi + 0x30]
push rdi
push rsi
push rdx
push rcx
push rbx
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
jmp [rsi + 0x38]
mov [rdi], rsp
mov rsp, rsi
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rbx
pop rcx
pop rdx
pop rsi
pop rdi
ret
; get_context(struct context *ctx)
get_context:
pop r8 ; Fetch RIP from stack
; Save callee-saved registers to the old struct
mov [rdi + 0x00], rbx
mov [rdi + 0x08], rsp
mov [rdi + 0x10], rbp
mov [rdi + 0x18], r12
mov [rdi + 0x20], r13
mov [rdi + 0x28], r14
mov [rdi + 0x30], r15
mov [rdi + 0x38], r8
push r8
ret
; restore_stack(uint64_t rsp, uint64_t rbp)
restore_stack:
mov rsp, rdi
mov rbp, rsi
ret

View file

@ -7,23 +7,29 @@
#include "../mm/kmalloc.h"
#include "sched.h"
extern void get_context(struct context *ctx);
extern void switch_context(context **old, context *new);
extern void switch_context(context *old, context *new);
extern void restore_stack(uint64_t rsp, uint64_t rbp);
#define QUANTUM_US 10000
int next_pid = 1;
void idle_task(){
kprintf("Hello world from idle task!\n");
for(;;){
kprintf("Idle!!1\n");
}
}
void test_task(){
for(;;){
kprintf("Hello world from scheduled task!\n");
return;
}
}
void best_task(){
for(;;){
kprintf("Hello world I am best\n");
}
}
/* Setup a process structure */
@ -36,12 +42,17 @@ proc *alloc_process(void){
p->state = READY;
p->kstack = kmalloc(INITIAL_STACK_SIZE);
p->kstack = kzalloc(8 * 4096);
p->pid = next_pid++;
p->context.rbp = (uint64_t)p->kstack;
p->context.rsp = (uint64_t)p->context.rbp + INITIAL_STACK_SIZE;
uint64_t *sp = (uint64_t*)((uint64_t)p->kstack + 8 * 4096);
// Allocate space for context
sp -= sizeof(context)/sizeof(uint64_t);
p->context = (context*)sp;
p->context->rbp = (uint64_t)p->kstack;
return p;
}
@ -49,8 +60,10 @@ proc *alloc_process(void){
klog(__func__, "Couldnt find free process!!!!!!\n");
return NULL;
}
proc *add_task(uint64_t *entry){
proc *add_process(uint64_t *entry){
proc *proc = alloc_process();
if (proc == NULL) {
@ -58,29 +71,31 @@ proc *add_task(uint64_t *entry){
kkill();
}
proc->context.rip = (uint64_t)entry;
proc->context->rip = (uint64_t)entry;
kprintf("entry: 0x{xn}", entry);
return proc;
}
void scheduler_init(){
if(!get_cpu_struct_initialized()){
kprintf("sched: cpu struct not initialized!");
klog(__func__, "CPU struct not initialized!");
kkill();
}
cpu_state *state = get_cpu_struct();
if(state->current_process != NULL){
kprintf("sched: scheduler on CPU {d} already initialized!\n", state->lapic_id);
kkill();
kprintf("scheduler on CPU {d} already initialized!\n", state->lapic_id);
return;
}
proc *proc_list = state->process_list;
memset(proc_list, 0, sizeof(proc) * 512);
proc *idle = add_task((uint64_t*)idle_task);
proc *idle = add_process((uint64_t*)idle_task);
if(idle == NULL){
klog(__func__, "Failed to allocate idle task");
@ -89,27 +104,30 @@ void scheduler_init(){
state->current_process = idle;
add_task((uint64_t*)test_task);
add_process((uint64_t*)test_task);
add_process((uint64_t *)best_task);
state->scheduler_initialized = true;
int i = 0;
for(;;){
for(int i = 0; i < PROC_MAX; i++){
for(; i < PROC_MAX; i++){
if(proc_list[i].state == READY){
context old_state = state->current_process->context;
proc *prev = state->current_process;
prev->state = READY;
state->current_process = &proc_list[i];
state->current_process->state = RUNNING;
switch_context(&(get_cpu_struct()->scheduler_context), get_cpu_struct()->current_process->context);
get_context(&state->scheduler_context);
switch_context(&old_state, &state->current_process->context);
}
}
i = 1;
}
}
void scheduler_tick(){
cpu_state *state = get_cpu_struct();
proc *proc_list = state->process_list;
switch_context(&state->current_process->context, &state->scheduler_context);
void enter_scheduler(){
switch_context(&get_cpu_struct()->current_process->context, (get_cpu_struct()->scheduler_context));
}

View file

@ -10,19 +10,19 @@ typedef enum proc_state {
}proc_state;
typedef struct context {
uint64_t rbx, rsp, rbp, r12, r13, r14, r15;
uint64_t rip;
} __attribute((packed))context;
uint64_t r15, r14, r13, r12, r11, r10, r9, r8, rbp, rbx, rcx, rdx, rsi, rdi, rip;
} context;
typedef struct proc {
uint64_t *mem;
uint64_t *kstack;
proc_state state;
uint16_t pid;
context context;
context *context;
}proc;
void scheduler_init();
void enter_scheduler();
#define PROC_MAX 512 // Max number of processes