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) diff --git a/src/apps/foo/src/foo.c b/src/apps/foo/src/foo.c index b048f044..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"); - proc_exit(0); + pull_event(EBUS_EVENT_KEY, 0); res = printf("Hello 0x%X\n", res); 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/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; } 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/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 d4469481..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/signal.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/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/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 c03711c3..beacc94c 100644 --- a/src/ebus/include/ebus.h +++ b/src/ebus/include/ebus.h @@ -24,22 +24,35 @@ enum EBUS_EVENT { EBUS_EVENT_ANY = 0, EBUS_EVENT_TIMER, EBUS_EVENT_KEY, + EBUS_EVENT_TASK_SWITCH, + EBUS_EVENT_TASK_KILL, }; typedef struct _ebus_event { int event_id; + int source_pid; union { struct { int id; uint32_t time; } timer; struct { + // raw = 0x83 + // keycode = 0x03 + // event = PRESS + // mods = SHIFT + ALT uint8_t event; uint8_t mods; char c; uint32_t keycode; uint32_t scancode; } key; + struct { + uint32_t next_task_pid; + } task_switch; + struct { + uint32_t task_pid; + } task_kill; }; } ebus_event_t; @@ -56,8 +69,6 @@ typedef struct _ebus { arr_t handlers; // ebus_handler_t cb_t queue; // ebus_event_t - int enabled; - int next_handler_id; } ebus_t; @@ -77,7 +88,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_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 b9c78cb1..e5e5759c 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" @@ -19,7 +20,6 @@ int ebus_create(ebus_t * bus, size_t event_queue_size) { } bus->next_handler_id = 1; - bus->enabled = 1; return 0; } @@ -42,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(); } @@ -69,24 +65,30 @@ 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) { + if (!bus) { + return -1; + } + + return cb_pop(&bus->queue, event_out); } int ebus_cycle(ebus_t * bus) { @@ -100,7 +102,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; } } @@ -109,6 +116,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) { @@ -116,9 +125,19 @@ static int handle_event(ebus_t * bus, ebus_event_t * event) { } if (!handler->event_id || handler->event_id == event->event_id) { - handler->callback_fn(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/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/include/kernel.h b/src/kernel/include/kernel.h index 9054b2ec..72610cd2 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -5,9 +5,12 @@ #include #include "cpu/mmu.h" +#include "drivers/disk.h" +#include "drivers/tar.h" #include "ebus.h" #include "memory_alloc.h" #include "process.h" +#include "process_manager.h" typedef struct _kernel { uint32_t ram_table_addr; @@ -16,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; /** @@ -38,10 +43,36 @@ 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(); +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); +// 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); + +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 +#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 1006ea24..428cfb09 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -4,7 +4,9 @@ #include #include +#include "ebus.h" #include "libc/datastruct/array.h" +#include "memory_alloc.h" typedef void (*signals_master_cb_t)(int); @@ -18,22 +20,36 @@ typedef struct _handle { int type; } handle_t; +enum PROCESS_STATE { + PROCESS_STATE_STARTING = 0, + PROCESS_STATE_LOADING, + PROCESS_STATE_LOADED, + PROCESS_STATE_SUSPENDED, + PROCESS_STATE_WAITING, + PROCESS_STATE_RUNNING, + PROCESS_STATE_DEAD, + PROCESS_STATE_ERROR, +}; + 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; - signals_master_cb_t signals_callback; + arr_t io_handles; // array + ebus_t event_queue; + memory_t memory; - arr_t io_handles; // array - - struct _process * next_proc; + uint32_t filter_event; + enum PROCESS_STATE state; + struct _process * next_proc; } process_t; /** @@ -56,6 +72,30 @@ 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); + +/** + * @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); + /** * @brief Add `count` pages to the process heap. * @@ -104,15 +144,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); - -typedef struct _proc_man { - process_t * idle_task; - process_t * task_begin; - process_t * curr_task; -} proc_man_t; +extern void set_active_task(process_t * active); +extern process_t * get_active_task(void); +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 new file mode 100644 index 00000000..ebc899a9 --- /dev/null +++ b/src/kernel/include/process_manager.h @@ -0,0 +1,32 @@ +#ifndef KERNEL_PROCESS_MANAGER_H +#define KERNEL_PROCESS_MANAGER_H + +#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 * idle_task; +} proc_man_t; + +int pm_create(proc_man_t * pm); + +// 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, int pid); + +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/commands.c b/src/kernel/src/commands.c index 27c32baf..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; } @@ -562,6 +559,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(); @@ -734,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; } @@ -750,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; @@ -764,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; } @@ -778,6 +780,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); @@ -791,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/exec.c b/src/kernel/src/exec.c index fce066e2..1bbee248 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -2,7 +2,9 @@ #include "cpu/mmu.h" #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" @@ -27,25 +29,14 @@ int command_exec(uint8_t * buff, size_t size, size_t argc, char ** argv) { return -1; } - puts("Go for call\n"); + process_set_entrypoint(proc, UINT2PTR(VADDR_USER_MEM)); + process_add_pages(proc, 32); + pm_add_proc(kernel_get_proc_man(), proc); - ff_t call = UINT2PTR(VADDR_USER_MEM); - - // mmu_change_dir(proc->cr3); - - tss_get_entry(0)->esp0 = proc->esp0; - tss_get_entry(0)->cr3 = proc->cr3; - tss_get_entry(0)->esp = proc->esp; - - jump_proc(proc->cr3, proc->esp, VADDR_USER_MEM); - - int res = call(argc, argv); - - puts("Done\n"); + int res = pm_resume_process(kernel_get_proc_man(), proc->pid, 0); + pm_remove_proc(kernel_get_proc_man(), proc->pid); process_free(proc); - puts("All good!\n"); - return res; } diff --git a/src/kernel/src/idle.c b/src/kernel/src/idle.c new file mode 100644 index 00000000..9868efcf --- /dev/null +++ b/src/kernel/src/idle.c @@ -0,0 +1,30 @@ +#include "idle.h" + +#include "kernel.h" +#include "libc/memory.h" +#include "libc/proc.h" +#include "libc/stdio.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); + proc->state = PROCESS_STATE_LOADED; + + return proc; +} + +static void idle_loop() { + for (;;) { + // printf("idle %u\n", getpid()); + ebus_cycle(get_kernel_ebus()); + asm("hlt"); + int curr_pid = get_current_process()->pid; + yield(); + } +} diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index f8bc1fcd..ead33d4b 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" @@ -28,6 +29,7 @@ #include "libk/defs.h" #include "libk/sys_call.h" #include "process.h" +#include "process_manager.h" #include "ram.h" #include "term.h" @@ -45,6 +47,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(); @@ -97,15 +102,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.proc.esp0 = VADDR_ISR_STACK; + __kernel.proc.state = PROCESS_STATE_LOADED; + set_active_task(&__kernel.proc); - // 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; + // Set initial ESP0 before first task switch + tss_set_esp0(VADDR_ISR_STACK); isr_install(); @@ -119,8 +121,18 @@ void kernel_main() { memory_init(&__kernel.kernel_memory, _sys_page_alloc); init_malloc(&__kernel.kernel_memory); + pm_create(&__kernel.pm); + + 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; + // 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)) { - PANIC("Failed to init ebus\n"); + KPANIC("Failed to init ebus\n"); } irq_install(); @@ -128,20 +140,71 @@ 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); ramdisk_create(4096); - // set_first_task(proc); + __kernel.disk = disk_open(0, DISK_DRIVER_ATA); + if (!__kernel.disk) { + KPANIC("Failed to open ATA disk"); + } - // switch_to_task(proc); + __kernel.tar = tar_open(__kernel.disk); + if (!__kernel.tar) { + KPANIC("Failed to open tar"); + } + + 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); - // jump_usermode(term_run); - jump_kernel_mode(term_run); + process_t bar_proc; + if (process_create(&bar_proc)) { + KPANIC("Failed to create bar task"); + } + process_set_entrypoint(&bar_proc, bar_task); + bar_proc.state = PROCESS_STATE_LOADED; + pm_add_proc(&__kernel.pm, &bar_proc); + + pm_resume_process(&__kernel.pm, __kernel.pm.idle_task->pid, 0); - PANIC("You shouldn't be here!"); + KPANIC("You shouldn't be here!"); +} + +static void foo_task() { + for (;;) { + // printf("foo %u\n", getpid()); + ebus_event_t event; + int ev = pull_event(EBUS_EVENT_KEY, &event); + // if (ev == EBUS_EVENT_KEY) { + // printf("Foo got event %u\n", ev); + // } + } +} + +static void bar_task() { + for (;;) { + // printf("bar %u\n", getpid()); + ebus_event_t event; + int ev = pull_event(EBUS_EVENT_ANY, &event); + // if (ev == EBUS_EVENT_KEY) { + // printf("Bar got event %u\n", ev); + // } + } +} + +int kernel_switch_task(int next_pid) { + return pm_resume_process(&__kernel.pm, next_pid, 0); } mmu_dir_t * get_kernel_dir() { @@ -153,16 +216,84 @@ mmu_table_t * get_kernel_table() { } process_t * get_current_process() { - return __kernel.pm.curr_task; + return get_active_task(); } 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); + get_active_task()->signals_callback = cb; + printf("Attached master signal callback at %p\n", get_active_task()->signals_callback); +} + +int kernel_add_task(process_t * proc) { + return pm_add_proc(&__kernel.pm, proc); +} + +int kernel_next_task() { + return pm_resume_process(&__kernel.pm, get_active_task()->pid, 0); +} + +int kernel_close_process(process_t * proc) { + if (!proc) { + return -1; + } + + proc->state = PROCESS_STATE_DEAD; + + process_t * next = pm_get_next(&__kernel.pm); + if (!next) { + next = __kernel.pm.idle_task; + } + + 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; +} + +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(); + 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() { @@ -188,7 +319,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; } @@ -225,7 +356,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 64586e3d..b87cc596 100644 --- a/src/kernel/src/kernel_entry.asm +++ b/src/kernel/src/kernel_entry.asm @@ -14,42 +14,90 @@ 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 +; proc_t * +active_task: dd 0 + +; void set_active_task(proc_t * active) +global set_active_task +set_active_task: + ; ebp = args + push ebp, + mov ebp, esp + add ebp, 4 - mov eax, cr3 push eax - push ebp + ; eax = active + mov eax, [ebp+4] + mov [active_task], eax - push esp + pop eax + pop ebp - call register_kernel_exit + ret -.exit: - call [.cb] +; proc_t * get_active_task(void) +global get_active_task +get_active_task: + mov eax, [active_task] ret -.cb: dd 0 +; switch_task(proc_t * next) +global switch_task +switch_task: + ; ebp = args + push ebp + mov ebp, esp + add ebp, 8 + + push edi + push esi + push eax + + ; edi = active + mov edi, [active_task] + ; esi = next + mov esi, [ebp] + + ; store cr3 + mov eax, cr3 + mov [edi+TCB_CR3], eax -; 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 + ; 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 esp, [esi+TCB_ESP] + + ; load cr3 + mov eax, [esi+TCB_CR3] mov cr3, eax - mov ebp, ebx - mov esp, ebx - jmp edx + pop eax + pop esi + pop edi + + pop ebp + + ret diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 08dbdfb8..13354a43 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -1,7 +1,10 @@ #include "process.h" #include "cpu/mmu.h" +#include "cpu/tss.h" +#include "kernel.h" #include "libc/string.h" +#include "libk/sys_call.h" #include "paging.h" #include "ram.h" @@ -25,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; } @@ -44,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; @@ -63,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); @@ -105,6 +126,71 @@ int process_free(process_t * proc) { return 0; } +int process_set_entrypoint(process_t * proc, void * entrypoint) { + if (!proc || !entrypoint || proc->state >= PROCESS_STATE_SUSPENDED) { + return -1; + } + + 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); + + 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); + + proc->esp -= (5 * 4) - 1; + + 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; + } + + process_t * active_before = get_active_task(); + active_before->state = PROCESS_STATE_SUSPENDED; + + 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) { if (!proc || !count) { return 0; @@ -163,6 +249,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 +301,8 @@ int process_load_heap(process_t * proc, const char * buff, size_t size) { paging_temp_free(proc->cr3); + proc->state = PROCESS_STATE_LOADED; + return 0; } @@ -220,6 +310,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; diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c new file mode 100644 index 00000000..4caedd0b --- /dev/null +++ b/src/kernel/src/process_manager.c @@ -0,0 +1,170 @@ +#include "process_manager.h" + +#include "kernel.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; + } + + if (arr_create(&pm->task_list, 4, sizeof(process_t *))) { + return -1; + } + + return 0; +} + +process_t * pm_get_active(proc_man_t * pm) { + if (!pm) { + return 0; + } + + // TODO this is redundant now + return get_active_task(); +} + +process_t * pm_find_pid(proc_man_t * pm, int pid) { + if (!pm || pid < 1) { + return 0; + } + + int i = pid_arr_index(&pm->task_list, pid); + if (i < 0) { + return 0; + } + + 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; + } + + if (arr_insert(&pm->task_list, arr_size(&pm->task_list), &proc)) { + return -1; + } + + return 0; +} + +int pm_remove_proc(proc_man_t * pm, int pid) { + if (!pm || pid < 1) { + return -1; + } + + if (pid == get_active_task()->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_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { + if (!pm) { + return -1; + } + + process_t * proc = pm_find_pid(pm, pid); + if (!proc) { + return -1; + } + + 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, get_active_task()->pid); + if (i < 0) { + return 0; + } + + int start_i = i++; + + 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 * active = get_active_task(); + if (PROCESS_STATE_LOADED <= active->state <= PROCESS_STATE_DEAD) { + return active; + } + + KPANIC("Process Loop!"); + + return 0; +} + +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; + } + } + + 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_LOADED || proc->state >= PROCESS_STATE_DEAD) { + continue; + } + + 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; + } + } + } + + return 0; +} 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 35360d7f..bf7b3aef 100644 --- a/src/kernel/src/system_call_proc.c +++ b/src/kernel/src/system_call_proc.c @@ -17,19 +17,31 @@ 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); - kernel_exit(); + } * args = (struct _args *)args_data; + printf("Proc exit with code %u\n", args->code); + process_t * proc = get_current_process(); + enable_interrupts(); + if (kernel_close_process(proc)) { + KPANIC("Kernel could not close process"); + } + kernel_next_task(); + KPANIC("Unexpected return from kernel_close_process"); } break; case SYS_INT_PROC_ABORT: { 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); - kernel_exit(); + } * args = (struct _args *)args_data; + printf("Proc abort with code %u\n", args->code); + puts(args->msg); + process_t * proc = get_current_process(); + enable_interrupts(); + if (kernel_close_process(proc)) { + KPANIC("Kernel could not close process"); + } + kernel_next_task(); + KPANIC("Unexpected return from kernel_close_process"); } break; case SYS_INT_PROC_PANIC: { @@ -37,18 +49,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,27 +72,60 @@ 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: { 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: { struct _args { ebus_event_t * event; - } args = *(struct _args *)args_data; + } * 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); + ebus_push(get_kernel_ebus(), args->event); } break; + + case SYS_INT_PROC_YIELD: { + struct _args { + int filter; + ebus_event_t * event_out; + } * args = (struct _args *)args_data; + + // TODO clear iret from stack? + 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()); + 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; + } + if (args->event_out) { + return args->event_out->event_id; + } + } + return 0; + }; } return res; 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; } diff --git a/src/kernel/src/term.c b/src/kernel/src/term.c index 50618efe..6bba009f 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) \ { \ @@ -54,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); @@ -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() { @@ -174,9 +187,12 @@ void term_run() { vga_puts("> "); for (;;) { + 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()); - asm("hlt"); } } diff --git a/src/libc/include/libc/proc.h b/src/libc/include/libc/proc.h index e3f9a4fa..3c2699b6 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,10 @@ 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 pull_event(int filter, ebus_event_t * event_out); +void yield(void); + 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..fb16a8a9 100644 --- a/src/libc/src/proc.c +++ b/src/libc/src/proc.c @@ -14,6 +14,18 @@ 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) { + _sys_queue_event(event); +} + +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) { return _sys_proc_getpid(); } diff --git a/src/libc/src/signal.c b/src/libc/src/signal.c index 88aca247..641e8606 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 { @@ -50,7 +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) { - _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..6d5b295e 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, 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 def54952..a820188c 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, ebus_event_t * event_out) { + return send_call(SYS_INT_PROC_YIELD, filter, event_out); +} + size_t _sys_putc(char c) { return send_call(SYS_INT_STDIO_PUTC, c); } diff --git a/tests/src/kernel/test_process.cpp b/tests/src/kernel/test_process.cpp index bbde3ce6..47d29277 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" @@ -14,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) { @@ -51,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); @@ -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(); } @@ -206,6 +230,99 @@ 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)); + 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(); + proc.esp = (int)temp_page.data() + temp_page.size() - 1; + EXPECT_EQ(0, process_set_entrypoint(&proc, (void *)3)); + + // TODO eip on stack + + EXPECT_EQ((int)temp_page.data() + temp_page.size() - (4 * 5), proc.esp); +} + +// Process Resume + +TEST_F(Process, process_resume_InvalidParameters) { + EXPECT_NE(0, process_resume(0, 0)); + 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)); +} + +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)); +} + +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); +} + +TEST_F(Process, process_resume) { + 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 TEST_F(Process, process_add_pages_InvalidParameters) { diff --git a/tests/src/libc/test_process.cpp b/tests/src/libc/test_process.cpp index 1021d42e..ee6f5546 100644 --- a/tests/src/libc/test_process.cpp +++ b/tests/src/libc/test_process.cpp @@ -39,8 +39,33 @@ 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)); + queue_event(&event); + 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; + yield(); + ASSERT_EQ(1, _sys_yield_fake.call_count); + EXPECT_EQ(0, _sys_yield_fake.arg0_val); + EXPECT_EQ(0, _sys_yield_fake.arg1_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); } 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); +// } diff --git a/tests/src/libk/test_libk.cpp b/tests/src/libk/test_libk.cpp index 638cf809..5e441d91 100644 --- a/tests/src/libk/test_libk.cpp +++ b/tests/src/libk/test_libk.cpp @@ -164,6 +164,15 @@ 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, (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) { send_call_fake.return_val = 1; size_t olen = _sys_putc('A'); 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..27e22b44 --- /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(tss_set_esp0, uint32_t); + +void reset_cpu_tss_mock(void); + +#ifdef __cplusplus +} // extern "C" +#endif 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 new file mode 100644 index 00000000..e044792e --- /dev/null +++ b/tests/src/mocks/include/libc/proc.mock.h @@ -0,0 +1,22 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#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); + +#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..4dab349f 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, 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/include/process.mock.h b/tests/src/mocks/include/process.mock.h index 5ef60591..ef9aaa29 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_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(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/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..54f613d9 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(tss_set_esp0, uint32_t); + +void reset_cpu_tss_mock() { + RESET_FAKE(init_tss); + RESET_FAKE(tss_get_entry); + RESET_FAKE(tss_set_esp0); +} 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 275d53d7..1601e744 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,26 @@ void reset_libc_memory_mock(void) { kfree_fake.custom_fake = free; } +// 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 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..d1f712d7 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, ebus_event_t *); 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..3bf16fc7 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_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(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_resume); RESET_FAKE(process_add_pages); RESET_FAKE(process_grow_stack); RESET_FAKE(process_load_heap); - RESET_FAKE(set_next_pid); + RESET_FAKE(set_active_task); + RESET_FAKE(get_active_task); + RESET_FAKE(switch_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();