From 437bd0e75104056ece3c374ff9ee16486e114b1d Mon Sep 17 00:00:00 2001 From: xamidev Date: Fri, 3 Apr 2026 18:45:12 +0200 Subject: [PATCH] process_create_user --- include/sched/process.h | 2 +- src/arch/x86/idt.c | 5 ++--- src/kmain.c | 15 ++++++--------- src/mem/vmm.c | 10 ++++++---- src/sched/process.c | 39 ++++++++++++++++++++++++++++++++------- src/sched/scheduler.c | 24 +++++++++++++----------- 6 files changed, 60 insertions(+), 35 deletions(-) diff --git a/include/sched/process.h b/include/sched/process.h index ef00d3e..13fe331 100644 --- a/include/sched/process.h +++ b/include/sched/process.h @@ -38,6 +38,6 @@ void process_exit(void); void process_display_list(struct process* processes_list); -void process_create_user(struct limine_file* file); +void process_create_user(struct limine_file* file, char* name); #endif diff --git a/src/arch/x86/idt.c b/src/arch/x86/idt.c index 4a29524..a319c95 100644 --- a/src/arch/x86/idt.c +++ b/src/arch/x86/idt.c @@ -264,10 +264,9 @@ struct cpu_status* interrupt_dispatch(struct cpu_status* context) // Send an EOI so that we can continue having interrupts outb(0x20, 0x20); - // Scheduler is temporarily disabled to test user trampoline - /* if (ticks % SCHEDULER_QUANTUM == 0) { + if (ticks % SCHEDULER_QUANTUM == 0) { return scheduler_schedule(context); - } */ + } break; diff --git a/src/kmain.c b/src/kmain.c index 89bd3b0..ccbd883 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -118,22 +118,19 @@ void kmain() process_init(); idle_proc = process_create("idle", (void*)idle_main, 0); - process_create("pedicel", (void*)pedicel_main, 0); - - scheduler_init(); if (!boot_ctx.module) { panic(NULL, "could not load 'hello' executable :("); } + if (boot_ctx.module->module_count == 1) { + file = boot_ctx.module->modules[0]; + DEBUG("file: addr=%p size=%u", file->address, file->size); + process_create_user(file, "hello"); + } + scheduler_init(); printf(PEPPEROS_SPLASH); init.all = true; - if (boot_ctx.module->module_count == 1) { - file = boot_ctx.module->modules[0]; - DEBUG("file: addr=%p size=%u", file->address, file->size); - process_create_user(file); - } - idle(); } diff --git a/src/mem/vmm.c b/src/mem/vmm.c index d17970a..2c851de 100644 --- a/src/mem/vmm.c +++ b/src/mem/vmm.c @@ -246,17 +246,19 @@ uintptr_t vmm_alloc_user_stack(uint64_t* pml4) for (size_t i=stack_top; i>stack_top-stack_size; i-=PAGE_SIZE) { vmm_map(pml4, i, PTE_PRESENT | PTE_WRITABLE | PTE_USER); } - return stack_top; } uintptr_t vmm_alloc_user_code(uint64_t* pml4, void* code_addr, uint64_t code_size) { uintptr_t code_start = USER_CODE_START; - - for (size_t i=code_start; iroot_page_table = kernel_pml4; + proc->kernel_stack = kalloc_stack(); + proc->next = 0; process_add(&processes_list, proc); @@ -229,29 +231,52 @@ extern struct tss tss; /* * process_create_user - Create a new user process * @file: pointer to Limine file structure + * @name: name for the new process * * This function takes a loaded Limine executable * module, and maps its code, a user stack, sets the * TSS RSP0 for interrupts, and finally jumps to the * user code. */ -void process_create_user(struct limine_file* file) +void process_create_user(struct limine_file* file, char* name) { + CLEAR_INTERRUPTS; + struct process* proc = (struct process*)kmalloc(sizeof(struct process)); + struct cpu_status* ctx = (struct cpu_status*)kmalloc(sizeof(struct cpu_status)); + + if (!proc || !ctx) panic(NULL, "out of memory while creating user process"); + + strncpy(proc->name, name, PROCESS_NAME_MAX); + memset(ctx, 0, sizeof(struct cpu_status)); // set GP registers to zero + proc->pid = next_free_pid++; + proc->status = READY; + proc->next = 0; + proc->context = ctx; + proc->context->iret_ss = USER_DATA_SEGMENT | 3; + proc->context->iret_cs = USER_CODE_SEGMENT | 3; + proc->context->iret_flags = 0x202; // Interrupt Flag set + void* exec_addr = file->address; uint64_t exec_size = file->size; uint64_t* user_pml4 = vmm_create_address_space(); + if (!user_pml4) panic(NULL, "failed to create user address space"); + proc->root_page_table = user_pml4; + uintptr_t stack_top = vmm_alloc_user_stack(user_pml4); uint64_t code = vmm_alloc_user_code(user_pml4, exec_addr, exec_size); - // Could be kalloc_stack()ed PER PROCESS when we grow that - tss.rsp0 = (uint64_t)(interrupt_stack + sizeof(interrupt_stack)); + proc->context->iret_rsp = stack_top; + proc->context->iret_rip = code; + proc->kernel_stack = kalloc_stack(); + if (!proc->kernel_stack) panic(NULL, "failed to allocate kernel stack"); - // Load user_pml4 into cr3 along here?? + // Copy code into user pages; for that we need to temporarily switch to the user pml4 load_cr3(VIRT_TO_PHYS((uint64_t)user_pml4)); - - // Copy code into user pages memcpy((uint64_t*)code, exec_addr, exec_size); + load_cr3(VIRT_TO_PHYS((uint64_t)kernel_pml4)); - process_jump_to_user(stack_top, code); + process_add(&processes_list, proc); + DEBUG("user process '%s' (pid=%u) enqueued for scheduling", name, proc->pid); + SET_INTERRUPTS; } \ No newline at end of file diff --git a/src/sched/scheduler.c b/src/sched/scheduler.c index c320b70..421f4fa 100644 --- a/src/sched/scheduler.c +++ b/src/sched/scheduler.c @@ -9,17 +9,21 @@ #include #include #include +#include extern struct process* processes_list; extern struct process* current_process; extern struct process* idle_proc; +extern struct tss tss; + /* * scheduler_init - Choose the first process */ void scheduler_init() { current_process = processes_list; + DEBUG("scheduler starting with: pid=%u, name='%s', context=%p", current_process->pid, current_process->name, current_process->context); } /* @@ -39,13 +43,15 @@ struct cpu_status* scheduler_schedule(struct cpu_status* context) } if (current_process == NULL) { - // If no more processes, then set IDLE as the current process, that's it. - current_process = idle_proc; + panic(NULL, "current_process is NULL"); + } + + if (current_process->context == NULL) { + panic(NULL, "current_process->context is NULL"); } - if (current_process == idle_proc && current_process->next == NULL) - { - return idle_proc->context; + if (current_process->next == NULL) { + return current_process->context; } current_process->context = context; @@ -61,20 +67,16 @@ struct cpu_status* scheduler_schedule(struct cpu_status* context) if (current_process != NULL && current_process->status == DEAD) { process_delete(&prev_process, current_process); current_process = NULL; + return idle_proc->context; } else { current_process->status = RUNNING; -/* if (prev_process != current_process) { - DEBUG("Changed from {pid=%u, name=%s} to {pid=%u, name=%s}", prev_process->pid, prev_process->name, current_process->pid, current_process->name); - } */ break; } } - //DEBUG("current_process={pid=%u, name='%s', root_page_table[virt]=%p}", current_process->pid, current_process->name, current_process->root_page_table); - + tss.rsp0 = (uint64_t)current_process->kernel_stack; load_cr3(VIRT_TO_PHYS((uint64_t)current_process->root_page_table)); - //DEBUG("Loaded process PML4 into CR3"); return current_process->context; } \ No newline at end of file