From 99c85f646b7e57cab82242183cdd3b0465ea3b43 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 16 Mar 2025 22:01:53 -0400 Subject: [PATCH 01/59] Add source pid to event --- src/ebus/include/ebus.h | 1 + src/libc/src/signal.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/ebus/include/ebus.h b/src/ebus/include/ebus.h index b9eeaf33..a6e1f74b 100644 --- a/src/ebus/include/ebus.h +++ b/src/ebus/include/ebus.h @@ -29,6 +29,7 @@ enum EBUS_EVENT { typedef struct _ebus_event { int event_id; + int source_pid; union { struct { int id; diff --git a/src/libc/src/signal.c b/src/libc/src/signal.c index 88aca247..7819f4eb 100644 --- a/src/libc/src/signal.c +++ b/src/libc/src/signal.c @@ -1,6 +1,7 @@ #include "libc/signal.h" #include "libc/memory.h" +#include "libc/proc.h" #include "libk/sys_call.h" typedef struct _signal { @@ -52,5 +53,6 @@ int register_signal(int sig_no, signal_handler callback) { } void queue_event(ebus_event_t * event) { + event->source_pid = getpid(); _sys_queue_event(event); } From 2c19f6b8ec56614420577ce561776235b37769a2 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 06:14:59 -0400 Subject: [PATCH 02/59] Add process state and entrypoint --- src/kernel/include/process.h | 16 ++++++++++++++++ src/kernel/src/process.c | 12 ++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 1006ea24..99c30840 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -18,6 +18,15 @@ typedef struct _handle { int type; } handle_t; +enum PROCESS_STATE { + PROCESS_STATE_STARTING = 0, + PROCESS_STATE_LOADING, + PROCESS_STATE_SUSPENDED, + PROCESS_STATE_WAITING, + PROCESS_STATE_RUNNING, + PROCESS_STATE_DEAD, +}; + typedef struct _process { uint32_t pid; uint32_t next_heap_page; @@ -28,11 +37,16 @@ typedef struct _process { uint32_t cr3; uint32_t esp; uint32_t esp0; + uint32_t eip; signals_master_cb_t signals_callback; arr_t io_handles; // array + uint32_t filter_event; + + enum PROCESS_STATE state; + struct _process * next_proc; } process_t; @@ -56,6 +70,8 @@ int process_create(process_t * proc); */ int process_free(process_t * proc); +int process_set_entrypoint(process_t * proc, void * entrypoint); + /** * @brief Add `count` pages to the process heap. * diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 08dbdfb8..d1e4beea 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -105,6 +105,14 @@ int process_free(process_t * proc) { return 0; } +int process_set_entrypoint(process_t * proc, void * entrypoint) { + if (!proc || !entrypoint) { + return -1; + } + + proc->eip = PTR2UINT(entrypoint); +} + void * process_add_pages(process_t * proc, size_t count) { if (!proc || !count) { return 0; @@ -163,6 +171,8 @@ int process_load_heap(process_t * proc, const char * buff, size_t size) { return -1; } + proc->state = PROCESS_STATE_LOADING; + size_t page_count = ADDR2PAGE(size); if (size & MASK_FLAGS) { page_count++; @@ -213,6 +223,8 @@ int process_load_heap(process_t * proc, const char * buff, size_t size) { paging_temp_free(proc->cr3); + proc->state = PROCESS_STATE_SUSPENDED; + return 0; } From 27fd40d834805d17ab9bb55cb883b0bc3299c2af Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 06:15:12 -0400 Subject: [PATCH 03/59] Move process manager to new file --- src/kernel/include/kernel.h | 5 +++ src/kernel/include/process.h | 6 --- src/kernel/include/process_manager.h | 20 +++++++++ src/kernel/src/kernel.c | 61 ++++++++++++++++++++++------ src/kernel/src/process_manager.c | 34 ++++++++++++++++ 5 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 src/kernel/include/process_manager.h create mode 100644 src/kernel/src/process_manager.c diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index 9054b2ec..7f9ba4a9 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -8,6 +8,7 @@ #include "ebus.h" #include "memory_alloc.h" #include "process.h" +#include "process_manager.h" typedef struct _kernel { uint32_t ram_table_addr; @@ -44,4 +45,8 @@ ebus_t * get_kernel_ebus(); void tmp_register_signals_cb(signals_master_cb_t cb); +ebus_event_t * pull_event(int event_id); + +void kernel_next_task(); + #endif // KERNEL_H diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 99c30840..e380d48f 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -125,10 +125,4 @@ void set_next_pid(uint32_t next); extern void set_first_task(process_t * next_proc); extern void switch_to_task(process_t * next_proc); -typedef struct _proc_man { - process_t * idle_task; - process_t * task_begin; - process_t * curr_task; -} proc_man_t; - #endif // KERNEL_PROCESS_H diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h new file mode 100644 index 00000000..ebbefbc5 --- /dev/null +++ b/src/kernel/include/process_manager.h @@ -0,0 +1,20 @@ +#ifndef KERNEL_PROCESS_MANAGER_H +#define KERNEL_PROCESS_MANAGER_H + +#include +#include + +#include "process.h" + +typedef struct _proc_man { + process_t * idle_task; + process_t * task_begin; + process_t * curr_task; +} proc_man_t; + +int pm_create(proc_man_t * pm); + +int pm_add_proc(proc_man_t * pm, process_t * proc); +int pm_remove_proc(proc_man_t * pm, process_t * proc); + +#endif // KERNEL_PROCESS_MANAGER_H diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index f8bc1fcd..2061800a 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -28,6 +28,7 @@ #include "libk/defs.h" #include "libk/sys_call.h" #include "process.h" +#include "process_manager.h" #include "ram.h" #include "term.h" @@ -35,6 +36,7 @@ static kernel_t __kernel; extern _Noreturn void halt(void); +static void init_kernel_proc(); static void id_map_range(mmu_table_t * table, size_t start, size_t end); static void id_map_page(mmu_table_t * table, size_t page); static void cursor(); @@ -94,21 +96,15 @@ void kernel_main() { init_gdt(); init_tss(); - // Kernel process used for memory allocation - __kernel.proc.next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); - __kernel.proc.cr3 = PADDR_KERNEL_DIR; - // Add isr stack to kernel's TSS set_kernel_stack(VADDR_ISR_STACK); - // Setup kernel process as idle process - __kernel.pm.idle_task = &__kernel.proc; - __kernel.pm.idle_task->next_proc = __kernel.pm.idle_task; - __kernel.pm.curr_task = __kernel.pm.idle_task; - __kernel.pm.task_begin = __kernel.pm.idle_task; - isr_install(); + pm_create(&__kernel.pm); + + init_kernel_proc(); + init_system_call(IRQ16); system_call_register(SYS_INT_FAMILY_IO, sys_call_io_cb); system_call_register(SYS_INT_FAMILY_MEM, sys_call_mem_cb); @@ -134,9 +130,11 @@ void kernel_main() { ramdisk_create(4096); - // set_first_task(proc); + set_first_task(__kernel.pm.curr_task); + + switch_to_task(__kernel.pm.curr_task); - // switch_to_task(proc); + PANIC("switch didn't happen\n"); // jump_usermode(term_run); jump_kernel_mode(term_run); @@ -165,6 +163,45 @@ void tmp_register_signals_cb(signals_master_cb_t cb) { printf("Attached master signal callback at %p\n", __kernel.pm.curr_task->signals_callback); } +ebus_event_t * pull_event(int event_id) { + process_t * proc = get_current_process(); + proc->filter_event = event_id; + kernel_next_task(); + + return 0; +} + +void kernel_next_task() { + process_t * curr = get_current_process(); + process_t * next = curr->next_proc; + if (!next) { + next = __kernel.pm.idle_task; + } + + // TODO save state of current task + + __kernel.pm.curr_task = next; + + // TODO load state of next task + + // TODO probably won't return after above +} + +static void init_kernel_proc() { + process_t * proc = &__kernel.proc; + if (process_create(proc)) { + PANIC("Failed to create idle task"); + } + + // Kernel process used for memory allocation + proc->next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); + + // Setup kernel process as idle process + __kernel.pm.idle_task = proc; + __kernel.pm.curr_task = proc; + pm_add_proc(&__kernel.pm, proc); +} + static void cursor() { vga_cursor(3, 3); diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c new file mode 100644 index 00000000..db2c5913 --- /dev/null +++ b/src/kernel/src/process_manager.c @@ -0,0 +1,34 @@ +#include "process_manager.h" + +int pm_create(proc_man_t * pm) { + if (!pm) { + return -1; + } + + pm->idle_task = 0; + pm->task_begin = 0; + pm->curr_task = 0; + + return 0; +} + +int pm_add_proc(proc_man_t * pm, process_t * proc) { + if (!pm || !proc) { + return -1; + } + + process_t * curr = pm->curr_task; + while (curr->next_proc && curr->next_proc != pm->idle_task) { + curr = curr->next_proc; + } + + curr->next_proc = proc; + proc->next_proc = pm->idle_task; + + return 0; +} + +int pm_remove_proc(proc_man_t * pm, process_t * proc) { + // TODO not yet implemented, because idk how this struct will be + return -1; +} From 3aec43e3f914266d875612c285ccc611eb4165a8 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 06:24:12 -0400 Subject: [PATCH 04/59] Move queue_event to proc.h, add yield --- src/drivers/src/keyboard.c | 2 +- src/drivers/src/timer.c | 2 +- src/libc/include/libc/proc.h | 4 ++++ src/libc/include/libc/signal.h | 2 -- src/libc/src/proc.c | 9 +++++++++ src/libc/src/signal.c | 5 ----- src/libk/include/libk/defs.h | 1 + src/libk/include/libk/sys_call.h | 1 + src/libk/src/sys_call.c | 4 ++++ 9 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/drivers/src/keyboard.c b/src/drivers/src/keyboard.c index d4469481..0541342d 100644 --- a/src/drivers/src/keyboard.c +++ b/src/drivers/src/keyboard.c @@ -2,7 +2,7 @@ #include "cpu/isr.h" #include "cpu/ports.h" -#include "libc/signal.h" +#include "libc/proc.h" #include "libc/stdio.h" static uint8_t last_code = 0; diff --git a/src/drivers/src/timer.c b/src/drivers/src/timer.c index ecbbf4a3..3119a2f5 100644 --- a/src/drivers/src/timer.c +++ b/src/drivers/src/timer.c @@ -4,7 +4,7 @@ #include "cpu/ports.h" #include "ebus.h" #include "libc/datastruct/array.h" -#include "libc/signal.h" +#include "libc/proc.h" #include "libc/stdio.h" // https://wiki.osdev.org/PIT diff --git a/src/libc/include/libc/proc.h b/src/libc/include/libc/proc.h index e3f9a4fa..da89ba0e 100644 --- a/src/libc/include/libc/proc.h +++ b/src/libc/include/libc/proc.h @@ -4,6 +4,7 @@ #include #include "debug.h" +#include "ebus.h" #ifdef TESTING #define NO_RETURN @@ -26,6 +27,9 @@ void proc_exit(uint8_t code); void proc_abort(uint8_t code, const char * msg); NO_RETURN void proc_panic(const char * msg, const char * file, unsigned int line); +void queue_event(ebus_event_t * event); +int yield(int filter); + int getpid(void); #endif // LIBC_PROC_H diff --git a/src/libc/include/libc/signal.h b/src/libc/include/libc/signal.h index 8629e8b6..7d32e29e 100644 --- a/src/libc/include/libc/signal.h +++ b/src/libc/include/libc/signal.h @@ -13,6 +13,4 @@ typedef void (*signal_handler)(void); int register_signal(int sig_no, signal_handler callback); -void queue_event(ebus_event_t * event); - #endif // LIBC_SIGNAL_H diff --git a/src/libc/src/proc.c b/src/libc/src/proc.c index 5410f2eb..f9ab8ebe 100644 --- a/src/libc/src/proc.c +++ b/src/libc/src/proc.c @@ -14,6 +14,15 @@ NO_RETURN void proc_panic(const char * msg, const char * file, unsigned int line _sys_proc_panic(msg, file, line); } +void queue_event(ebus_event_t * event) { + event->source_pid = getpid(); + _sys_queue_event(event); +} + +int yield(int filter) { + return _sys_yield(filter); +} + int getpid(void) { return _sys_proc_getpid(); } diff --git a/src/libc/src/signal.c b/src/libc/src/signal.c index 7819f4eb..641e8606 100644 --- a/src/libc/src/signal.c +++ b/src/libc/src/signal.c @@ -51,8 +51,3 @@ int register_signal(int sig_no, signal_handler callback) { _sys_register_signals(signal_callback); return 0; } - -void queue_event(ebus_event_t * event) { - event->source_pid = getpid(); - _sys_queue_event(event); -} diff --git a/src/libk/include/libk/defs.h b/src/libk/include/libk/defs.h index bf0aef17..279b7735 100644 --- a/src/libk/include/libk/defs.h +++ b/src/libk/include/libk/defs.h @@ -21,6 +21,7 @@ #define SYS_INT_PROC_REG_SIG 0x0303 #define SYS_INT_PROC_GETPID 0x0304 #define SYS_INT_PROC_QUEUE_EVENT 0x0305 +#define SYS_INT_PROC_YIELD 0x0306 #define SYS_INT_STDIO_PUTC 0x1000 #define SYS_INT_STDIO_PUTS 0x1001 diff --git a/src/libk/include/libk/sys_call.h b/src/libk/include/libk/sys_call.h index 63a157b4..a7ec0bdb 100644 --- a/src/libk/include/libk/sys_call.h +++ b/src/libk/include/libk/sys_call.h @@ -30,6 +30,7 @@ int _sys_proc_getpid(void); void _sys_register_signals(void * callback); void _sys_queue_event(ebus_event_t * event); +int _sys_yield(int filter); size_t _sys_putc(char c); size_t _sys_puts(const char * str); diff --git a/src/libk/src/sys_call.c b/src/libk/src/sys_call.c index def54952..6f05a533 100644 --- a/src/libk/src/sys_call.c +++ b/src/libk/src/sys_call.c @@ -66,6 +66,10 @@ void _sys_queue_event(ebus_event_t * event) { send_call(SYS_INT_PROC_QUEUE_EVENT, event); } +int _sys_yield(int filter) { + return send_call(SYS_INT_PROC_YIELD, filter); +} + size_t _sys_putc(char c) { return send_call(SYS_INT_STDIO_PUTC, c); } From 706c8622595cdcdaacfc97ce1f4e761e7bd2444d Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 06:26:47 -0400 Subject: [PATCH 05/59] Handle system call for yield --- src/kernel/src/system_call_proc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 35360d7f..d77f0e7d 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -81,6 +81,15 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { ebus_push(get_kernel_ebus(), args.event); } break; + + case SYS_INT_PROC_YIELD: { + struct _args { + int filter; + } args = *(struct _args *)args_data; + + process_t * proc = get_current_process(); + process_yield(proc, args.filter); + }; } return res; From dadb884c1c86a4089ede98492f9aba6af3e1f7e1 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 08:28:46 -0400 Subject: [PATCH 06/59] Keep args as pointer --- src/kernel/src/system_call_io.c | 34 +++++++++++++++--------------- src/kernel/src/system_call_mem.c | 4 ++-- src/kernel/src/system_call_proc.c | 34 +++++++++++++++--------------- src/kernel/src/system_call_stdio.c | 8 +++---- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/kernel/src/system_call_io.c b/src/kernel/src/system_call_io.c index 35d05c53..a1019d31 100644 --- a/src/kernel/src/system_call_io.c +++ b/src/kernel/src/system_call_io.c @@ -17,9 +17,9 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { struct _args { const char * path; const char * mode; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; - if (!args.path || !args.mode || !*args.path || !*args.mode) { + if (!args->path || !args->mode || !*args->path || !*args->mode) { return 0; } @@ -36,13 +36,13 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { case SYS_INT_IO_CLOSE: { struct _args { int handle; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; - if (args.handle > arr_size(io_handles)) { + if (args->handle > arr_size(io_handles)) { return 0; // TODO proper error } - handle_t * handle = arr_at(io_handles, args.handle - 1); + handle_t * handle = arr_at(io_handles, args->handle - 1); if (handle->type == HANDLE_TYPE_FREE) { return 0; // TODO proper error @@ -58,13 +58,13 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { int handle; char * buff; size_t count; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; - if (args.handle > arr_size(io_handles)) { + if (args->handle > arr_size(io_handles)) { return 0; // TODO proper error } - handle_t * handle = arr_at(io_handles, args.handle - 1); + handle_t * handle = arr_at(io_handles, args->handle - 1); if (handle->type == HANDLE_TYPE_FREE) { return 0; // TODO proper error @@ -78,13 +78,13 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { int handle; const char * buff; size_t count; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; - if (args.handle > arr_size(io_handles)) { + if (args->handle > arr_size(io_handles)) { return 0; // TODO proper error } - handle_t * handle = arr_at(io_handles, args.handle - 1); + handle_t * handle = arr_at(io_handles, args->handle - 1); if (handle->type == HANDLE_TYPE_FREE) { return 0; // TODO proper error @@ -98,13 +98,13 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { int handle; int pos; int seek; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; - if (args.handle > arr_size(io_handles)) { + if (args->handle > arr_size(io_handles)) { return 0; // TODO proper error } - handle_t * handle = arr_at(io_handles, args.handle - 1); + handle_t * handle = arr_at(io_handles, args->handle - 1); if (handle->type == HANDLE_TYPE_FREE) { return 0; // TODO proper error @@ -116,13 +116,13 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { case SYS_INT_IO_TELL: { struct _args { int handle; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; - if (args.handle > arr_size(io_handles)) { + if (args->handle > arr_size(io_handles)) { return 0; // TODO proper error } - handle_t * handle = arr_at(io_handles, args.handle - 1); + handle_t * handle = arr_at(io_handles, args->handle - 1); if (handle->type == HANDLE_TYPE_FREE) { return 0; // TODO proper error diff --git a/src/kernel/src/system_call_mem.c b/src/kernel/src/system_call_mem.c index 09ceae05..d487cd42 100644 --- a/src/kernel/src/system_call_mem.c +++ b/src/kernel/src/system_call_mem.c @@ -13,11 +13,11 @@ int sys_call_mem_cb(uint16_t int_no, void * args_data, registers_t * regs) { case SYS_INT_MEM_PAGE_ALLOC: { struct _args { size_t count; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; process_t * curr_proc = get_current_process(); - res = PTR2UINT(process_add_pages(curr_proc, args.count)); + res = PTR2UINT(process_add_pages(curr_proc, args->count)); } break; } diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index d77f0e7d..335573c6 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -17,8 +17,8 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { case SYS_INT_PROC_EXIT: { struct _args { uint8_t code; - } args = *(struct _args *)args_data; - printf("Proc exit with code %u\n", args.code); + } * args = (struct _args *)args_data; + printf("Proc exit with code %u\n", args->code); kernel_exit(); } break; @@ -26,9 +26,9 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { struct _args { uint8_t code; const char * msg; - } args = *(struct _args *)args_data; - printf("Proc abort with code %u\n", args.code); - puts(args.msg); + } * args = (struct _args *)args_data; + printf("Proc abort with code %u\n", args->code); + puts(args->msg); kernel_exit(); } break; @@ -37,18 +37,18 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { const char * msg; const char * file; unsigned int line; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; vga_color(VGA_FG_WHITE | VGA_BG_RED); vga_puts("[PANIC]"); - if (args.file) { + if (args->file) { vga_putc('['); - vga_puts(args.file); + vga_puts(args->file); vga_puts("]:"); - vga_putu(args.line); + vga_putu(args->line); } - if (args.msg) { + if (args->msg) { vga_putc(' '); - vga_puts(args.msg); + vga_puts(args->msg); } vga_cursor_hide(); asm("cli"); @@ -60,8 +60,8 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { case SYS_INT_PROC_REG_SIG: { struct _args { signals_master_cb_t cb; - } args = *(struct _args *)args_data; - tmp_register_signals_cb(args.cb); + } * args = (struct _args *)args_data; + tmp_register_signals_cb(args->cb); } break; case SYS_INT_PROC_GETPID: { @@ -77,18 +77,18 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { case SYS_INT_PROC_QUEUE_EVENT: { struct _args { ebus_event_t * event; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; - ebus_push(get_kernel_ebus(), args.event); + ebus_push(get_kernel_ebus(), args->event); } break; case SYS_INT_PROC_YIELD: { struct _args { int filter; - } args = *(struct _args *)args_data; + } * args = (struct _args *)args_data; process_t * proc = get_current_process(); - process_yield(proc, args.filter); + process_yield(proc, regs->esp, args->filter); }; } diff --git a/src/kernel/src/system_call_stdio.c b/src/kernel/src/system_call_stdio.c index db77c06e..61541926 100644 --- a/src/kernel/src/system_call_stdio.c +++ b/src/kernel/src/system_call_stdio.c @@ -13,15 +13,15 @@ int sys_call_tmp_stdio_cb(uint16_t int_no, void * args_data, registers_t * regs) case SYS_INT_STDIO_PUTC: { struct _args { char c; - } args = *(struct _args *)args_data; - res = vga_putc(args.c); + } * args = (struct _args *)args_data; + res = vga_putc(args->c); } break; case SYS_INT_STDIO_PUTS: { struct _args { const char * str; - } args = *(struct _args *)args_data; - res = vga_puts(args.str); + } * args = (struct _args *)args_data; + res = vga_puts(args->str); } break; } From 3436059dfa62bbe08dbfc2bee2c1c30cfdfb11c1 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 18:30:34 -0400 Subject: [PATCH 07/59] Working idle process --- src/cpu/i386/src/cpu.asm | 82 ---------------------- src/kernel/include/process.h | 21 +++--- src/kernel/src/kernel.c | 49 +++++++++---- src/kernel/src/kernel_entry.asm | 119 ++++++++++++++++++++++++++++++++ src/kernel/src/process.c | 31 ++++++++- 5 files changed, 196 insertions(+), 106 deletions(-) diff --git a/src/cpu/i386/src/cpu.asm b/src/cpu/i386/src/cpu.asm index 606b251b..8298c781 100644 --- a/src/cpu/i386/src/cpu.asm +++ b/src/cpu/i386/src/cpu.asm @@ -31,85 +31,3 @@ flush_tss: mov ax, (5 * 8) | 0 ; fifth 8-byte selector, symbolically OR-ed with 0 to set the RPL (requested privilege level). ltr ax ret - -global jump_usermode -jump_usermode: - mov ebx, [esp+4] - mov ax, (4 * 8) | 3 ; ring 3 data with bottom 2 bits set for ring 3 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax ; SS is handled by iret - - ; set up the stack frame iret expects - mov eax, esp - push (4 * 8) | 3 ; data selector - push eax ; current esp - pushf ; eflags - push (3 * 8) | 3 ; code selector (ring 3 code with bottom 2 bits set for ring 3) - push ebx ; instruction address to return to - iret - -; https://wiki.osdev.org/Brendan%27s_Multi-tasking_Tutorial - -;C declaration: -; void switch_to_task(thread_control_block *next_thread); -; -;WARNING: Caller is expected to disable IRQs before calling, and enable IRQs again after function returns - -TCB_EIP equ 4 -TCB_ESP equ 8 -TCB_CR3 equ 12 -TCB_ESP0 equ 16 -TSS_ESP0 equ 20 - -current_task_TCB: dd 0 - -global set_first_task -set_first_task: - mov eax, [esp + 4] - mov [current_task_TCB], eax - ret - -global switch_to_task -switch_to_task: - - ;Save previous task's state - - ;Notes: - ; For cdecl; EAX, ECX, and EDX are already saved by the caller and don't need to be saved again - ; EIP is already saved on the stack by the caller's "CALL" instruction - ; The task isn't able to change CR3 so it doesn't need to be saved - ; Segment registers are constants (while running kernel code) so they don't need to be saved - - push ebx - push esi - push edi - push ebp - - mov edi,[current_task_TCB] ;edi = address of the previous task's "thread control block" - mov [edi+TCB_ESP],esp ;Save ESP for previous task's kernel stack in the thread's TCB - - ;Load next task's state - - mov esi,[esp+(4+1)*4] ;esi = address of the next task's "thread control block" (parameter passed on stack) - mov [current_task_TCB],esi ;Current task's TCB is the next task TCB - - mov esp,[esi+TCB_ESP] ;Load ESP for next task's kernel stack from the thread's TCB - mov eax,[esi+TCB_CR3] ;eax = address of page directory for next task - mov ebx,[esi+TCB_ESP0] ;ebx = address for the top of the next task's kernel stack - mov [TSS_ESP0],ebx ;Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) - mov ecx,cr3 ;ecx = previous task's virtual address space - - cmp eax,ecx ;Does the virtual address space need to being changed? - je .doneVAS ; no, virtual address space is the same, so don't reload it and cause TLB flushes - mov cr3,eax ; yes, load the next task's virtual address space - -.doneVAS: - - pop ebp - pop edi - pop esi - pop ebx - - ret ;Load next task's EIP from its kernel stack \ No newline at end of file diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index e380d48f..e247ed3a 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -4,6 +4,7 @@ #include #include +#include "ebus.h" #include "libc/datastruct/array.h" typedef void (*signals_master_cb_t)(int); @@ -28,16 +29,17 @@ enum PROCESS_STATE { }; typedef struct _process { + uint32_t cr3; + uint32_t esp; + uint32_t esp0; + uint32_t pid; uint32_t next_heap_page; uint32_t stack_page_count; // TODO heap & stack limits - uint32_t cr3; - uint32_t esp; - uint32_t esp0; - uint32_t eip; + uint32_t entrypoint; signals_master_cb_t signals_callback; @@ -72,6 +74,10 @@ int process_free(process_t * proc); int process_set_entrypoint(process_t * proc, void * entrypoint); +void process_yield(process_t * proc, uint32_t esp, int filter); + +int process_resume(process_t * proc, const ebus_event_t * event); + /** * @brief Add `count` pages to the process heap. * @@ -120,9 +126,8 @@ int process_load_heap(process_t * proc, const char * buff, size_t size); */ void set_next_pid(uint32_t next); -// Old - -extern void set_first_task(process_t * next_proc); -extern void switch_to_task(process_t * next_proc); +extern _Noreturn void start_task(uint32_t cr3, uint32_t esp, uint32_t esp0, uint32_t eip, const ebus_event_t * event); +extern _Noreturn void resume_task(uint32_t cr3, uint32_t esp, uint32_t esp0, const ebus_event_t * event); +extern _Noreturn void switch_to_task(process_t * next_proc); #endif // KERNEL_PROCESS_H diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 2061800a..510bf5ae 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -36,7 +36,8 @@ static kernel_t __kernel; extern _Noreturn void halt(void); -static void init_kernel_proc(); +static void init_idle_proc(); +static void idle(); static void id_map_range(mmu_table_t * table, size_t start, size_t end); static void id_map_page(mmu_table_t * table, size_t page); static void cursor(); @@ -96,15 +97,18 @@ void kernel_main() { init_gdt(); init_tss(); + pm_create(&__kernel.pm); + + // Kernel process used for memory allocation + __kernel.proc.next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); + __kernel.proc.cr3 = PADDR_KERNEL_DIR; + __kernel.pm.curr_task = &__kernel.proc; + // Add isr stack to kernel's TSS set_kernel_stack(VADDR_ISR_STACK); isr_install(); - pm_create(&__kernel.pm); - - init_kernel_proc(); - init_system_call(IRQ16); system_call_register(SYS_INT_FAMILY_IO, sys_call_io_cb); system_call_register(SYS_INT_FAMILY_MEM, sys_call_mem_cb); @@ -115,6 +119,10 @@ void kernel_main() { memory_init(&__kernel.kernel_memory, _sys_page_alloc); init_malloc(&__kernel.kernel_memory); + init_idle_proc(); + __kernel.proc.next_proc = __kernel.pm.idle_task; + __kernel.pm.curr_task = &__kernel.proc; + if (ebus_create(&__kernel.event_bus, 4096)) { PANIC("Failed to init ebus\n"); } @@ -130,9 +138,11 @@ void kernel_main() { ramdisk_create(4096); - set_first_task(__kernel.pm.curr_task); + // set_first_task(__kernel.pm.curr_task); + + // switch_to_task(__kernel.pm.curr_task); - switch_to_task(__kernel.pm.curr_task); + process_resume(__kernel.pm.idle_task, 0); PANIC("switch didn't happen\n"); @@ -178,28 +188,37 @@ void kernel_next_task() { next = __kernel.pm.idle_task; } - // TODO save state of current task - __kernel.pm.curr_task = next; - // TODO load state of next task + // TODO interrupt back to process for sigint - // TODO probably won't return after above + if (process_resume(__kernel.pm.curr_task, 0)) { + PANIC("Failed to resume task"); + } } -static void init_kernel_proc() { - process_t * proc = &__kernel.proc; +static void init_idle_proc() { + process_t * proc = kmalloc(sizeof(process_t)); if (process_create(proc)) { PANIC("Failed to create idle task"); } // Kernel process used for memory allocation proc->next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); + process_set_entrypoint(proc, idle); // Setup kernel process as idle process __kernel.pm.idle_task = proc; - __kernel.pm.curr_task = proc; - pm_add_proc(&__kernel.pm, proc); + // __kernel.pm.task_begin = proc; +} + +void idle() { + vga_puts("Start idle task\n"); + for (;;) { + term_update(); + ebus_cycle(get_kernel_ebus()); + asm("hlt"); + } } static void cursor() { diff --git a/src/kernel/src/kernel_entry.asm b/src/kernel/src/kernel_entry.asm index 64586e3d..ad9341d7 100644 --- a/src/kernel/src/kernel_entry.asm +++ b/src/kernel/src/kernel_entry.asm @@ -53,3 +53,122 @@ jump_proc: mov esp, ebx jmp edx + +global jump_usermode +jump_usermode: + mov ebx, [esp+4] + mov ax, (4 * 8) | 3 ; ring 3 data with bottom 2 bits set for ring 3 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax ; SS is handled by iret + + ; set up the stack frame iret expects + mov eax, esp + push (4 * 8) | 3 ; data selector + push eax ; current esp + pushf ; eflags + push (3 * 8) | 3 ; code selector (ring 3 code with bottom 2 bits set for ring 3) + push ebx ; instruction address to return to + iret + +; https://wiki.osdev.org/Brendan%27s_Multi-tasking_Tutorial + +;C declaration: +; void switch_to_task(thread_control_block *next_thread); +; +;WARNING: Caller is expected to disable IRQs before calling, and enable IRQs again after function returns + +TCB_CR3 equ 4 +TCB_ESP equ 8 +TCB_ESP0 equ 12 + +current_task_TCB: dd 0 + +global set_first_task +set_first_task: + mov eax, [esp + 4] + mov [current_task_TCB], eax + ret + +; void start_task(uint32_t cr3, uint32_t esp, uint32_t esp0, uint32_t eip, const ebus_event_t * event) +global start_task +start_task: + mov ebp, esp + mov ecx, [ebp+4] ; cr3 + mov ebx, [ebp+8] ; esp + mov edx, [ebp+12] ; esp0 + mov edi, [ebp+16] ; eip + mov eax, [ebp+20] ; event + + mov esp, ebx + mov cr3, ecx + + jmp edi + + +; void resume_task(uint32_t cr3, uint32_t esp, uint32_t esp0, const ebus_event_t * event) +global resume_task +resume_task: + mov esp, ebp + mov eax, [ebp+4] ; cr3 + mov esp, [ebp+8] ; esp + mov ebx, [ebp+12] ; esp0 + mov eax, [ebp+16] ; event + + ;Load next task's state + + ; TODO get tss and set it's esp0 + ; mov [TSS_ESP0], ebx ;Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) + mov ecx, cr3 ;ecx = previous task's virtual address space + + cmp eax, ecx ;Does the virtual address space need to being changed? + je .doneVAS ; no, virtual address space is the same, so don't reload it and cause TLB flushes + mov cr3, eax ; yes, load the next task's virtual address space + +.doneVAS: + + ret ;Load next task's EIP from its kernel stack + +global switch_to_task +switch_to_task: + + ;Save previous task's state + + ;Notes: + ; For cdecl; EAX, ECX, and EDX are already saved by the caller and don't need to be saved again + ; EIP is already saved on the stack by the caller's "CALL" instruction + ; The task isn't able to change CR3 so it doesn't need to be saved + ; Segment registers are constants (while running kernel code) so they don't need to be saved + + push ebx + push esi + push edi + push ebp + + mov edi, [current_task_TCB] ;edi = address of the previous task's "thread control block" + mov [edi+TCB_ESP], esp ;Save ESP for previous task's kernel stack in the thread's TCB + + ;Load next task's state + + mov esi, [esp+(4+1)*4] ;esi = address of the next task's "thread control block" (parameter passed on stack) + mov [current_task_TCB], esi ;Current task's TCB is the next task TCB + + mov esp, [esi+TCB_ESP] ;Load ESP for next task's kernel stack from the thread's TCB + mov eax, [esi+TCB_CR3] ;eax = address of page directory for next task + mov ebx, [esi+TCB_ESP0] ;ebx = address for the top of the next task's kernel stack + ; mov [TSS_ESP0], ebx ;Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) + mov ecx, cr3 ;ecx = previous task's virtual address space + + cmp eax, ecx ;Does the virtual address space need to being changed? + je .doneVAS ; no, virtual address space is the same, so don't reload it and cause TLB flushes + mov cr3, eax ; yes, load the next task's virtual address space + +.doneVAS: + + pop ebp + pop edi + pop esi + pop ebx + + ret ;Load next task's EIP from its kernel stack diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index d1e4beea..b491b75b 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -1,6 +1,8 @@ #include "process.h" #include "cpu/mmu.h" +#include "cpu/tss.h" +#include "kernel.h" #include "libc/string.h" #include "paging.h" #include "ram.h" @@ -110,7 +112,34 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { return -1; } - proc->eip = PTR2UINT(entrypoint); + proc->entrypoint = PTR2UINT(entrypoint); +} + +void process_yield(process_t * proc, uint32_t esp, int filter) { + proc->filter_event = filter; + proc->esp = esp; + proc->state = PROCESS_STATE_WAITING; + kernel_next_task(); +} + +int process_resume(process_t * proc, const ebus_event_t * event) { + if (!proc) { + return -1; + } + + if (proc->state < PROCESS_STATE_SUSPENDED) { + proc->state = PROCESS_STATE_RUNNING; + tss_get_entry(0)->esp0 = proc->esp0; + start_task(proc->cr3, proc->esp, proc->esp0, proc->entrypoint, event); + } + + // TODO implement this + if (!proc->filter_event || !event || proc->filter_event == event->event_id) { + proc->state = PROCESS_STATE_RUNNING; + tss_get_entry(0)->esp0 = proc->esp0; + switch_to_task(proc); + } + return -1; } void * process_add_pages(process_t * proc, size_t count) { From 6e0ac7db36d665c76f653acd46b3db314a7eb74b Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 19:14:18 -0400 Subject: [PATCH 08/59] Add kernel panic, can load and start applications --- src/kernel/include/kernel.h | 9 +++++++++ src/kernel/include/process.h | 1 + src/kernel/src/exec.c | 24 ++++++++++------------- src/kernel/src/kernel.c | 34 ++++++++++++++++++++++++++------- src/kernel/src/kernel_entry.asm | 28 +++++++++++---------------- src/kernel/src/process.c | 4 ++-- 6 files changed, 60 insertions(+), 40 deletions(-) diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index 7f9ba4a9..148aefb8 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -49,4 +49,13 @@ ebus_event_t * pull_event(int event_id); void kernel_next_task(); +#ifdef TESTING +#define NO_RETURN +#else +#define NO_RETURN _Noreturn +#endif + +#define KPANIC(MSG) kernel_panic((MSG), __FILE__, __LINE__) +NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int line); + #endif // KERNEL_H diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index e247ed3a..4f79cd84 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -22,6 +22,7 @@ typedef struct _handle { enum PROCESS_STATE { PROCESS_STATE_STARTING = 0, PROCESS_STATE_LOADING, + PROCESS_STATE_LOADED, PROCESS_STATE_SUSPENDED, PROCESS_STATE_WAITING, PROCESS_STATE_RUNNING, diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index fce066e2..c3f6b7c1 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -2,6 +2,7 @@ #include "cpu/mmu.h" #include "cpu/tss.h" +#include "kernel.h" #include "libc/memory.h" #include "libc/stdio.h" #include "libc/string.h" @@ -27,25 +28,20 @@ int command_exec(uint8_t * buff, size_t size, size_t argc, char ** argv) { return -1; } - puts("Go for call\n"); - - ff_t call = UINT2PTR(VADDR_USER_MEM); - - // mmu_change_dir(proc->cr3); + process_set_entrypoint(proc, UINT2PTR(VADDR_USER_MEM)); - tss_get_entry(0)->esp0 = proc->esp0; - tss_get_entry(0)->cr3 = proc->cr3; - tss_get_entry(0)->esp = proc->esp; + process_add_pages(proc, 32); - jump_proc(proc->cr3, proc->esp, VADDR_USER_MEM); + puts("Go for call\n"); - int res = call(argc, argv); + if (process_resume(proc, 0)) { + KPANIC("Failed to resume process"); + } - puts("Done\n"); + // if process_resume does not fail, it will not return + KPANIC("How did you get here?"); process_free(proc); - puts("All good!\n"); - - return res; + return -1; } diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 510bf5ae..1472b054 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -124,7 +124,7 @@ void kernel_main() { __kernel.pm.curr_task = &__kernel.proc; if (ebus_create(&__kernel.event_bus, 4096)) { - PANIC("Failed to init ebus\n"); + KPANIC("Failed to init ebus\n"); } irq_install(); @@ -144,12 +144,12 @@ void kernel_main() { process_resume(__kernel.pm.idle_task, 0); - PANIC("switch didn't happen\n"); + KPANIC("switch didn't happen\n"); // jump_usermode(term_run); jump_kernel_mode(term_run); - PANIC("You shouldn't be here!"); + KPANIC("You shouldn't be here!"); } mmu_dir_t * get_kernel_dir() { @@ -193,14 +193,14 @@ void kernel_next_task() { // TODO interrupt back to process for sigint if (process_resume(__kernel.pm.curr_task, 0)) { - PANIC("Failed to resume task"); + KPANIC("Failed to resume task"); } } static void init_idle_proc() { process_t * proc = kmalloc(sizeof(process_t)); if (process_create(proc)) { - PANIC("Failed to create idle task"); + KPANIC("Failed to create idle task"); } // Kernel process used for memory allocation @@ -221,6 +221,26 @@ void idle() { } } +NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int line) { + vga_color(VGA_FG_WHITE | VGA_BG_RED); + vga_puts("[KERNEL PANIC]"); + if (file) { + vga_putc('['); + vga_puts(file); + vga_puts("]:"); + vga_putu(line); + } + if (msg) { + vga_putc(' '); + vga_puts(msg); + } + vga_cursor_hide(); + asm("cli"); + for (;;) { + asm("hlt"); + } +} + static void cursor() { vga_cursor(3, 3); @@ -244,7 +264,7 @@ static void irq_install() { static int kill(size_t argc, char ** argv) { printf("Leaving process now\n"); kernel_exit(); - PANIC("Never return!"); + KPANIC("Never return!"); return 0; } @@ -281,7 +301,7 @@ static void map_first_table(mmu_table_t * table) { static void id_map_range(mmu_table_t * table, size_t start, size_t end) { if (end > 1023) { - PANIC("End is past table limits"); + KPANIC("End is past table limits"); end = 1023; } diff --git a/src/kernel/src/kernel_entry.asm b/src/kernel/src/kernel_entry.asm index ad9341d7..02c8e45f 100644 --- a/src/kernel/src/kernel_entry.asm +++ b/src/kernel/src/kernel_entry.asm @@ -85,12 +85,6 @@ TCB_ESP0 equ 12 current_task_TCB: dd 0 -global set_first_task -set_first_task: - mov eax, [esp + 4] - mov [current_task_TCB], eax - ret - ; void start_task(uint32_t cr3, uint32_t esp, uint32_t esp0, uint32_t eip, const ebus_event_t * event) global start_task start_task: @@ -110,23 +104,23 @@ start_task: ; void resume_task(uint32_t cr3, uint32_t esp, uint32_t esp0, const ebus_event_t * event) global resume_task resume_task: - mov esp, ebp - mov eax, [ebp+4] ; cr3 - mov esp, [ebp+8] ; esp - mov ebx, [ebp+12] ; esp0 + mov ebp, esp + mov ecx, [ebp+4] ; cr3 + mov ebx, [ebp+8] ; esp + mov edx, [ebp+12] ; esp0 mov eax, [ebp+16] ; event - ;Load next task's state - ; TODO get tss and set it's esp0 ; mov [TSS_ESP0], ebx ;Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) - mov ecx, cr3 ;ecx = previous task's virtual address space + mov edi, cr3 ;edi = previous task's virtual address space - cmp eax, ecx ;Does the virtual address space need to being changed? - je .doneVAS ; no, virtual address space is the same, so don't reload it and cause TLB flushes - mov cr3, eax ; yes, load the next task's virtual address space + cmp ecx, edi ;Does the virtual address space need to being changed? + je .done ; no, virtual address space is the same, so don't reload it and cause TLB flushes + mov cr3, ecx ; yes, load the next task's virtual address space -.doneVAS: +.done: + + mov esp, ebx ret ;Load next task's EIP from its kernel stack diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index b491b75b..d4866b9a 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -137,7 +137,7 @@ int process_resume(process_t * proc, const ebus_event_t * event) { if (!proc->filter_event || !event || proc->filter_event == event->event_id) { proc->state = PROCESS_STATE_RUNNING; tss_get_entry(0)->esp0 = proc->esp0; - switch_to_task(proc); + resume_task(proc->cr3, proc->esp, proc->esp0, event); } return -1; } @@ -252,7 +252,7 @@ int process_load_heap(process_t * proc, const char * buff, size_t size) { paging_temp_free(proc->cr3); - proc->state = PROCESS_STATE_SUSPENDED; + proc->state = PROCESS_STATE_LOADED; return 0; } From 59a3deef7aac34f1f8998a66dd0f0eacb6c22f53 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 19:28:02 -0400 Subject: [PATCH 09/59] Fix process test noreturn compile error --- src/kernel/include/process.h | 12 +++++++++--- tests/src/kernel/test_process.cpp | 2 -- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 4f79cd84..a686695e 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -127,8 +127,14 @@ int process_load_heap(process_t * proc, const char * buff, size_t size); */ void set_next_pid(uint32_t next); -extern _Noreturn void start_task(uint32_t cr3, uint32_t esp, uint32_t esp0, uint32_t eip, const ebus_event_t * event); -extern _Noreturn void resume_task(uint32_t cr3, uint32_t esp, uint32_t esp0, const ebus_event_t * event); -extern _Noreturn void switch_to_task(process_t * next_proc); +#ifdef TESTING +#define NO_RETURN +#else +#define NO_RETURN _Noreturn +#endif + +extern NO_RETURN void start_task(uint32_t cr3, uint32_t esp, uint32_t esp0, uint32_t eip, const ebus_event_t * event); +extern NO_RETURN void resume_task(uint32_t cr3, uint32_t esp, uint32_t esp0, const ebus_event_t * event); +extern NO_RETURN void switch_to_task(process_t * next_proc); #endif // KERNEL_PROCESS_H diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index bbde3ce6..87e2480e 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -4,8 +4,6 @@ #include "test_common.h" extern "C" { -#define _Noreturn - #include "addr.h" #include "cpu/mmu.h" #include "libc/datastruct/array.h" From f71d5d691e23c94c98bfbe6304cfdf8fb5e6abb7 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 20:02:17 -0400 Subject: [PATCH 10/59] Working on kernel task switching --- src/kernel/include/kernel.h | 4 +++- src/kernel/src/exec.c | 2 ++ src/kernel/src/kernel.c | 33 ++++++++++++++++++++++++++++++- src/kernel/src/process_manager.c | 27 +++++++++++++++++++++++++ src/kernel/src/system_call_proc.c | 21 +++++++++++++------- 5 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index 148aefb8..fbd44d48 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -47,7 +47,9 @@ void tmp_register_signals_cb(signals_master_cb_t cb); ebus_event_t * pull_event(int event_id); -void kernel_next_task(); +int kernel_add_task(process_t * proc); +int kernel_next_task(); +int kernel_close_process(process_t * proc); #ifdef TESTING #define NO_RETURN diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index c3f6b7c1..c1dbc32b 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -32,6 +32,8 @@ int command_exec(uint8_t * buff, size_t size, size_t argc, char ** argv) { process_add_pages(proc, 32); + kernel_add_task(proc); + puts("Go for call\n"); if (process_resume(proc, 0)) { diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 1472b054..9c2ec639 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -122,6 +122,7 @@ void kernel_main() { init_idle_proc(); __kernel.proc.next_proc = __kernel.pm.idle_task; __kernel.pm.curr_task = &__kernel.proc; + __kernel.pm.task_begin = &__kernel.proc; if (ebus_create(&__kernel.event_bus, 4096)) { KPANIC("Failed to init ebus\n"); @@ -181,7 +182,20 @@ ebus_event_t * pull_event(int event_id) { return 0; } -void kernel_next_task() { +int kernel_add_task(process_t * proc) { + if (!proc) { + return -1; + } + process_t * curr = __kernel.pm.task_begin; + while (curr->next_proc && curr->next_proc != __kernel.pm.idle_task) { + curr = curr->next_proc; + } + curr->next_proc = proc; + proc->next_proc = __kernel.pm.idle_task; + return 0; +} + +int kernel_next_task() { process_t * curr = get_current_process(); process_t * next = curr->next_proc; if (!next) { @@ -195,6 +209,23 @@ void kernel_next_task() { if (process_resume(__kernel.pm.curr_task, 0)) { KPANIC("Failed to resume task"); } + + return 0; +} + +int kernel_close_process(process_t * proc) { + if (!proc) { + return -1; + } + + if (pm_remove_proc(&__kernel.pm, proc)) { + KPANIC("Failed to remove process from pm"); + return -1; + } + + process_free(proc); + + return 0; } static void init_idle_proc() { diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index db2c5913..2870fd3a 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -29,6 +29,33 @@ int pm_add_proc(proc_man_t * pm, process_t * proc) { } int pm_remove_proc(proc_man_t * pm, process_t * proc) { + if (!pm || !proc) { + return -1; + } + + if (!proc->pid || proc->pid == pm->idle_task->pid) { + return -1; + } + + if (pm->curr_task->pid == proc->pid) { + pm->curr_task = pm->curr_task->next_proc; + } + // TODO not yet implemented, because idk how this struct will be + process_t * curr = pm->task_begin; + + if (curr->pid == proc->pid) { + pm->task_begin = curr->next_proc; + return 0; + } + + while (curr->next_proc && curr->next_proc != pm->idle_task && curr->next_proc != pm->curr_task) { + if (curr->next_proc->pid == proc->pid) { + curr->next_proc = curr->next_proc->next_proc; + return 0; + } + curr = curr->next_proc; + } + return -1; } diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 335573c6..897418d7 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -19,7 +19,11 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { uint8_t code; } * args = (struct _args *)args_data; printf("Proc exit with code %u\n", args->code); - kernel_exit(); + if (kernel_close_process(get_current_process())) { + KPANIC("Kernel could not close process"); + } + kernel_next_task(); + KPANIC("Unexpected return from kernel_close_process"); } break; case SYS_INT_PROC_ABORT: { @@ -29,7 +33,11 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { } * args = (struct _args *)args_data; printf("Proc abort with code %u\n", args->code); puts(args->msg); - kernel_exit(); + if (kernel_close_process(get_current_process())) { + KPANIC("Kernel could not close process"); + } + kernel_next_task(); + KPANIC("Unexpected return from kernel_close_process"); } break; case SYS_INT_PROC_PANIC: { @@ -66,12 +74,10 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { case SYS_INT_PROC_GETPID: { process_t * p = get_current_process(); - if (p) { - res = p->pid; - } - else { - res = -1; + if (!p) { + KPANIC("Failed to find current process"); } + res = p->pid; } break; case SYS_INT_PROC_QUEUE_EVENT: { @@ -87,6 +93,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { int filter; } * args = (struct _args *)args_data; + // TODO clear iret from stack? process_t * proc = get_current_process(); process_yield(proc, regs->esp, args->filter); }; From 0e98a07531f07f2411d8be434e27d8678c182a31 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 21:55:59 -0400 Subject: [PATCH 11/59] Working towards task switching --- src/ebus/include/ebus.h | 4 ++ src/kernel/include/kernel.h | 1 + src/kernel/include/process.h | 4 +- src/kernel/src/exec.c | 25 +++++--- src/kernel/src/kernel.c | 103 +++++++++++++++++--------------- src/kernel/src/kernel_entry.asm | 5 +- src/kernel/src/process.c | 26 ++++---- 7 files changed, 95 insertions(+), 73 deletions(-) diff --git a/src/ebus/include/ebus.h b/src/ebus/include/ebus.h index 41a7676e..82db28e5 100644 --- a/src/ebus/include/ebus.h +++ b/src/ebus/include/ebus.h @@ -24,6 +24,7 @@ enum EBUS_EVENT { EBUS_EVENT_ANY = 0, EBUS_EVENT_TIMER, EBUS_EVENT_KEY, + EBUS_EVENT_TASK_SWITCH, }; typedef struct _ebus_event { @@ -41,6 +42,9 @@ typedef struct _ebus_event { uint32_t keycode; uint32_t scancode; } key; + struct { + uint32_t next_task_pid; + } task_switch; }; } ebus_event_t; diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index fbd44d48..d966370a 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -50,6 +50,7 @@ ebus_event_t * pull_event(int event_id); int kernel_add_task(process_t * proc); int kernel_next_task(); int kernel_close_process(process_t * proc); +int kernel_set_current_task(process_t * proc); #ifdef TESTING #define NO_RETURN diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index a686695e..c5ef59f1 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -133,8 +133,8 @@ void set_next_pid(uint32_t next); #define NO_RETURN _Noreturn #endif -extern NO_RETURN void start_task(uint32_t cr3, uint32_t esp, uint32_t esp0, uint32_t eip, const ebus_event_t * event); -extern NO_RETURN void resume_task(uint32_t cr3, uint32_t esp, uint32_t esp0, const ebus_event_t * event); +extern NO_RETURN void start_task(uint32_t cr3, uint32_t esp, uint32_t eip, const ebus_event_t * event); +extern NO_RETURN void resume_task(uint32_t cr3, uint32_t esp, const ebus_event_t * event); extern NO_RETURN void switch_to_task(process_t * next_proc); #endif // KERNEL_PROCESS_H diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index c1dbc32b..63a9e6d7 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -4,6 +4,7 @@ #include "cpu/tss.h" #include "kernel.h" #include "libc/memory.h" +#include "libc/proc.h" #include "libc/stdio.h" #include "libc/string.h" #include "paging.h" @@ -34,16 +35,24 @@ int command_exec(uint8_t * buff, size_t size, size_t argc, char ** argv) { kernel_add_task(proc); - puts("Go for call\n"); + ebus_event_t event; + event.event_id = EBUS_EVENT_TASK_SWITCH; + event.task_switch.next_task_pid = proc->pid; - if (process_resume(proc, 0)) { - KPANIC("Failed to resume process"); - } + queue_event(&event); + + // kernel_set_current_task(proc); + + // puts("Go for call\n"); + + // if (process_resume(proc, 0)) { + // KPANIC("Failed to resume process"); + // } - // if process_resume does not fail, it will not return - KPANIC("How did you get here?"); + // // if process_resume does not fail, it will not return + // KPANIC("How did you get here?"); - process_free(proc); + // process_free(proc); - return -1; + return 0; } diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 9c2ec639..5ebca67b 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -36,6 +36,7 @@ static kernel_t __kernel; extern _Noreturn void halt(void); +static void early_boot(); static void init_idle_proc(); static void idle(); static void id_map_range(mmu_table_t * table, size_t start, size_t end); @@ -49,53 +50,7 @@ static void map_first_table(mmu_table_t * table); extern void jump_kernel_mode(void * fn); void kernel_main() { - init_vga(UINT2PTR(PADDR_VGA)); - vga_clear(); - - kmemset(&__kernel, 0, sizeof(kernel_t)); - - boot_params_t * bparams = get_boot_params(); - - // Init RAM - __kernel.ram_table_addr = PADDR_RAM_TABLE; - ram_init((void *)__kernel.ram_table_addr, (void *)VADDR_RAM_BITMASKS); - - for (size_t i = 0; i < bparams->mem_entries_count; i++) { - upper_ram_t * entry = &bparams->mem_entries[i]; - - // End of second stage kernel - if (entry->base_addr <= 0x9fbff) { - continue; - } - - if (entry->type == RAM_TYPE_USABLE || entry->type == RAM_TYPE_ACPI_RECLAIMABLE) { - ram_region_add_memory(entry->base_addr, entry->length); - } - } - - // Init Page Dir - __kernel.cr3 = PADDR_KERNEL_DIR; - mmu_dir_t * pdir = (mmu_dir_t *)__kernel.cr3; - mmu_dir_clear(pdir); - - // Init first table - uint32_t first_table_addr = ram_page_palloc(); - mmu_dir_set(pdir, 0, first_table_addr, MMU_DIR_RW); - - // Map first table - mmu_table_t * first_table = UINT2PTR(first_table_addr); - mmu_table_clear(first_table); - map_first_table(first_table); - - // Map last table to dir for access to tables - mmu_dir_set(pdir, MMU_DIR_SIZE - 1, __kernel.cr3, MMU_DIR_RW); - - // Enter Paging - mmu_enable_paging(__kernel.cr3); - - // GDT & TSS - init_gdt(); - init_tss(); + early_boot(); pm_create(&__kernel.pm); @@ -228,6 +183,60 @@ int kernel_close_process(process_t * proc) { return 0; } +int kernel_set_current_task(process_t * proc) { + __kernel.pm.curr_task = proc; +} + +static void early_boot() { + init_vga(UINT2PTR(PADDR_VGA)); + vga_clear(); + + kmemset(&__kernel, 0, sizeof(kernel_t)); + + boot_params_t * bparams = get_boot_params(); + + // Init RAM + __kernel.ram_table_addr = PADDR_RAM_TABLE; + ram_init((void *)__kernel.ram_table_addr, (void *)VADDR_RAM_BITMASKS); + + for (size_t i = 0; i < bparams->mem_entries_count; i++) { + upper_ram_t * entry = &bparams->mem_entries[i]; + + // End of second stage kernel + if (entry->base_addr <= 0x9fbff) { + continue; + } + + if (entry->type == RAM_TYPE_USABLE || entry->type == RAM_TYPE_ACPI_RECLAIMABLE) { + ram_region_add_memory(entry->base_addr, entry->length); + } + } + + // Init Page Dir + __kernel.cr3 = PADDR_KERNEL_DIR; + mmu_dir_t * pdir = (mmu_dir_t *)__kernel.cr3; + mmu_dir_clear(pdir); + + // Init first table + uint32_t first_table_addr = ram_page_palloc(); + mmu_dir_set(pdir, 0, first_table_addr, MMU_DIR_RW); + + // Map first table + mmu_table_t * first_table = UINT2PTR(first_table_addr); + mmu_table_clear(first_table); + map_first_table(first_table); + + // Map last table to dir for access to tables + mmu_dir_set(pdir, MMU_DIR_SIZE - 1, __kernel.cr3, MMU_DIR_RW); + + // Enter Paging + mmu_enable_paging(__kernel.cr3); + + // GDT & TSS + init_gdt(); + init_tss(); +} + static void init_idle_proc() { process_t * proc = kmalloc(sizeof(process_t)); if (process_create(proc)) { diff --git a/src/kernel/src/kernel_entry.asm b/src/kernel/src/kernel_entry.asm index 02c8e45f..a9c99064 100644 --- a/src/kernel/src/kernel_entry.asm +++ b/src/kernel/src/kernel_entry.asm @@ -85,13 +85,12 @@ TCB_ESP0 equ 12 current_task_TCB: dd 0 -; void start_task(uint32_t cr3, uint32_t esp, uint32_t esp0, uint32_t eip, const ebus_event_t * event) +; void start_task(uint32_t cr3, uint32_t esp, uint32_t eip, const ebus_event_t * event) global start_task start_task: mov ebp, esp mov ecx, [ebp+4] ; cr3 mov ebx, [ebp+8] ; esp - mov edx, [ebp+12] ; esp0 mov edi, [ebp+16] ; eip mov eax, [ebp+20] ; event @@ -101,7 +100,7 @@ start_task: jmp edi -; void resume_task(uint32_t cr3, uint32_t esp, uint32_t esp0, const ebus_event_t * event) +; void resume_task(uint32_t cr3, uint32_t esp, const ebus_event_t * event) global resume_task resume_task: mov ebp, esp diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index d4866b9a..1d79e59f 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -123,22 +123,22 @@ void process_yield(process_t * proc, uint32_t esp, int filter) { } int process_resume(process_t * proc, const ebus_event_t * event) { - if (!proc) { + if (!proc || proc->state == PROCESS_STATE_DEAD) { return -1; } - if (proc->state < PROCESS_STATE_SUSPENDED) { - proc->state = PROCESS_STATE_RUNNING; - tss_get_entry(0)->esp0 = proc->esp0; - start_task(proc->cr3, proc->esp, proc->esp0, proc->entrypoint, event); - } - - // TODO implement this - if (!proc->filter_event || !event || proc->filter_event == event->event_id) { - proc->state = PROCESS_STATE_RUNNING; - tss_get_entry(0)->esp0 = proc->esp0; - resume_task(proc->cr3, proc->esp, proc->esp0, event); - } + // if (proc->state < PROCESS_STATE_SUSPENDED) { + proc->state = PROCESS_STATE_RUNNING; + tss_get_entry(0)->esp0 = proc->esp0; + start_task(proc->cr3, proc->esp, proc->entrypoint, event); + // } + + // // TODO implement this + // else if (!proc->filter_event || !event || proc->filter_event == event->event_id) { + // proc->state = PROCESS_STATE_RUNNING; + // tss_get_entry(0)->esp0 = proc->esp0; + // start_task(proc->cr3, proc->esp, proc->entrypoint, event); + // } return -1; } From af7abfe98b7062cd2dcf6abec79575b079580e64 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 17 Mar 2025 22:07:28 -0400 Subject: [PATCH 12/59] Revert early boot --- src/kernel/src/kernel.c | 101 +++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 53 deletions(-) diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 5ebca67b..663507a7 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -36,7 +36,6 @@ static kernel_t __kernel; extern _Noreturn void halt(void); -static void early_boot(); static void init_idle_proc(); static void idle(); static void id_map_range(mmu_table_t * table, size_t start, size_t end); @@ -50,7 +49,53 @@ static void map_first_table(mmu_table_t * table); extern void jump_kernel_mode(void * fn); void kernel_main() { - early_boot(); + init_vga(UINT2PTR(PADDR_VGA)); + vga_clear(); + + kmemset(&__kernel, 0, sizeof(kernel_t)); + + boot_params_t * bparams = get_boot_params(); + + // Init RAM + __kernel.ram_table_addr = PADDR_RAM_TABLE; + ram_init((void *)__kernel.ram_table_addr, (void *)VADDR_RAM_BITMASKS); + + for (size_t i = 0; i < bparams->mem_entries_count; i++) { + upper_ram_t * entry = &bparams->mem_entries[i]; + + // End of second stage kernel + if (entry->base_addr <= 0x9fbff) { + continue; + } + + if (entry->type == RAM_TYPE_USABLE || entry->type == RAM_TYPE_ACPI_RECLAIMABLE) { + ram_region_add_memory(entry->base_addr, entry->length); + } + } + + // Init Page Dir + __kernel.cr3 = PADDR_KERNEL_DIR; + mmu_dir_t * pdir = (mmu_dir_t *)__kernel.cr3; + mmu_dir_clear(pdir); + + // Init first table + uint32_t first_table_addr = ram_page_palloc(); + mmu_dir_set(pdir, 0, first_table_addr, MMU_DIR_RW); + + // Map first table + mmu_table_t * first_table = UINT2PTR(first_table_addr); + mmu_table_clear(first_table); + map_first_table(first_table); + + // Map last table to dir for access to tables + mmu_dir_set(pdir, MMU_DIR_SIZE - 1, __kernel.cr3, MMU_DIR_RW); + + // Enter Paging + mmu_enable_paging(__kernel.cr3); + + // GDT & TSS + init_gdt(); + init_tss(); pm_create(&__kernel.pm); @@ -187,56 +232,6 @@ int kernel_set_current_task(process_t * proc) { __kernel.pm.curr_task = proc; } -static void early_boot() { - init_vga(UINT2PTR(PADDR_VGA)); - vga_clear(); - - kmemset(&__kernel, 0, sizeof(kernel_t)); - - boot_params_t * bparams = get_boot_params(); - - // Init RAM - __kernel.ram_table_addr = PADDR_RAM_TABLE; - ram_init((void *)__kernel.ram_table_addr, (void *)VADDR_RAM_BITMASKS); - - for (size_t i = 0; i < bparams->mem_entries_count; i++) { - upper_ram_t * entry = &bparams->mem_entries[i]; - - // End of second stage kernel - if (entry->base_addr <= 0x9fbff) { - continue; - } - - if (entry->type == RAM_TYPE_USABLE || entry->type == RAM_TYPE_ACPI_RECLAIMABLE) { - ram_region_add_memory(entry->base_addr, entry->length); - } - } - - // Init Page Dir - __kernel.cr3 = PADDR_KERNEL_DIR; - mmu_dir_t * pdir = (mmu_dir_t *)__kernel.cr3; - mmu_dir_clear(pdir); - - // Init first table - uint32_t first_table_addr = ram_page_palloc(); - mmu_dir_set(pdir, 0, first_table_addr, MMU_DIR_RW); - - // Map first table - mmu_table_t * first_table = UINT2PTR(first_table_addr); - mmu_table_clear(first_table); - map_first_table(first_table); - - // Map last table to dir for access to tables - mmu_dir_set(pdir, MMU_DIR_SIZE - 1, __kernel.cr3, MMU_DIR_RW); - - // Enter Paging - mmu_enable_paging(__kernel.cr3); - - // GDT & TSS - init_gdt(); - init_tss(); -} - static void init_idle_proc() { process_t * proc = kmalloc(sizeof(process_t)); if (process_create(proc)) { @@ -253,7 +248,7 @@ static void init_idle_proc() { } void idle() { - vga_puts("Start idle task\n"); + vga_puts("Start idle task\n> "); for (;;) { term_update(); ebus_cycle(get_kernel_ebus()); From 47cddd632d3d3231957d88e2b9f2e450e7b559b3 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Tue, 18 Mar 2025 05:01:36 -0400 Subject: [PATCH 13/59] Add link script file as link dependency --- cmake/targets.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/targets.cmake b/cmake/targets.cmake index 9371ad92..cccb9070 100644 --- a/cmake/targets.cmake +++ b/cmake/targets.cmake @@ -31,7 +31,7 @@ function(cross_target_binary target) -nostdlib "-L${CROSS_PREFIX}/lib/gcc/i386-elf/12.2.0" -lgcc - DEPENDS ${target} ${TARGET_LINK_FILES}) + DEPENDS ${target} ${TARGET_LINK_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/link.ld) add_custom_target(${target}_image ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${target}.bin) From 4c5b5f7a54d931626a69a64fdba86467eaa3f987 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Tue, 18 Mar 2025 05:41:12 -0400 Subject: [PATCH 14/59] Back to working term --- src/kernel/include/process.h | 12 ++++++------ src/kernel/src/exec.c | 8 ++++---- src/kernel/src/kernel.c | 14 ++++++++++---- src/kernel/src/kernel_entry.asm | 13 ++++++------- src/kernel/src/process.c | 22 ++++++++++++++++++++-- src/kernel/src/system_call_proc.c | 1 + 6 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index c5ef59f1..737eaadf 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -6,6 +6,7 @@ #include "ebus.h" #include "libc/datastruct/array.h" +#include "memory_alloc.h" typedef void (*signals_master_cb_t)(int); @@ -43,14 +44,13 @@ typedef struct _process { uint32_t entrypoint; signals_master_cb_t signals_callback; + arr_t io_handles; // array + ebus_t event_queue; + memory_t memory; - arr_t io_handles; // array - - uint32_t filter_event; - + uint32_t filter_event; enum PROCESS_STATE state; - - struct _process * next_proc; + struct _process * next_proc; } process_t; /** diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index 63a9e6d7..a09f1671 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -35,11 +35,11 @@ int command_exec(uint8_t * buff, size_t size, size_t argc, char ** argv) { kernel_add_task(proc); - ebus_event_t event; - event.event_id = EBUS_EVENT_TASK_SWITCH; - event.task_switch.next_task_pid = proc->pid; + // ebus_event_t event; + // event.event_id = EBUS_EVENT_TASK_SWITCH; + // event.task_switch.next_task_pid = proc->pid; - queue_event(&event); + // queue_event(&event); // kernel_set_current_task(proc); diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 663507a7..b8bb4058 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -97,6 +97,14 @@ void kernel_main() { init_gdt(); init_tss(); + // if (process_create(&__kernel.proc)) { + // KPANIC("Failed to create kernel process"); + // } + + // process_set_entrypoint(&__kernel.proc, idle); + // process_resume(&__kernel.proc, 0); + // halt(); + pm_create(&__kernel.pm); // Kernel process used for memory allocation @@ -104,6 +112,7 @@ void kernel_main() { __kernel.proc.cr3 = PADDR_KERNEL_DIR; __kernel.pm.curr_task = &__kernel.proc; + // TODO make this part of task switching code // Add isr stack to kernel's TSS set_kernel_stack(VADDR_ISR_STACK); @@ -270,10 +279,7 @@ NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int li vga_puts(msg); } vga_cursor_hide(); - asm("cli"); - for (;;) { - asm("hlt"); - } + halt(); } static void cursor() { diff --git a/src/kernel/src/kernel_entry.asm b/src/kernel/src/kernel_entry.asm index a9c99064..d0481e9a 100644 --- a/src/kernel/src/kernel_entry.asm +++ b/src/kernel/src/kernel_entry.asm @@ -90,14 +90,14 @@ global start_task start_task: mov ebp, esp mov ecx, [ebp+4] ; cr3 - mov ebx, [ebp+8] ; esp - mov edi, [ebp+16] ; eip - mov eax, [ebp+20] ; event + mov edx, [ebp+8] ; esp + mov ebx, [ebp+12] ; eip + mov eax, [ebp+16] ; event - mov esp, ebx + mov esp, edx mov cr3, ecx - jmp edi + jmp ebx ; void resume_task(uint32_t cr3, uint32_t esp, const ebus_event_t * event) @@ -106,8 +106,7 @@ resume_task: mov ebp, esp mov ecx, [ebp+4] ; cr3 mov ebx, [ebp+8] ; esp - mov edx, [ebp+12] ; esp0 - mov eax, [ebp+16] ; event + mov eax, [ebp+12] ; event ; TODO get tss and set it's esp0 ; mov [TSS_ESP0], ebx ;Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 1d79e59f..f7c58f1f 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -4,6 +4,7 @@ #include "cpu/tss.h" #include "kernel.h" #include "libc/string.h" +#include "libk/sys_call.h" #include "paging.h" #include "ram.h" @@ -27,10 +28,25 @@ int process_create(process_t * proc) { return -1; } + if (ebus_create(&proc->event_queue, 4096)) { + arr_free(&proc->io_handles); + ram_page_free(proc->cr3); + return -1; + } + + if (memory_init(&proc->memory, _sys_page_alloc)) { + ebus_free(&proc->event_queue); + arr_free(&proc->io_handles); + ram_page_free(proc->cr3); + return -1; + } + // Setup page directory mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + ebus_free(&proc->event_queue); + arr_free(&proc->io_handles); ram_page_free(proc->cr3); return -1; } @@ -46,6 +62,8 @@ int process_create(process_t * proc) { // Allocate pages for ISR stack + first page of user stack if (paging_add_pages(dir, ADDR2PAGE(proc->esp), ADDR2PAGE(proc->esp0))) { + ebus_free(&proc->event_queue); + arr_free(&proc->io_handles); paging_temp_free(proc->cr3); ram_page_free(proc->cr3); return -1; @@ -128,8 +146,8 @@ int process_resume(process_t * proc, const ebus_event_t * event) { } // if (proc->state < PROCESS_STATE_SUSPENDED) { - proc->state = PROCESS_STATE_RUNNING; - tss_get_entry(0)->esp0 = proc->esp0; + proc->state = PROCESS_STATE_RUNNING; + set_kernel_stack(proc->esp0); start_task(proc->cr3, proc->esp, proc->entrypoint, event); // } diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 897418d7..fbefc863 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -95,6 +95,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { // TODO clear iret from stack? process_t * proc = get_current_process(); + proc->entrypoint = regs->eip; process_yield(proc, regs->esp, args->filter); }; } From 536c0962d0fadbdc4f90a82a99ff8e536cda540c Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Tue, 18 Mar 2025 18:55:11 -0400 Subject: [PATCH 15/59] Launching and killing first task --- src/ebus/CMakeLists.txt | 2 +- src/ebus/include/ebus.h | 4 ++ src/ebus/src/ebus.c | 3 ++ src/kernel/include/kernel.h | 2 + src/kernel/include/process_manager.h | 2 + src/kernel/src/exec.c | 8 ++-- src/kernel/src/kernel.c | 62 ++++++++++++++++++++++++++-- src/kernel/src/process_manager.c | 24 +++++++++++ src/kernel/src/system_call_proc.c | 8 +++- 9 files changed, 104 insertions(+), 11 deletions(-) diff --git a/src/ebus/CMakeLists.txt b/src/ebus/CMakeLists.txt index 707d3469..d69da301 100644 --- a/src/ebus/CMakeLists.txt +++ b/src/ebus/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET ebus) cross_target(${TARGET}) -target_link_libraries(${TARGET} libc) +target_link_libraries(${TARGET} libc kernel) diff --git a/src/ebus/include/ebus.h b/src/ebus/include/ebus.h index 82db28e5..51050d93 100644 --- a/src/ebus/include/ebus.h +++ b/src/ebus/include/ebus.h @@ -25,6 +25,7 @@ enum EBUS_EVENT { EBUS_EVENT_TIMER, EBUS_EVENT_KEY, EBUS_EVENT_TASK_SWITCH, + EBUS_EVENT_TASK_KILL, }; typedef struct _ebus_event { @@ -45,6 +46,9 @@ typedef struct _ebus_event { struct { uint32_t next_task_pid; } task_switch; + struct { + uint32_t task_pid; + } task_kill; }; } ebus_event_t; diff --git a/src/ebus/src/ebus.c b/src/ebus/src/ebus.c index b9c78cb1..c1fee79b 100644 --- a/src/ebus/src/ebus.c +++ b/src/ebus/src/ebus.c @@ -1,5 +1,6 @@ #include "ebus.h" +#include "kernel.h" #include "libc/proc.h" #include "libc/stdio.h" @@ -115,6 +116,8 @@ static int handle_event(ebus_t * bus, ebus_event_t * event) { return -1; } + kernel_switch_task(handler->pid); + if (!handler->event_id || handler->event_id == event->event_id) { handler->callback_fn(event); } diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index d966370a..48d41f84 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -52,6 +52,8 @@ int kernel_next_task(); int kernel_close_process(process_t * proc); int kernel_set_current_task(process_t * proc); +int kernel_switch_task(int next_pid); + #ifdef TESTING #define NO_RETURN #else diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h index ebbefbc5..564239dd 100644 --- a/src/kernel/include/process_manager.h +++ b/src/kernel/include/process_manager.h @@ -14,6 +14,8 @@ typedef struct _proc_man { int pm_create(proc_man_t * pm); +process_t * pm_get_pid(proc_man_t * pm, int pid); + int pm_add_proc(proc_man_t * pm, process_t * proc); int pm_remove_proc(proc_man_t * pm, process_t * proc); diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index a09f1671..63a9e6d7 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -35,11 +35,11 @@ int command_exec(uint8_t * buff, size_t size, size_t argc, char ** argv) { kernel_add_task(proc); - // ebus_event_t event; - // event.event_id = EBUS_EVENT_TASK_SWITCH; - // event.task_switch.next_task_pid = proc->pid; + ebus_event_t event; + event.event_id = EBUS_EVENT_TASK_SWITCH; + event.task_switch.next_task_pid = proc->pid; - // queue_event(&event); + queue_event(&event); // kernel_set_current_task(proc); diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index b8bb4058..9428e4a4 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -36,6 +36,8 @@ static kernel_t __kernel; extern _Noreturn void halt(void); +static void handle_launch(const ebus_event_t * event); +static void handle_kill(const ebus_event_t * event); static void init_idle_proc(); static void idle(); static void id_map_range(mmu_table_t * table, size_t start, size_t end); @@ -137,6 +139,16 @@ void kernel_main() { KPANIC("Failed to init ebus\n"); } + ebus_handler_t launch_handler; + launch_handler.callback_fn = handle_launch; + launch_handler.event_id = EBUS_EVENT_TASK_SWITCH; + ebus_register_handler(&__kernel.event_bus, &launch_handler); + + ebus_handler_t kill_handler; + kill_handler.callback_fn = handle_kill; + kill_handler.event_id = EBUS_EVENT_TASK_KILL; + ebus_register_handler(&__kernel.event_bus, &kill_handler); + irq_install(); vga_puts("Welcome to kernel v" PROJECT_VERSION "\n"); @@ -162,6 +174,36 @@ void kernel_main() { KPANIC("You shouldn't be here!"); } +static void handle_launch(const ebus_event_t * event) { + printf("Start task %u\n", event->task_switch.next_task_pid); + process_t * proc = pm_get_pid(&__kernel.pm, event->task_switch.next_task_pid); + __kernel.pm.curr_task = proc; + process_resume(proc, 0); +} + +static void handle_kill(const ebus_event_t * event) { + printf("Kill task %u\n", event->task_switch.next_task_pid); + process_t * proc = pm_get_pid(&__kernel.pm, event->task_kill.task_pid); + if (pm_remove_proc(&__kernel.pm, proc)) { + KPANIC("Failed to remove process from pm"); + } + + process_free(proc); +} + +int kernel_switch_task(int next_pid) { + process_t * proc = pm_get_pid(&__kernel.pm, next_pid); + if (!proc || proc->state == PROCESS_STATE_DEAD) { + return -1; + } + + __kernel.pm.curr_task = proc; + proc->state = PROCESS_STATE_RUNNING; + set_kernel_stack(proc->esp0); + mmu_change_dir(proc->cr3); + return 0; +} + mmu_dir_t * get_kernel_dir() { return (mmu_dir_t *)__kernel.cr3; } @@ -227,12 +269,24 @@ int kernel_close_process(process_t * proc) { return -1; } - if (pm_remove_proc(&__kernel.pm, proc)) { - KPANIC("Failed to remove process from pm"); - return -1; + proc->state = PROCESS_STATE_DEAD; + + process_t * next = __kernel.pm.curr_task->next_proc; + if (!next) { + next = __kernel.pm.idle_task; } - process_free(proc); + ebus_event_t launch_event; + launch_event.event_id = EBUS_EVENT_TASK_SWITCH; + launch_event.task_switch.next_task_pid = next->pid; + + queue_event(&launch_event); + + ebus_event_t kill_event; + kill_event.event_id = EBUS_EVENT_TASK_KILL; + kill_event.task_kill.task_pid = proc->pid; + + queue_event(&kill_event); return 0; } diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 2870fd3a..928b24ac 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -12,6 +12,30 @@ int pm_create(proc_man_t * pm) { return 0; } +process_t * pm_get_pid(proc_man_t * pm, int pid) { + if (!pm || pid < 1) { + return 0; + } + + if (pm->idle_task->pid == pid) { + return pm->idle_task; + } + + if (pm->curr_task->pid == pid) { + return pm->curr_task; + } + + process_t * curr = pm->task_begin; + while (curr && curr->pid != pm->idle_task->pid) { + if (curr->pid == pid) { + return curr; + } + curr = curr->next_proc; + } + + return 0; +} + int pm_add_proc(proc_man_t * pm, process_t * proc) { if (!pm || !proc) { return -1; diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index fbefc863..73d03fb4 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -19,7 +19,9 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { uint8_t code; } * args = (struct _args *)args_data; printf("Proc exit with code %u\n", args->code); - if (kernel_close_process(get_current_process())) { + process_t * proc = get_current_process(); + enable_interrupts(); + if (kernel_close_process(proc)) { KPANIC("Kernel could not close process"); } kernel_next_task(); @@ -33,7 +35,9 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { } * args = (struct _args *)args_data; printf("Proc abort with code %u\n", args->code); puts(args->msg); - if (kernel_close_process(get_current_process())) { + process_t * proc = get_current_process(); + enable_interrupts(); + if (kernel_close_process(proc)) { KPANIC("Kernel could not close process"); } kernel_next_task(); From 5374fa0fb9239a6319fc1dbd4abc67fa8f210209 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Tue, 18 Mar 2025 19:35:14 -0400 Subject: [PATCH 16/59] Try using a call as proc fn --- src/apps/foo/src/foo.c | 2 +- src/ebus/src/ebus.c | 4 +--- src/kernel/include/kernel.h | 4 ++++ src/kernel/src/kernel.c | 31 +++++++++++++++++++++++++------ src/kernel/src/system_call_proc.c | 1 + 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/apps/foo/src/foo.c b/src/apps/foo/src/foo.c index b048f044..b9e39986 100644 --- a/src/apps/foo/src/foo.c +++ b/src/apps/foo/src/foo.c @@ -4,7 +4,7 @@ void foo() { uint32_t res = puts("Hello\n"); - proc_exit(0); + yield(EBUS_EVENT_KEY); res = printf("Hello 0x%X\n", res); diff --git a/src/ebus/src/ebus.c b/src/ebus/src/ebus.c index c1fee79b..5f4d4d5a 100644 --- a/src/ebus/src/ebus.c +++ b/src/ebus/src/ebus.c @@ -116,10 +116,8 @@ static int handle_event(ebus_t * bus, ebus_event_t * event) { return -1; } - kernel_switch_task(handler->pid); - if (!handler->event_id || handler->event_id == event->event_id) { - handler->callback_fn(event); + kernel_call_as_proc(handler->pid, (_proc_call_t)(handler->callback_fn), (void *)event); } } diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index 48d41f84..4cfd1948 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -52,6 +52,10 @@ int kernel_next_task(); int kernel_close_process(process_t * proc); int kernel_set_current_task(process_t * proc); +typedef int (*_proc_call_t)(void * data); + +int kernel_call_as_proc(int pid, _proc_call_t fn, void * data); + int kernel_switch_task(int next_pid); #ifdef TESTING diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 9428e4a4..f511777c 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -139,14 +139,14 @@ void kernel_main() { KPANIC("Failed to init ebus\n"); } - ebus_handler_t launch_handler; - launch_handler.callback_fn = handle_launch; - launch_handler.event_id = EBUS_EVENT_TASK_SWITCH; + ebus_handler_t launch_handler = {0}; + launch_handler.callback_fn = handle_launch; + launch_handler.event_id = EBUS_EVENT_TASK_SWITCH; ebus_register_handler(&__kernel.event_bus, &launch_handler); - ebus_handler_t kill_handler; - kill_handler.callback_fn = handle_kill; - kill_handler.event_id = EBUS_EVENT_TASK_KILL; + ebus_handler_t kill_handler = {0}; + kill_handler.callback_fn = handle_kill; + kill_handler.event_id = EBUS_EVENT_TASK_KILL; ebus_register_handler(&__kernel.event_bus, &kill_handler); irq_install(); @@ -191,6 +191,25 @@ static void handle_kill(const ebus_event_t * event) { process_free(proc); } +int kernel_call_as_proc(int pid, _proc_call_t fn, void * data) { + if (!fn) { + return -1; + } + + process_t * curr = get_current_process(); + if (curr->pid != pid) { + kernel_switch_task(pid); + } + + int res = fn(data); + + if (curr->pid != pid) { + kernel_switch_task(curr->pid); + } + + return res; +} + int kernel_switch_task(int next_pid) { process_t * proc = pm_get_pid(&__kernel.pm, next_pid); if (!proc || proc->state == PROCESS_STATE_DEAD) { diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 73d03fb4..edf31d00 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -100,6 +100,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { // TODO clear iret from stack? process_t * proc = get_current_process(); proc->entrypoint = regs->eip; + enable_interrupts(); process_yield(proc, regs->esp, args->filter); }; } From 899c99a090633d9dae03ed82bec54a3593d8473e Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Wed, 19 Mar 2025 19:04:35 -0400 Subject: [PATCH 17/59] Add pid command --- src/kernel/src/commands.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/kernel/src/commands.c b/src/kernel/src/commands.c index 27c32baf..b2292714 100644 --- a/src/kernel/src/commands.c +++ b/src/kernel/src/commands.c @@ -562,6 +562,11 @@ static int currdir(size_t argc, char ** argv) { return 0; } +static int currproc(size_t argc, char ** argv) { + printf("Current pid is %p\n", get_current_process()->pid); + return 0; +} + static int hotswap(size_t argc, char ** argv) { uint32_t curr_dir = mmu_get_curr_dir(); @@ -778,6 +783,7 @@ void commands_init() { set_command_lookup(command_lookup); term_command_add("currdir", currdir); + term_command_add("pid", currproc); term_command_add("hotswap", hotswap); term_command_add("procswap", procswap); From 344cec5a9e8c163bcfd4b4c45f39f89447b2ac23 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Wed, 19 Mar 2025 19:27:03 -0400 Subject: [PATCH 18/59] Add disk and tar to kernel, mount in kernel_entry --- src/kernel/include/kernel.h | 7 ++ src/kernel/src/commands.c | 155 ++++++++++++++++++------------------ src/kernel/src/kernel.c | 18 +++++ 3 files changed, 101 insertions(+), 79 deletions(-) diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index 4cfd1948..e46eece1 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -5,6 +5,8 @@ #include #include "cpu/mmu.h" +#include "drivers/disk.h" +#include "drivers/tar.h" #include "ebus.h" #include "memory_alloc.h" #include "process.h" @@ -17,6 +19,8 @@ typedef struct _kernel { proc_man_t pm; memory_t kernel_memory; ebus_t event_bus; + disk_t * disk; + tar_fs_t * tar; } kernel_t; /** @@ -39,6 +43,9 @@ mmu_dir_t * get_kernel_dir(); */ mmu_table_t * get_kernel_table(); +disk_t * kernel_get_disk(); +tar_fs_t * kernel_get_tar(); + process_t * get_current_process(); ebus_t * get_kernel_ebus(); diff --git a/src/kernel/src/commands.c b/src/kernel/src/commands.c index b2292714..b796ee22 100644 --- a/src/kernel/src/commands.c +++ b/src/kernel/src/commands.c @@ -27,9 +27,6 @@ bool debug = false; -static disk_t * disk = 0; -static tar_fs_t * tar = 0; - static int clear_cmd(size_t argc, char ** argv) { vga_clear(); return 0; @@ -192,55 +189,55 @@ static int ret_cmd(size_t argc, char ** argv) { // return 1; // } -// if (!disk) { +// if (!kernel_get_disk()) { // disk = disk_open(0, DISK_DRIVER_ATA); -// if (!disk) { +// if (!kernel_get_disk()) { // puts("Failed to open disk\n"); // return 1; // } // } // puts("Formatting disk, this may take some time\n"); -// // fs_format(disk); +// // fs_format(kernel_get_disk()); // puts("Done!\n"); // return 0; // } -static int mount_cmd(size_t argc, char ** argv) { - if (tar) { - puts("Filesystem already mounted\n"); - return 0; - } +// static int mount_cmd(size_t argc, char ** argv) { +// if (kernel_get_tar()) { +// puts("Filesystem already mounted\n"); +// return 0; +// } - if (!disk) { - disk = disk_open(0, DISK_DRIVER_ATA); - if (!disk) { - puts("Failed to open disk\n"); - return 1; - } - } +// if (!kernel_get_disk()) { +// disk = disk_open(0, DISK_DRIVER_ATA); +// if (!kernel_get_disk()) { +// puts("Failed to open disk\n"); +// return 1; +// } +// } - tar = tar_open(disk); - if (!tar) { - puts("Failed to mount filesystem\n"); - return 1; - } +// tar = tar_open(kernel_get_disk()); +// if (!kernel_get_tar()) { +// puts("Failed to mount filesystem\n"); +// return 1; +// } - return 0; -} +// return 0; +// } -static int unmount_cmd(size_t argc, char ** argv) { - if (tar) { - tar_close(tar); - tar = 0; - } - if (disk) { - disk_close(disk); - disk = 0; - } - return 0; -} +// static int unmount_cmd(size_t argc, char ** argv) { +// if (kernel_get_tar()) { +// tar_close(kernel_get_tar()); +// tar = 0; +// } +// if (kernel_get_disk()) { +// disk_close(kernel_get_disk()); +// disk = 0; +// } +// return 0; +// } static void print_64(uint64_t v) { uint32_t u = v >> 32; @@ -335,17 +332,17 @@ static void ls_print_file(tar_stat_t * stat) { } static int ls_cmd(size_t argc, char ** argv) { - if (!tar) { + if (!kernel_get_tar()) { puts("Filesystem not mounted\n"); return 1; } - size_t file_count = tar_file_count(tar); + size_t file_count = tar_file_count(kernel_get_tar()); printf("Found %u files\n", file_count); tar_stat_t stat; for (size_t i = 0; i < file_count; i++) { - if (!tar_stat_file_i(tar, i, &stat)) { + if (!tar_stat_file_i(kernel_get_tar(), i, &stat)) { return 1; } ls_print_file(&stat); @@ -356,13 +353,13 @@ static int ls_cmd(size_t argc, char ** argv) { } static int stat_cmd(size_t argc, char ** argv) { - if (!tar) { + if (!kernel_get_tar()) { puts("Filesystem not mounted\n"); return 1; } tar_stat_t stat; - if (!tar_stat_file_i(tar, 0, &stat)) { + if (!tar_stat_file_i(kernel_get_tar(), 0, &stat)) { puts("Failed to stat file\n"); return 1; } @@ -384,13 +381,13 @@ static int fs_read_cmd(size_t argc, char ** argv) { char * filename = argv[1]; - if (!tar) { + if (!kernel_get_tar()) { puts("Filesystem not mounted\n"); return 1; } tar_stat_t stat; - if (!tar_stat_file(tar, filename, &stat)) { + if (!tar_stat_file(kernel_get_tar(), filename, &stat)) { puts("Failed to find file\n"); return 1; } @@ -401,7 +398,7 @@ static int fs_read_cmd(size_t argc, char ** argv) { return 1; } - tar_fs_file_t * file = tar_file_open(tar, filename); + tar_fs_file_t * file = tar_file_open(kernel_get_tar(), filename); if (!file) { kfree(buff); return 1; @@ -414,7 +411,7 @@ static int fs_read_cmd(size_t argc, char ** argv) { } print_hexblock(buff, stat.size, 0); - if (!disk || !buff) { + if (!buff) { return 0; } @@ -432,13 +429,13 @@ static int fs_cat_cmd(size_t argc, char ** argv) { char * filename = argv[1]; - if (!tar) { + if (!kernel_get_tar()) { puts("Filesystem not mounted\n"); return 1; } tar_stat_t stat; - if (!tar_stat_file(tar, filename, &stat)) { + if (!tar_stat_file(kernel_get_tar(), filename, &stat)) { puts("Failed to find file\n"); return 1; } @@ -448,7 +445,7 @@ static int fs_cat_cmd(size_t argc, char ** argv) { return 1; } - tar_fs_file_t * file = tar_file_open(tar, filename); + tar_fs_file_t * file = tar_file_open(kernel_get_tar(), filename); if (!file) { kfree(buff); return 1; @@ -463,7 +460,7 @@ static int fs_cat_cmd(size_t argc, char ** argv) { putc(buff[i]); } - if (!disk || !buff) { + if (!buff) { return 0; } @@ -487,13 +484,13 @@ static int disk_read_cmd(size_t argc, char ** argv) { size_t pos = katoi(argv[1]); size_t count = katoi(argv[2]); - if (!disk) { - disk = disk_open(0, DISK_DRIVER_ATA); - if (!disk) { - puts("Failed to open disk\n"); - return 1; - } - } + // if (!kernel_get_disk()) { + // disk = disk_open(0, DISK_DRIVER_ATA); + // if (!kernel_get_disk()) { + // puts("Failed to open disk\n"); + // return 1; + // } + // } char data[513]; size_t steps = count / 512; @@ -505,7 +502,7 @@ static int disk_read_cmd(size_t argc, char ** argv) { if (to_read > 512) { to_read = 512; } - size_t read = disk_read(disk, data, to_read, pos); + size_t read = disk_read(kernel_get_disk(), data, to_read, pos); data[read] = 0; print_hexblock(data, read, 512 * i); count -= to_read; @@ -516,13 +513,13 @@ static int disk_read_cmd(size_t argc, char ** argv) { } static int disk_write_cmd(size_t argc, char ** argv) { - if (!disk) { - disk = disk_open(0, DISK_DRIVER_ATA); - if (!disk) { - puts("Failed to open disk\n"); - return 1; - } - } + // if (!kernel_get_disk()) { + // disk = disk_open(0, DISK_DRIVER_ATA); + // if (!kernel_get_disk()) { + // puts("Failed to open disk\n"); + // return 1; + // } + // } char data[512] = {0}; for (size_t i = 0; i < 512; i++) { @@ -540,19 +537,19 @@ static int disk_write_cmd(size_t argc, char ** argv) { data[i * 2 + 1] = (i & 0xf) + 'a' - 10; } } - disk_write(disk, data, 512, 0); + disk_write(kernel_get_disk(), data, 512, 0); return 0; } static int disk_size_cmd(size_t argc, char ** argv) { - if (!disk) { - disk = disk_open(0, DISK_DRIVER_ATA); - if (!disk) { - puts("Failed to open disk\n"); - return 1; - } - } - size_t size = disk_size(disk); + // if (!kernel_get_disk()) { + // disk = disk_open(0, DISK_DRIVER_ATA); + // if (!kernel_get_disk()) { + // puts("Failed to open disk\n"); + // return 1; + // } + // } + size_t size = disk_size(kernel_get_disk()); printf("Disk size %u\n", size); return 0; } @@ -739,13 +736,13 @@ static int procswap(size_t argc, char ** argv) { static int command_lookup(size_t argc, char ** argv) { char * filename = argv[0]; - if (!tar) { + if (!kernel_get_tar()) { puts("Filesystem not mounted\n"); return 1; } tar_stat_t stat; - if (!tar_stat_file(tar, filename, &stat)) { + if (!tar_stat_file(kernel_get_tar(), filename, &stat)) { puts("Failed to find file\n"); return 1; } @@ -755,7 +752,7 @@ static int command_lookup(size_t argc, char ** argv) { return 1; } - tar_fs_file_t * file = tar_file_open(tar, filename); + tar_fs_file_t * file = tar_file_open(kernel_get_tar(), filename); if (!file) { kfree(buff); return 1; @@ -769,7 +766,7 @@ static int command_lookup(size_t argc, char ** argv) { int res = command_exec(buff, stat.size, argc, argv); - if (!disk || !buff) { + if (!buff) { return 0; } @@ -797,8 +794,8 @@ void commands_init() { term_command_add("sleep", sleep_cmd); term_command_add("ret", ret_cmd); // term_command_add("format", format_cmd); - term_command_add("mount", mount_cmd); - term_command_add("unmount", unmount_cmd); + // term_command_add("mount", mount_cmd); + // term_command_add("unmount", unmount_cmd); // term_command_add("mem", mem_cmd); term_command_add("ls", ls_cmd); term_command_add("stat", stat_cmd); diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index f511777c..2cf7e24b 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -160,6 +160,16 @@ void kernel_main() { ramdisk_create(4096); + __kernel.disk = disk_open(0, DISK_DRIVER_ATA); + if (!__kernel.disk) { + KPANIC("Failed to open ATA disk"); + } + + __kernel.tar = tar_open(__kernel.disk); + if (!__kernel.tar) { + KPANIC("Failed to open tar"); + } + // set_first_task(__kernel.pm.curr_task); // switch_to_task(__kernel.pm.curr_task); @@ -239,6 +249,14 @@ ebus_t * get_kernel_ebus() { return &__kernel.event_bus; } +disk_t * kernel_get_disk() { + return __kernel.disk; +} + +tar_fs_t * kernel_get_tar() { + return __kernel.tar; +} + void tmp_register_signals_cb(signals_master_cb_t cb) { __kernel.pm.curr_task->signals_callback = cb; printf("Attached master signal callback at %p\n", __kernel.pm.curr_task->signals_callback); From e3e1b35e793aa5f30aee8c7ef8a5a6286659d6ef Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Fri, 21 Mar 2025 23:26:12 -0400 Subject: [PATCH 19/59] Add wip unused idle.c and idle.h --- src/kernel/include/idle.h | 8 ++++++++ src/kernel/src/idle.c | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/kernel/include/idle.h create mode 100644 src/kernel/src/idle.c diff --git a/src/kernel/include/idle.h b/src/kernel/include/idle.h new file mode 100644 index 00000000..02296d87 --- /dev/null +++ b/src/kernel/include/idle.h @@ -0,0 +1,8 @@ +#ifndef KERNEL_IDLE_H +#define KERNEL_IDLE_H + +#include + +process_t * init_idle(); + +#endif // KERNEL_IDLE_H diff --git a/src/kernel/src/idle.c b/src/kernel/src/idle.c new file mode 100644 index 00000000..26713888 --- /dev/null +++ b/src/kernel/src/idle.c @@ -0,0 +1,25 @@ +#include "idle.h" + +#include "kernel.h" +#include "libc/memory.h" +#include "libc/proc.h" + +static void idle_loop(); + +process_t * init_idle() { + process_t * proc = kmalloc(sizeof(process_t)); + if (!proc || process_create(proc)) { + return 0; + } + + process_set_entrypoint(proc, idle_loop); + + return proc; +} + +static void idle_loop() { + for (;;) { + ebus_cycle(get_kernel_ebus()); + asm("hlt"); + } +} From ae8e2f10aaee725b8ea0d04725407223c4d308f7 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Fri, 21 Mar 2025 23:28:43 -0400 Subject: [PATCH 20/59] Add process_activate --- src/kernel/include/process.h | 4 ++++ src/kernel/src/process.c | 28 +++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 737eaadf..9bdaca13 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -28,6 +28,7 @@ enum PROCESS_STATE { PROCESS_STATE_WAITING, PROCESS_STATE_RUNNING, PROCESS_STATE_DEAD, + PROCESS_STATE_ERROR, }; typedef struct _process { @@ -75,6 +76,9 @@ int process_free(process_t * proc); int process_set_entrypoint(process_t * proc, void * entrypoint); +// Load page table and esp0, don't resume +int process_activate(process_t * proc); + void process_yield(process_t * proc, uint32_t esp, int filter); int process_resume(process_t * proc, const ebus_event_t * event); diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index f7c58f1f..d29a3519 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -83,6 +83,7 @@ int process_free(process_t * proc) { return -1; } + ebus_free(&proc->event_queue); arr_free(&proc->io_handles); mmu_dir_t * dir = paging_temp_map(proc->cr3); @@ -133,6 +134,17 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { proc->entrypoint = PTR2UINT(entrypoint); } +int process_activate(process_t * proc) { + if (!proc) { + return -1; + } + + set_kernel_stack(proc->esp0); // just updates tss 0 + mmu_change_dir(proc->cr3); + + return 0; +} + void process_yield(process_t * proc, uint32_t esp, int filter) { proc->filter_event = filter; proc->esp = esp; @@ -141,22 +153,15 @@ void process_yield(process_t * proc, uint32_t esp, int filter) { } int process_resume(process_t * proc, const ebus_event_t * event) { - if (!proc || proc->state == PROCESS_STATE_DEAD) { + if (!proc || proc->state >= PROCESS_STATE_DEAD) { return -1; } - // if (proc->state < PROCESS_STATE_SUSPENDED) { + process_activate(proc); proc->state = PROCESS_STATE_RUNNING; - set_kernel_stack(proc->esp0); start_task(proc->cr3, proc->esp, proc->entrypoint, event); - // } - - // // TODO implement this - // else if (!proc->filter_event || !event || proc->filter_event == event->event_id) { - // proc->state = PROCESS_STATE_RUNNING; - // tss_get_entry(0)->esp0 = proc->esp0; - // start_task(proc->cr3, proc->esp, proc->entrypoint, event); - // } + + proc->state = PROCESS_STATE_ERROR; return -1; } @@ -279,6 +284,7 @@ static uint32_t __pid; static uint32_t next_pid() { static int pid_set = 0; + // Handle initializing __pid because there is no static init if (!pid_set) { __pid = 1; pid_set = 1; From 05218bad199f87803b8abb1901676f67579baaa1 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Fri, 21 Mar 2025 23:33:13 -0400 Subject: [PATCH 21/59] hybrid updated process manager --- src/kernel/include/process_manager.h | 21 ++- src/kernel/src/kernel.c | 50 +++---- src/kernel/src/process_manager.c | 186 ++++++++++++++++++++++----- 3 files changed, 189 insertions(+), 68 deletions(-) diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h index 564239dd..0c0121f2 100644 --- a/src/kernel/include/process_manager.h +++ b/src/kernel/include/process_manager.h @@ -4,19 +4,32 @@ #include #include +#include "ebus.h" +#include "libc/datastruct/array.h" #include "process.h" typedef struct _proc_man { + arr_t task_list; // process_t * + process_t * active; process_t * idle_task; - process_t * task_begin; - process_t * curr_task; } proc_man_t; int pm_create(proc_man_t * pm); -process_t * pm_get_pid(proc_man_t * pm, int pid); +// TODO pm_free + +process_t * pm_get_active(proc_man_t * pm); +process_t * pm_find_pid(proc_man_t * pm, int pid); int pm_add_proc(proc_man_t * pm, process_t * proc); -int pm_remove_proc(proc_man_t * pm, process_t * proc); +int pm_remove_proc(proc_man_t * pm, int pid); + +int pm_activate_process(proc_man_t * pm, int pid); +int pm_switch_process(proc_man_t * pm); +int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event); + +process_t * pm_get_next(proc_man_t * pm); + +int pm_push_event(proc_man_t * pm, ebus_event_t * event); #endif // KERNEL_PROCESS_MANAGER_H diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 2cf7e24b..8f67dfbb 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -112,7 +112,7 @@ void kernel_main() { // Kernel process used for memory allocation __kernel.proc.next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); __kernel.proc.cr3 = PADDR_KERNEL_DIR; - __kernel.pm.curr_task = &__kernel.proc; + __kernel.pm.active = &__kernel.proc; // TODO make this part of task switching code // Add isr stack to kernel's TSS @@ -132,8 +132,9 @@ void kernel_main() { init_idle_proc(); __kernel.proc.next_proc = __kernel.pm.idle_task; - __kernel.pm.curr_task = &__kernel.proc; - __kernel.pm.task_begin = &__kernel.proc; + __kernel.pm.active = &__kernel.proc; + pm_add_proc(&__kernel.pm, &__kernel.proc); + // __kernel.pm.task_begin = &__kernel.proc; if (ebus_create(&__kernel.event_bus, 4096)) { KPANIC("Failed to init ebus\n"); @@ -170,9 +171,9 @@ void kernel_main() { KPANIC("Failed to open tar"); } - // set_first_task(__kernel.pm.curr_task); + // set_first_task(__kernel.pm.active); - // switch_to_task(__kernel.pm.curr_task); + // switch_to_task(__kernel.pm.active); process_resume(__kernel.pm.idle_task, 0); @@ -186,15 +187,15 @@ void kernel_main() { static void handle_launch(const ebus_event_t * event) { printf("Start task %u\n", event->task_switch.next_task_pid); - process_t * proc = pm_get_pid(&__kernel.pm, event->task_switch.next_task_pid); - __kernel.pm.curr_task = proc; + process_t * proc = pm_find_pid(&__kernel.pm, event->task_switch.next_task_pid); + __kernel.pm.active = proc; process_resume(proc, 0); } static void handle_kill(const ebus_event_t * event) { printf("Kill task %u\n", event->task_switch.next_task_pid); - process_t * proc = pm_get_pid(&__kernel.pm, event->task_kill.task_pid); - if (pm_remove_proc(&__kernel.pm, proc)) { + process_t * proc = pm_find_pid(&__kernel.pm, event->task_kill.task_pid); + if (pm_remove_proc(&__kernel.pm, proc->pid)) { KPANIC("Failed to remove process from pm"); } @@ -221,13 +222,13 @@ int kernel_call_as_proc(int pid, _proc_call_t fn, void * data) { } int kernel_switch_task(int next_pid) { - process_t * proc = pm_get_pid(&__kernel.pm, next_pid); + process_t * proc = pm_find_pid(&__kernel.pm, next_pid); if (!proc || proc->state == PROCESS_STATE_DEAD) { return -1; } - __kernel.pm.curr_task = proc; - proc->state = PROCESS_STATE_RUNNING; + __kernel.pm.active = proc; + proc->state = PROCESS_STATE_RUNNING; set_kernel_stack(proc->esp0); mmu_change_dir(proc->cr3); return 0; @@ -242,7 +243,7 @@ mmu_table_t * get_kernel_table() { } process_t * get_current_process() { - return __kernel.pm.curr_task; + return __kernel.pm.active; } ebus_t * get_kernel_ebus() { @@ -258,8 +259,8 @@ tar_fs_t * kernel_get_tar() { } void tmp_register_signals_cb(signals_master_cb_t cb) { - __kernel.pm.curr_task->signals_callback = cb; - printf("Attached master signal callback at %p\n", __kernel.pm.curr_task->signals_callback); + __kernel.pm.active->signals_callback = cb; + printf("Attached master signal callback at %p\n", __kernel.pm.active->signals_callback); } ebus_event_t * pull_event(int event_id) { @@ -271,16 +272,7 @@ ebus_event_t * pull_event(int event_id) { } int kernel_add_task(process_t * proc) { - if (!proc) { - return -1; - } - process_t * curr = __kernel.pm.task_begin; - while (curr->next_proc && curr->next_proc != __kernel.pm.idle_task) { - curr = curr->next_proc; - } - curr->next_proc = proc; - proc->next_proc = __kernel.pm.idle_task; - return 0; + return pm_add_proc(&__kernel.pm, proc); } int kernel_next_task() { @@ -290,11 +282,11 @@ int kernel_next_task() { next = __kernel.pm.idle_task; } - __kernel.pm.curr_task = next; + __kernel.pm.active = next; // TODO interrupt back to process for sigint - if (process_resume(__kernel.pm.curr_task, 0)) { + if (process_resume(__kernel.pm.active, 0)) { KPANIC("Failed to resume task"); } @@ -308,7 +300,7 @@ int kernel_close_process(process_t * proc) { proc->state = PROCESS_STATE_DEAD; - process_t * next = __kernel.pm.curr_task->next_proc; + process_t * next = __kernel.pm.active->next_proc; if (!next) { next = __kernel.pm.idle_task; } @@ -329,7 +321,7 @@ int kernel_close_process(process_t * proc) { } int kernel_set_current_task(process_t * proc) { - __kernel.pm.curr_task = proc; + __kernel.pm.active = proc; } static void init_idle_proc() { diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 928b24ac..5807f1b5 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -1,85 +1,201 @@ #include "process_manager.h" +#include "libc/proc.h" +#include "libc/stdio.h" + +static int pid_arr_index(arr_t * arr, int pid); + int pm_create(proc_man_t * pm) { if (!pm) { return -1; } - pm->idle_task = 0; - pm->task_begin = 0; - pm->curr_task = 0; + if (arr_create(&pm->task_list, 4, sizeof(process_t *))) { + return -1; + } + + pm->active = 0; return 0; } -process_t * pm_get_pid(proc_man_t * pm, int pid) { +process_t * pm_get_active(proc_man_t * pm) { + if (!pm) { + return 0; + } + + return pm->active; +} + +process_t * pm_find_pid(proc_man_t * pm, int pid) { if (!pm || pid < 1) { return 0; } - if (pm->idle_task->pid == pid) { - return pm->idle_task; + int i = pid_arr_index(&pm->task_list, pid); + if (i < 0) { + return 0; } - if (pm->curr_task->pid == pid) { - return pm->curr_task; + process_t * proc; + arr_get(&pm->task_list, i, &proc); + + return proc; +} + +int pm_add_proc(proc_man_t * pm, process_t * proc) { + if (!pm || !proc) { + return -1; } - process_t * curr = pm->task_begin; - while (curr && curr->pid != pm->idle_task->pid) { - if (curr->pid == pid) { - return curr; - } - curr = curr->next_proc; + if (arr_insert(&pm->task_list, arr_size(&pm->task_list), &proc)) { + return -1; } return 0; } -int pm_add_proc(proc_man_t * pm, process_t * proc) { - if (!pm || !proc) { +int pm_remove_proc(proc_man_t * pm, int pid) { + if (!pm || pid < 1) { return -1; } - process_t * curr = pm->curr_task; - while (curr->next_proc && curr->next_proc != pm->idle_task) { - curr = curr->next_proc; + if (pid == pm->active->pid) { + return -1; + } + + int i = pid_arr_index(&pm->task_list, pid); + if (i < 0 || arr_remove(&pm->task_list, i, 0)) { + return -1; + } + + return -1; +} + +int pm_activate_process(proc_man_t * pm, int pid) { + if (!pm) { + return -1; } - curr->next_proc = proc; - proc->next_proc = pm->idle_task; + if (pid == pm->active->pid) { + return 0; + } + + process_t * proc = pm_find_pid(pm, pid); + if (!pid) { + return -1; + } + + if (proc->state >= PROCESS_STATE_DEAD) { + return -1; + } + + if (process_activate(proc)) { + return -1; + } + + if (pm->active->state == PROCESS_STATE_RUNNING) { + pm->active->state = PROCESS_STATE_SUSPENDED; + } + + proc->state = PROCESS_STATE_RUNNING; + pm->active = proc; return 0; } -int pm_remove_proc(proc_man_t * pm, process_t * proc) { - if (!pm || !proc) { +int pm_switch_process(proc_man_t * pm) { + if (!pm) { + return -1; + } + + int last_pid = pm->active->pid; + + do { + pm->active = pm_get_next(pm); + + if (pm->active->pid == last_pid) { + PANIC("Process loop detected"); + } + } while (pm->active->state < PROCESS_STATE_DEAD); + + pm_activate_process(pm, pm->active->pid); + + return -1; +} + +int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { + if (!pm) { return -1; } - if (!proc->pid || proc->pid == pm->idle_task->pid) { + process_t * proc = pm_find_pid(pm, pid); + if (!proc) { return -1; } - if (pm->curr_task->pid == proc->pid) { - pm->curr_task = pm->curr_task->next_proc; + return process_resume(proc, event); +} + +process_t * pm_get_next(proc_man_t * pm) { + if (!pm) { + return 0; + } + + int i = pid_arr_index(&pm->task_list, pm->active->pid); + if (i < 0) { + return 0; } - // TODO not yet implemented, because idk how this struct will be - process_t * curr = pm->task_begin; + i++; + + if (i >= arr_size(&pm->task_list)) { + i = 0; + } - if (curr->pid == proc->pid) { - pm->task_begin = curr->next_proc; + process_t * proc; + if (arr_get(&pm->task_list, i, &proc)) { return 0; } - while (curr->next_proc && curr->next_proc != pm->idle_task && curr->next_proc != pm->curr_task) { - if (curr->next_proc->pid == proc->pid) { - curr->next_proc = curr->next_proc->next_proc; - return 0; + return proc; +} + +static int pid_arr_index(arr_t * arr, int pid) { + if (!arr) { + return -1; + } + + for (int i = 0; i < arr_size(arr); i++) { + process_t * proc; + arr_get(arr, i, &proc); + + if (proc->pid == pid) { + return i; } - curr = curr->next_proc; } return -1; } + +int pm_push_event(proc_man_t * pm, ebus_event_t * event) { + if (!pm || !event) { + return -1; + } + + for (size_t i = 0; i < arr_size(&pm->task_list); i++) { + process_t * proc; + arr_get(&pm->task_list, i, &proc); + + if (proc->state >= PROCESS_STATE_DEAD) { + continue; + } + + ebus_push(&proc->event_queue, event); + if (proc->filter_event && event && event->event_id == proc->filter_event) { + proc->state = PROCESS_STATE_SUSPENDED; + } + } + + return 0; +} From 504fa5ece8d08c0d975ab363375f75c5c8b3ba31 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Fri, 21 Mar 2025 23:37:22 -0400 Subject: [PATCH 22/59] Use new idle process --- src/kernel/src/kernel.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 8f67dfbb..44005433 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -14,6 +14,7 @@ #include "drivers/rtc.h" #include "drivers/timer.h" #include "drivers/vga.h" +#include "idle.h" #include "io/file.h" #include "kernel/boot_params.h" #include "kernel/system_call.h" @@ -38,7 +39,7 @@ extern _Noreturn void halt(void); static void handle_launch(const ebus_event_t * event); static void handle_kill(const ebus_event_t * event); -static void init_idle_proc(); +// static void init_idle_proc(); static void idle(); static void id_map_range(mmu_table_t * table, size_t start, size_t end); static void id_map_page(mmu_table_t * table, size_t page); @@ -130,7 +131,8 @@ void kernel_main() { memory_init(&__kernel.kernel_memory, _sys_page_alloc); init_malloc(&__kernel.kernel_memory); - init_idle_proc(); + process_t * idle = init_idle(); + __kernel.pm.idle_task = idle; __kernel.proc.next_proc = __kernel.pm.idle_task; __kernel.pm.active = &__kernel.proc; pm_add_proc(&__kernel.pm, &__kernel.proc); @@ -324,20 +326,20 @@ int kernel_set_current_task(process_t * proc) { __kernel.pm.active = proc; } -static void init_idle_proc() { - process_t * proc = kmalloc(sizeof(process_t)); - if (process_create(proc)) { - KPANIC("Failed to create idle task"); - } +// static void init_idle_proc() { +// process_t * proc = kmalloc(sizeof(process_t)); +// if (process_create(proc)) { +// KPANIC("Failed to create idle task"); +// } - // Kernel process used for memory allocation - proc->next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); - process_set_entrypoint(proc, idle); +// // Kernel process used for memory allocation +// proc->next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); +// process_set_entrypoint(proc, idle); - // Setup kernel process as idle process - __kernel.pm.idle_task = proc; - // __kernel.pm.task_begin = proc; -} +// // Setup kernel process as idle process +// __kernel.pm.idle_task = proc; +// // __kernel.pm.task_begin = proc; +// } void idle() { vga_puts("Start idle task\n> "); From dacad62988115ed0dfa9d444eb14f6fe3cf129d7 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 10:15:19 -0400 Subject: [PATCH 23/59] Mostly working process init --- src/ebus/src/ebus.c | 21 +++++- src/kernel/include/kernel.h | 4 +- src/kernel/src/kernel.c | 115 ++++++++++++++++++------------- src/kernel/src/process_manager.c | 3 + src/kernel/src/term.c | 28 ++++++-- 5 files changed, 113 insertions(+), 58 deletions(-) diff --git a/src/ebus/src/ebus.c b/src/ebus/src/ebus.c index 5f4d4d5a..d13fbabd 100644 --- a/src/ebus/src/ebus.c +++ b/src/ebus/src/ebus.c @@ -101,7 +101,12 @@ int ebus_cycle(ebus_t * bus) { return -1; } - if (handle_event(bus, &event)) { + // if (handle_event(bus, &event)) { + // // Handler consumed event + // continue; + // } + + if (pm_push_event(kernel_get_proc_man(), &event)) { return -1; } } @@ -110,6 +115,8 @@ int ebus_cycle(ebus_t * bus) { } static int handle_event(ebus_t * bus, ebus_event_t * event) { + process_t * curr = get_current_process(); + for (size_t i = 0; i < arr_size(&bus->handlers); i++) { ebus_handler_t * handler = arr_at(&bus->handlers, i); if (!handler) { @@ -117,9 +124,19 @@ static int handle_event(ebus_t * bus, ebus_event_t * event) { } if (!handler->event_id || handler->event_id == event->event_id) { - kernel_call_as_proc(handler->pid, (_proc_call_t)(handler->callback_fn), (void *)event); + process_t * proc = kernel_find_pid(handler->pid); + if (!proc) { + PANIC("Handler does not exist"); + } + + // TODO push to process and mark as ready + + // set_current_process(proc); + // handler->callback_fn(event); } } + pm_activate_process(kernel_get_proc_man(), curr->pid); + return 0; } diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index e46eece1..351176ac 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -48,7 +48,9 @@ tar_fs_t * kernel_get_tar(); process_t * get_current_process(); -ebus_t * get_kernel_ebus(); +ebus_t * get_kernel_ebus(); +proc_man_t * kernel_get_proc_man(); +process_t * kernel_find_pid(int pid); void tmp_register_signals_cb(signals_master_cb_t cb); diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 44005433..209dd964 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -108,8 +108,6 @@ void kernel_main() { // process_resume(&__kernel.proc, 0); // halt(); - pm_create(&__kernel.pm); - // Kernel process used for memory allocation __kernel.proc.next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); __kernel.proc.cr3 = PADDR_KERNEL_DIR; @@ -131,11 +129,16 @@ void kernel_main() { memory_init(&__kernel.kernel_memory, _sys_page_alloc); init_malloc(&__kernel.kernel_memory); - process_t * idle = init_idle(); + pm_create(&__kernel.pm); + __kernel.pm.active = &__kernel.proc; + + process_t * idle = init_idle(); + printf("Idle task pid is %u\n", idle->pid); __kernel.pm.idle_task = idle; __kernel.proc.next_proc = __kernel.pm.idle_task; __kernel.pm.active = &__kernel.proc; - pm_add_proc(&__kernel.pm, &__kernel.proc); + // pm_add_proc(&__kernel.pm, &__kernel.proc); + pm_add_proc(&__kernel.pm, idle); // __kernel.pm.task_begin = &__kernel.proc; if (ebus_create(&__kernel.event_bus, 4096)) { @@ -145,11 +148,13 @@ void kernel_main() { ebus_handler_t launch_handler = {0}; launch_handler.callback_fn = handle_launch; launch_handler.event_id = EBUS_EVENT_TASK_SWITCH; + launch_handler.pid = 0; ebus_register_handler(&__kernel.event_bus, &launch_handler); ebus_handler_t kill_handler = {0}; kill_handler.callback_fn = handle_kill; kill_handler.event_id = EBUS_EVENT_TASK_KILL; + launch_handler.pid = 0; ebus_register_handler(&__kernel.event_bus, &kill_handler); irq_install(); @@ -157,6 +162,10 @@ void kernel_main() { vga_puts("Welcome to kernel v" PROJECT_VERSION "\n"); term_init(); + if (arr_size(&__kernel.pm.task_list) == 0) { + KPANIC("No process"); + } + commands_init(); term_command_add("exit", kill); @@ -204,36 +213,37 @@ static void handle_kill(const ebus_event_t * event) { process_free(proc); } -int kernel_call_as_proc(int pid, _proc_call_t fn, void * data) { - if (!fn) { - return -1; - } +// int kernel_call_as_proc(int pid, _proc_call_t fn, void * data) { +// if (!fn) { +// return -1; +// } - process_t * curr = get_current_process(); - if (curr->pid != pid) { - kernel_switch_task(pid); - } +// process_t * curr = get_current_process(); +// if (curr->pid != pid) { +// kernel_switch_task(pid); +// } - int res = fn(data); +// int res = fn(data); - if (curr->pid != pid) { - kernel_switch_task(curr->pid); - } +// if (curr->pid != pid) { +// kernel_switch_task(curr->pid); +// } - return res; -} +// return res; +// } int kernel_switch_task(int next_pid) { - process_t * proc = pm_find_pid(&__kernel.pm, next_pid); - if (!proc || proc->state == PROCESS_STATE_DEAD) { - return -1; - } + return pm_activate_process(&__kernel.pm, next_pid); + // process_t * proc = pm_find_pid(&__kernel.pm, next_pid); + // if (!proc || proc->state == PROCESS_STATE_DEAD) { + // return -1; + // } - __kernel.pm.active = proc; - proc->state = PROCESS_STATE_RUNNING; - set_kernel_stack(proc->esp0); - mmu_change_dir(proc->cr3); - return 0; + // __kernel.pm.active = proc; + // proc->state = PROCESS_STATE_RUNNING; + // set_kernel_stack(proc->esp0); + // mmu_change_dir(proc->cr3); + // return 0; } mmu_dir_t * get_kernel_dir() { @@ -278,21 +288,22 @@ int kernel_add_task(process_t * proc) { } int kernel_next_task() { - process_t * curr = get_current_process(); - process_t * next = curr->next_proc; - if (!next) { - next = __kernel.pm.idle_task; - } + return pm_switch_process(&__kernel.pm); + // process_t * curr = get_current_process(); + // process_t * next = curr->next_proc; + // if (!next) { + // next = __kernel.pm.idle_task; + // } - __kernel.pm.active = next; + // __kernel.pm.active = next; - // TODO interrupt back to process for sigint + // // TODO interrupt back to process for sigint - if (process_resume(__kernel.pm.active, 0)) { - KPANIC("Failed to resume task"); - } + // if (process_resume(__kernel.pm.active, 0)) { + // KPANIC("Failed to resume task"); + // } - return 0; + // return 0; } int kernel_close_process(process_t * proc) { @@ -341,14 +352,14 @@ int kernel_set_current_task(process_t * proc) { // // __kernel.pm.task_begin = proc; // } -void idle() { - vga_puts("Start idle task\n> "); - for (;;) { - term_update(); - ebus_cycle(get_kernel_ebus()); - asm("hlt"); - } -} +// void idle() { +// vga_puts("Start idle task\n> "); +// for (;;) { +// term_update(); +// ebus_cycle(get_kernel_ebus()); +// asm("hlt"); +// } +// } NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int line) { vga_color(VGA_FG_WHITE | VGA_BG_RED); @@ -367,6 +378,14 @@ NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int li halt(); } +proc_man_t * kernel_get_proc_man() { + return &__kernel.pm; +} + +process_t * kernel_find_pid(int pid) { + return pm_find_pid(&__kernel.pm, pid); +} + static void cursor() { vga_cursor(3, 3); @@ -378,13 +397,13 @@ static void cursor() { static void irq_install() { enable_interrupts(); /* IRQ0: timer */ - init_timer(TIMER_FREQ_MS); // milliseconds + // init_timer(TIMER_FREQ_MS); // milliseconds /* IRQ1: keyboard */ init_keyboard(); /* IRQ14: ata disk */ init_ata(); /* IRQ8: real time clock */ - init_rtc(RTC_RATE_1024_HZ); + // init_rtc(RTC_RATE_1024_HZ); } static int kill(size_t argc, char ** argv) { diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 5807f1b5..0b19ba22 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -183,6 +183,8 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { return -1; } + printf("Task list size is %u\n", pm->task_list.size); + for (size_t i = 0; i < arr_size(&pm->task_list); i++) { process_t * proc; arr_get(&pm->task_list, i, &proc); @@ -192,6 +194,7 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { } ebus_push(&proc->event_queue, event); + printf("Proc %u size is %u\n", proc->pid, proc->event_queue.queue.size); if (proc->filter_event && event && event->event_id == proc->filter_event) { proc->state = PROCESS_STATE_SUSPENDED; } diff --git a/src/kernel/src/term.c b/src/kernel/src/term.c index 50618efe..08b839fd 100644 --- a/src/kernel/src/term.c +++ b/src/kernel/src/term.c @@ -10,6 +10,8 @@ #include "libc/proc.h" #include "libc/stdio.h" #include "libc/string.h" +#include "process.h" +#include "process_manager.h" #define ERROR(MSG) \ { \ @@ -108,12 +110,23 @@ void term_init() { } command_ready = false; - ebus_handler_t handler; - handler.callback_fn = key_event_handler; - handler.event_id = EBUS_EVENT_KEY; - if (ebus_register_handler(get_kernel_ebus(), &handler) < 1) { - PANIC("Failed to register keyboard event handler"); + process_t * proc = kmalloc(sizeof(process_t)); + if (!proc || process_create(proc)) { + return; } + + process_set_entrypoint(proc, term_run); + proc->state = PROCESS_STATE_LOADED; + + kernel_add_task(proc); + + // ebus_handler_t handler; + // handler.callback_fn = key_event_handler; + // handler.event_id = EBUS_EVENT_KEY; + // handler.pid = 0; + // if (ebus_register_handler(get_kernel_ebus(), &handler) < 1) { + // PANIC("Failed to register keyboard event handler"); + // } } void term_update() { @@ -175,8 +188,9 @@ void term_run() { for (;;) { term_update(); - ebus_cycle(get_kernel_ebus()); - asm("hlt"); + // ebus_cycle(get_kernel_ebus()); + yield(0); + // asm("hlt"); } } From a09d91552e9fcd3ad6ad7c864917b24a4a64a9f0 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 10:54:19 -0400 Subject: [PATCH 24/59] Working process loop --- src/kernel/src/idle.c | 2 ++ src/kernel/src/kernel.c | 2 +- src/kernel/src/process.c | 2 +- src/kernel/src/process_manager.c | 6 ++++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/kernel/src/idle.c b/src/kernel/src/idle.c index 26713888..eeafefc9 100644 --- a/src/kernel/src/idle.c +++ b/src/kernel/src/idle.c @@ -21,5 +21,7 @@ static void idle_loop() { for (;;) { ebus_cycle(get_kernel_ebus()); asm("hlt"); + int curr_pid = get_current_process()->pid; + yield(0); } } diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 209dd964..9d40c646 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -186,7 +186,7 @@ void kernel_main() { // switch_to_task(__kernel.pm.active); - process_resume(__kernel.pm.idle_task, 0); + pm_resume_process(&__kernel.pm, __kernel.pm.idle_task->pid, 0); KPANIC("switch didn't happen\n"); diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index d29a3519..b3193829 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -148,7 +148,7 @@ int process_activate(process_t * proc) { void process_yield(process_t * proc, uint32_t esp, int filter) { proc->filter_event = filter; proc->esp = esp; - proc->state = PROCESS_STATE_WAITING; + proc->state = PROCESS_STATE_SUSPENDED; kernel_next_task(); } diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 0b19ba22..e0ca2404 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -117,7 +117,7 @@ int pm_switch_process(proc_man_t * pm) { if (pm->active->pid == last_pid) { PANIC("Process loop detected"); } - } while (pm->active->state < PROCESS_STATE_DEAD); + } while (pm->active->state >= PROCESS_STATE_DEAD); pm_activate_process(pm, pm->active->pid); @@ -134,6 +134,8 @@ int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { return -1; } + pm->active = proc; + return process_resume(proc, event); } @@ -194,7 +196,7 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { } ebus_push(&proc->event_queue, event); - printf("Proc %u size is %u\n", proc->pid, proc->event_queue.queue.size); + printf("Proc %u size is %u\n", proc->pid, proc->event_queue.queue.len); if (proc->filter_event && event && event->event_id == proc->filter_event) { proc->state = PROCESS_STATE_SUSPENDED; } From ee4bf800c2ab9c2a09d014f5365e02bb3fab0a4e Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 11:05:55 -0400 Subject: [PATCH 25/59] idk why it breaks at mmu_change_dir process.c:146 --- src/kernel/src/kernel.c | 5 ++++- src/kernel/src/process.c | 7 +++++++ src/kernel/src/process_manager.c | 6 ++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 9d40c646..73a48a9a 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -288,7 +288,10 @@ int kernel_add_task(process_t * proc) { } int kernel_next_task() { - return pm_switch_process(&__kernel.pm); + if (pm_switch_process(&__kernel.pm)) { + return -1; + } + return pm_resume_process(&__kernel.pm, __kernel.pm.active->pid, 0); // process_t * curr = get_current_process(); // process_t * next = curr->next_proc; // if (!next) { diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index b3193829..5d4ff7c6 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -3,6 +3,7 @@ #include "cpu/mmu.h" #include "cpu/tss.h" #include "kernel.h" +#include "libc/stdio.h" #include "libc/string.h" #include "libk/sys_call.h" #include "paging.h" @@ -139,6 +140,8 @@ int process_activate(process_t * proc) { return -1; } + printf("a%u ", proc->pid); + set_kernel_stack(proc->esp0); // just updates tss 0 mmu_change_dir(proc->cr3); @@ -146,6 +149,8 @@ int process_activate(process_t * proc) { } void process_yield(process_t * proc, uint32_t esp, int filter) { + printf("y%u ", proc->pid); + proc->filter_event = filter; proc->esp = esp; proc->state = PROCESS_STATE_SUSPENDED; @@ -157,6 +162,8 @@ int process_resume(process_t * proc, const ebus_event_t * event) { return -1; } + printf("r%u ", proc->pid); + process_activate(proc); proc->state = PROCESS_STATE_RUNNING; start_task(proc->cr3, proc->esp, proc->entrypoint, event); diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index e0ca2404..c2e5bf20 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -119,9 +119,11 @@ int pm_switch_process(proc_man_t * pm) { } } while (pm->active->state >= PROCESS_STATE_DEAD); - pm_activate_process(pm, pm->active->pid); + if (pm_activate_process(pm, pm->active->pid)) { + return -1; + } - return -1; + return 0; } int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { From 5731c4a90cc688d471fdade4cd524052f2fefa2d Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 17:42:57 -0400 Subject: [PATCH 26/59] Fix tests --- src/kernel/include/process.h | 4 +--- src/kernel/src/process.c | 14 ++++++-------- src/kernel/src/system_call_proc.c | 1 + tests/src/mocks/include/cpu/tss.mock.h | 18 ++++++++++++++++++ tests/src/mocks/include/libc/proc.mock.h | 17 +++++++++++++++++ tests/src/mocks/include/libk/sys_call.mock.h | 1 + tests/src/mocks/include/process.mock.h | 6 +++++- tests/src/mocks/include/test_common.h | 2 ++ tests/src/mocks/src/cpu.mock.c | 13 +++++++++++++ tests/src/mocks/src/libc.mock.c | 11 +++++++++++ tests/src/mocks/src/libk.mock.c | 2 ++ tests/src/mocks/src/process.mock.c | 12 ++++++++++-- tests/src/mocks/src/test_common.c | 2 ++ 13 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 tests/src/mocks/include/cpu/tss.mock.h create mode 100644 tests/src/mocks/include/libc/proc.mock.h diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 9bdaca13..e14cc453 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -79,7 +79,7 @@ int process_set_entrypoint(process_t * proc, void * entrypoint); // Load page table and esp0, don't resume int process_activate(process_t * proc); -void process_yield(process_t * proc, uint32_t esp, int filter); +int process_yield(process_t * proc, uint32_t esp, int filter); int process_resume(process_t * proc, const ebus_event_t * event); @@ -138,7 +138,5 @@ void set_next_pid(uint32_t next); #endif extern NO_RETURN void start_task(uint32_t cr3, uint32_t esp, uint32_t eip, const ebus_event_t * event); -extern NO_RETURN void resume_task(uint32_t cr3, uint32_t esp, const ebus_event_t * event); -extern NO_RETURN void switch_to_task(process_t * next_proc); #endif // KERNEL_PROCESS_H diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 5d4ff7c6..0f0d417c 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -3,7 +3,6 @@ #include "cpu/mmu.h" #include "cpu/tss.h" #include "kernel.h" -#include "libc/stdio.h" #include "libc/string.h" #include "libk/sys_call.h" #include "paging.h" @@ -140,21 +139,22 @@ int process_activate(process_t * proc) { return -1; } - printf("a%u ", proc->pid); - set_kernel_stack(proc->esp0); // just updates tss 0 mmu_change_dir(proc->cr3); return 0; } -void process_yield(process_t * proc, uint32_t esp, int filter) { - printf("y%u ", proc->pid); +int process_yield(process_t * proc, uint32_t esp, int filter) { + if (!proc || !esp) { + return -1; + } proc->filter_event = filter; proc->esp = esp; proc->state = PROCESS_STATE_SUSPENDED; - kernel_next_task(); + + return 0; } int process_resume(process_t * proc, const ebus_event_t * event) { @@ -162,8 +162,6 @@ int process_resume(process_t * proc, const ebus_event_t * event) { return -1; } - printf("r%u ", proc->pid); - process_activate(proc); proc->state = PROCESS_STATE_RUNNING; start_task(proc->cr3, proc->esp, proc->entrypoint, event); diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index edf31d00..41cb169e 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -102,6 +102,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { proc->entrypoint = regs->eip; enable_interrupts(); process_yield(proc, regs->esp, args->filter); + // TODO switch task }; } diff --git a/tests/src/mocks/include/cpu/tss.mock.h b/tests/src/mocks/include/cpu/tss.mock.h new file mode 100644 index 00000000..648c1530 --- /dev/null +++ b/tests/src/mocks/include/cpu/tss.mock.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpu/tss.h" +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(init_tss); +DECLARE_FAKE_VALUE_FUNC(tss_entry_t *, tss_get_entry, size_t); +DECLARE_FAKE_VOID_FUNC(set_kernel_stack, uint32_t); + +void reset_cpu_tss_mock(void); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/tests/src/mocks/include/libc/proc.mock.h b/tests/src/mocks/include/libc/proc.mock.h new file mode 100644 index 00000000..ae98e3a8 --- /dev/null +++ b/tests/src/mocks/include/libc/proc.mock.h @@ -0,0 +1,17 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "fff.h" +#include "libc/proc.h" + +DECLARE_FAKE_VOID_FUNC(set_next_pid, uint32_t); +DECLARE_FAKE_VOID_FUNC(queue_event, ebus_event_t *); + +void reset_libc_proc_mock(void); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/tests/src/mocks/include/libk/sys_call.mock.h b/tests/src/mocks/include/libk/sys_call.mock.h index 35acb96c..c95fea57 100644 --- a/tests/src/mocks/include/libk/sys_call.mock.h +++ b/tests/src/mocks/include/libk/sys_call.mock.h @@ -14,6 +14,7 @@ DECLARE_FAKE_VOID_FUNC(_sys_proc_panic, const char *, const char *, unsigned int DECLARE_FAKE_VALUE_FUNC(int, _sys_proc_getpid); DECLARE_FAKE_VOID_FUNC(_sys_register_signals, void *); DECLARE_FAKE_VOID_FUNC(_sys_queue_event, ebus_event_t *); +DECLARE_FAKE_VALUE_FUNC(int, _sys_yield, int); DECLARE_FAKE_VALUE_FUNC(size_t, _sys_putc, char); DECLARE_FAKE_VALUE_FUNC(size_t, _sys_puts, const char *); diff --git a/tests/src/mocks/include/process.mock.h b/tests/src/mocks/include/process.mock.h index 5ef60591..68ff83d9 100644 --- a/tests/src/mocks/include/process.mock.h +++ b/tests/src/mocks/include/process.mock.h @@ -9,10 +9,14 @@ extern "C" { DECLARE_FAKE_VALUE_FUNC(int, process_create, process_t *); DECLARE_FAKE_VALUE_FUNC(int, process_free, process_t *); +DECLARE_FAKE_VALUE_FUNC(int, process_set_entrypoint, process_t *, void *); +DECLARE_FAKE_VALUE_FUNC(int, process_activate, process_t *); +DECLARE_FAKE_VALUE_FUNC(int, process_yield, process_t *, uint32_t, int); +DECLARE_FAKE_VALUE_FUNC(int, process_resume, process_t *, const ebus_event_t *); DECLARE_FAKE_VALUE_FUNC(void *, process_add_pages, process_t *, size_t); DECLARE_FAKE_VALUE_FUNC(int, process_grow_stack, process_t *); DECLARE_FAKE_VALUE_FUNC(int, process_load_heap, process_t *, const char *, size_t); -DECLARE_FAKE_VOID_FUNC(set_next_pid, uint32_t); +DECLARE_FAKE_VOID_FUNC(start_task, uint32_t, uint32_t, uint32_t, const ebus_event_t *); void reset_process_mock(void); diff --git a/tests/src/mocks/include/test_common.h b/tests/src/mocks/include/test_common.h index 050c2200..fc45548f 100644 --- a/tests/src/mocks/include/test_common.h +++ b/tests/src/mocks/include/test_common.h @@ -23,9 +23,11 @@ extern void * memset(void *, int, size_t); #include "cpu/mmu.mock.h" #include "cpu/ports.mock.h" +#include "cpu/tss.mock.h" #include "ebus.mock.h" #include "libc/datastruct/array.mock.h" #include "libc/memory.mock.h" +#include "libc/proc.mock.h" #include "libc/string.mock.h" #include "libk/sys_call.mock.h" #include "memory_alloc.mock.h" diff --git a/tests/src/mocks/src/cpu.mock.c b/tests/src/mocks/src/cpu.mock.c index e7b86238..269fde32 100644 --- a/tests/src/mocks/src/cpu.mock.c +++ b/tests/src/mocks/src/cpu.mock.c @@ -1,5 +1,6 @@ #include "cpu/mmu.mock.h" #include "cpu/ports.mock.h" +#include "cpu/tss.mock.h" // cpu/mmu.h @@ -58,3 +59,15 @@ void reset_cpu_ports_mock() { RESET_FAKE(port_word_in); RESET_FAKE(port_word_out); } + +// cpu/tss.h + +DEFINE_FAKE_VOID_FUNC(init_tss); +DEFINE_FAKE_VALUE_FUNC(tss_entry_t *, tss_get_entry, size_t); +DEFINE_FAKE_VOID_FUNC(set_kernel_stack, uint32_t); + +void reset_cpu_tss_mock() { + RESET_FAKE(init_tss); + RESET_FAKE(tss_get_entry); + RESET_FAKE(set_kernel_stack); +} diff --git a/tests/src/mocks/src/libc.mock.c b/tests/src/mocks/src/libc.mock.c index 275d53d7..63394ed6 100644 --- a/tests/src/mocks/src/libc.mock.c +++ b/tests/src/mocks/src/libc.mock.c @@ -3,6 +3,7 @@ #include #include "libc/memory.mock.h" +#include "libc/proc.mock.h" #include "libc/string.mock.h" // libc/memory.h @@ -21,6 +22,16 @@ void reset_libc_memory_mock(void) { kfree_fake.custom_fake = free; } +// libc/proc.h + +DEFINE_FAKE_VOID_FUNC(set_next_pid, uint32_t); +DEFINE_FAKE_VOID_FUNC(queue_event, ebus_event_t *); + +void reset_libc_proc_mock(void) { + RESET_FAKE(set_next_pid); + RESET_FAKE(queue_event); +} + // libc/string.h DEFINE_FAKE_VALUE_FUNC(int, kmemcmp, const void *, const void *, size_t); diff --git a/tests/src/mocks/src/libk.mock.c b/tests/src/mocks/src/libk.mock.c index ae0fe170..79848830 100644 --- a/tests/src/mocks/src/libk.mock.c +++ b/tests/src/mocks/src/libk.mock.c @@ -13,6 +13,7 @@ DEFINE_FAKE_VOID_FUNC(_sys_proc_panic, const char *, const char *, unsigned int) DEFINE_FAKE_VALUE_FUNC(int, _sys_proc_getpid); DEFINE_FAKE_VOID_FUNC(_sys_register_signals, void *); DEFINE_FAKE_VOID_FUNC(_sys_queue_event, ebus_event_t *); +DEFINE_FAKE_VALUE_FUNC(int, _sys_yield, int); DEFINE_FAKE_VALUE_FUNC(size_t, _sys_putc, char); DEFINE_FAKE_VALUE_FUNC(size_t, _sys_puts, const char *); @@ -24,6 +25,7 @@ void reset_libk_sys_call_mock(void) { RESET_FAKE(_sys_proc_getpid); RESET_FAKE(_sys_register_signals); RESET_FAKE(_sys_queue_event); + RESET_FAKE(_sys_yield); RESET_FAKE(_sys_putc); RESET_FAKE(_sys_puts); } diff --git a/tests/src/mocks/src/process.mock.c b/tests/src/mocks/src/process.mock.c index 3c83777c..4999f119 100644 --- a/tests/src/mocks/src/process.mock.c +++ b/tests/src/mocks/src/process.mock.c @@ -3,16 +3,24 @@ DEFINE_FAKE_VALUE_FUNC(int, process_create, process_t *); DEFINE_FAKE_VALUE_FUNC(int, process_free, process_t *); +DEFINE_FAKE_VALUE_FUNC(int, process_set_entrypoint, process_t *, void *); +DEFINE_FAKE_VALUE_FUNC(int, process_activate, process_t *); +DEFINE_FAKE_VALUE_FUNC(int, process_yield, process_t *, uint32_t, int); +DEFINE_FAKE_VALUE_FUNC(int, process_resume, process_t *, const ebus_event_t *); DEFINE_FAKE_VALUE_FUNC(void *, process_add_pages, process_t *, size_t); DEFINE_FAKE_VALUE_FUNC(int, process_grow_stack, process_t *); DEFINE_FAKE_VALUE_FUNC(int, process_load_heap, process_t *, const char *, size_t); -DEFINE_FAKE_VOID_FUNC(set_next_pid, uint32_t); +DEFINE_FAKE_VOID_FUNC(start_task, uint32_t, uint32_t, uint32_t, const ebus_event_t *); void reset_process_mock() { RESET_FAKE(process_create); RESET_FAKE(process_free); + RESET_FAKE(process_set_entrypoint); + RESET_FAKE(process_activate); + RESET_FAKE(process_yield); + RESET_FAKE(process_resume); RESET_FAKE(process_add_pages); RESET_FAKE(process_grow_stack); RESET_FAKE(process_load_heap); - RESET_FAKE(set_next_pid); + RESET_FAKE(start_task); } diff --git a/tests/src/mocks/src/test_common.c b/tests/src/mocks/src/test_common.c index 243819fd..d1673b11 100644 --- a/tests/src/mocks/src/test_common.c +++ b/tests/src/mocks/src/test_common.c @@ -7,8 +7,10 @@ void init_mocks() { reset_cpu_mmu_mock(); reset_cpu_ports_mock(); + reset_cpu_tss_mock(); reset_libc_datastruct_array_mock(); reset_libc_memory_mock(); + reset_libc_proc_mock(); reset_libc_string_mock(); reset_libk_sys_call_mock(); reset_ebus_mock(); From f558d4017117b205a6756f3d93fd7901bc19b3c1 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 17:46:03 -0400 Subject: [PATCH 27/59] Tmp disable queue_event test until I can figure out why it isn't working --- tests/src/libc/test_signal.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/src/libc/test_signal.cpp b/tests/src/libc/test_signal.cpp index 9f27bc9a..d5ea6e1f 100644 --- a/tests/src/libc/test_signal.cpp +++ b/tests/src/libc/test_signal.cpp @@ -53,11 +53,11 @@ TEST_F(Signal, register_signal) { EXPECT_NE(0, register_signal(1, callback)); } -TEST_F(Signal, queue_event) { - ebus_event_t event; - event.event_id = EBUS_EVENT_TIMER; - event.timer.time = 2; - queue_event(&event); - ASSERT_EQ(1, _sys_queue_event_fake.call_count); - EXPECT_EQ(&event, _sys_queue_event_fake.arg0_val); -} +// TEST_F(Signal, queue_event) { +// ebus_event_t event; +// event.event_id = EBUS_EVENT_TIMER; +// event.timer.time = 2; +// queue_event(&event); +// ASSERT_EQ(1, _sys_queue_event_fake.call_count); +// EXPECT_EQ(&event, _sys_queue_event_fake.arg0_val); +// } From aa79378d4395d227e866db5fd26560a494a80b50 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 17:54:16 -0400 Subject: [PATCH 28/59] Add test and docstring for process_set_entrypoint --- src/kernel/include/process.h | 9 +++++++++ src/kernel/src/process.c | 1 + tests/src/kernel/test_process.cpp | 13 +++++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index e14cc453..5dba586c 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -74,6 +74,15 @@ int process_create(process_t * proc); */ int process_free(process_t * proc); +/** + * @brief Set the entry point or eip of the process. + * + * This entrypoint is used when the process starts or is resumed. + * + * @param proc pointer to the process object + * @param entrypoint eip or address of the entrypoint or function + * @return int 0 for success + */ int process_set_entrypoint(process_t * proc, void * entrypoint); // Load page table and esp0, don't resume diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 0f0d417c..b66618f7 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -132,6 +132,7 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { } proc->entrypoint = PTR2UINT(entrypoint); + return 0; } int process_activate(process_t * proc) { diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index 87e2480e..68fc8292 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -204,6 +204,19 @@ TEST_F(Process, process_free) { ASSERT_TEMP_MAP_BALANCED(); } +// Process Set Entrypoint + +TEST_F(Process, process_set_entrypoint_InvalidParameters) { + EXPECT_NE(0, process_set_entrypoint(0, 0)); + EXPECT_NE(0, process_set_entrypoint(&proc, 0)); + EXPECT_NE(0, process_set_entrypoint(0, (void *)1)); +} + +TEST_F(Process, process_set_entrypoint) { + EXPECT_EQ(0, process_set_entrypoint(&proc, (void *)3)); + EXPECT_EQ(3, proc.entrypoint); +} + // Process Add Pages TEST_F(Process, process_add_pages_InvalidParameters) { From 499f0b72e278d865bf54db924dda4ac0287042a9 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 18:42:41 -0400 Subject: [PATCH 29/59] Add test and docsstring for process_activate --- src/kernel/include/process.h | 9 ++++++++- tests/src/kernel/test_process.cpp | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 5dba586c..44af4cf7 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -85,7 +85,14 @@ int process_free(process_t * proc); */ int process_set_entrypoint(process_t * proc, void * entrypoint); -// Load page table and esp0, don't resume +/** + * @brief Load process without entering. + * + * Load the cr3 and esp0. This does not start or resume the process. + * + * @param proc pointer to the process object + * @return int 0 for success + */ int process_activate(process_t * proc); int process_yield(process_t * proc, uint32_t esp, int filter); diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index 68fc8292..188349d7 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -217,6 +217,22 @@ TEST_F(Process, process_set_entrypoint) { EXPECT_EQ(3, proc.entrypoint); } +// Process Activate + +TEST_F(Process, process_set_activate_InvalidParameters) { + EXPECT_NE(0, process_activate(0)); +} + +TEST_F(Process, process_activate) { + proc.esp0 = 3; + proc.cr3 = 4; + EXPECT_EQ(0, process_activate(&proc)); + ASSERT_EQ(1, set_kernel_stack_fake.call_count); + EXPECT_EQ(3, set_kernel_stack_fake.arg0_val); + ASSERT_EQ(1, mmu_change_dir_fake.call_count); + EXPECT_EQ(4, mmu_change_dir_fake.arg0_val); +} + // Process Add Pages TEST_F(Process, process_add_pages_InvalidParameters) { From 4e7a7f8d28d31e88d2e29bd7bc2ad73bb3f74d68 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 18:43:29 -0400 Subject: [PATCH 30/59] Fix test name --- tests/src/kernel/test_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index 188349d7..817e1806 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -219,7 +219,7 @@ TEST_F(Process, process_set_entrypoint) { // Process Activate -TEST_F(Process, process_set_activate_InvalidParameters) { +TEST_F(Process, process_activate_InvalidParameters) { EXPECT_NE(0, process_activate(0)); } From 16b99b4273e77008b94f137d3b6ce1366c758ba6 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 18:53:04 -0400 Subject: [PATCH 31/59] Rename entrypoint field to eip --- src/kernel/include/process.h | 2 +- src/kernel/src/process.c | 4 ++-- src/kernel/src/system_call_proc.c | 2 +- tests/src/kernel/test_process.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 44af4cf7..2d379a3d 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -42,7 +42,7 @@ typedef struct _process { // TODO heap & stack limits - uint32_t entrypoint; + uint32_t eip; signals_master_cb_t signals_callback; arr_t io_handles; // array diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index b66618f7..095d8345 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -131,7 +131,7 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { return -1; } - proc->entrypoint = PTR2UINT(entrypoint); + proc->eip = PTR2UINT(entrypoint); return 0; } @@ -165,7 +165,7 @@ int process_resume(process_t * proc, const ebus_event_t * event) { process_activate(proc); proc->state = PROCESS_STATE_RUNNING; - start_task(proc->cr3, proc->esp, proc->entrypoint, event); + start_task(proc->cr3, proc->esp, proc->eip, event); proc->state = PROCESS_STATE_ERROR; return -1; diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 41cb169e..1714d331 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -99,7 +99,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { // TODO clear iret from stack? process_t * proc = get_current_process(); - proc->entrypoint = regs->eip; + proc->eip = regs->eip; enable_interrupts(); process_yield(proc, regs->esp, args->filter); // TODO switch task diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index 817e1806..900e130a 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -214,7 +214,7 @@ TEST_F(Process, process_set_entrypoint_InvalidParameters) { TEST_F(Process, process_set_entrypoint) { EXPECT_EQ(0, process_set_entrypoint(&proc, (void *)3)); - EXPECT_EQ(3, proc.entrypoint); + EXPECT_EQ(3, proc.eip); } // Process Activate From ea5f91e8ea7a4b5cb3b50ae40dc56361070aab59 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 18:58:08 -0400 Subject: [PATCH 32/59] Test and add docstring for process_yield, add eip to process_yield --- src/kernel/include/process.h | 11 ++++++++++- src/kernel/src/process.c | 5 +++-- src/kernel/src/system_call_proc.c | 2 +- tests/src/kernel/test_process.cpp | 19 +++++++++++++++++++ tests/src/mocks/include/process.mock.h | 2 +- tests/src/mocks/src/process.mock.c | 2 +- 6 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 2d379a3d..63ee2980 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -95,7 +95,16 @@ int process_set_entrypoint(process_t * proc, void * entrypoint); */ int process_activate(process_t * proc); -int process_yield(process_t * proc, uint32_t esp, int filter); +/** + * @brief Store the current process state for later use when resuming. + * + * @param proc pointer to the process object + * @param esp stack pointer + * @param eip instruction pointer + * @param filter ebus event type if polling for an event, 0 for no filter + * @return int 0 for success + */ +int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter); int process_resume(process_t * proc, const ebus_event_t * event); diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 095d8345..d199df44 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -146,11 +146,12 @@ int process_activate(process_t * proc) { return 0; } -int process_yield(process_t * proc, uint32_t esp, int filter) { - if (!proc || !esp) { +int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter) { + if (!proc || !esp || !eip) { return -1; } + proc->eip = eip; proc->filter_event = filter; proc->esp = esp; proc->state = PROCESS_STATE_SUSPENDED; diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 1714d331..da540ad7 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -101,7 +101,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); proc->eip = regs->eip; enable_interrupts(); - process_yield(proc, regs->esp, args->filter); + process_yield(proc, regs->esp, regs->eip, args->filter); // TODO switch task }; } diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index 900e130a..675110da 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -233,6 +233,25 @@ TEST_F(Process, process_activate) { EXPECT_EQ(4, mmu_change_dir_fake.arg0_val); } +// Process Yield + +TEST_F(Process, process_yield_InvalidParameters) { + EXPECT_NE(0, process_yield(0, 0, 0, 0)); + EXPECT_NE(0, process_yield(&proc, 0, 0, 0)); + EXPECT_NE(0, process_yield(0, 1, 0, 0)); + EXPECT_NE(0, process_yield(0, 0, 1, 0)); + EXPECT_NE(0, process_yield(&proc, 1, 0, 0)); + EXPECT_NE(0, process_yield(&proc, 0, 1, 0)); + EXPECT_NE(0, process_yield(0, 1, 1, 0)); +} + +TEST_F(Process, process_yield) { + EXPECT_EQ(0, process_yield(&proc, 1, 2, 3)); + EXPECT_EQ(1, proc.esp); + EXPECT_EQ(2, proc.eip); + EXPECT_EQ(3, proc.filter_event); +} + // Process Add Pages TEST_F(Process, process_add_pages_InvalidParameters) { diff --git a/tests/src/mocks/include/process.mock.h b/tests/src/mocks/include/process.mock.h index 68ff83d9..b3d904ed 100644 --- a/tests/src/mocks/include/process.mock.h +++ b/tests/src/mocks/include/process.mock.h @@ -11,7 +11,7 @@ DECLARE_FAKE_VALUE_FUNC(int, process_create, process_t *); DECLARE_FAKE_VALUE_FUNC(int, process_free, process_t *); DECLARE_FAKE_VALUE_FUNC(int, process_set_entrypoint, process_t *, void *); DECLARE_FAKE_VALUE_FUNC(int, process_activate, process_t *); -DECLARE_FAKE_VALUE_FUNC(int, process_yield, process_t *, uint32_t, int); +DECLARE_FAKE_VALUE_FUNC(int, process_yield, process_t *, uint32_t, uint32_t, int); DECLARE_FAKE_VALUE_FUNC(int, process_resume, process_t *, const ebus_event_t *); DECLARE_FAKE_VALUE_FUNC(void *, process_add_pages, process_t *, size_t); DECLARE_FAKE_VALUE_FUNC(int, process_grow_stack, process_t *); diff --git a/tests/src/mocks/src/process.mock.c b/tests/src/mocks/src/process.mock.c index 4999f119..fbfe1098 100644 --- a/tests/src/mocks/src/process.mock.c +++ b/tests/src/mocks/src/process.mock.c @@ -5,7 +5,7 @@ DEFINE_FAKE_VALUE_FUNC(int, process_create, process_t *); DEFINE_FAKE_VALUE_FUNC(int, process_free, process_t *); DEFINE_FAKE_VALUE_FUNC(int, process_set_entrypoint, process_t *, void *); DEFINE_FAKE_VALUE_FUNC(int, process_activate, process_t *); -DEFINE_FAKE_VALUE_FUNC(int, process_yield, process_t *, uint32_t, int); +DEFINE_FAKE_VALUE_FUNC(int, process_yield, process_t *, uint32_t, uint32_t, int); DEFINE_FAKE_VALUE_FUNC(int, process_resume, process_t *, const ebus_event_t *); DEFINE_FAKE_VALUE_FUNC(void *, process_add_pages, process_t *, size_t); DEFINE_FAKE_VALUE_FUNC(int, process_grow_stack, process_t *); From 6be43a4f4742a544c961306d6c2af4882b03ed8d Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 19:20:25 -0400 Subject: [PATCH 33/59] Add test and docstring for process_resume --- src/kernel/include/process.h | 11 +++++++++ tests/src/kernel/test_process.cpp | 41 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 63ee2980..24d9633a 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -106,6 +106,17 @@ int process_activate(process_t * proc); */ int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter); +/** + * @brief Activate and jump to the process. + * + * If the jump is successful this function will never return. Returning from + * this function signals an error. If this is the first call, the entrypoint is + * used. If this is resuming from a yield, the last eip will be used. + * + * @param proc pointer to the process object + * @param event ebus event to return from yield or 0 + * @return int No Return, if this function returns it is an error + */ int process_resume(process_t * proc, const ebus_event_t * event); /** diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index 675110da..afad70ca 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -252,6 +252,47 @@ TEST_F(Process, process_yield) { EXPECT_EQ(3, proc.filter_event); } +// Process Resume + +TEST_F(Process, process_resume_InvalidParameters) { + EXPECT_NE(0, process_resume(0, 0)); + EXPECT_EQ(0, set_kernel_stack_fake.call_count); + EXPECT_EQ(0, mmu_change_dir_fake.call_count); + proc.state = PROCESS_STATE_DEAD; + EXPECT_NE(0, process_resume(0, 0)); +} + +TEST_F(Process, process_resume_ProcessDead) { + proc.state = PROCESS_STATE_DEAD; + EXPECT_NE(0, process_resume(&proc, 0)); + proc.state = PROCESS_STATE_ERROR; + EXPECT_NE(0, process_resume(&proc, 0)); +} + +static void custom_start_task(uint32_t cr3, uint32_t esp, uint32_t eip, const ebus_event_t * event) { + ASSERT_EQ(PROCESS_STATE_RUNNING, proc.state); +} + +TEST_F(Process, process_resume) { + proc.esp = 1; + proc.eip = 2; + proc.esp0 = 3; + proc.cr3 = 4; + start_task_fake.custom_fake = custom_start_task; + EXPECT_NE(0, process_resume(&proc, (ebus_event_t *)5)); + ASSERT_EQ(1, set_kernel_stack_fake.call_count); + EXPECT_EQ(3, set_kernel_stack_fake.arg0_val); + ASSERT_EQ(1, mmu_change_dir_fake.call_count); + EXPECT_EQ(4, mmu_change_dir_fake.arg0_val); + ASSERT_EQ(1, start_task_fake.call_count); + EXPECT_EQ(4, start_task_fake.arg0_val); + EXPECT_EQ(1, start_task_fake.arg1_val); + EXPECT_EQ(2, start_task_fake.arg2_val); + EXPECT_EQ((ebus_event_t *)5, start_task_fake.arg3_val); + + EXPECT_EQ(PROCESS_STATE_ERROR, proc.state); +} + // Process Add Pages TEST_F(Process, process_add_pages_InvalidParameters) { From 1a176a9d9b9b74f9f39df2f4e95fc6d31be40e71 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 19:29:33 -0400 Subject: [PATCH 34/59] Add test for _sys_yield in libk --- src/kernel/src/system_call_proc.c | 3 +-- tests/src/libk/test_libk.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index da540ad7..8cbdd8b8 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -99,9 +99,8 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { // TODO clear iret from stack? process_t * proc = get_current_process(); - proc->eip = regs->eip; - enable_interrupts(); process_yield(proc, regs->esp, regs->eip, args->filter); + enable_interrupts(); // TODO switch task }; } diff --git a/tests/src/libk/test_libk.cpp b/tests/src/libk/test_libk.cpp index 638cf809..ce8e68f0 100644 --- a/tests/src/libk/test_libk.cpp +++ b/tests/src/libk/test_libk.cpp @@ -164,6 +164,14 @@ TEST_F(LibK, queue_event) { EXPECT_EQ(&event, (void *)send_call_fake.arg1_val); } +TEST_F(LibK, yield) { + send_call_fake.return_val = 2; + EXPECT_EQ(2, _sys_yield(5)); + ASSERT_EQ(1, send_call_fake.call_count); + EXPECT_EQ(0x306, send_call_fake.arg0_val); + EXPECT_EQ(5, send_call_fake.arg1_val); +} + TEST_F(LibK, putc) { send_call_fake.return_val = 1; size_t olen = _sys_putc('A'); From a7d6240c1d99d7bee5e80210cc6733753e501638 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 19:45:02 -0400 Subject: [PATCH 35/59] Test libc queue_event, yield and getpid --- tests/src/libc/test_process.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/src/libc/test_process.cpp b/tests/src/libc/test_process.cpp index 1021d42e..27370543 100644 --- a/tests/src/libc/test_process.cpp +++ b/tests/src/libc/test_process.cpp @@ -44,3 +44,26 @@ TEST_F(LibC, proc_getpid) { EXPECT_EQ(3, getpid()); EXPECT_EQ(1, _sys_proc_getpid_fake.call_count); } + +TEST_F(LibC, queue_event) { + ebus_event_t event; + memset(&event, 0, sizeof(ebus_event_t)); + _sys_proc_getpid_fake.return_val = 2; + queue_event(&event); + EXPECT_EQ(2, event.source_pid); + ASSERT_EQ(1, _sys_queue_event_fake.call_count); + EXPECT_EQ(&event, _sys_queue_event_fake.arg0_val); +} + +TEST_F(LibC, yield) { + _sys_yield_fake.return_val = 2; + EXPECT_EQ(2, yield(3)); + ASSERT_EQ(1, _sys_yield_fake.call_count); + EXPECT_EQ(3, _sys_yield_fake.arg0_val); +} + +TEST_F(LibC, getpid) { + _sys_proc_getpid_fake.return_val = 2; + EXPECT_EQ(2, getpid()); + ASSERT_EQ(1, _sys_proc_getpid_fake.call_count); +} From d3f53a7d6ab8c46531aee2864f1130d3a4697b60 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 20:15:46 -0400 Subject: [PATCH 36/59] Stepping through functions now --- src/ebus/src/ebus.c | 2 +- src/kernel/include/process.h | 2 +- src/kernel/include/process_manager.h | 4 +- src/kernel/src/kernel.c | 40 ++++++++++++-- src/kernel/src/process.c | 18 +++---- src/kernel/src/process_manager.c | 80 ++++++++++++++-------------- src/kernel/src/system_call_proc.c | 5 +- 7 files changed, 93 insertions(+), 58 deletions(-) diff --git a/src/ebus/src/ebus.c b/src/ebus/src/ebus.c index d13fbabd..503f1f65 100644 --- a/src/ebus/src/ebus.c +++ b/src/ebus/src/ebus.c @@ -136,7 +136,7 @@ static int handle_event(ebus_t * bus, ebus_event_t * event) { } } - pm_activate_process(kernel_get_proc_man(), curr->pid); + // pm_activate_process(kernel_get_proc_man(), curr->pid); return 0; } diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 24d9633a..e73a41d4 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -93,7 +93,7 @@ int process_set_entrypoint(process_t * proc, void * entrypoint); * @param proc pointer to the process object * @return int 0 for success */ -int process_activate(process_t * proc); +// int process_activate(process_t * proc); /** * @brief Store the current process state for later use when resuming. diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h index 0c0121f2..a0e0b8ff 100644 --- a/src/kernel/include/process_manager.h +++ b/src/kernel/include/process_manager.h @@ -24,8 +24,8 @@ process_t * pm_find_pid(proc_man_t * pm, int pid); int pm_add_proc(proc_man_t * pm, process_t * proc); int pm_remove_proc(proc_man_t * pm, int pid); -int pm_activate_process(proc_man_t * pm, int pid); -int pm_switch_process(proc_man_t * pm); +// int pm_activate_process(proc_man_t * pm, int pid); +// int pm_switch_process(proc_man_t * pm); int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event); process_t * pm_get_next(proc_man_t * pm); diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 73a48a9a..389ce1c6 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -51,6 +51,9 @@ static void map_first_table(mmu_table_t * table); extern void jump_kernel_mode(void * fn); +static void foo_task(); +static void bar_task(); + void kernel_main() { init_vga(UINT2PTR(PADDR_VGA)); vga_clear(); @@ -186,6 +189,20 @@ void kernel_main() { // switch_to_task(__kernel.pm.active); + process_t foo_proc; + if (process_create(&foo_proc)) { + KPANIC("Failed to create foo task"); + } + process_set_entrypoint(&foo_proc, foo_task); + pm_add_proc(&__kernel.pm, &foo_proc); + + process_t bar_proc; + if (process_create(&bar_proc)) { + KPANIC("Failed to create bar task"); + } + process_set_entrypoint(&bar_proc, bar_task); + pm_add_proc(&__kernel.pm, &bar_proc); + pm_resume_process(&__kernel.pm, __kernel.pm.idle_task->pid, 0); KPANIC("switch didn't happen\n"); @@ -196,6 +213,20 @@ void kernel_main() { KPANIC("You shouldn't be here!"); } +static void foo_task() { + for (;;) { + printf("foo\n"); + yield(0); + } +} + +static void bar_task() { + for (;;) { + printf("bar\n"); + yield(EBUS_EVENT_KEY); + } +} + static void handle_launch(const ebus_event_t * event) { printf("Start task %u\n", event->task_switch.next_task_pid); process_t * proc = pm_find_pid(&__kernel.pm, event->task_switch.next_task_pid); @@ -233,7 +264,8 @@ static void handle_kill(const ebus_event_t * event) { // } int kernel_switch_task(int next_pid) { - return pm_activate_process(&__kernel.pm, next_pid); + return pm_resume_process(&__kernel.pm, next_pid, 0); + // return pm_activate_process(&__kernel.pm, next_pid); // process_t * proc = pm_find_pid(&__kernel.pm, next_pid); // if (!proc || proc->state == PROCESS_STATE_DEAD) { // return -1; @@ -288,9 +320,9 @@ int kernel_add_task(process_t * proc) { } int kernel_next_task() { - if (pm_switch_process(&__kernel.pm)) { - return -1; - } + // if (pm_switch_process(&__kernel.pm)) { + // return -1; + // } return pm_resume_process(&__kernel.pm, __kernel.pm.active->pid, 0); // process_t * curr = get_current_process(); // process_t * next = curr->next_proc; diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index d199df44..34978b8d 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -135,16 +135,16 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { return 0; } -int process_activate(process_t * proc) { - if (!proc) { - return -1; - } +// int process_activate(process_t * proc) { +// if (!proc) { +// return -1; +// } - set_kernel_stack(proc->esp0); // just updates tss 0 - mmu_change_dir(proc->cr3); +// set_kernel_stack(proc->esp0); // just updates tss 0 +// mmu_change_dir(proc->cr3); - return 0; -} +// return 0; +// } int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter) { if (!proc || !esp || !eip) { @@ -164,7 +164,7 @@ int process_resume(process_t * proc, const ebus_event_t * event) { return -1; } - process_activate(proc); + // process_activate(proc); proc->state = PROCESS_STATE_RUNNING; start_task(proc->cr3, proc->esp, proc->eip, event); diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index c2e5bf20..b18b6a69 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -72,59 +72,59 @@ int pm_remove_proc(proc_man_t * pm, int pid) { return -1; } -int pm_activate_process(proc_man_t * pm, int pid) { - if (!pm) { - return -1; - } +// int pm_activate_process(proc_man_t * pm, int pid) { +// if (!pm) { +// return -1; +// } - if (pid == pm->active->pid) { - return 0; - } +// if (pid == pm->active->pid) { +// return 0; +// } - process_t * proc = pm_find_pid(pm, pid); - if (!pid) { - return -1; - } +// process_t * proc = pm_find_pid(pm, pid); +// if (!pid) { +// return -1; +// } - if (proc->state >= PROCESS_STATE_DEAD) { - return -1; - } +// if (proc->state >= PROCESS_STATE_DEAD) { +// return -1; +// } - if (process_activate(proc)) { - return -1; - } +// if (process_activate(proc)) { +// return -1; +// } - if (pm->active->state == PROCESS_STATE_RUNNING) { - pm->active->state = PROCESS_STATE_SUSPENDED; - } +// if (pm->active->state == PROCESS_STATE_RUNNING) { +// pm->active->state = PROCESS_STATE_SUSPENDED; +// } - proc->state = PROCESS_STATE_RUNNING; - pm->active = proc; +// proc->state = PROCESS_STATE_RUNNING; +// pm->active = proc; - return 0; -} +// return 0; +// } -int pm_switch_process(proc_man_t * pm) { - if (!pm) { - return -1; - } +// int pm_switch_process(proc_man_t * pm) { +// if (!pm) { +// return -1; +// } - int last_pid = pm->active->pid; +// int last_pid = pm->active->pid; - do { - pm->active = pm_get_next(pm); +// do { +// pm->active = pm_get_next(pm); - if (pm->active->pid == last_pid) { - PANIC("Process loop detected"); - } - } while (pm->active->state >= PROCESS_STATE_DEAD); +// if (pm->active->pid == last_pid) { +// PANIC("Process loop detected"); +// } +// } while (pm->active->state >= PROCESS_STATE_DEAD); - if (pm_activate_process(pm, pm->active->pid)) { - return -1; - } +// if (pm_activate_process(pm, pm->active->pid)) { +// return -1; +// } - return 0; -} +// return 0; +// } int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { if (!pm) { diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 8cbdd8b8..c1623e0a 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -101,7 +101,10 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); process_yield(proc, regs->esp, regs->eip, args->filter); enable_interrupts(); - // TODO switch task + process_t * next = pm_get_next(kernel_get_proc_man()); + if (pm_resume_process(kernel_get_proc_man(), next->pid, 0)) { + KPANIC("Failed to resume process"); + } }; } From 212d11d7453eabb728a4798baccdebcde39d6b1c Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 21:01:37 -0400 Subject: [PATCH 37/59] Change isr to kpanic --- src/cpu/i386/src/isr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cpu/i386/src/isr.c b/src/cpu/i386/src/isr.c index 8680a4a6..d18cdfc8 100644 --- a/src/cpu/i386/src/isr.c +++ b/src/cpu/i386/src/isr.c @@ -2,6 +2,7 @@ #include "cpu/idt.h" #include "cpu/ports.h" +#include "kernel.h" #include "libc/proc.h" #include "libc/stdio.h" @@ -161,7 +162,7 @@ void isr_handler(registers_t r) { default: break; } - PANIC("STOP HERE"); + KPANIC("STOP HERE"); } /* @@ -191,7 +192,7 @@ void irq_handler(registers_t r) { if (r.int_no >= 256) { printf("BAD INTERRUPT 0x%X\n", r.int_no); print_trace(&r); - PANIC("BAD INTERRUPT"); + KPANIC("BAD INTERRUPT"); return; } From cf8ee217061391aea26ee4109e5eb6040be6a2b3 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 22 Mar 2025 21:06:31 -0400 Subject: [PATCH 38/59] Print pid for each task --- src/kernel/src/idle.c | 2 ++ src/kernel/src/kernel.c | 8 ++++---- src/kernel/src/term.c | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/kernel/src/idle.c b/src/kernel/src/idle.c index eeafefc9..6eabe0c8 100644 --- a/src/kernel/src/idle.c +++ b/src/kernel/src/idle.c @@ -3,6 +3,7 @@ #include "kernel.h" #include "libc/memory.h" #include "libc/proc.h" +#include "libc/stdio.h" static void idle_loop(); @@ -19,6 +20,7 @@ process_t * init_idle() { static void idle_loop() { for (;;) { + printf("idle %u\n", getpid()); ebus_cycle(get_kernel_ebus()); asm("hlt"); int curr_pid = get_current_process()->pid; diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 389ce1c6..eca7fd02 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -215,15 +215,15 @@ void kernel_main() { static void foo_task() { for (;;) { - printf("foo\n"); - yield(0); + printf("foo %u\n", getpid()); + yield(EBUS_EVENT_KEY); } } static void bar_task() { for (;;) { - printf("bar\n"); - yield(EBUS_EVENT_KEY); + printf("bar %u\n", getpid()); + yield(0); } } diff --git a/src/kernel/src/term.c b/src/kernel/src/term.c index 08b839fd..1de76ea2 100644 --- a/src/kernel/src/term.c +++ b/src/kernel/src/term.c @@ -187,6 +187,7 @@ void term_run() { vga_puts("> "); for (;;) { + printf("term %u\n", getpid()); term_update(); // ebus_cycle(get_kernel_ebus()); yield(0); From ef245a58768541f604f983af0604cb637835497b Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 02:08:02 -0400 Subject: [PATCH 39/59] wip re-write task switch --- src/cpu/i386/src/tss.c | 6 +- src/cpu/include/cpu/tss.h | 3 +- src/kernel/include/kernel.h | 2 +- src/kernel/include/process.h | 11 +- src/kernel/include/process_manager.h | 1 - src/kernel/src/idle.c | 1 + src/kernel/src/kernel.c | 43 ++--- src/kernel/src/kernel_entry.asm | 223 ++++++++++++------------- src/kernel/src/process.c | 25 ++- src/kernel/src/process_manager.c | 11 +- src/kernel/src/term.c | 2 +- tests/src/kernel/test_process.cpp | 10 +- tests/src/mocks/include/cpu/tss.mock.h | 2 +- tests/src/mocks/src/cpu.mock.c | 4 +- 14 files changed, 176 insertions(+), 168 deletions(-) diff --git a/src/cpu/i386/src/tss.c b/src/cpu/i386/src/tss.c index d8b0186e..3c6d9f27 100644 --- a/src/cpu/i386/src/tss.c +++ b/src/cpu/i386/src/tss.c @@ -24,6 +24,10 @@ tss_entry_t * tss_get_entry(size_t i) { return &tss_stack[i]; } -void set_kernel_stack(uint32_t stack) { // Used when an interrupt occurs +uint32_t tss_get_esp0() { + return tss_stack[0].esp0; +} + +void tss_set_esp0(uint32_t stack) { // Used when an interrupt occurs tss_stack[0].esp0 = stack; } diff --git a/src/cpu/include/cpu/tss.h b/src/cpu/include/cpu/tss.h index fc87c298..999ddb50 100644 --- a/src/cpu/include/cpu/tss.h +++ b/src/cpu/include/cpu/tss.h @@ -51,6 +51,7 @@ void init_tss(); tss_entry_t * tss_get_entry(size_t i); -void set_kernel_stack(uint32_t stack); +uint32_t tss_get_esp0(void); +void tss_set_esp0(uint32_t stack); #endif // TSS_H diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index 351176ac..d7cf1c11 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -59,7 +59,7 @@ ebus_event_t * pull_event(int event_id); int kernel_add_task(process_t * proc); int kernel_next_task(); int kernel_close_process(process_t * proc); -int kernel_set_current_task(process_t * proc); +// int kernel_set_current_task(process_t * proc); typedef int (*_proc_call_t)(void * data); diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index e73a41d4..a12ba7d1 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -167,12 +167,9 @@ int process_load_heap(process_t * proc, const char * buff, size_t size); */ void set_next_pid(uint32_t next); -#ifdef TESTING -#define NO_RETURN -#else -#define NO_RETURN _Noreturn -#endif - -extern NO_RETURN void start_task(uint32_t cr3, uint32_t esp, uint32_t eip, const ebus_event_t * event); +extern void set_active_task(process_t * active); +extern process_t * get_active_task(void); +extern void start_task(process_t * proc, uint32_t entrypoint); +extern void switch_task(process_t * proc); #endif // KERNEL_PROCESS_H diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h index a0e0b8ff..f18b4669 100644 --- a/src/kernel/include/process_manager.h +++ b/src/kernel/include/process_manager.h @@ -10,7 +10,6 @@ typedef struct _proc_man { arr_t task_list; // process_t * - process_t * active; process_t * idle_task; } proc_man_t; diff --git a/src/kernel/src/idle.c b/src/kernel/src/idle.c index 6eabe0c8..26533d5f 100644 --- a/src/kernel/src/idle.c +++ b/src/kernel/src/idle.c @@ -14,6 +14,7 @@ process_t * init_idle() { } process_set_entrypoint(proc, idle_loop); + proc->state = PROCESS_STATE_LOADED; return proc; } diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index eca7fd02..ebde5ece 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -114,11 +114,12 @@ void kernel_main() { // Kernel process used for memory allocation __kernel.proc.next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); __kernel.proc.cr3 = PADDR_KERNEL_DIR; - __kernel.pm.active = &__kernel.proc; + __kernel.proc.esp0 = VADDR_ISR_STACK; + __kernel.proc.state = PROCESS_STATE_LOADED; + set_active_task(&__kernel.proc); - // TODO make this part of task switching code - // Add isr stack to kernel's TSS - set_kernel_stack(VADDR_ISR_STACK); + // Set initial ESP0 before first task switch + tss_set_esp0(VADDR_ISR_STACK); isr_install(); @@ -133,13 +134,11 @@ void kernel_main() { init_malloc(&__kernel.kernel_memory); pm_create(&__kernel.pm); - __kernel.pm.active = &__kernel.proc; process_t * idle = init_idle(); printf("Idle task pid is %u\n", idle->pid); __kernel.pm.idle_task = idle; __kernel.proc.next_proc = __kernel.pm.idle_task; - __kernel.pm.active = &__kernel.proc; // pm_add_proc(&__kernel.pm, &__kernel.proc); pm_add_proc(&__kernel.pm, idle); // __kernel.pm.task_begin = &__kernel.proc; @@ -194,16 +193,21 @@ void kernel_main() { KPANIC("Failed to create foo task"); } process_set_entrypoint(&foo_proc, foo_task); - pm_add_proc(&__kernel.pm, &foo_proc); + foo_proc.state = PROCESS_STATE_LOADED; + // pm_add_proc(&__kernel.pm, &foo_proc); process_t bar_proc; if (process_create(&bar_proc)) { KPANIC("Failed to create bar task"); } process_set_entrypoint(&bar_proc, bar_task); - pm_add_proc(&__kernel.pm, &bar_proc); + bar_proc.state = PROCESS_STATE_LOADED; + // pm_add_proc(&__kernel.pm, &bar_proc); - pm_resume_process(&__kernel.pm, __kernel.pm.idle_task->pid, 0); + for (;;) { + pm_resume_process(&__kernel.pm, __kernel.pm.idle_task->pid, 0); + asm("hlt"); + } KPANIC("switch didn't happen\n"); @@ -229,8 +233,7 @@ static void bar_task() { static void handle_launch(const ebus_event_t * event) { printf("Start task %u\n", event->task_switch.next_task_pid); - process_t * proc = pm_find_pid(&__kernel.pm, event->task_switch.next_task_pid); - __kernel.pm.active = proc; + process_t * proc = pm_find_pid(&__kernel.pm, event->task_switch.next_task_pid); process_resume(proc, 0); } @@ -273,7 +276,7 @@ int kernel_switch_task(int next_pid) { // __kernel.pm.active = proc; // proc->state = PROCESS_STATE_RUNNING; - // set_kernel_stack(proc->esp0); + // tss_set_esp0(proc->esp0); // mmu_change_dir(proc->cr3); // return 0; } @@ -287,7 +290,7 @@ mmu_table_t * get_kernel_table() { } process_t * get_current_process() { - return __kernel.pm.active; + return get_active_task(); } ebus_t * get_kernel_ebus() { @@ -303,8 +306,8 @@ tar_fs_t * kernel_get_tar() { } void tmp_register_signals_cb(signals_master_cb_t cb) { - __kernel.pm.active->signals_callback = cb; - printf("Attached master signal callback at %p\n", __kernel.pm.active->signals_callback); + get_active_task()->signals_callback = cb; + printf("Attached master signal callback at %p\n", get_active_task()->signals_callback); } ebus_event_t * pull_event(int event_id) { @@ -323,7 +326,7 @@ int kernel_next_task() { // if (pm_switch_process(&__kernel.pm)) { // return -1; // } - return pm_resume_process(&__kernel.pm, __kernel.pm.active->pid, 0); + return pm_resume_process(&__kernel.pm, get_active_task()->pid, 0); // process_t * curr = get_current_process(); // process_t * next = curr->next_proc; // if (!next) { @@ -348,7 +351,7 @@ int kernel_close_process(process_t * proc) { proc->state = PROCESS_STATE_DEAD; - process_t * next = __kernel.pm.active->next_proc; + process_t * next = pm_get_next(&__kernel.pm); if (!next) { next = __kernel.pm.idle_task; } @@ -368,9 +371,9 @@ int kernel_close_process(process_t * proc) { return 0; } -int kernel_set_current_task(process_t * proc) { - __kernel.pm.active = proc; -} +// int kernel_set_current_task(process_t * proc) { +// __kernel.pm.active = proc; +// } // static void init_idle_proc() { // process_t * proc = kmalloc(sizeof(process_t)); diff --git a/src/kernel/src/kernel_entry.asm b/src/kernel/src/kernel_entry.asm index d0481e9a..1965c032 100644 --- a/src/kernel/src/kernel_entry.asm +++ b/src/kernel/src/kernel_entry.asm @@ -14,153 +14,148 @@ halt: hlt jmp halt -[extern register_kernel_exit] +[extern tss_set_esp0] +[extern tss_get_esp0] -; void jump_kernel_mode(void * fn); -global jump_kernel_mode -jump_kernel_mode: - mov eax, [esp+4] - mov [.cb], eax +TCB_CR3 equ 0 +TCB_ESP equ 4 +TCB_ESP0 equ 8 - mov eax, .exit - push eax - - mov eax, cr3 - push eax +; proc_t * +active_task: dd 0 - push ebp +; void set_active_task(proc_t * active) +global set_active_task +set_active_task: + ; ebp = args + push ebp, + mov ebp, esp + add ebp, 4 - push esp + push eax - call register_kernel_exit + ; eax = active + mov eax, [ebp+4] + mov [active_task], eax -.exit: - call [.cb] + pop eax + pop ebp ret -.cb: dd 0 +; proc_t * get_active_task(void) +global get_active_task +get_active_task: + mov eax, [active_task] -; void jump_proc(uint32_t cr3, uint32_t esp, uint32_t call); -global jump_proc -jump_proc: - mov eax, [esp+4] ; cr3 - mov ebx, [esp+8] ; esp - mov edx, [esp+12] ; call + ret - mov cr3, eax - mov ebp, ebx - mov esp, ebx - - jmp edx - -global jump_usermode -jump_usermode: - mov ebx, [esp+4] - mov ax, (4 * 8) | 3 ; ring 3 data with bottom 2 bits set for ring 3 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax ; SS is handled by iret - - ; set up the stack frame iret expects - mov eax, esp - push (4 * 8) | 3 ; data selector - push eax ; current esp - pushf ; eflags - push (3 * 8) | 3 ; code selector (ring 3 code with bottom 2 bits set for ring 3) - push ebx ; instruction address to return to - iret - -; https://wiki.osdev.org/Brendan%27s_Multi-tasking_Tutorial - -;C declaration: -; void switch_to_task(thread_control_block *next_thread); -; -;WARNING: Caller is expected to disable IRQs before calling, and enable IRQs again after function returns - -TCB_CR3 equ 4 -TCB_ESP equ 8 -TCB_ESP0 equ 12 - -current_task_TCB: dd 0 - -; void start_task(uint32_t cr3, uint32_t esp, uint32_t eip, const ebus_event_t * event) +; void start_task(proc_t * new, uint32_t entrypoint) global start_task start_task: - mov ebp, esp - mov ecx, [ebp+4] ; cr3 - mov edx, [ebp+8] ; esp - mov ebx, [ebp+12] ; eip - mov eax, [ebp+16] ; event + ; ebp = args + push ebp + mov ebp, esp + add ebp, 4 - mov esp, edx - mov cr3, ecx + push edi + push esi + push eax - jmp ebx + ; edi = active + mov edi, [active_task] + ; esi = next + mov esi, [ebp+4] + ; store cr3 + mov eax, cr3 + mov [edi+TCB_CR3], eax -; void resume_task(uint32_t cr3, uint32_t esp, const ebus_event_t * event) -global resume_task -resume_task: - mov ebp, esp - mov ecx, [ebp+4] ; cr3 - mov ebx, [ebp+8] ; esp - mov eax, [ebp+12] ; event + ; store esp + mov [edi+TCB_ESP], esp - ; TODO get tss and set it's esp0 - ; mov [TSS_ESP0], ebx ;Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) - mov edi, cr3 ;edi = previous task's virtual address space + ; store esp0 + call tss_get_esp0 + mov [edi+TCB_ESP0], eax - cmp ecx, edi ;Does the virtual address space need to being changed? - je .done ; no, virtual address space is the same, so don't reload it and cause TLB flushes - mov cr3, ecx ; yes, load the next task's virtual address space +.resume: + mov [active_task], esi -.done: + ; load esp0 + mov eax, [esi+TCB_ESP0] + push eax + call tss_set_esp0 + pop eax - mov esp, ebx + ; load esp + mov esp, [esi+TCB_ESP] - ret ;Load next task's EIP from its kernel stack + ; load cr3 + mov eax, [esi+TCB_CR3] + mov cr3, eax -global switch_to_task -switch_to_task: + ; eax = entrypoint + mov eax, [ebp+4] - ;Save previous task's state + ; Start task + call eax - ;Notes: - ; For cdecl; EAX, ECX, and EDX are already saved by the caller and don't need to be saved again - ; EIP is already saved on the stack by the caller's "CALL" instruction - ; The task isn't able to change CR3 so it doesn't need to be saved - ; Segment registers are constants (while running kernel code) so they don't need to be saved + pop eax + pop esi + pop edi - push ebx - push esi - push edi + pop ebp + + ret + +; switch_task(proc_t * next) +global switch_task +switch_task: + ; ebp = args push ebp + mov ebp, esp + add ebp, 4 - mov edi, [current_task_TCB] ;edi = address of the previous task's "thread control block" - mov [edi+TCB_ESP], esp ;Save ESP for previous task's kernel stack in the thread's TCB + push edi + push esi + push eax - ;Load next task's state + ; edi = active + mov edi, [active_task] + ; esi = next + mov esi, [ebp+4] - mov esi, [esp+(4+1)*4] ;esi = address of the next task's "thread control block" (parameter passed on stack) - mov [current_task_TCB], esi ;Current task's TCB is the next task TCB + ; store cr3 + mov eax, cr3 + mov [edi+TCB_CR3], eax - mov esp, [esi+TCB_ESP] ;Load ESP for next task's kernel stack from the thread's TCB - mov eax, [esi+TCB_CR3] ;eax = address of page directory for next task - mov ebx, [esi+TCB_ESP0] ;ebx = address for the top of the next task's kernel stack - ; mov [TSS_ESP0], ebx ;Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) - mov ecx, cr3 ;ecx = previous task's virtual address space + ; store esp + mov [edi+TCB_ESP], esp - cmp eax, ecx ;Does the virtual address space need to being changed? - je .doneVAS ; no, virtual address space is the same, so don't reload it and cause TLB flushes - mov cr3, eax ; yes, load the next task's virtual address space + ; store esp0 + call tss_get_esp0 + mov [edi+TCB_ESP0], eax -.doneVAS: +.resume: + mov [active_task], esi - pop ebp - pop edi + ; load esp0 + mov eax, [esi+TCB_ESP0] + push eax + call tss_set_esp0 + pop eax + + ; load esp + mov esp, [esi+TCB_ESP] + + ; load cr3 + mov eax, [esi+TCB_CR3] + mov cr3, eax + + pop eax pop esi - pop ebx + pop edi + + pop ebp - ret ;Load next task's EIP from its kernel stack + ret diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 34978b8d..21aed7e3 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -140,7 +140,7 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { // return -1; // } -// set_kernel_stack(proc->esp0); // just updates tss 0 +// tss_set_esp0(proc->esp0); // just updates tss 0 // mmu_change_dir(proc->cr3); // return 0; @@ -160,16 +160,27 @@ int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter) { } int process_resume(process_t * proc, const ebus_event_t * event) { - if (!proc || proc->state >= PROCESS_STATE_DEAD) { + if (!proc || proc->state < PROCESS_STATE_LOADED || proc->state >= PROCESS_STATE_DEAD) { return -1; } - // process_activate(proc); - proc->state = PROCESS_STATE_RUNNING; - start_task(proc->cr3, proc->esp, proc->eip, event); + process_t * active_before = get_active_task(); + active_before->state = PROCESS_STATE_SUSPENDED; - proc->state = PROCESS_STATE_ERROR; - return -1; + if (proc->state == PROCESS_STATE_LOADED) { + proc->state = PROCESS_STATE_RUNNING; + start_task(proc, proc->eip); + } + else { + proc->state = PROCESS_STATE_RUNNING; + switch_task(proc); + } + + // Call this again because we are a new process now + process_t * active_after = get_active_task(); + active_after->state = PROCESS_STATE_RUNNING; + + return 0; } void * process_add_pages(process_t * proc, size_t count) { diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index b18b6a69..8c72da8f 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -14,8 +14,6 @@ int pm_create(proc_man_t * pm) { return -1; } - pm->active = 0; - return 0; } @@ -24,7 +22,8 @@ process_t * pm_get_active(proc_man_t * pm) { return 0; } - return pm->active; + // TODO this is redundant now + return get_active_task(); } process_t * pm_find_pid(proc_man_t * pm, int pid) { @@ -60,7 +59,7 @@ int pm_remove_proc(proc_man_t * pm, int pid) { return -1; } - if (pid == pm->active->pid) { + if (pid == get_active_task()->pid) { return -1; } @@ -136,8 +135,6 @@ int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { return -1; } - pm->active = proc; - return process_resume(proc, event); } @@ -146,7 +143,7 @@ process_t * pm_get_next(proc_man_t * pm) { return 0; } - int i = pid_arr_index(&pm->task_list, pm->active->pid); + int i = pid_arr_index(&pm->task_list, get_active_task()->pid); if (i < 0) { return 0; } diff --git a/src/kernel/src/term.c b/src/kernel/src/term.c index 1de76ea2..24fa2099 100644 --- a/src/kernel/src/term.c +++ b/src/kernel/src/term.c @@ -188,7 +188,7 @@ void term_run() { for (;;) { printf("term %u\n", getpid()); - term_update(); + term_update(); // ebus_cycle(get_kernel_ebus()); yield(0); // asm("hlt"); diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index afad70ca..cbb4562b 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -227,8 +227,8 @@ TEST_F(Process, process_activate) { proc.esp0 = 3; proc.cr3 = 4; EXPECT_EQ(0, process_activate(&proc)); - ASSERT_EQ(1, set_kernel_stack_fake.call_count); - EXPECT_EQ(3, set_kernel_stack_fake.arg0_val); + ASSERT_EQ(1, tss_set_esp0_fake.call_count); + EXPECT_EQ(3, tss_set_esp0_fake.arg0_val); ASSERT_EQ(1, mmu_change_dir_fake.call_count); EXPECT_EQ(4, mmu_change_dir_fake.arg0_val); } @@ -256,7 +256,7 @@ TEST_F(Process, process_yield) { TEST_F(Process, process_resume_InvalidParameters) { EXPECT_NE(0, process_resume(0, 0)); - EXPECT_EQ(0, set_kernel_stack_fake.call_count); + EXPECT_EQ(0, tss_set_esp0_fake.call_count); EXPECT_EQ(0, mmu_change_dir_fake.call_count); proc.state = PROCESS_STATE_DEAD; EXPECT_NE(0, process_resume(0, 0)); @@ -280,8 +280,8 @@ TEST_F(Process, process_resume) { proc.cr3 = 4; start_task_fake.custom_fake = custom_start_task; EXPECT_NE(0, process_resume(&proc, (ebus_event_t *)5)); - ASSERT_EQ(1, set_kernel_stack_fake.call_count); - EXPECT_EQ(3, set_kernel_stack_fake.arg0_val); + ASSERT_EQ(1, tss_set_esp0_fake.call_count); + EXPECT_EQ(3, tss_set_esp0_fake.arg0_val); ASSERT_EQ(1, mmu_change_dir_fake.call_count); EXPECT_EQ(4, mmu_change_dir_fake.arg0_val); ASSERT_EQ(1, start_task_fake.call_count); diff --git a/tests/src/mocks/include/cpu/tss.mock.h b/tests/src/mocks/include/cpu/tss.mock.h index 648c1530..27e22b44 100644 --- a/tests/src/mocks/include/cpu/tss.mock.h +++ b/tests/src/mocks/include/cpu/tss.mock.h @@ -9,7 +9,7 @@ extern "C" { DECLARE_FAKE_VOID_FUNC(init_tss); DECLARE_FAKE_VALUE_FUNC(tss_entry_t *, tss_get_entry, size_t); -DECLARE_FAKE_VOID_FUNC(set_kernel_stack, uint32_t); +DECLARE_FAKE_VOID_FUNC(tss_set_esp0, uint32_t); void reset_cpu_tss_mock(void); diff --git a/tests/src/mocks/src/cpu.mock.c b/tests/src/mocks/src/cpu.mock.c index 269fde32..54f613d9 100644 --- a/tests/src/mocks/src/cpu.mock.c +++ b/tests/src/mocks/src/cpu.mock.c @@ -64,10 +64,10 @@ void reset_cpu_ports_mock() { DEFINE_FAKE_VOID_FUNC(init_tss); DEFINE_FAKE_VALUE_FUNC(tss_entry_t *, tss_get_entry, size_t); -DEFINE_FAKE_VOID_FUNC(set_kernel_stack, uint32_t); +DEFINE_FAKE_VOID_FUNC(tss_set_esp0, uint32_t); void reset_cpu_tss_mock() { RESET_FAKE(init_tss); RESET_FAKE(tss_get_entry); - RESET_FAKE(set_kernel_stack); + RESET_FAKE(tss_set_esp0); } From 50c1f47f26bf65160c92e6c6ddf214f910e3b840 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 02:38:48 -0400 Subject: [PATCH 40/59] getting closer --- src/kernel/src/kernel_entry.asm | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/kernel/src/kernel_entry.asm b/src/kernel/src/kernel_entry.asm index 1965c032..46793dd5 100644 --- a/src/kernel/src/kernel_entry.asm +++ b/src/kernel/src/kernel_entry.asm @@ -56,16 +56,17 @@ start_task: ; ebp = args push ebp mov ebp, esp - add ebp, 4 + add ebp, 8 push edi push esi push eax + push ecx ; edi = active mov edi, [active_task] ; esi = next - mov esi, [ebp+4] + mov esi, [ebp] ; store cr3 mov eax, cr3 @@ -88,18 +89,21 @@ start_task: pop eax ; load esp - mov esp, [esi+TCB_ESP] + mov ecx, [esi+TCB_ESP] + + ; edi = entrypoint + mov edi, [ebp+4] ; load cr3 mov eax, [esi+TCB_CR3] mov cr3, eax - ; eax = entrypoint - mov eax, [ebp+4] + mov esp, ecx ; Start task - call eax + call edi + pop ecx pop eax pop esi pop edi @@ -114,7 +118,7 @@ switch_task: ; ebp = args push ebp mov ebp, esp - add ebp, 4 + add ebp, 8 push edi push esi From a55d1ec1bc69e1efdde12d365d8129afb76160c6 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 02:52:45 -0400 Subject: [PATCH 41/59] Might be getting further --- src/kernel/src/kernel_entry.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/src/kernel_entry.asm b/src/kernel/src/kernel_entry.asm index 46793dd5..906e14dd 100644 --- a/src/kernel/src/kernel_entry.asm +++ b/src/kernel/src/kernel_entry.asm @@ -127,7 +127,7 @@ switch_task: ; edi = active mov edi, [active_task] ; esi = next - mov esi, [ebp+4] + mov esi, [ebp] ; store cr3 mov eax, cr3 From fa5b1c1b2db2eed46045220677513f053cb0c8ed Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 11:03:54 -0400 Subject: [PATCH 42/59] TASK SWITCH WORKS! --- src/kernel/include/process.h | 6 +-- src/kernel/src/process.c | 72 ++++++++++++++++++++++--------- src/kernel/src/system_call_proc.c | 2 +- 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index a12ba7d1..89d90fcc 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -42,8 +42,6 @@ typedef struct _process { // TODO heap & stack limits - uint32_t eip; - signals_master_cb_t signals_callback; arr_t io_handles; // array ebus_t event_queue; @@ -104,7 +102,7 @@ int process_set_entrypoint(process_t * proc, void * entrypoint); * @param filter ebus event type if polling for an event, 0 for no filter * @return int 0 for success */ -int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter); +// int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter); /** * @brief Activate and jump to the process. @@ -169,7 +167,7 @@ void set_next_pid(uint32_t next); extern void set_active_task(process_t * active); extern process_t * get_active_task(void); -extern void start_task(process_t * proc, uint32_t entrypoint); +// extern void start_task(process_t * proc, uint32_t entrypoint); extern void switch_task(process_t * proc); #endif // KERNEL_PROCESS_H diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 21aed7e3..c7b8e77e 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -127,11 +127,49 @@ int process_free(process_t * proc) { } int process_set_entrypoint(process_t * proc, void * entrypoint) { - if (!proc || !entrypoint) { + if (!proc || !entrypoint || proc->state >= PROCESS_STATE_SUSPENDED) { return -1; } - proc->eip = PTR2UINT(entrypoint); + uint32_t ret_addr = proc->esp; + uint32_t ret_page = ADDR2PAGE(ret_addr); + uint32_t dir_i = ret_page / MMU_DIR_SIZE; + uint32_t table_i = ret_page % MMU_TABLE_SIZE; + + mmu_dir_t * dir = paging_temp_map(proc->cr3); + + if (!dir) { + return -1; + } + + uint32_t table_addr = mmu_dir_get_addr(dir, dir_i); + + mmu_table_t * table = paging_temp_map(table_addr); + + if (!table) { + paging_temp_free(proc->cr3); + return -1; + } + + uint32_t page_addr = mmu_table_get_addr(table, table_i); + + uint32_t * stack = paging_temp_map(page_addr); + + int ret_i = (proc->esp % PAGE_SIZE) / 4; + stack[ret_i] = PTR2UINT(entrypoint); + + if (!stack) { + paging_temp_free(table_addr); + paging_temp_free(proc->cr3); + return -1; + } + + paging_temp_free(page_addr); + paging_temp_free(table_addr); + paging_temp_free(proc->cr3); + + proc->esp -= (5 * 4) - 1; + return 0; } @@ -146,18 +184,18 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { // return 0; // } -int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter) { - if (!proc || !esp || !eip) { - return -1; - } +// int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter) { +// if (!proc || !esp || !eip) { +// return -1; +// } - proc->eip = eip; - proc->filter_event = filter; - proc->esp = esp; - proc->state = PROCESS_STATE_SUSPENDED; +// proc->eip = eip; +// proc->filter_event = filter; +// proc->esp = esp; +// proc->state = PROCESS_STATE_SUSPENDED; - return 0; -} +// return 0; +// } int process_resume(process_t * proc, const ebus_event_t * event) { if (!proc || proc->state < PROCESS_STATE_LOADED || proc->state >= PROCESS_STATE_DEAD) { @@ -167,14 +205,8 @@ int process_resume(process_t * proc, const ebus_event_t * event) { process_t * active_before = get_active_task(); active_before->state = PROCESS_STATE_SUSPENDED; - if (proc->state == PROCESS_STATE_LOADED) { - proc->state = PROCESS_STATE_RUNNING; - start_task(proc, proc->eip); - } - else { - proc->state = PROCESS_STATE_RUNNING; - switch_task(proc); - } + proc->state = PROCESS_STATE_RUNNING; + switch_task(proc); // Call this again because we are a new process now process_t * active_after = get_active_task(); diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index c1623e0a..7a26dcae 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -99,7 +99,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { // TODO clear iret from stack? process_t * proc = get_current_process(); - process_yield(proc, regs->esp, regs->eip, args->filter); + // process_yield(proc, regs->esp, regs->eip, args->filter); enable_interrupts(); process_t * next = pm_get_next(kernel_get_proc_man()); if (pm_resume_process(kernel_get_proc_man(), next->pid, 0)) { From bbd4b8e3e4bb2db070333b49d4ca1dcbc54ebe52 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 11:04:05 -0400 Subject: [PATCH 43/59] Format --- src/kernel/include/process.h | 2 +- src/kernel/src/term.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 89d90fcc..7793ac3a 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -168,6 +168,6 @@ void set_next_pid(uint32_t next); extern void set_active_task(process_t * active); extern process_t * get_active_task(void); // extern void start_task(process_t * proc, uint32_t entrypoint); -extern void switch_task(process_t * proc); +extern void switch_task(process_t * proc); #endif // KERNEL_PROCESS_H diff --git a/src/kernel/src/term.c b/src/kernel/src/term.c index 24fa2099..1de76ea2 100644 --- a/src/kernel/src/term.c +++ b/src/kernel/src/term.c @@ -188,7 +188,7 @@ void term_run() { for (;;) { printf("term %u\n", getpid()); - term_update(); + term_update(); // ebus_cycle(get_kernel_ebus()); yield(0); // asm("hlt"); From 6627ff124f41cd77369276a56763f3a6553a9afc Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 11:10:11 -0400 Subject: [PATCH 44/59] cleanup --- src/kernel/include/kernel.h | 1 - src/kernel/include/process.h | 24 +------- src/kernel/include/process_manager.h | 2 - src/kernel/src/kernel.c | 89 +--------------------------- src/kernel/src/kernel_entry.asm | 62 ------------------- src/kernel/src/process.c | 24 -------- src/kernel/src/process_manager.c | 54 ----------------- 7 files changed, 3 insertions(+), 253 deletions(-) diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index d7cf1c11..f5bb0f8d 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -59,7 +59,6 @@ ebus_event_t * pull_event(int event_id); int kernel_add_task(process_t * proc); int kernel_next_task(); int kernel_close_process(process_t * proc); -// int kernel_set_current_task(process_t * proc); typedef int (*_proc_call_t)(void * data); diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 7793ac3a..428cfb09 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -83,27 +83,6 @@ int process_free(process_t * proc); */ int process_set_entrypoint(process_t * proc, void * entrypoint); -/** - * @brief Load process without entering. - * - * Load the cr3 and esp0. This does not start or resume the process. - * - * @param proc pointer to the process object - * @return int 0 for success - */ -// int process_activate(process_t * proc); - -/** - * @brief Store the current process state for later use when resuming. - * - * @param proc pointer to the process object - * @param esp stack pointer - * @param eip instruction pointer - * @param filter ebus event type if polling for an event, 0 for no filter - * @return int 0 for success - */ -// int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter); - /** * @brief Activate and jump to the process. * @@ -167,7 +146,6 @@ void set_next_pid(uint32_t next); extern void set_active_task(process_t * active); extern process_t * get_active_task(void); -// extern void start_task(process_t * proc, uint32_t entrypoint); -extern void switch_task(process_t * proc); +extern void switch_task(process_t * proc); #endif // KERNEL_PROCESS_H diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h index f18b4669..ebc899a9 100644 --- a/src/kernel/include/process_manager.h +++ b/src/kernel/include/process_manager.h @@ -23,8 +23,6 @@ process_t * pm_find_pid(proc_man_t * pm, int pid); int pm_add_proc(proc_man_t * pm, process_t * proc); int pm_remove_proc(proc_man_t * pm, int pid); -// int pm_activate_process(proc_man_t * pm, int pid); -// int pm_switch_process(proc_man_t * pm); int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event); process_t * pm_get_next(proc_man_t * pm); diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index ebde5ece..3d114ffc 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -184,17 +184,13 @@ void kernel_main() { KPANIC("Failed to open tar"); } - // set_first_task(__kernel.pm.active); - - // switch_to_task(__kernel.pm.active); - process_t foo_proc; if (process_create(&foo_proc)) { KPANIC("Failed to create foo task"); } process_set_entrypoint(&foo_proc, foo_task); foo_proc.state = PROCESS_STATE_LOADED; - // pm_add_proc(&__kernel.pm, &foo_proc); + pm_add_proc(&__kernel.pm, &foo_proc); process_t bar_proc; if (process_create(&bar_proc)) { @@ -202,18 +198,13 @@ void kernel_main() { } process_set_entrypoint(&bar_proc, bar_task); bar_proc.state = PROCESS_STATE_LOADED; - // pm_add_proc(&__kernel.pm, &bar_proc); + pm_add_proc(&__kernel.pm, &bar_proc); for (;;) { pm_resume_process(&__kernel.pm, __kernel.pm.idle_task->pid, 0); asm("hlt"); } - KPANIC("switch didn't happen\n"); - - // jump_usermode(term_run); - jump_kernel_mode(term_run); - KPANIC("You shouldn't be here!"); } @@ -247,38 +238,8 @@ static void handle_kill(const ebus_event_t * event) { process_free(proc); } -// int kernel_call_as_proc(int pid, _proc_call_t fn, void * data) { -// if (!fn) { -// return -1; -// } - -// process_t * curr = get_current_process(); -// if (curr->pid != pid) { -// kernel_switch_task(pid); -// } - -// int res = fn(data); - -// if (curr->pid != pid) { -// kernel_switch_task(curr->pid); -// } - -// return res; -// } - int kernel_switch_task(int next_pid) { return pm_resume_process(&__kernel.pm, next_pid, 0); - // return pm_activate_process(&__kernel.pm, next_pid); - // process_t * proc = pm_find_pid(&__kernel.pm, next_pid); - // if (!proc || proc->state == PROCESS_STATE_DEAD) { - // return -1; - // } - - // __kernel.pm.active = proc; - // proc->state = PROCESS_STATE_RUNNING; - // tss_set_esp0(proc->esp0); - // mmu_change_dir(proc->cr3); - // return 0; } mmu_dir_t * get_kernel_dir() { @@ -323,25 +284,7 @@ int kernel_add_task(process_t * proc) { } int kernel_next_task() { - // if (pm_switch_process(&__kernel.pm)) { - // return -1; - // } return pm_resume_process(&__kernel.pm, get_active_task()->pid, 0); - // process_t * curr = get_current_process(); - // process_t * next = curr->next_proc; - // if (!next) { - // next = __kernel.pm.idle_task; - // } - - // __kernel.pm.active = next; - - // // TODO interrupt back to process for sigint - - // if (process_resume(__kernel.pm.active, 0)) { - // KPANIC("Failed to resume task"); - // } - - // return 0; } int kernel_close_process(process_t * proc) { @@ -371,34 +314,6 @@ int kernel_close_process(process_t * proc) { return 0; } -// int kernel_set_current_task(process_t * proc) { -// __kernel.pm.active = proc; -// } - -// static void init_idle_proc() { -// process_t * proc = kmalloc(sizeof(process_t)); -// if (process_create(proc)) { -// KPANIC("Failed to create idle task"); -// } - -// // Kernel process used for memory allocation -// proc->next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); -// process_set_entrypoint(proc, idle); - -// // Setup kernel process as idle process -// __kernel.pm.idle_task = proc; -// // __kernel.pm.task_begin = proc; -// } - -// void idle() { -// vga_puts("Start idle task\n> "); -// for (;;) { -// term_update(); -// ebus_cycle(get_kernel_ebus()); -// asm("hlt"); -// } -// } - NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int line) { vga_color(VGA_FG_WHITE | VGA_BG_RED); vga_puts("[KERNEL PANIC]"); diff --git a/src/kernel/src/kernel_entry.asm b/src/kernel/src/kernel_entry.asm index 906e14dd..b87cc596 100644 --- a/src/kernel/src/kernel_entry.asm +++ b/src/kernel/src/kernel_entry.asm @@ -50,68 +50,6 @@ get_active_task: ret -; void start_task(proc_t * new, uint32_t entrypoint) -global start_task -start_task: - ; ebp = args - push ebp - mov ebp, esp - add ebp, 8 - - push edi - push esi - push eax - push ecx - - ; edi = active - mov edi, [active_task] - ; esi = next - mov esi, [ebp] - - ; store cr3 - mov eax, cr3 - mov [edi+TCB_CR3], eax - - ; store esp - mov [edi+TCB_ESP], esp - - ; store esp0 - call tss_get_esp0 - mov [edi+TCB_ESP0], eax - -.resume: - mov [active_task], esi - - ; load esp0 - mov eax, [esi+TCB_ESP0] - push eax - call tss_set_esp0 - pop eax - - ; load esp - mov ecx, [esi+TCB_ESP] - - ; edi = entrypoint - mov edi, [ebp+4] - - ; load cr3 - mov eax, [esi+TCB_CR3] - mov cr3, eax - - mov esp, ecx - - ; Start task - call edi - - pop ecx - pop eax - pop esi - pop edi - - pop ebp - - ret - ; switch_task(proc_t * next) global switch_task switch_task: diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index c7b8e77e..c5cc73bf 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -173,30 +173,6 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { return 0; } -// int process_activate(process_t * proc) { -// if (!proc) { -// return -1; -// } - -// tss_set_esp0(proc->esp0); // just updates tss 0 -// mmu_change_dir(proc->cr3); - -// return 0; -// } - -// int process_yield(process_t * proc, uint32_t esp, uint32_t eip, int filter) { -// if (!proc || !esp || !eip) { -// return -1; -// } - -// proc->eip = eip; -// proc->filter_event = filter; -// proc->esp = esp; -// proc->state = PROCESS_STATE_SUSPENDED; - -// return 0; -// } - int process_resume(process_t * proc, const ebus_event_t * event) { if (!proc || proc->state < PROCESS_STATE_LOADED || proc->state >= PROCESS_STATE_DEAD) { return -1; diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 8c72da8f..13289c24 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -71,60 +71,6 @@ int pm_remove_proc(proc_man_t * pm, int pid) { return -1; } -// int pm_activate_process(proc_man_t * pm, int pid) { -// if (!pm) { -// return -1; -// } - -// if (pid == pm->active->pid) { -// return 0; -// } - -// process_t * proc = pm_find_pid(pm, pid); -// if (!pid) { -// return -1; -// } - -// if (proc->state >= PROCESS_STATE_DEAD) { -// return -1; -// } - -// if (process_activate(proc)) { -// return -1; -// } - -// if (pm->active->state == PROCESS_STATE_RUNNING) { -// pm->active->state = PROCESS_STATE_SUSPENDED; -// } - -// proc->state = PROCESS_STATE_RUNNING; -// pm->active = proc; - -// return 0; -// } - -// int pm_switch_process(proc_man_t * pm) { -// if (!pm) { -// return -1; -// } - -// int last_pid = pm->active->pid; - -// do { -// pm->active = pm_get_next(pm); - -// if (pm->active->pid == last_pid) { -// PANIC("Process loop detected"); -// } -// } while (pm->active->state >= PROCESS_STATE_DEAD); - -// if (pm_activate_process(pm, pm->active->pid)) { -// return -1; -// } - -// return 0; -// } - int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { if (!pm) { return -1; From ebc3fc61b6812832bf3dc575db62641bdffac370 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 11:28:54 -0400 Subject: [PATCH 45/59] Updating tests --- tests/src/kernel/test_process.cpp | 69 ++++++-------------------- tests/src/mocks/include/process.mock.h | 6 +-- tests/src/mocks/src/process.mock.c | 12 ++--- 3 files changed, 24 insertions(+), 63 deletions(-) diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index cbb4562b..909074af 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -12,6 +12,7 @@ extern "C" { mmu_dir_t dir; mmu_table_t table; process_t proc; +process_t alt_proc; int custom_mmu_dir_set(mmu_dir_t * dir, size_t i, uint32_t addr, uint32_t flags) { if (!dir || i >= MMU_DIR_SIZE) { @@ -49,6 +50,7 @@ class Process : public ::testing::Test { memset(&dir, 0, sizeof(dir)); memset(&table, 0, sizeof(table)); memset(&proc, 0, sizeof(proc)); + memset(&alt_proc, 0, sizeof(alt_proc)); temp_page.fill(0); @@ -214,42 +216,6 @@ TEST_F(Process, process_set_entrypoint_InvalidParameters) { TEST_F(Process, process_set_entrypoint) { EXPECT_EQ(0, process_set_entrypoint(&proc, (void *)3)); - EXPECT_EQ(3, proc.eip); -} - -// Process Activate - -TEST_F(Process, process_activate_InvalidParameters) { - EXPECT_NE(0, process_activate(0)); -} - -TEST_F(Process, process_activate) { - proc.esp0 = 3; - proc.cr3 = 4; - EXPECT_EQ(0, process_activate(&proc)); - ASSERT_EQ(1, tss_set_esp0_fake.call_count); - EXPECT_EQ(3, tss_set_esp0_fake.arg0_val); - ASSERT_EQ(1, mmu_change_dir_fake.call_count); - EXPECT_EQ(4, mmu_change_dir_fake.arg0_val); -} - -// Process Yield - -TEST_F(Process, process_yield_InvalidParameters) { - EXPECT_NE(0, process_yield(0, 0, 0, 0)); - EXPECT_NE(0, process_yield(&proc, 0, 0, 0)); - EXPECT_NE(0, process_yield(0, 1, 0, 0)); - EXPECT_NE(0, process_yield(0, 0, 1, 0)); - EXPECT_NE(0, process_yield(&proc, 1, 0, 0)); - EXPECT_NE(0, process_yield(&proc, 0, 1, 0)); - EXPECT_NE(0, process_yield(0, 1, 1, 0)); -} - -TEST_F(Process, process_yield) { - EXPECT_EQ(0, process_yield(&proc, 1, 2, 3)); - EXPECT_EQ(1, proc.esp); - EXPECT_EQ(2, proc.eip); - EXPECT_EQ(3, proc.filter_event); } // Process Resume @@ -269,28 +235,23 @@ TEST_F(Process, process_resume_ProcessDead) { EXPECT_NE(0, process_resume(&proc, 0)); } -static void custom_start_task(uint32_t cr3, uint32_t esp, uint32_t eip, const ebus_event_t * event) { +static void customswitch_task(process_t *) { ASSERT_EQ(PROCESS_STATE_RUNNING, proc.state); + ASSERT_EQ(PROCESS_STATE_SUSPENDED, alt_proc.state); } TEST_F(Process, process_resume) { - proc.esp = 1; - proc.eip = 2; - proc.esp0 = 3; - proc.cr3 = 4; - start_task_fake.custom_fake = custom_start_task; - EXPECT_NE(0, process_resume(&proc, (ebus_event_t *)5)); - ASSERT_EQ(1, tss_set_esp0_fake.call_count); - EXPECT_EQ(3, tss_set_esp0_fake.arg0_val); - ASSERT_EQ(1, mmu_change_dir_fake.call_count); - EXPECT_EQ(4, mmu_change_dir_fake.arg0_val); - ASSERT_EQ(1, start_task_fake.call_count); - EXPECT_EQ(4, start_task_fake.arg0_val); - EXPECT_EQ(1, start_task_fake.arg1_val); - EXPECT_EQ(2, start_task_fake.arg2_val); - EXPECT_EQ((ebus_event_t *)5, start_task_fake.arg3_val); - - EXPECT_EQ(PROCESS_STATE_ERROR, proc.state); + proc.esp = 1; + proc.esp0 = 3; + proc.cr3 = 4; + switch_task_fake.custom_fake = customswitch_task; + proc.state = PROCESS_STATE_SUSPENDED; + alt_proc.state = PROCESS_STATE_RUNNING; + get_active_task_fake.return_val = &alt_proc; + EXPECT_EQ(0, process_resume(&proc, (ebus_event_t *)5)); + ASSERT_EQ(1, switch_task_fake.call_count); + EXPECT_EQ(&proc, switch_task_fake.arg0_val); + EXPECT_EQ(PROCESS_STATE_RUNNING, alt_proc.state); } // Process Add Pages diff --git a/tests/src/mocks/include/process.mock.h b/tests/src/mocks/include/process.mock.h index b3d904ed..ef9aaa29 100644 --- a/tests/src/mocks/include/process.mock.h +++ b/tests/src/mocks/include/process.mock.h @@ -10,13 +10,13 @@ extern "C" { DECLARE_FAKE_VALUE_FUNC(int, process_create, process_t *); DECLARE_FAKE_VALUE_FUNC(int, process_free, process_t *); DECLARE_FAKE_VALUE_FUNC(int, process_set_entrypoint, process_t *, void *); -DECLARE_FAKE_VALUE_FUNC(int, process_activate, process_t *); -DECLARE_FAKE_VALUE_FUNC(int, process_yield, process_t *, uint32_t, uint32_t, int); DECLARE_FAKE_VALUE_FUNC(int, process_resume, process_t *, const ebus_event_t *); DECLARE_FAKE_VALUE_FUNC(void *, process_add_pages, process_t *, size_t); DECLARE_FAKE_VALUE_FUNC(int, process_grow_stack, process_t *); DECLARE_FAKE_VALUE_FUNC(int, process_load_heap, process_t *, const char *, size_t); -DECLARE_FAKE_VOID_FUNC(start_task, uint32_t, uint32_t, uint32_t, const ebus_event_t *); +DECLARE_FAKE_VOID_FUNC(set_active_task, process_t *); +DECLARE_FAKE_VALUE_FUNC(process_t *, get_active_task); +DECLARE_FAKE_VOID_FUNC(switch_task, process_t *); void reset_process_mock(void); diff --git a/tests/src/mocks/src/process.mock.c b/tests/src/mocks/src/process.mock.c index fbfe1098..3bf16fc7 100644 --- a/tests/src/mocks/src/process.mock.c +++ b/tests/src/mocks/src/process.mock.c @@ -4,23 +4,23 @@ DEFINE_FAKE_VALUE_FUNC(int, process_create, process_t *); DEFINE_FAKE_VALUE_FUNC(int, process_free, process_t *); DEFINE_FAKE_VALUE_FUNC(int, process_set_entrypoint, process_t *, void *); -DEFINE_FAKE_VALUE_FUNC(int, process_activate, process_t *); -DEFINE_FAKE_VALUE_FUNC(int, process_yield, process_t *, uint32_t, uint32_t, int); DEFINE_FAKE_VALUE_FUNC(int, process_resume, process_t *, const ebus_event_t *); DEFINE_FAKE_VALUE_FUNC(void *, process_add_pages, process_t *, size_t); DEFINE_FAKE_VALUE_FUNC(int, process_grow_stack, process_t *); DEFINE_FAKE_VALUE_FUNC(int, process_load_heap, process_t *, const char *, size_t); -DEFINE_FAKE_VOID_FUNC(start_task, uint32_t, uint32_t, uint32_t, const ebus_event_t *); +DEFINE_FAKE_VOID_FUNC(set_active_task, process_t *); +DEFINE_FAKE_VALUE_FUNC(process_t *, get_active_task); +DEFINE_FAKE_VOID_FUNC(switch_task, process_t *); void reset_process_mock() { RESET_FAKE(process_create); RESET_FAKE(process_free); RESET_FAKE(process_set_entrypoint); - RESET_FAKE(process_activate); - RESET_FAKE(process_yield); RESET_FAKE(process_resume); RESET_FAKE(process_add_pages); RESET_FAKE(process_grow_stack); RESET_FAKE(process_load_heap); - RESET_FAKE(start_task); + RESET_FAKE(set_active_task); + RESET_FAKE(get_active_task); + RESET_FAKE(switch_task); } From d58201a4980ebfd35b5d1965fd7aa950f280670f Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 11:50:48 -0400 Subject: [PATCH 46/59] More tests --- src/kernel/src/process.c | 6 ++--- tests/src/kernel/test_process.cpp | 38 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index c5cc73bf..13354a43 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -155,15 +155,15 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { uint32_t * stack = paging_temp_map(page_addr); - int ret_i = (proc->esp % PAGE_SIZE) / 4; - stack[ret_i] = PTR2UINT(entrypoint); - if (!stack) { paging_temp_free(table_addr); paging_temp_free(proc->cr3); return -1; } + int ret_i = (proc->esp % PAGE_SIZE) / 4; + stack[ret_i] = PTR2UINT(entrypoint); + paging_temp_free(page_addr); paging_temp_free(table_addr); paging_temp_free(proc->cr3); diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index 909074af..32d06f21 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -212,10 +212,48 @@ TEST_F(Process, process_set_entrypoint_InvalidParameters) { EXPECT_NE(0, process_set_entrypoint(0, 0)); EXPECT_NE(0, process_set_entrypoint(&proc, 0)); EXPECT_NE(0, process_set_entrypoint(0, (void *)1)); + ASSERT_TEMP_MAP_BALANCED(); +} + +TEST_F(Process, process_set_entrypoint_AlreadyRunning) { + proc.state = PROCESS_STATE_SUSPENDED; + EXPECT_NE(0, process_set_entrypoint(&proc, 0)); + EXPECT_NE(0, process_set_entrypoint(0, (void *)1)); + EXPECT_NE(0, process_set_entrypoint(&proc, (void *)1)); + ASSERT_TEMP_MAP_BALANCED(); +} + +TEST_F(Process, process_set_entrypoint_FailMapDir) { + paging_temp_map_fake.return_val = 0; + EXPECT_NE(0, process_set_entrypoint(&proc, (void *)1)); + EXPECT_EQ(1, paging_temp_map_fake.call_count); + ASSERT_TEMP_MAP_BALANCE_OFFSET(1); +} + +TEST_F(Process, process_set_entrypoint_FailMapTable) { + void * paging_temp_map_seq[2] = {(void *)2, 0}; + SET_RETURN_SEQ(paging_temp_map, paging_temp_map_seq, 2); + + EXPECT_NE(0, process_set_entrypoint(&proc, (void *)1)); + EXPECT_EQ(2, paging_temp_map_fake.call_count); + ASSERT_TEMP_MAP_BALANCE_OFFSET(1); +} + +TEST_F(Process, process_set_entrypoint_FailMapStack) { + void * paging_temp_map_seq[3] = {(void *)2, (void *)3, 0}; + SET_RETURN_SEQ(paging_temp_map, paging_temp_map_seq, 3); + + EXPECT_NE(0, process_set_entrypoint(&proc, (void *)1)); + EXPECT_EQ(3, paging_temp_map_fake.call_count); + ASSERT_TEMP_MAP_BALANCE_OFFSET(1); } TEST_F(Process, process_set_entrypoint) { + paging_temp_map_fake.return_val = temp_page.data(); EXPECT_EQ(0, process_set_entrypoint(&proc, (void *)3)); + + // TODO eip on stack + // TODO esp updated } // Process Resume From 6472022561d57fd209907c2f8e55105806103623 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 12:05:26 -0400 Subject: [PATCH 47/59] Add coverage of resume state before loaded --- tests/src/kernel/test_process.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index 32d06f21..eb0c23e1 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -250,10 +250,12 @@ TEST_F(Process, process_set_entrypoint_FailMapStack) { TEST_F(Process, process_set_entrypoint) { paging_temp_map_fake.return_val = temp_page.data(); + proc.esp = (int)temp_page.data() + temp_page.size() - 1; EXPECT_EQ(0, process_set_entrypoint(&proc, (void *)3)); // TODO eip on stack - // TODO esp updated + + EXPECT_EQ((int)temp_page.data() + temp_page.size() - (4 * 5), proc.esp); } // Process Resume @@ -273,6 +275,11 @@ TEST_F(Process, process_resume_ProcessDead) { EXPECT_NE(0, process_resume(&proc, 0)); } +TEST_F(Process, process_resume_ProcessUnloaded) { + proc.state = PROCESS_STATE_LOADING; + EXPECT_NE(0, process_resume(&proc, 0)); +} + static void customswitch_task(process_t *) { ASSERT_EQ(PROCESS_STATE_RUNNING, proc.state); ASSERT_EQ(PROCESS_STATE_SUSPENDED, alt_proc.state); From 182dbd0b695d9d1c7503510995ce70cb439851e4 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 12:09:06 -0400 Subject: [PATCH 48/59] Finish tests for updated process --- tests/src/kernel/test_process.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index eb0c23e1..47d29277 100644 --- a/tests/src/kernel/test_process.cpp +++ b/tests/src/kernel/test_process.cpp @@ -85,6 +85,28 @@ TEST_F(Process, process_create_FailCreateArray) { arr_create_fake.return_val = -1; EXPECT_NE(0, process_create(&proc)); + EXPECT_EQ(1, ram_page_free_fake.call_count); + ASSERT_RAM_ALLOC_BALANCED(); +} + +TEST_F(Process, process_create_FailCreateEbus) { + ram_page_alloc_fake.return_val = 0x2000; + ebus_create_fake.return_val = -1; + + EXPECT_NE(0, process_create(&proc)); + EXPECT_EQ(1, ram_page_free_fake.call_count); + EXPECT_EQ(1, arr_free_fake.call_count); + ASSERT_RAM_ALLOC_BALANCED(); +} + +TEST_F(Process, process_create_FailMemoryInit) { + ram_page_alloc_fake.return_val = 0x2000; + memory_init_fake.return_val = -1; + + EXPECT_NE(0, process_create(&proc)); + EXPECT_EQ(1, ram_page_free_fake.call_count); + EXPECT_EQ(1, arr_free_fake.call_count); + EXPECT_EQ(1, ebus_free_fake.call_count); ASSERT_RAM_ALLOC_BALANCED(); } @@ -96,6 +118,8 @@ TEST_F(Process, process_create_FailDirTempMap) { EXPECT_NE(0, process_create(&proc)); EXPECT_EQ(1, ram_page_free_fake.call_count); + EXPECT_EQ(1, arr_free_fake.call_count); + EXPECT_EQ(1, ebus_free_fake.call_count); ASSERT_TEMP_MAP_BALANCE_OFFSET(1); ASSERT_RAM_ALLOC_BALANCED(); } From 75b468768ce594938038caf05471417a3ce71d48 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 16:48:02 -0400 Subject: [PATCH 49/59] Never return to kernel task --- src/kernel/src/kernel.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 3d114ffc..e59eaa52 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -200,10 +200,7 @@ void kernel_main() { bar_proc.state = PROCESS_STATE_LOADED; pm_add_proc(&__kernel.pm, &bar_proc); - for (;;) { - pm_resume_process(&__kernel.pm, __kernel.pm.idle_task->pid, 0); - asm("hlt"); - } + pm_resume_process(&__kernel.pm, __kernel.pm.idle_task->pid, 0); KPANIC("You shouldn't be here!"); } @@ -218,7 +215,7 @@ static void foo_task() { static void bar_task() { for (;;) { printf("bar %u\n", getpid()); - yield(0); + yield(EBUS_EVENT_KEY); } } From ce5618c16ecf18974b96198a07f7c6e7b1782257 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 17:58:14 -0400 Subject: [PATCH 50/59] Remove filter from yield, replace pull_event with system call --- src/apps/foo/src/foo.c | 2 +- src/kernel/include/kernel.h | 2 +- src/kernel/src/idle.c | 4 ++-- src/kernel/src/kernel.c | 20 ++++++++++++-------- src/kernel/src/term.c | 2 +- src/libc/include/libc/proc.h | 3 ++- src/libc/src/proc.c | 8 ++++++-- src/libk/include/libk/sys_call.h | 2 +- src/libk/src/sys_call.c | 4 ++-- 9 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/apps/foo/src/foo.c b/src/apps/foo/src/foo.c index b9e39986..293b553a 100644 --- a/src/apps/foo/src/foo.c +++ b/src/apps/foo/src/foo.c @@ -4,7 +4,7 @@ void foo() { uint32_t res = puts("Hello\n"); - yield(EBUS_EVENT_KEY); + pull_event(EBUS_EVENT_KEY, 0); res = printf("Hello 0x%X\n", res); diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index f5bb0f8d..72610cd2 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -54,7 +54,7 @@ process_t * kernel_find_pid(int pid); void tmp_register_signals_cb(signals_master_cb_t cb); -ebus_event_t * pull_event(int event_id); +// ebus_event_t * pull_event(int event_id); int kernel_add_task(process_t * proc); int kernel_next_task(); diff --git a/src/kernel/src/idle.c b/src/kernel/src/idle.c index 26533d5f..9868efcf 100644 --- a/src/kernel/src/idle.c +++ b/src/kernel/src/idle.c @@ -21,10 +21,10 @@ process_t * init_idle() { static void idle_loop() { for (;;) { - printf("idle %u\n", getpid()); + // printf("idle %u\n", getpid()); ebus_cycle(get_kernel_ebus()); asm("hlt"); int curr_pid = get_current_process()->pid; - yield(0); + yield(); } } diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index e59eaa52..e3d2f3bd 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -208,14 +208,18 @@ void kernel_main() { static void foo_task() { for (;;) { printf("foo %u\n", getpid()); - yield(EBUS_EVENT_KEY); + ebus_event_t event; + int ev = pull_event(EBUS_EVENT_KEY, &event); + printf("Foo got event %u\n", ev); } } static void bar_task() { for (;;) { printf("bar %u\n", getpid()); - yield(EBUS_EVENT_KEY); + ebus_event_t event; + int ev = pull_event(EBUS_EVENT_ANY, &event); + printf("Bar got event %u\n", ev); } } @@ -268,13 +272,13 @@ void tmp_register_signals_cb(signals_master_cb_t cb) { printf("Attached master signal callback at %p\n", get_active_task()->signals_callback); } -ebus_event_t * pull_event(int event_id) { - process_t * proc = get_current_process(); - proc->filter_event = event_id; - kernel_next_task(); +// ebus_event_t * pull_event(int event_id) { +// process_t * proc = get_current_process(); +// proc->filter_event = event_id; +// kernel_next_task(); - return 0; -} +// return 0; +// } int kernel_add_task(process_t * proc) { return pm_add_proc(&__kernel.pm, proc); diff --git a/src/kernel/src/term.c b/src/kernel/src/term.c index 1de76ea2..9f4ac2a7 100644 --- a/src/kernel/src/term.c +++ b/src/kernel/src/term.c @@ -190,7 +190,7 @@ void term_run() { printf("term %u\n", getpid()); term_update(); // ebus_cycle(get_kernel_ebus()); - yield(0); + yield(); // asm("hlt"); } } diff --git a/src/libc/include/libc/proc.h b/src/libc/include/libc/proc.h index da89ba0e..3c2699b6 100644 --- a/src/libc/include/libc/proc.h +++ b/src/libc/include/libc/proc.h @@ -28,7 +28,8 @@ void proc_abort(uint8_t code, const char * msg); NO_RETURN void proc_panic(const char * msg, const char * file, unsigned int line); void queue_event(ebus_event_t * event); -int yield(int filter); +int pull_event(int filter, ebus_event_t * event_out); +void yield(void); int getpid(void); diff --git a/src/libc/src/proc.c b/src/libc/src/proc.c index f9ab8ebe..7b569b5c 100644 --- a/src/libc/src/proc.c +++ b/src/libc/src/proc.c @@ -19,8 +19,12 @@ void queue_event(ebus_event_t * event) { _sys_queue_event(event); } -int yield(int filter) { - return _sys_yield(filter); +int pull_event(int filter, ebus_event_t * event_out) { + return _sys_yield(filter, event_out); +} + +void yield() { + _sys_yield(0, 0); } int getpid(void) { diff --git a/src/libk/include/libk/sys_call.h b/src/libk/include/libk/sys_call.h index a7ec0bdb..6d5b295e 100644 --- a/src/libk/include/libk/sys_call.h +++ b/src/libk/include/libk/sys_call.h @@ -30,7 +30,7 @@ int _sys_proc_getpid(void); void _sys_register_signals(void * callback); void _sys_queue_event(ebus_event_t * event); -int _sys_yield(int filter); +int _sys_yield(int filter, ebus_event_t * event_out); size_t _sys_putc(char c); size_t _sys_puts(const char * str); diff --git a/src/libk/src/sys_call.c b/src/libk/src/sys_call.c index 6f05a533..a820188c 100644 --- a/src/libk/src/sys_call.c +++ b/src/libk/src/sys_call.c @@ -66,8 +66,8 @@ void _sys_queue_event(ebus_event_t * event) { send_call(SYS_INT_PROC_QUEUE_EVENT, event); } -int _sys_yield(int filter) { - return send_call(SYS_INT_PROC_YIELD, filter); +int _sys_yield(int filter, ebus_event_t * event_out) { + return send_call(SYS_INT_PROC_YIELD, filter, event_out); } size_t _sys_putc(char c) { From 7bec77f39b73098c6e86f32681e55ebbafa0008f Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 18:06:19 -0400 Subject: [PATCH 51/59] ebus pop and return from yield --- src/ebus/include/ebus.h | 1 + src/ebus/src/ebus.c | 12 ++++++++++++ src/kernel/src/system_call_proc.c | 7 +++++++ src/libc/src/proc.c | 8 +++++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/ebus/include/ebus.h b/src/ebus/include/ebus.h index 51050d93..7483d80a 100644 --- a/src/ebus/include/ebus.h +++ b/src/ebus/include/ebus.h @@ -87,6 +87,7 @@ int ebus_register_handler(ebus_t * bus, ebus_handler_t * handler); void ebus_unregister_handler(ebus_t * bus, int handler_id); void ebus_push(ebus_t * bus, ebus_event_t * event); +int ebus_pop(ebus_t * bus, ebus_event_t * event_out); int ebus_cycle(ebus_t * bus); diff --git a/src/ebus/src/ebus.c b/src/ebus/src/ebus.c index 503f1f65..51a3f4ab 100644 --- a/src/ebus/src/ebus.c +++ b/src/ebus/src/ebus.c @@ -90,6 +90,18 @@ void ebus_push(ebus_t * bus, ebus_event_t * event) { cb_push(&bus->queue, event); } +int ebus_pop(ebus_t * bus, ebus_event_t * event_out) { + if (!bus) { + return -1; + } + + if (cb_pop(&bus->queue, event_out)) { + return -1; + } + + return 0; +} + int ebus_cycle(ebus_t * bus) { if (!bus) { return -1; diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 7a26dcae..3405eab9 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -95,6 +95,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { case SYS_INT_PROC_YIELD: { struct _args { int filter; + ebus_event_t * event_out; } * args = (struct _args *)args_data; // TODO clear iret from stack? @@ -105,6 +106,12 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { if (pm_resume_process(kernel_get_proc_man(), next->pid, 0)) { KPANIC("Failed to resume process"); } + proc = get_current_process(); + if (ebus_queue_size(&proc->event_queue) > 0) { + if (ebus_pop(&proc->event_queue, args->event_out)) { + return -1; + } + } }; } diff --git a/src/libc/src/proc.c b/src/libc/src/proc.c index 7b569b5c..23026ff3 100644 --- a/src/libc/src/proc.c +++ b/src/libc/src/proc.c @@ -20,7 +20,13 @@ void queue_event(ebus_event_t * event) { } int pull_event(int filter, ebus_event_t * event_out) { - return _sys_yield(filter, event_out); + if (_sys_yield(filter, event_out)) { + return -1; + } + if (event_out) { + return event_out->event_id; + } + return 0; } void yield() { From 7aade8117c618ebf6819145d447224e3273f192d Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 18:14:56 -0400 Subject: [PATCH 52/59] Return errors for ebus_push, cleanup ebus_pop, filter push events --- src/ebus/include/ebus.h | 6 ++---- src/ebus/src/ebus.c | 27 ++++++++------------------- src/kernel/src/process_manager.c | 20 +++++++++++++++----- src/kernel/src/term.c | 2 +- 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/src/ebus/include/ebus.h b/src/ebus/include/ebus.h index 7483d80a..66ae1410 100644 --- a/src/ebus/include/ebus.h +++ b/src/ebus/include/ebus.h @@ -65,8 +65,6 @@ typedef struct _ebus { arr_t handlers; // ebus_handler_t cb_t queue; // ebus_event_t - int enabled; - int next_handler_id; } ebus_t; @@ -86,8 +84,8 @@ int ebus_queue_size(ebus_t * bus); int ebus_register_handler(ebus_t * bus, ebus_handler_t * handler); void ebus_unregister_handler(ebus_t * bus, int handler_id); -void ebus_push(ebus_t * bus, ebus_event_t * event); -int ebus_pop(ebus_t * bus, ebus_event_t * event_out); +int ebus_push(ebus_t * bus, ebus_event_t * event); +int ebus_pop(ebus_t * bus, ebus_event_t * event_out); int ebus_cycle(ebus_t * bus); diff --git a/src/ebus/src/ebus.c b/src/ebus/src/ebus.c index 51a3f4ab..e5e5759c 100644 --- a/src/ebus/src/ebus.c +++ b/src/ebus/src/ebus.c @@ -20,7 +20,6 @@ int ebus_create(ebus_t * bus, size_t event_queue_size) { } bus->next_handler_id = 1; - bus->enabled = 1; return 0; } @@ -43,10 +42,6 @@ int ebus_register_handler(ebus_t * bus, ebus_handler_t * handler) { return -1; } - if (!bus->enabled) { - return 0; - } - if (handler->pid < 1) { handler->pid = getpid(); } @@ -70,24 +65,22 @@ void ebus_unregister_handler(ebus_t * bus, int handler_id) { } } -void ebus_push(ebus_t * bus, ebus_event_t * event) { +int ebus_push(ebus_t * bus, ebus_event_t * event) { if (!bus || !event) { - return; - } - - if (!bus->enabled) { - return; + return -1; } if (event->event_id < 1) { - return; + KPANIC("Bad event!"); } if (cb_len(&bus->queue) == cb_buff_size(&bus->queue)) { - cb_pop(&bus->queue, 0); + if (cb_pop(&bus->queue, 0)) { + return -1; + } } - cb_push(&bus->queue, event); + return cb_push(&bus->queue, event); } int ebus_pop(ebus_t * bus, ebus_event_t * event_out) { @@ -95,11 +88,7 @@ int ebus_pop(ebus_t * bus, ebus_event_t * event_out) { return -1; } - if (cb_pop(&bus->queue, event_out)) { - return -1; - } - - return 0; + return cb_pop(&bus->queue, event_out); } int ebus_cycle(ebus_t * bus) { diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 13289c24..6956a0a1 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -136,15 +136,25 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { process_t * proc; arr_get(&pm->task_list, i, &proc); - if (proc->state >= PROCESS_STATE_DEAD) { + if (proc->state <= PROCESS_STATE_LOADED || proc->state >= PROCESS_STATE_DEAD) { continue; } - ebus_push(&proc->event_queue, event); - printf("Proc %u size is %u\n", proc->pid, proc->event_queue.queue.len); - if (proc->filter_event && event && event->event_id == proc->filter_event) { - proc->state = PROCESS_STATE_SUSPENDED; + if (!proc->filter_event || proc->filter_event == event->event_id) { + if (ebus_push(&proc->event_queue, event)) { + return -1; + } + + if (proc->state == PROCESS_STATE_WAITING) { + proc->state = PROCESS_STATE_SUSPENDED; + } } + + // ebus_push(&proc->event_queue, event); + // printf("Proc %u size is %u\n", proc->pid, proc->event_queue.queue.len); + // if (proc->filter_event && event && event->event_id == proc->filter_event) { + // proc->state = PROCESS_STATE_SUSPENDED; + // } } return 0; diff --git a/src/kernel/src/term.c b/src/kernel/src/term.c index 9f4ac2a7..ce495236 100644 --- a/src/kernel/src/term.c +++ b/src/kernel/src/term.c @@ -187,7 +187,7 @@ void term_run() { vga_puts("> "); for (;;) { - printf("term %u\n", getpid()); + // printf("term %u\n", getpid()); term_update(); // ebus_cycle(get_kernel_ebus()); yield(); From 1bbac1bd1e2351a43297963777fee600c7f14338 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 19:50:48 -0400 Subject: [PATCH 53/59] Working terminal, but slow --- src/kernel/src/kernel.c | 12 ++++++---- src/kernel/src/process_manager.c | 39 +++++++++++++++++++------------ src/kernel/src/system_call_proc.c | 10 ++++++-- src/kernel/src/term.c | 11 +++++---- src/libc/src/proc.c | 8 +------ 5 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index e3d2f3bd..2523bc51 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -207,19 +207,23 @@ void kernel_main() { static void foo_task() { for (;;) { - printf("foo %u\n", getpid()); + // printf("foo %u\n", getpid()); ebus_event_t event; int ev = pull_event(EBUS_EVENT_KEY, &event); - printf("Foo got event %u\n", ev); + // if (ev == EBUS_EVENT_KEY) { + // printf("Foo got event %u\n", ev); + // } } } static void bar_task() { for (;;) { - printf("bar %u\n", getpid()); + // printf("bar %u\n", getpid()); ebus_event_t event; int ev = pull_event(EBUS_EVENT_ANY, &event); - printf("Bar got event %u\n", ev); + // if (ev == EBUS_EVENT_KEY) { + // printf("Bar got event %u\n", ev); + // } } } diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 6956a0a1..4caedd0b 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -1,5 +1,6 @@ #include "process_manager.h" +#include "kernel.h" #include "libc/proc.h" #include "libc/stdio.h" @@ -94,18 +95,34 @@ process_t * pm_get_next(proc_man_t * pm) { return 0; } - i++; + int start_i = i++; - if (i >= arr_size(&pm->task_list)) { - i = 0; + while (i != start_i) { + if (i >= arr_size(&pm->task_list)) { + i = 0; + } + + process_t * proc; + if (arr_get(&pm->task_list, i, &proc)) { + KPANIC("Failed to get proc"); + return 0; + } + + if (proc->state == PROCESS_STATE_LOADED || proc->state == PROCESS_STATE_SUSPENDED || proc->state == PROCESS_STATE_RUNNING) { + return proc; + } + + i++; } - process_t * proc; - if (arr_get(&pm->task_list, i, &proc)) { - return 0; + process_t * active = get_active_task(); + if (PROCESS_STATE_LOADED <= active->state <= PROCESS_STATE_DEAD) { + return active; } - return proc; + KPANIC("Process Loop!"); + + return 0; } static int pid_arr_index(arr_t * arr, int pid) { @@ -130,8 +147,6 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { return -1; } - printf("Task list size is %u\n", pm->task_list.size); - for (size_t i = 0; i < arr_size(&pm->task_list); i++) { process_t * proc; arr_get(&pm->task_list, i, &proc); @@ -149,12 +164,6 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { proc->state = PROCESS_STATE_SUSPENDED; } } - - // ebus_push(&proc->event_queue, event); - // printf("Proc %u size is %u\n", proc->pid, proc->event_queue.queue.len); - // if (proc->filter_event && event && event->event_id == proc->filter_event) { - // proc->state = PROCESS_STATE_SUSPENDED; - // } } return 0; diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 3405eab9..8a09e8a4 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -94,12 +94,14 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { case SYS_INT_PROC_YIELD: { struct _args { - int filter; + int filter; ebus_event_t * event_out; } * args = (struct _args *)args_data; // TODO clear iret from stack? - process_t * proc = get_current_process(); + process_t * proc = get_current_process(); + proc->filter_event = args->filter; + proc->state = (args->filter ? PROCESS_STATE_WAITING : PROCESS_STATE_SUSPENDED); // process_yield(proc, regs->esp, regs->eip, args->filter); enable_interrupts(); process_t * next = pm_get_next(kernel_get_proc_man()); @@ -111,7 +113,11 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { if (ebus_pop(&proc->event_queue, args->event_out)) { return -1; } + if (args->event_out) { + return args->event_out->event_id; + } } + return 0; }; } diff --git a/src/kernel/src/term.c b/src/kernel/src/term.c index ce495236..469b653e 100644 --- a/src/kernel/src/term.c +++ b/src/kernel/src/term.c @@ -56,7 +56,7 @@ static void dump_buff() { } static void key_cb(uint8_t code, char c, keyboard_event_t event, keyboard_mod_t mod) { - if (event != KEY_EVENT_RELEASE && c) { + if (event != KEY_EVENT_PRESS && c) { if (cb_len(&keybuff) >= MAX_CHARS) { ERROR("key buffer overflow"); printf("(%u out of %u)", cb_len(&keybuff), MAX_CHARS); @@ -187,11 +187,12 @@ void term_run() { vga_puts("> "); for (;;) { - // printf("term %u\n", getpid()); + ebus_event_t event; + int ev = pull_event(EBUS_EVENT_KEY, &event); + if (ev == EBUS_EVENT_KEY) { + key_cb(event.key.keycode, event.key.c, event.key.event, event.key.mods); + } term_update(); - // ebus_cycle(get_kernel_ebus()); - yield(); - // asm("hlt"); } } diff --git a/src/libc/src/proc.c b/src/libc/src/proc.c index 23026ff3..7b569b5c 100644 --- a/src/libc/src/proc.c +++ b/src/libc/src/proc.c @@ -20,13 +20,7 @@ void queue_event(ebus_event_t * event) { } int pull_event(int filter, ebus_event_t * event_out) { - if (_sys_yield(filter, event_out)) { - return -1; - } - if (event_out) { - return event_out->event_id; - } - return 0; + return _sys_yield(filter, event_out); } void yield() { From eb54e7b7b31e8cd86847b51bd8da1e166b8cd53f Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 20:11:33 -0400 Subject: [PATCH 54/59] Set source pid in system call handler --- src/kernel/src/system_call_proc.c | 7 +++++++ src/libc/src/proc.c | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/kernel/src/system_call_proc.c b/src/kernel/src/system_call_proc.c index 8a09e8a4..bf7b3aef 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -89,6 +89,13 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { ebus_event_t * event; } * args = (struct _args *)args_data; + if (!args->event) { + return -1; + } + + process_t * proc = get_current_process(); + args->event->source_pid = proc->pid; + ebus_push(get_kernel_ebus(), args->event); } break; diff --git a/src/libc/src/proc.c b/src/libc/src/proc.c index 7b569b5c..fb16a8a9 100644 --- a/src/libc/src/proc.c +++ b/src/libc/src/proc.c @@ -15,7 +15,6 @@ NO_RETURN void proc_panic(const char * msg, const char * file, unsigned int line } void queue_event(ebus_event_t * event) { - event->source_pid = getpid(); _sys_queue_event(event); } From 709aa7e18130ef609c2b5ba67baa58fc4a7ec729 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 20:11:41 -0400 Subject: [PATCH 55/59] Update mocks and tests --- tests/src/libc/test_process.cpp | 22 +++++++++++--------- tests/src/libk/test_libk.cpp | 3 ++- tests/src/mocks/include/ebus.mock.h | 3 ++- tests/src/mocks/include/libc/proc.mock.h | 5 +++++ tests/src/mocks/include/libk/sys_call.mock.h | 2 +- tests/src/mocks/src/ebus.mock.c | 4 +++- tests/src/mocks/src/libc.mock.c | 10 +++++++++ tests/src/mocks/src/libk.mock.c | 2 +- 8 files changed, 36 insertions(+), 15 deletions(-) diff --git a/tests/src/libc/test_process.cpp b/tests/src/libc/test_process.cpp index 27370543..ee6f5546 100644 --- a/tests/src/libc/test_process.cpp +++ b/tests/src/libc/test_process.cpp @@ -39,27 +39,29 @@ TEST_F(LibC, proc_panic) { EXPECT_EQ(_sys_proc_panic_fake.arg2_val, 17); } -TEST_F(LibC, proc_getpid) { - _sys_proc_getpid_fake.return_val = 3; - EXPECT_EQ(3, getpid()); - EXPECT_EQ(1, _sys_proc_getpid_fake.call_count); -} - TEST_F(LibC, queue_event) { ebus_event_t event; memset(&event, 0, sizeof(ebus_event_t)); - _sys_proc_getpid_fake.return_val = 2; queue_event(&event); - EXPECT_EQ(2, event.source_pid); ASSERT_EQ(1, _sys_queue_event_fake.call_count); EXPECT_EQ(&event, _sys_queue_event_fake.arg0_val); } +TEST_F(LibC, pull_event) { + _sys_yield_fake.return_val = 3; + ebus_event_t event; + EXPECT_EQ(3, pull_event(1, &event)); + ASSERT_EQ(1, _sys_yield_fake.call_count); + EXPECT_EQ(1, _sys_yield_fake.arg0_val); + EXPECT_EQ(&event, _sys_yield_fake.arg1_val); +} + TEST_F(LibC, yield) { _sys_yield_fake.return_val = 2; - EXPECT_EQ(2, yield(3)); + yield(); ASSERT_EQ(1, _sys_yield_fake.call_count); - EXPECT_EQ(3, _sys_yield_fake.arg0_val); + EXPECT_EQ(0, _sys_yield_fake.arg0_val); + EXPECT_EQ(0, _sys_yield_fake.arg1_val); } TEST_F(LibC, getpid) { diff --git a/tests/src/libk/test_libk.cpp b/tests/src/libk/test_libk.cpp index ce8e68f0..5e441d91 100644 --- a/tests/src/libk/test_libk.cpp +++ b/tests/src/libk/test_libk.cpp @@ -166,10 +166,11 @@ TEST_F(LibK, queue_event) { TEST_F(LibK, yield) { send_call_fake.return_val = 2; - EXPECT_EQ(2, _sys_yield(5)); + EXPECT_EQ(2, _sys_yield(5, (ebus_event_t *)3)); ASSERT_EQ(1, send_call_fake.call_count); EXPECT_EQ(0x306, send_call_fake.arg0_val); EXPECT_EQ(5, send_call_fake.arg1_val); + EXPECT_EQ(3, send_call_fake.arg2_val); } TEST_F(LibK, putc) { diff --git a/tests/src/mocks/include/ebus.mock.h b/tests/src/mocks/include/ebus.mock.h index 90f5c569..55fef90a 100644 --- a/tests/src/mocks/include/ebus.mock.h +++ b/tests/src/mocks/include/ebus.mock.h @@ -12,7 +12,8 @@ DECLARE_FAKE_VOID_FUNC(ebus_free, ebus_t *); DECLARE_FAKE_VALUE_FUNC(int, ebus_queue_size, ebus_t *); DECLARE_FAKE_VALUE_FUNC(int, ebus_register_handler, ebus_t *, ebus_handler_t *); DECLARE_FAKE_VOID_FUNC(ebus_uregister_handler, ebus_t *, int); -DECLARE_FAKE_VOID_FUNC(ebus_push, ebus_t *, ebus_event_t *); +DECLARE_FAKE_VALUE_FUNC(int, ebus_push, ebus_t *, ebus_event_t *); +DECLARE_FAKE_VALUE_FUNC(int, ebus_pop, ebus_t *, ebus_event_t *); DECLARE_FAKE_VALUE_FUNC(int, ebus_cycle, ebus_t *); void reset_ebus_mock(void); diff --git a/tests/src/mocks/include/libc/proc.mock.h b/tests/src/mocks/include/libc/proc.mock.h index ae98e3a8..e044792e 100644 --- a/tests/src/mocks/include/libc/proc.mock.h +++ b/tests/src/mocks/include/libc/proc.mock.h @@ -7,8 +7,13 @@ extern "C" { #include "fff.h" #include "libc/proc.h" +DECLARE_FAKE_VOID_FUNC(proc_exit, uint8_t); +DECLARE_FAKE_VOID_FUNC(proc_abort, uint8_t, const char *); +DECLARE_FAKE_VOID_FUNC(proc_panic, const char *, const char *, unsigned int); DECLARE_FAKE_VOID_FUNC(set_next_pid, uint32_t); DECLARE_FAKE_VOID_FUNC(queue_event, ebus_event_t *); +DECLARE_FAKE_VALUE_FUNC(int, pull_event, int, ebus_event_t *); +DECLARE_FAKE_VOID_FUNC(yield); void reset_libc_proc_mock(void); diff --git a/tests/src/mocks/include/libk/sys_call.mock.h b/tests/src/mocks/include/libk/sys_call.mock.h index c95fea57..4dab349f 100644 --- a/tests/src/mocks/include/libk/sys_call.mock.h +++ b/tests/src/mocks/include/libk/sys_call.mock.h @@ -14,7 +14,7 @@ DECLARE_FAKE_VOID_FUNC(_sys_proc_panic, const char *, const char *, unsigned int DECLARE_FAKE_VALUE_FUNC(int, _sys_proc_getpid); DECLARE_FAKE_VOID_FUNC(_sys_register_signals, void *); DECLARE_FAKE_VOID_FUNC(_sys_queue_event, ebus_event_t *); -DECLARE_FAKE_VALUE_FUNC(int, _sys_yield, int); +DECLARE_FAKE_VALUE_FUNC(int, _sys_yield, int, ebus_event_t *); DECLARE_FAKE_VALUE_FUNC(size_t, _sys_putc, char); DECLARE_FAKE_VALUE_FUNC(size_t, _sys_puts, const char *); diff --git a/tests/src/mocks/src/ebus.mock.c b/tests/src/mocks/src/ebus.mock.c index b56d3dd7..fa673e69 100644 --- a/tests/src/mocks/src/ebus.mock.c +++ b/tests/src/mocks/src/ebus.mock.c @@ -7,7 +7,8 @@ DEFINE_FAKE_VOID_FUNC(ebus_free, ebus_t *); DEFINE_FAKE_VALUE_FUNC(int, ebus_queue_size, ebus_t *); DEFINE_FAKE_VALUE_FUNC(int, ebus_register_handler, ebus_t *, ebus_handler_t *); DEFINE_FAKE_VOID_FUNC(ebus_uregister_handler, ebus_t *, int); -DEFINE_FAKE_VOID_FUNC(ebus_push, ebus_t *, ebus_event_t *); +DEFINE_FAKE_VALUE_FUNC(int, ebus_push, ebus_t *, ebus_event_t *); +DEFINE_FAKE_VALUE_FUNC(int, ebus_pop, ebus_t *, ebus_event_t *); DEFINE_FAKE_VALUE_FUNC(int, ebus_cycle, ebus_t *); void reset_ebus_mock() { @@ -17,5 +18,6 @@ void reset_ebus_mock() { RESET_FAKE(ebus_register_handler); RESET_FAKE(ebus_uregister_handler); RESET_FAKE(ebus_push); + RESET_FAKE(ebus_pop); RESET_FAKE(ebus_cycle); } diff --git a/tests/src/mocks/src/libc.mock.c b/tests/src/mocks/src/libc.mock.c index 63394ed6..1601e744 100644 --- a/tests/src/mocks/src/libc.mock.c +++ b/tests/src/mocks/src/libc.mock.c @@ -24,12 +24,22 @@ void reset_libc_memory_mock(void) { // libc/proc.h +DEFINE_FAKE_VOID_FUNC(proc_exit, uint8_t); +DEFINE_FAKE_VOID_FUNC(proc_abort, uint8_t, const char *); +DEFINE_FAKE_VOID_FUNC(proc_panic, const char *, const char *, unsigned int); DEFINE_FAKE_VOID_FUNC(set_next_pid, uint32_t); DEFINE_FAKE_VOID_FUNC(queue_event, ebus_event_t *); +DEFINE_FAKE_VALUE_FUNC(int, pull_event, int, ebus_event_t *); +DEFINE_FAKE_VOID_FUNC(yield); void reset_libc_proc_mock(void) { + RESET_FAKE(proc_exit); + RESET_FAKE(proc_abort); + RESET_FAKE(proc_panic); RESET_FAKE(set_next_pid); RESET_FAKE(queue_event); + RESET_FAKE(pull_event); + RESET_FAKE(yield); } // libc/string.h diff --git a/tests/src/mocks/src/libk.mock.c b/tests/src/mocks/src/libk.mock.c index 79848830..d1f712d7 100644 --- a/tests/src/mocks/src/libk.mock.c +++ b/tests/src/mocks/src/libk.mock.c @@ -13,7 +13,7 @@ DEFINE_FAKE_VOID_FUNC(_sys_proc_panic, const char *, const char *, unsigned int) DEFINE_FAKE_VALUE_FUNC(int, _sys_proc_getpid); DEFINE_FAKE_VOID_FUNC(_sys_register_signals, void *); DEFINE_FAKE_VOID_FUNC(_sys_queue_event, ebus_event_t *); -DEFINE_FAKE_VALUE_FUNC(int, _sys_yield, int); +DEFINE_FAKE_VALUE_FUNC(int, _sys_yield, int, ebus_event_t *); DEFINE_FAKE_VALUE_FUNC(size_t, _sys_putc, char); DEFINE_FAKE_VALUE_FUNC(size_t, _sys_puts, const char *); From a43940264c9e54dd69a763f0e677fc1fdc3d2728 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 23:27:57 -0400 Subject: [PATCH 56/59] Fix key repeat and state key state --- src/drivers/include/drivers/keyboard.h | 2 - src/drivers/src/keyboard.c | 136 ++++++++++++++----------- src/ebus/include/ebus.h | 4 + src/kernel/src/term.c | 2 +- 4 files changed, 83 insertions(+), 61 deletions(-) diff --git a/src/drivers/include/drivers/keyboard.h b/src/drivers/include/drivers/keyboard.h index 1bb2c69c..c8e72822 100644 --- a/src/drivers/include/drivers/keyboard.h +++ b/src/drivers/include/drivers/keyboard.h @@ -82,6 +82,4 @@ typedef enum keyboard_key { void init_keyboard(); -char keyboard_char(uint8_t code, bool shift); - #endif // KEYBOARD_H diff --git a/src/drivers/src/keyboard.c b/src/drivers/src/keyboard.c index 0541342d..cd2f6ae6 100644 --- a/src/drivers/src/keyboard.c +++ b/src/drivers/src/keyboard.c @@ -1,70 +1,104 @@ #include "drivers/keyboard.h" +#include + #include "cpu/isr.h" #include "cpu/ports.h" #include "libc/proc.h" #include "libc/stdio.h" +#include "libc/string.h" + +static bool e0_mode; +static uint32_t keystate[8]; +static char keyMap[0xFF] = {0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '+', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static char shiftKeyMap[0xFF] = {0, 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, 0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static void keyboard_callback(registers_t * regs); +static char keyboard_char(uint8_t code, bool shift); +static bool get_key_state(uint8_t keycode); +static void set_key_state(uint8_t keycode, bool state); +static uint8_t get_mods(); + +void init_keyboard() { + e0_mode = false; + kmemset(keystate, 0, sizeof(keystate)); + register_interrupt_handler(IRQ1, keyboard_callback); +} + +static bool get_key_state(uint8_t keycode) { + int i = keycode / 32; + int b = keycode % 32; -static uint8_t last_code = 0; -static bool lctrl = false; -static bool rctrl = false; -static bool lalt = false; -static bool ralt = false; -static bool lshift = false; -static bool rshift = false; -static bool lsuper = false; -static bool rsuper = false; + return keystate[i] & (1 << b); +} + +static void set_key_state(uint8_t keycode, bool state) { + int i = keycode / 32; + int b = keycode % 32; + + if (state) { + keystate[i] |= (1 << b); + } + else { + keystate[i] &= ~(1 << b); + } +} + +static uint8_t get_mods() { + uint8_t mods = 0; + // TODO handle 0xE0 to get right ctrl + if (get_key_state(KEY_LCTRL)) { + mods |= KEY_MOD_CTRL; + } + // TODO handle 0xE0 to get right alt + if (get_key_state(KEY_LALT)) { + mods |= KEY_MOD_ALT; + } + if (get_key_state(KEY_LSHIFT) || get_key_state(KEY_RSHIFT)) { + mods |= KEY_MOD_SHIFT; + } + // TODO handle 0xE0 to get right super + if (get_key_state(KEY_SUPER)) { + mods |= KEY_MOD_SUPER; + } + return mods; +} + +static char keyboard_char(uint8_t code, bool shift) { + code = code & 0x7F; + if (shift) { + return shiftKeyMap[code]; + } + return keyMap[code]; +} static void keyboard_callback(registers_t * regs) { /* The PIC leaves us the scancode in port 0x60 */ - uint8_t scancode = port_byte_in(0x60); + uint8_t scancode = port_byte_in(0x60); + if (scancode == 0xE0) { + e0_mode = true; + return; + } + // printf("%02X ", scancode); uint8_t keycode = scancode; keyboard_event_t key_event = KEY_EVENT_PRESS; + uint8_t mods = get_mods(); bool press = keycode < 0x80; if (press) { - if (keycode == last_code) { + if (get_key_state(keycode)) { key_event = KEY_EVENT_REPEAT; } - else { - if (keycode == KEY_LSHIFT) { - lshift = true; - } - if (keycode == KEY_RSHIFT) { - lshift = true; - } - } - last_code = keycode; + set_key_state(keycode, true); } else { keycode -= 0x80; key_event = KEY_EVENT_RELEASE; - last_code = 0; - - if (keycode == KEY_LSHIFT) { - lshift = false; - } - if (keycode == KEY_RSHIFT) { - lshift = false; - } + set_key_state(keycode, false); } - char c = keyboard_char(keycode, lshift || rshift); - - keyboard_mod_t mods = 0; - if (lctrl || rctrl) { - mods |= KEY_MOD_CTRL; - } - if (lalt || ralt) { - mods |= KEY_MOD_ALT; - } - if (lshift || rshift) { - mods |= KEY_MOD_SHIFT; - } - if (lsuper || rsuper) { - mods |= KEY_MOD_SUPER; - } + char c = keyboard_char(keycode, mods & KEY_MOD_SHIFT); ebus_event_t event; event.event_id = EBUS_EVENT_KEY; @@ -74,19 +108,5 @@ static void keyboard_callback(registers_t * regs) { event.key.keycode = keycode; event.key.scancode = scancode; queue_event(&event); -} - -void init_keyboard() { - register_interrupt_handler(IRQ1, keyboard_callback); -} - -char keyMap[0xFF] = {0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '+', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -char shiftKeyMap[0xFF] = {0, 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, 0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -char keyboard_char(uint8_t code, bool shift) { - code = code & 0x7F; - if (shift) { - return shiftKeyMap[code]; - } - return keyMap[code]; + e0_mode = false; } diff --git a/src/ebus/include/ebus.h b/src/ebus/include/ebus.h index 66ae1410..beacc94c 100644 --- a/src/ebus/include/ebus.h +++ b/src/ebus/include/ebus.h @@ -37,6 +37,10 @@ typedef struct _ebus_event { uint32_t time; } timer; struct { + // raw = 0x83 + // keycode = 0x03 + // event = PRESS + // mods = SHIFT + ALT uint8_t event; uint8_t mods; char c; diff --git a/src/kernel/src/term.c b/src/kernel/src/term.c index 469b653e..6bba009f 100644 --- a/src/kernel/src/term.c +++ b/src/kernel/src/term.c @@ -56,7 +56,7 @@ static void dump_buff() { } static void key_cb(uint8_t code, char c, keyboard_event_t event, keyboard_mod_t mod) { - if (event != KEY_EVENT_PRESS && c) { + if (event == KEY_EVENT_PRESS && c) { if (cb_len(&keybuff) >= MAX_CHARS) { ERROR("key buffer overflow"); printf("(%u out of %u)", cb_len(&keybuff), MAX_CHARS); From 6c19930762016383fef27210980463defdeb48d2 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 23 Mar 2025 23:57:23 -0400 Subject: [PATCH 57/59] wip update command_exec --- src/kernel/src/exec.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index 63a9e6d7..1bbee248 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -30,29 +30,13 @@ int command_exec(uint8_t * buff, size_t size, size_t argc, char ** argv) { } process_set_entrypoint(proc, UINT2PTR(VADDR_USER_MEM)); - process_add_pages(proc, 32); + pm_add_proc(kernel_get_proc_man(), proc); - kernel_add_task(proc); - - ebus_event_t event; - event.event_id = EBUS_EVENT_TASK_SWITCH; - event.task_switch.next_task_pid = proc->pid; - - queue_event(&event); - - // kernel_set_current_task(proc); - - // puts("Go for call\n"); - - // if (process_resume(proc, 0)) { - // KPANIC("Failed to resume process"); - // } - - // // if process_resume does not fail, it will not return - // KPANIC("How did you get here?"); + int res = pm_resume_process(kernel_get_proc_man(), proc->pid, 0); - // process_free(proc); + pm_remove_proc(kernel_get_proc_man(), proc->pid); + process_free(proc); - return 0; + return res; } From 7eff8d9060ef4532eb30e02bf6c9804780b267ad Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 24 Mar 2025 08:41:21 -0400 Subject: [PATCH 58/59] Enable timer and rtc --- src/kernel/src/kernel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 2523bc51..84a1d37f 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -355,13 +355,13 @@ static void cursor() { static void irq_install() { enable_interrupts(); /* IRQ0: timer */ - // init_timer(TIMER_FREQ_MS); // milliseconds + init_timer(TIMER_FREQ_MS); // milliseconds /* IRQ1: keyboard */ init_keyboard(); /* IRQ14: ata disk */ init_ata(); /* IRQ8: real time clock */ - // init_rtc(RTC_RATE_1024_HZ); + init_rtc(RTC_RATE_1024_HZ); } static int kill(size_t argc, char ** argv) { From 6162af4561742c107227a211b3a8a1fb8359054f Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 24 Mar 2025 08:43:49 -0400 Subject: [PATCH 59/59] cleanup --- src/kernel/src/kernel.c | 48 ----------------------------------------- 1 file changed, 48 deletions(-) diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 84a1d37f..ead33d4b 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -37,10 +37,6 @@ static kernel_t __kernel; extern _Noreturn void halt(void); -static void handle_launch(const ebus_event_t * event); -static void handle_kill(const ebus_event_t * event); -// static void init_idle_proc(); -static void idle(); static void id_map_range(mmu_table_t * table, size_t start, size_t end); static void id_map_page(mmu_table_t * table, size_t page); static void cursor(); @@ -103,14 +99,6 @@ void kernel_main() { init_gdt(); init_tss(); - // if (process_create(&__kernel.proc)) { - // KPANIC("Failed to create kernel process"); - // } - - // process_set_entrypoint(&__kernel.proc, idle); - // process_resume(&__kernel.proc, 0); - // halt(); - // Kernel process used for memory allocation __kernel.proc.next_heap_page = ADDR2PAGE(VADDR_RAM_BITMASKS) + ram_region_table_count(); __kernel.proc.cr3 = PADDR_KERNEL_DIR; @@ -147,18 +135,6 @@ void kernel_main() { KPANIC("Failed to init ebus\n"); } - ebus_handler_t launch_handler = {0}; - launch_handler.callback_fn = handle_launch; - launch_handler.event_id = EBUS_EVENT_TASK_SWITCH; - launch_handler.pid = 0; - ebus_register_handler(&__kernel.event_bus, &launch_handler); - - ebus_handler_t kill_handler = {0}; - kill_handler.callback_fn = handle_kill; - kill_handler.event_id = EBUS_EVENT_TASK_KILL; - launch_handler.pid = 0; - ebus_register_handler(&__kernel.event_bus, &kill_handler); - irq_install(); vga_puts("Welcome to kernel v" PROJECT_VERSION "\n"); @@ -227,22 +203,6 @@ static void bar_task() { } } -static void handle_launch(const ebus_event_t * event) { - printf("Start task %u\n", event->task_switch.next_task_pid); - process_t * proc = pm_find_pid(&__kernel.pm, event->task_switch.next_task_pid); - process_resume(proc, 0); -} - -static void handle_kill(const ebus_event_t * event) { - printf("Kill task %u\n", event->task_switch.next_task_pid); - process_t * proc = pm_find_pid(&__kernel.pm, event->task_kill.task_pid); - if (pm_remove_proc(&__kernel.pm, proc->pid)) { - KPANIC("Failed to remove process from pm"); - } - - process_free(proc); -} - int kernel_switch_task(int next_pid) { return pm_resume_process(&__kernel.pm, next_pid, 0); } @@ -276,14 +236,6 @@ void tmp_register_signals_cb(signals_master_cb_t cb) { printf("Attached master signal callback at %p\n", get_active_task()->signals_callback); } -// ebus_event_t * pull_event(int event_id) { -// process_t * proc = get_current_process(); -// proc->filter_event = event_id; -// kernel_next_task(); - -// return 0; -// } - int kernel_add_task(process_t * proc) { return pm_add_proc(&__kernel.pm, proc); }