diff --git a/kernel/common.S b/kernel/common.S index 31f5c73..aefd570 100644 --- a/kernel/common.S +++ b/kernel/common.S @@ -126,3 +126,8 @@ outsw: fetch_cr3: mov %cr3, %eax ret + +.global kpanic +kpanic: + cli + hlt \ No newline at end of file diff --git a/kernel/common.h b/kernel/common.h index 0cd97ab..45ed218 100644 --- a/kernel/common.h +++ b/kernel/common.h @@ -7,6 +7,8 @@ void enable_interrupts(); void disable_interrupts(); uint32_t fetch_cr3(); +void kpanic(); + void liftoff(uint32_t entry_point, uint32_t user_stack) __attribute__((noreturn)); #endif \ No newline at end of file diff --git a/kernel/interrupts.S b/kernel/interrupts.S index 3ca959f..460a216 100644 --- a/kernel/interrupts.S +++ b/kernel/interrupts.S @@ -59,21 +59,16 @@ isr32: pushal call send_eoi_master - xor %eax, %eax - mov %ds, %ax - pushl %eax + push %ds mov $0x10, %ax mov %ax, %ds - mov %ax, %es pushl %esp call switch_context movl %eax, %esp - popl %eax - mov %ax, %ds - mov %ax, %es + pop %ds popal sti diff --git a/kernel/interrupts.c b/kernel/interrupts.c index cadab17..526b16f 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -6,6 +6,8 @@ #include "syscall.h" #include "common.h" #include "gdt.h" +#include "scheduler.h" +#include "process.h" #include #include @@ -114,8 +116,10 @@ void common_interrupt_handler(intr_regs_t *args) { case 12: case 13: case 15: - case 16: + case 16: { + process_t* task = current_task(); kprintf("\n--- CPU Exception ---\n"); + kprintf("Current Task PID: %d\n", task->pid); kprintf("Error: [%d] %s\n", args->int_no, err_messages[args->int_no]); kprintf("Error Code: 0x%x\n", args->error_code); kprintf("Instruction Pointer: 0x%x\n", args->eip); @@ -127,12 +131,16 @@ void common_interrupt_handler(intr_regs_t *args) { kprintf("Current cr3: 0x%x\n", fetch_cr3()); kprintf("tss.esp0: 0x%x\n", tss.esp0); kprintf("instruction: 0x%x\n", *(uint32_t*)args->eip); - asm volatile("hlt"); + kpanic(); break; + } case 14:{ + disable_interrupts(); uint32_t faulting_address; + process_t* task = current_task(); asm volatile("mov %%cr2, %0" : "=r"(faulting_address)); kprintf("\n--- PAGE FAULT ---\n"); + kprintf("Current Task PID: %d\n", task->pid); kprintf("Faulted Virtual Address: 0x%x\n", faulting_address); kprintf("Error Code: 0x%x\n", args->error_code); kprintf("Instruction Pointer: 0x%x\n", args->eip); @@ -154,7 +162,7 @@ void common_interrupt_handler(intr_regs_t *args) { (args->error_code & 0x01) ? "Protection Violation" : "Page Not Present", (args->error_code & 0x02) ? "Write" : "Read", (args->error_code & 0x04) ? "User" : "Supervisor"); - asm volatile("hlt"); + kpanic(); break; } case 32: { diff --git a/kernel/kmain.c b/kernel/kmain.c index 6dc5a9d..6020952 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -57,9 +57,10 @@ vfs_node_t* load_initrd() { } void load_root_program(const char* path) { - disable_interrupts(); + lock_scheduler(); uint32_t kernel_cr3 = fetch_cr3(); void* cr3 = create_task_pd(); + load_pd(cr3); flush_tlb(); @@ -132,7 +133,8 @@ void load_root_program(const char* path) { process_t* process = kalloc(sizeof(process_t)); init_task(process, e_hdr->e_entry, (uint32_t)cr3, 1, (uint32_t)u_esp); add_task(process); - enable_interrupts(); + + unlock_scheduler(); load_pd((void*)kernel_cr3); flush_tlb(); @@ -177,4 +179,6 @@ void kmain(uint32_t magic, multiboot_info* mbi) { kprintf("loading test program\n"); load_root_program("/test.elf"); + + kprintf("kernel going to sleep...\n"); } diff --git a/kernel/memory/mm.c b/kernel/memory/mm.c index 1814e83..5735e04 100644 --- a/kernel/memory/mm.c +++ b/kernel/memory/mm.c @@ -2,7 +2,7 @@ #include "multiboot.h" #include -#include +#include extern uint8_t __kernel_start; extern uint8_t __kernel_end; diff --git a/kernel/scheduler.c b/kernel/scheduler.c index 700bc0c..0e9f248 100644 --- a/kernel/scheduler.c +++ b/kernel/scheduler.c @@ -17,34 +17,20 @@ static process_t* idle_task = NULL; static int total_processes = 0; -static void lock_scheduler() { +void lock_scheduler() { disable_interrupts(); } -static void unlock_scheduler() { +void unlock_scheduler() { enable_interrupts(); } uint32_t switch_context(uint32_t current_esp) { current_process->esp = current_esp; - for (int i = 0; i < total_processes; i++) { - if (process_table[i].state == STATE_SLEEPING) { - if (process_table[i].sleep > 0) { - process_table[i].sleep--; - } - - if (process_table[i].sleep == 0) { - process_table[i].state = STATE_READY; - } - } - } - - process_t* next_process = current_process; + process_t* next_process = current_process->sched_next; int found_ready = 0; - - while (1) { - next_process = (process_t*)next_process->sched_next; + while (next_process != NULL) { if (next_process != idle_task && next_process->state == STATE_READY) { found_ready = 1; break; @@ -53,10 +39,12 @@ uint32_t switch_context(uint32_t current_esp) { if (next_process == current_process) { break; } + + next_process = (process_t*)next_process->sched_next; } if (!found_ready) { - if (current_process->state == STATE_READY) { + if (current_process && current_process->state == STATE_READY) { next_process = current_process; } else { next_process = idle_task; @@ -68,6 +56,7 @@ uint32_t switch_context(uint32_t current_esp) { uint32_t current_cr3 = fetch_cr3(); if (current_cr3 != current_process->cr3) { load_pd((void*)current_process->cr3); + flush_tlb(); } if (current_process->flags & PROCESS_FLAG_USER) { @@ -145,25 +134,19 @@ void init_task ( } int get_next_pid() { - lock_scheduler(); int pid = total_processes; total_processes++; - unlock_scheduler(); return pid; } void add_task(process_t* task) { - lock_scheduler(); - if (!task) { - unlock_scheduler(); return; } if (process_table->sched_next == NULL) { process_table->sched_next = task; task->sched_next = process_table; - unlock_scheduler(); return; } @@ -174,37 +157,27 @@ void add_task(process_t* task) { curr->sched_next = task; task->sched_next = process_table; - - unlock_scheduler(); } process_t* current_task() { - lock_scheduler(); process_t* rtn = current_process; - unlock_scheduler(); return rtn; } void sleep(uint32_t ms) { if (ms == 0) return; - lock_scheduler(); current_process->sleep = ms; current_process->state = STATE_SLEEPING; yield(); - unlock_scheduler(); } void exit() { - lock_scheduler(); current_process->state = STATE_DEAD; yield(); // yield forever - unlock_scheduler(); } void wake(process_t* task) { - lock_scheduler(); if (task->state == STATE_SLEEPING || task->state == STATE_BLOCKED) { task->state = STATE_READY; } - unlock_scheduler(); } \ No newline at end of file diff --git a/kernel/scheduler.h b/kernel/scheduler.h index e9b3ffc..d9fab39 100644 --- a/kernel/scheduler.h +++ b/kernel/scheduler.h @@ -4,6 +4,9 @@ #include "process.h" #include +void lock_scheduler(); +void unlock_scheduler(); + void init_scheduler(); void init_task(process_t* process, uint32_t entry_point, uint32_t cr3, int user, uint32_t u_esp); diff --git a/kernel/syscall.S b/kernel/syscall.S index 931e612..3663c5b 100644 --- a/kernel/syscall.S +++ b/kernel/syscall.S @@ -4,33 +4,16 @@ syscall_handler: cli - push $0 - push $0x80 - - pusha - + pushal push %ds - push %es - push %fs - push %gs mov $0x10, %ax mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs push %esp - call syscall + call syscall add $4, %esp - - mov 28(%esp), %eax - pop %gs - pop %fs - pop %es pop %ds - - popa - add $8, %esp + popal iret \ No newline at end of file diff --git a/kernel/syscall.c b/kernel/syscall.c index 7292b7a..74af192 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -2,7 +2,6 @@ #include #include -#include "common.h" #include "lib/memory.h" #include "lib/ringbuf.h" #include "memory/mm.h" @@ -16,11 +15,10 @@ #include typedef struct registers { - uint32_t gs, fs, es, ds; // Pushed manually - uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha - uint32_t int_no, err_code; // Pushed manually - uint32_t eip, cs, eflags, useresp, ss; // Pushed automatically by CPU -} registers_t; + uint32_t ds; // push %ds + uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // pushal + uint32_t eip, cs, eflags, useresp, ss; // pushed by cpu +} __attribute__((packed)) registers_t; static int32_t sys_exit(int status) { process_t* task = current_task(); @@ -126,7 +124,7 @@ static int32_t sys_pty(int* slave_fd) { static int32_t sys_fork(registers_t* parent_regs) { process_t* parent = current_task(); - + process_t* child = kalloc(sizeof(process_t)); if (!child) { return -1; @@ -142,36 +140,37 @@ static int32_t sys_fork(registers_t* parent_regs) { child->fd_table[i] = parent->fd_table[i]; } - disable_interrupts(); - uint32_t kstack_size = 4096; void* kstack_alloc = kalloc(kstack_size); child->kstack_top = (uint32_t)kstack_alloc + kstack_size; - - child->cr3 = (uint32_t)clone_task_pd(); registers_t* child_regs = (registers_t*)(child->kstack_top - sizeof(registers_t)); - memcpy(child_regs, parent_regs, sizeof(registers_t)); + memcpy(parent_regs, child_regs, sizeof(registers_t)); child_regs->eax = 0; child->esp = (uint32_t)child_regs; - enable_interrupts(); + kprintf("child registers for PID %d\n", child->pid); + kprintf("\tEIP: 0x%x\n", child_regs->eip); + + // uint32_t cr3 = (uint32_t)clone_task_pd(); + child->cr3 = parent->cr3; add_task(child); return child->pid; } -int32_t syscall(registers_t* regs) { +void syscall(registers_t* regs) { + int32_t ret; switch(regs->eax) { - case 1: return sys_exit(regs->ebx); - case 3: return sys_read(regs->ebx, (void*)regs->ecx, regs->edx); - case 4: return sys_write(regs->ebx, (const void*)regs->ecx, regs->edx); - case 5: return sys_open((const char*)regs->ebx, regs->ecx); - case 6: return sys_close(regs->ebx); - case 12: return sys_brk(regs->ebx); - case 20: return sys_pty((int*)regs->ebx); - case 21: return sys_fork(regs); - default: - return -1; + case 1: ret = sys_exit(regs->ebx); break; + case 3: ret = sys_read(regs->ebx, (void*)regs->ecx, regs->edx); break; + case 4: ret = sys_write(regs->ebx, (const void*)regs->ecx, regs->edx); break; + case 5: ret = sys_open((const char*)regs->ebx, regs->ecx); break; + case 6: ret = sys_close(regs->ebx); break; + case 12: ret = sys_brk(regs->ebx); break; + case 20: ret = sys_pty((int*)regs->ebx); break; + case 21: ret = sys_fork(regs); break; + default: ret = -1; } + regs->eax = ret; } \ No newline at end of file diff --git a/programs/lib/rlibc.a b/programs/lib/rlibc.a index f41ac65..eb5773c 100644 Binary files a/programs/lib/rlibc.a and b/programs/lib/rlibc.a differ diff --git a/programs/test/main.c b/programs/test/main.c index c786f2b..cadd0ee 100644 --- a/programs/test/main.c +++ b/programs/test/main.c @@ -4,9 +4,10 @@ int main(int argc, char *argv[]) { (void)argc; (void)argv; - if (!fork()) { - exit(1); + int fk = 0; + if ((fk = fork()) > 0) { + return fk; } - + return 0; } \ No newline at end of file diff --git a/rocklibc/src/syscall.c b/rocklibc/src/syscall.c index e06c253..1dc0da9 100644 --- a/rocklibc/src/syscall.c +++ b/rocklibc/src/syscall.c @@ -11,7 +11,6 @@ static inline int syscall1(int num, uint32_t arg1) { return ret; } -/* A generic wrapper for a system call with 3 arguments */ static inline int syscall3(int num, uint32_t arg1, uint32_t arg2, uint32_t arg3) { int ret; asm volatile (