diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/drivers/interrupts.c | 38 | ||||
-rw-r--r-- | kernel/features/load.c | 13 | ||||
-rw-r--r-- | kernel/features/mm.c | 32 | ||||
-rw-r--r-- | kernel/features/proc.c | 11 | ||||
-rw-r--r-- | kernel/inc/interrupts.h | 1 | ||||
-rw-r--r-- | kernel/inc/load.h | 2 | ||||
-rw-r--r-- | kernel/main.c | 5 |
7 files changed, 70 insertions, 32 deletions
diff --git a/kernel/drivers/interrupts.c b/kernel/drivers/interrupts.c index fa455d7..55926b7 100644 --- a/kernel/drivers/interrupts.c +++ b/kernel/drivers/interrupts.c @@ -169,26 +169,30 @@ void isr_uninstall_handler(int isr) isr_routines[isr] = 0; } -void isr_handler(struct regs *r); -void isr_handler(struct regs *r) +void isr_panic(struct regs *r) { - if (r->int_no <= 32) { - struct proc *proc = proc_current(); - printf("%s Exception at 0x%x, exiting!\n", isr_exceptions[r->int_no], r->eip); - if (proc) { - printf("\t-> Exception occurred in %s at addr 0x%x\n", proc->name, - r->eip - proc->entry); - proc_exit(proc, 1); - } else { - __asm__ volatile("cli\nhlt"); - } - proc_yield(r); + struct proc *proc = proc_current(); + printf("%s Exception (%x) at 0x%x, exiting!\n", isr_exceptions[r->int_no], r->err_code, + r->eip); + if (proc) { + printf("\t-> Exception occurred in %s at addr 0x%x\n", proc->name, + r->eip - proc->entry); + proc_exit(proc, 1); } else { - // Execute fault handler if exists - void (*handler)(struct regs * r) = isr_routines[r->int_no]; - if (handler) - handler(r); + __asm__ volatile("cli\nhlt"); } + proc_yield(r); +} + +void isr_handler(struct regs *r); +void isr_handler(struct regs *r) +{ + // Execute fault handler if exists + void (*handler)(struct regs * r) = isr_routines[r->int_no]; + if (handler) + handler(r); + else + isr_panic(r); } static void isr_install(void) diff --git a/kernel/features/load.c b/kernel/features/load.c index 610abf8..4b3f8ea 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -8,16 +8,15 @@ #define PROC_STACK_SIZE 0x4000 -void proc_load(struct proc *proc, void *data) +void proc_load(struct proc *proc, u32 entry) { u32 stack; memory_alloc(proc->page_dir, PROC_STACK_SIZE, MEMORY_CLEAR, &stack); - u32 ptr = stack + PROC_STACK_SIZE - 1; - proc->regs.ebp = (u32)ptr; - proc->regs.useresp = (u32)ptr; - proc->regs.eip = (u32)data; - proc->entry = (u32)data; + proc->regs.ebp = stack; + proc->regs.useresp = stack; + proc->regs.eip = entry; + proc->entry = entry; } int bin_load(const char *path, struct proc *proc) @@ -30,7 +29,7 @@ int bin_load(const char *path, struct proc *proc) return 1; strcpy(proc->name, path); - proc_load(proc, (void *)data); + proc_load(proc, data); return 0; } diff --git a/kernel/features/mm.c b/kernel/features/mm.c index ccc2727..ad70685 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -25,6 +25,7 @@ void paging_enable(void) void paging_switch_dir(u32 dir) { + assert(dir); cr3_set(dir); } @@ -418,7 +419,7 @@ void memory_initialize(struct mem_info *mem_info) memory_map_identity(&kernel_dir, memory_range_around_address(HEAP_START, HEAP_INIT_SIZE), MEMORY_NONE); - // TODO: Map something, idk? Triple fault prevention? + // TODO: Triple fault prevention? Probably bootloader stuff or something memory_map_identity(&kernel_dir, memory_range_around_address(0x7000, 0x1000), MEMORY_NONE); // Unmap NULL byte/page @@ -429,8 +430,37 @@ void memory_initialize(struct mem_info *mem_info) paging_enable(); } +static void page_fault(struct regs *r) +{ + // Check error code + const char *type = (r->err_code & 4) ? "present" : "non-present"; + const char *operation = (r->err_code & 2) ? "write" : "read"; + const char *super = (r->err_code & 1) ? "User" : "Super"; + + // Check cr2 address + u32 vaddr; + __asm__ volatile("movl %%cr2, %%eax" : "=a"(vaddr)); + struct proc *proc = proc_current(); + struct page_dir *dir = NULL; + if (proc && proc->page_dir) { + dir = proc->page_dir; + printf("Stack is at %x, entry at %x\n", virtual_to_physical(dir, proc->regs.ebp), + virtual_to_physical(dir, proc->entry)); + } else { + dir = &kernel_dir; + } + u32 paddr = virtual_to_physical(dir, vaddr); + + // Print! + printf("%s process tried to %s a %s page at [vaddr=%x; paddr=%x]\n", super, operation, type, + vaddr, paddr); + + isr_panic(r); +} + void paging_install(struct mem_info *mem_info) { memory_initialize(mem_info); heap_init(HEAP_START); + isr_install_handler(14, page_fault); } diff --git a/kernel/features/proc.c b/kernel/features/proc.c index bbe675e..43cedb6 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -20,7 +20,7 @@ struct list *proc_list = NULL; struct node *idle_proc = NULL; struct node *current = NULL; -// TODO: Use less memcpy and only copy relevant registers +// TODO: Use less memcpy and only copy relevant registers (rewrite for efficiency argh) // TODO: 20 priority queues (https://www.kernel.org/doc/html/latest/scheduler/sched-nice-design.html) void scheduler(struct regs *regs) { @@ -57,8 +57,8 @@ void scheduler(struct regs *regs) } } - memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs)); memory_dir_switch(((struct proc *)current->data)->page_dir); + memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs)); if (regs->cs != GDT_USER_CODE_OFFSET) { regs->gs = GDT_USER_DATA_OFFSET; @@ -473,8 +473,7 @@ void proc_init(void) // Idle proc struct proc *kernel_proc = proc_make(PROC_PRIV_NONE); - void (*func)(void) = kernel_idle; - proc_load(kernel_proc, *(void **)&func); + proc_load(kernel_proc, (u32)kernel_idle); strcpy(kernel_proc->name, "idle"); kernel_proc->state = PROC_SLEEPING; idle_proc = list_add(proc_list, kernel_proc); @@ -494,11 +493,11 @@ void proc_init(void) argv[2] = NULL; ((u32 *)_esp)[0] = argc; // First argument (argc) - ((u32 *)_esp)[1] = (u32)argv; // Second argument (argv) + ((u32 *)_esp)[-1] = (u32)argv; // Second argument (argv) printf("Jumping to userspace!\n"); - proc_jump_userspace(); memory_dir_switch(((struct proc *)new->data)->page_dir); + proc_jump_userspace(); while (1) { }; } diff --git a/kernel/inc/interrupts.h b/kernel/inc/interrupts.h index 30c91c3..fc00402 100644 --- a/kernel/inc/interrupts.h +++ b/kernel/inc/interrupts.h @@ -32,6 +32,7 @@ void irq_uninstall_handler(int irq); void isr_install_handler(int isr, void (*handler)(struct regs *r)); void isr_uninstall_handler(int isr); +void isr_panic(struct regs *r); void interrupts_install(void); diff --git a/kernel/inc/load.h b/kernel/inc/load.h index 407fbeb..330caca 100644 --- a/kernel/inc/load.h +++ b/kernel/inc/load.h @@ -5,7 +5,7 @@ #include <proc.h> -void proc_load(struct proc *proc, void *data); +void proc_load(struct proc *proc, u32 entry); int bin_load(const char *path, struct proc *proc); #endif diff --git a/kernel/main.c b/kernel/main.c index b46db0d..2e2e030 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -7,6 +7,7 @@ #include <interrupts.h> #include <keyboard.h> #include <load.h> +#include <mem.h> #include <mm.h> #include <mouse.h> #include <net.h> @@ -21,6 +22,10 @@ struct vid_info *boot_passed; void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info); // Decl void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info) { + // Clear stack + for (u32 i = 0; i < STACK_SIZE; i++) + ((u8 *)STACK_START)[-i] = 0; + // Serial connection serial_install(); serial_print("\nKernel was compiled at " __TIME__ " on " __DATE__ "\n"); |