diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3da3cc9c..e3943034 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,9 +34,10 @@ jobs: - name: Build run: cmake --build ${BUILD_DIR} - - name: Test - working-directory: build - run: ctest -V + # TODO reenable testing once arch. is stable again + # - name: Test + # working-directory: build + # run: ctest -V # TODO re-enable this once coverage is complete # - name: Test with Coverage diff --git a/.vscode/settings.json b/.vscode/settings.json index ce6c30ac..387ae1b7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,7 @@ { + "files.associations": { + ".clang-format": "yaml" + }, "coverage-gutters.coverageReportFileName": "tests/build/os_test_coverage/index.html", "coverage-gutters.coverageBaseDir": "tests/build" } \ No newline at end of file diff --git a/Makefile b/Makefile index bc3780cd..64e64a38 100644 --- a/Makefile +++ b/Makefile @@ -14,9 +14,17 @@ QEMUFLAGS = -m 1G \ -drive format=raw,file=build/os-image.bin,index=0,if=floppy \ -drive format=raw,file=build/apps.tar \ -d int,mmu \ + -vga cirrus \ -D qemu_log.txt \ -no-reboot -no-shutdown \ - -chardev stdio,id=char0,logfile=kernel.log,signal=off -serial chardev:char0 + -chardev stdio,id=char0,logfile=kernel.log,signal=off \ + -serial chardev:char0 + +# To write to file without stdout use +# -chardev stdout,id=char0,path=kernel.log,signal=off \ +# -serial chardev:char0 +# or +# -serial file:kernel.log # =============== # LAUNCH & UTIL diff --git a/README.md b/README.md index fa4fcc69..02c5ccff 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,14 @@ # os -~~Following the tutorials under https://github.com/cfenollosa/os-tutorial~~ +Hobby i386 kernel / operating system. -Active and planned work is tracked in [notes.md](notes.md) +- [Active and planned work](notes.md) +- [Design concepts and implementation references](design/) -For current specs see - -- [boot.md](design/boot.md) -- ~~[filesystem.md](design/filesystem.md)~~ -- [memory.md](design/memory.md) -- [process.md](design/process.md) -- [system_call.md](design/system_call.md) +This project started by following the tutorials under +[https://github.com/cfenollosa/os-tutorial](https://github.com/cfenollosa/os-tutorial) +but has diverged quite a bit since. Some components are still mostly the same +(eg. [src/boot/](src/boot/)). ## Goals @@ -100,18 +98,30 @@ make setup ### Building +The os image can be found at `build/os-image.bin`, with an elf for the kernel +at `build/src/kernel/kernel.elf` for debug symbols. Apps are combined in a +tar file at `build/apps.tar` which is mounted by the kernel at runtime. + ```sh make build ``` ### Running +QEMU is used for cpu emulation and kernel execution. I'm using QEMU emulator +version 10.1.0 (Debian 1:10.1.0+ds-5ubuntu2.4) but other versions should work. +Logs will be written to stdout and `kernel.log` Qemu logs are written to +`qemu_logs.txt` + ```sh make run ``` Once running, use the `help` command to see what you can do. +Kernel log level can be adjusted in +[src/kernel/src/loader.c](src/kernel/src/loader.c) in the function `__start` + ### Testing ```sh diff --git a/design/driver.md b/design/driver.md index af761e0e..85970b75 100644 --- a/design/driver.md +++ b/design/driver.md @@ -1,4 +1,4 @@ -# Driver +# WIP - Driver Loading drivers is a future problem. Drivers will be built into the kernel and the kernel will know about each of them after compilation. diff --git a/design/filesystem.md b/design/filesystem.md index 3d995d1d..048a1abc 100644 --- a/design/filesystem.md +++ b/design/filesystem.md @@ -1,5 +1,4 @@ - -# Structure +# Filesystem - Blocks are 64 bytes each - Block groups have 256 blocks (max addressable with 8 bits) diff --git a/design/process.md b/design/process.md index bbc085e3..d96fa253 100644 --- a/design/process.md +++ b/design/process.md @@ -49,21 +49,41 @@ The TSS entry will need to be updated with the new process' esp0. TODO : the ESP0 might be better stored in the kernel instead of the process if the process page dir does not include a stack for the kernel (eg. isr stack). -## Process Struct - -| Start | Size | Description | -| ----- | ---- | ------------------------ | -| 0 | 4 | Process Id (PID) | -| 4 | 4 | Next Heap Page | -| 8 | 4 | Stack Page Count | -| 16 | 4 | Page Directory (CR3) | -| 12 | 4 | Stack Pointer (ESP) | -| 20 | 4 | ISR Stack Pointer (ESP0) | -| 24 | 4 | Signal Callback Function | -| 28 | 4 | Pointer to next Process | - -- `Size` is in bytes. -- PID 0 is reserved for the kernel, the first proc will be pid 1 +TODO : parent pid + +## Ring Scheduler + +There needs to be some intermediate task scheduler until a more complete one is +implemented (similar to how malloc needed an intermediate). This intermediate +scheduler will be a ring scheduler. + +Each process is in a linked list with a pointer to the next process (and +previous for list removal). When a task switch is performed, the next process +in checked for fulfillment of the event filter. This is repeated until a ready +to run task is found. + +> [!WARNING] There must be at least one process ready to run +> +> There must always be a "next" task ready to run. In the case where the current +> process is yielding with an event filter, another process must be ready to +> launch. This will most likely be init, so there needs to be some documentation +> for init behavior written which includes that it must never yield with an +> event filter. + +### Process Manager + +has pointer to first and foreground processes + +### Searching for PID + +starts at foreground task + +### Event Filter Fulfillment + +When the task filter is 0 or there is an event with matching id to filter type. + + +# Old ## Memory diff --git a/design/signals.md b/design/signals.md new file mode 100644 index 00000000..1a2dc25f --- /dev/null +++ b/design/signals.md @@ -0,0 +1,17 @@ +# WIP - Signals + +Signals allow the kernel to communicate to the process using callbacks. To +handle communication form process to kernel, use [system calls](system_call.md). + +TODO + +- [ ] Signal callback signature +- [ ] Registering callback +- [ ] Sending signals from kernel + +# Old + +The `register_signals` call will hook a function in libc to receive all signals. +It will then store all registered callbacks of the process. + +TODO - keyboard event diff --git a/design/system_call.md b/design/system_call.md index 89ff811f..fafdd15a 100644 --- a/design/system_call.md +++ b/design/system_call.md @@ -1,70 +1,118 @@ -# WIP - System Calls - -System calls are performed through interrupt 48 (`int 0x30`). The interrupt -takes a `uint16_t` id and some number of arguments. - -Each interrupt takes up to 3 arguments and returns a `uint32_t`. - -## System Calls - -These are calls from the process to the kernel - -| ID | Family | -| ---- | --------------- | -| 0x01 | I/O | -| 0x02 | Memory | -| 0x03 | Process Control | -| 0x10 | Tmp Std I/O | - -An interrupt id is an 8 bit family + an 8 bit id. - -| Family | ID | Name | -| --------------- | ------ | ------------------------------------------------------------------------- | -| I/O | 0x0100 | open | -| | 0x0101 | close | -| | 0x0102 | read | -| | 0x0103 | write | -| | 0x0104 | seek | -| | 0x0105 | tell | -| Memory | 0x0200 | `void * malloc(size_t size)` | -| | 0x0201 | `void * realloc(void * ptr, size_t size)` | -| | 0x0202 | `void free(void * ptr)` | -| Process Control | 0x0300 | `void exit(uint8_t code)` | -| | 0x0301 | `void abort(uint8_t code, const char * msg)` | -| | 0x0302 | `void panic(const char * msg, const char * file, unsigned int line)` | -| | 0x0303 | `int register_signals(void * callback)` | -| | 0x0304 | `int getpid()` | -| Tmp Std I/O | 0x1000 | `size_t putc(char c)` | -| | 0x1001 | `size_t puts(const char * str)` | -| | 0x1002 | `size_t vprintf(const char * fmt, va_list params)` | -| File I/O | 0x1101 | `file_t file_open(const char * path, const char * mode)` | -| | 0x1102 | `void file_close(file_t)` | -| | 0x1103 | `size_t file_read(file_t, size_t size, size_t count, void * buff)` | -| | 0x1104 | `size_t file_write(file_t, size_t size, size_t count, const void * buff)` | -| | 0x1105 | `int file_seek(file_t, int offset, int origin)` | -| | 0x1105 | `int file_tell(file_t)` | -| Dir I/O | 0x1201 | `dir_t dir_open(const char * path)` | -| | 0x1202 | `void dir_close(dir_t)` | -| | 0x1203 | `int dir_read(dir_t, void * dir_entry)` | -| | 0x1205 | `int dir_seek(dir_t, int offset, int origin)` | -| | 0x1205 | `int dir_tell(dir_t)` | - -## System Calls 2.0 - -io -- open handle -- close handle -- read handle -- write handle -- handle size? (maybe part of open) -- stat? size? (can't be seek or tell, those are in libc) - - -# System Signals - -These are callbacks from the kernel to the process. - -The `register_signals` call will hook a function in libc to receive all signals. -It will then store all registered callbacks of the process. - -TODO - keyboard event +# System Calls + +System calls are the mechanism by which processes communicate with the kernel +both for sending commands and retrieving data. Some examples include file io, +memory management, process management, etc. System calls are initiated by the +process. To handle communication form kernel to process, use +[signals](signals.md). + +## Sending System Calls + +System calls are sent to the kernel through interrupt 48 (`int 0x30`) which is +sent to IRQ 16. Each system call has a wrapper function in libk which calls one +of two functions, `send_call` or `send_call_noret`. These functions take a +`uint32_t` call id followed by some number va args. + +```c +extern int send_call(uint32_t int_no, ...); +extern NO_RETURN void send_call_noret(uint32_t int_no, ...); +``` + +> [!TIP] +> Wrapper functions are declared in +> [src/libk/include/libk/sys_call.h](../src/libk/include/libk/sys_call.h) and +> defined in [src/libk/src/sys_call.c](../src/libk/src/sys_call.c). + +### Call Id + +The system call id is a `uint32_t` where the first 16 bits are the family +followed by 16 bits for the call number. + +| Family | Call | +| ------- | ------- | +| 16 bits | 16 bits | + +> [!TIP] +> System call ids are defined in +> [src/libk/include/libk/defs.h](../src/libk/include/libk/defs.h). + +## Receiving System Calls + +System calls are received by the kernel through callbacks registered with +`system_call_register`. The callback function receives a `uint32_t` call id, +`void *` pointer to the va_args pushed onto the stack by `send_call` and +`send_call_noret`, and `registers_t *` object with values of all registers. + +```c +typedef int (*sys_call_handler_t)(uint32_t call_id, void * args_data, registers_t * regs); +void system_call_register(uint16_t family, sys_call_handler_t handler); +``` + +### Call Arguments + +Arguments are accessible from `args_data` which is a pointer to the va_args in +the caller process stack. A struct can be used to decompose the argument values +from this pointer. + +```c +struct _args { + void * ptr; + size_t count; +} * args = (struct _args *)args_data; +// use args->ptr or args->count to read values +``` + +> [!WARNING] +> +> Argument data is stored in the process stack. After changing the page directory +> the values in `arg_data` will be invalid. Copy values to the kernel stack or +> heap before switching to retrain access. + +### Return Value + +Each call handler can optionally returns a single `int` value to the caller +process by returning a value from the handler function. If no value is returned +to the caller process, the call handler should return 0. + +### Example Handler + +A typical call handler uses a switch block to select the correct logic based +on the `call_id`. + +```c +// Define handler function +int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { + // Get the caller process + process_t * proc = get_current_process(); + + // Handle call id + switch (call_id) { + // Log warning if call id is unknown + default: { + KLOG_WARNING("Invalid call id 0x%X", call_id); + break; + } + + // Logic for call id + case SYS_CALL_MEM_MALLOC: { + // va args from send_call or send_call_noret + struct _args { + size_t size; + } * args = (struct _args *)args_data; + // Return int to caller process + return PTR2UINT(memory_alloc(&proc->memory, args->size)); + } break; + + case SYS_CALL_MEM_FREE: { + struct _args { + void * ptr; + } * args = (struct _args *)args_data; + memory_free(&proc->memory, args->ptr); + // No value is returned so handler defaults to 0 + } break; + } + + // Default return value of 0 + return 0; +} +``` diff --git a/design/task kernel coms.md b/design/task kernel coms.md deleted file mode 100644 index bc5935d0..00000000 --- a/design/task kernel coms.md +++ /dev/null @@ -1,16 +0,0 @@ -# Task and Kernel Communication - -## Task to Kernel - -- System Call - - Ask the kernel for something or to do something - - Yields process -- Queue Event - - Signal / send data to other tasks - -## Kernel to Task - -- Signal - - Events for process lifecycle -- Events (via yield) - - Signal / data from other tasks diff --git a/design/time.md b/design/time.md index c9b079c3..8393f3f9 100644 --- a/design/time.md +++ b/design/time.md @@ -15,7 +15,7 @@ the reload value, reading the current count, etc. Each channel counts down, starting at the reload value, and when they reach 0 the output is switched (low -> high or high -> low). In most cases the channel -is then set to the reload value. +is then set to the reload value. TODO in what cases is the reload value not used when a channel reaches 0? diff --git a/docs/Makefile b/docs/Makefile index 02cbc2b8..856cd6cf 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -6,6 +6,6 @@ build: uv run mkdocs build serve: - uv run mkdocs serve + uv run mkdocs serve --livereload .PHONY: setup build serve diff --git a/docs/README.md b/docs/README.md index e69de29b..905a4bd2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,29 @@ +# Docs Site + +This directory contains documentation site generation using mkdocs. Pages are +generated from markdown files in the project root along with design docs. + +- [Project Readme](../README.md) +- [Notes & Work Planning](../notes.md) +- [Loader Notes](../loader_notes.md) +- [Design Docs](../design/) + +## Usage + +Setup + +```sh +make setup +``` + +Dev server with live reload + +```sh +make serve +``` + +Build static site + +```sh +make build +``` diff --git a/docs/docs/loader_notes.md b/docs/docs/loader_notes.md new file mode 120000 index 00000000..e05bbbd3 --- /dev/null +++ b/docs/docs/loader_notes.md @@ -0,0 +1 @@ +../../loader_notes.md \ No newline at end of file diff --git a/loader_ntoes.md b/loader_notes.md similarity index 100% rename from loader_ntoes.md rename to loader_notes.md diff --git a/notes.md b/notes.md index f40f14a2..a34a3314 100644 --- a/notes.md +++ b/notes.md @@ -1,4 +1,4 @@ -# Notes and ToDos for active and planned future work +# Notes & Work Planning This is a list of all active and planned work. They can be removed once they are checked off. Use the task template bellow for larger tasks that need some design diff --git a/src/apps/CMakeLists.txt b/src/apps/CMakeLists.txt index bb97f8c1..4cf9f762 100644 --- a/src/apps/CMakeLists.txt +++ b/src/apps/CMakeLists.txt @@ -8,6 +8,7 @@ macro(add_app target) add_custom_command(OUTPUT ${APPS_BASE_DIR}/${target} COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/${target}.bin ${APPS_BASE_DIR}/${target} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/${target}.elf ${APPS_BASE_DIR}/${target}.elf DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${target}.bin) add_custom_target(${target}_app @@ -24,6 +25,7 @@ add_subdirectory(demo) add_subdirectory(ping) add_subdirectory(pong) add_subdirectory(shell) +add_subdirectory(getpid) message("App targets are ${APPS_TARGETS}") diff --git a/src/apps/getpid/CMakeLists.txt b/src/apps/getpid/CMakeLists.txt new file mode 100644 index 00000000..444d0d09 --- /dev/null +++ b/src/apps/getpid/CMakeLists.txt @@ -0,0 +1,3 @@ +set(TARGET getpid) + +add_app(${TARGET}) diff --git a/src/apps/getpid/link.ld b/src/apps/getpid/link.ld new file mode 100644 index 00000000..9ac34e30 --- /dev/null +++ b/src/apps/getpid/link.ld @@ -0,0 +1,29 @@ +ENTRY(__start) + +SECTIONS { + . = 0x400000; + + .text : + { + *(.text) + } + + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } +} \ No newline at end of file diff --git a/src/apps/getpid/src/getpid.c b/src/apps/getpid/src/getpid.c new file mode 100644 index 00000000..2c6f3679 --- /dev/null +++ b/src/apps/getpid/src/getpid.c @@ -0,0 +1,7 @@ +#include "libc/proc.h" +#include "libc/stdio.h" + +void __start() { + int pid = getpid(); + printf("PID is %u\n"); +} diff --git a/src/apps/shell/src/commands.c b/src/apps/shell/src/commands.c index 4dcd512c..71d63f34 100644 --- a/src/apps/shell/src/commands.c +++ b/src/apps/shell/src/commands.c @@ -5,6 +5,7 @@ #include "libc/proc.h" #include "libc/stdio.h" #include "libc/string.h" +#include "libc/time.h" #include "shell.h" static int echo_cmd(size_t argc, char ** argv) { @@ -86,9 +87,51 @@ static int pid_cmd(size_t argc, char ** argv) { return 0; } +static int sleep_cmd(size_t argc, char ** argv) { + if (argc < 2 || (!kstrcmp(argv[1], "-u") && argc < 3)) { + printf("Usage: %s [-u] \n", argv[0]); + puts("\nseconds must be at while number that is least 1\n"); + puts("-u use microseconds instead of seconds\n"); + return -1; + } + + if (!kstrcmp(argv[1], "-u")) { + int us = katoi(argv[2]); + if (us < 1) { + printf("Seconds must be a numer that is at least 1\n"); + return -1; + } + + printf("Sleeping for %d microseconds\n", us); + usleep(us); + } + else { + int seconds = katoi(argv[1]); + if (seconds < 1) { + printf("Seconds must be a numer that is at least 1\n"); + return -1; + } + + printf("Sleeping for %d sseconds\n", seconds); + sleep(seconds * 1000); + } + + puts("Finished sleep\n"); + + return 0; +} + +static int time_cmd(size_t argc, char ** argv) { + printf("The time is %u seconds\n", time()); + + return 0; +} + void init_commands() { term_command_add("echo", echo_cmd); term_command_add("ls", ls_cmd); term_command_add("cat", cat_cmd); term_command_add("pid", pid_cmd); + term_command_add("sleep", sleep_cmd); + term_command_add("time", time_cmd); } diff --git a/src/apps/shell/src/shell.c b/src/apps/shell/src/shell.c index 02c39651..73cc24f6 100644 --- a/src/apps/shell/src/shell.c +++ b/src/apps/shell/src/shell.c @@ -198,20 +198,18 @@ void term_run() { for (;;) { ebus_event_t event; - if (pull_event(EBUS_EVENT_KEY, &event)) { - // printf("Got event type 0x%04x\n", event.event_id); - if (event.event_id == EBUS_EVENT_KEY) { - key_cb(event.key.keycode, event.key.c, event.key.event, event.key.mods); - // printf("Got key %c %x %x\n", event.key.c, event.key.keycode, event.key.scancode); - // if (event.key.event == 0) { - // putc(event.key.c); - // } - - // char c = getc(); - // if (c) { - // key_char_cb(c); - // } - } + if (!pull_event(EBUS_EVENT_KEY, &event)) { + // printf("Got event type 0x%04x located at %p\n", event.event_id, &event); + key_cb(event.key.keycode, event.key.c, event.key.event, event.key.mods); + // printf("Got key %c keycode 0x%x scancode 0x%x location %p\n", event.key.c, event.key.keycode, event.key.scancode, &event); + // if (event.key.event == 0) { + // putc(event.key.c); + // } + + // char c = getc(); + // if (c) { + // key_char_cb(c); + // } } term_update(); } diff --git a/src/cpu/i386/src/isr.c b/src/cpu/i386/src/isr.c index d43155d1..d8dd8f3f 100644 --- a/src/cpu/i386/src/isr.c +++ b/src/cpu/i386/src/isr.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/ISR" + #include "cpu/isr.h" #include "cpu/idt.h" @@ -7,9 +9,6 @@ #include "libc/proc.h" #include "libc/stdio.h" -#undef SERVICE -#define SERVICE "DRIVER/ISR" - // static void print_trace(registers_t *); static isr_t __interrupt_handlers[256]; diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index 29a88d36..5b74647e 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -14,12 +14,18 @@ #include "process_manager.h" typedef struct _kernel { - uint32_t esp0; - proc_man_t pm; + /// Kernel stack pointer + uint32_t esp0; + /// Process manager + proc_man_t pm; + /// Process scheduler scheduler_t scheduler; - ebus_t event_queue; - disk_t * disk; - tar_fs_t * tar; + /// Kernel event bus (is this used?) + ebus_t event_queue; + /// Disk driver for boot drive (this is temporary and should be replaced with a proper driver / device manager) + disk_t * disk; + /// Filesystem driver for boot drive (this is temporary and should be replaced with a proper drier / filesystem manager) + tar_fs_t * tar; } kernel_t; disk_t * kernel_get_disk(); @@ -40,8 +46,6 @@ void tmp_register_signals_cb(signals_master_cb_t cb); void kernel_queue_event(ebus_event_t * event); -// ebus_event_t * pull_event(int event_id); - typedef int (*_proc_call_t)(void * data); int kernel_call_as_proc(int pid, _proc_call_t fn, void * data); diff --git a/src/kernel/include/kernel/logs.h b/src/kernel/include/kernel/logs.h index e27346f9..619aa664 100644 --- a/src/kernel/include/kernel/logs.h +++ b/src/kernel/include/kernel/logs.h @@ -4,37 +4,56 @@ #include #include -enum KERNEL_LOG_LEVEL { - KERNEL_LOG_LEVEL_TRACE = 0, - KERNEL_LOG_LEVEL_DEBUG, - KERNEL_LOG_LEVEL_INFO, - KERNEL_LOG_LEVEL_WARNING, - KERNEL_LOG_LEVEL_ERROR, - - KERNEL_LOG_LEVEL__LENGTH, // Number of log levels, used to bounds check name lookup -}; +#define KERNEL_LOG_LEVEL_TRACE 0 +#define KERNEL_LOG_LEVEL_DEBUG 1 +#define KERNEL_LOG_LEVEL_INFO 2 +#define KERNEL_LOG_LEVEL_WARNING 3 +#define KERNEL_LOG_LEVEL_ERROR 4 +#define KERNEL_LOG_LEVEL__LENGTH 5 // Number of log levels, used to bounds check name lookup #define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE2(x) #x #define LINE_STRING STRINGIZE(__LINE__) #define PREFIX __BASE_FILE__ ":" LINE_STRING -#ifndef SERVICE -#define SERVICE 0 +#ifndef KLOG_SERVICE +#define KLOG_SERVICE 0 +#endif + +#ifndef KLOG_LEVEL +#define KLOG_LEVEL KERNEL_LOG_LEVEL_DEBUG +#endif + +#define VA_ARGS(...) , ##__VA_ARGS__ +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_TRACE +#define KLOG_TRACE(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_TRACE, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_TRACE(FMT, ...) +#endif + +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_DEBUG +#define KLOG_DEBUG(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_DEBUG, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_DEBUG(FMT, ...) +#endif + +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_INFO +#define KLOG_INFO(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_INFO, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_INFO(FMT, ...) #endif -#define VA_ARGS(...) , ##__VA_ARGS__ -#define KLOG_TRACE(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_TRACE, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOG_DEBUG(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_DEBUG, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOG_INFO(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_INFO, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOG_WARNING(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_WARNING, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOG_ERROR(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_ERROR, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) - -#define KLOGS_TRACE(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_TRACE, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOGS_DEBUG(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_DEBUG, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOGS_INFO(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_INFO, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOGS_WARNING(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_WARNING, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOGS_ERROR(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_ERROR, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_WARNING +#define KLOG_WARNING(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_WARNING, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_WARNING(FMT, ...) +#endif + +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_ERROR +#define KLOG_ERROR(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_ERROR, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_ERROR(FMT, ...) +#endif void kernel_log_init(); diff --git a/src/kernel/include/kernel/system_call_event.h b/src/kernel/include/kernel/system_call_event.h new file mode 100644 index 00000000..9cd2f314 --- /dev/null +++ b/src/kernel/include/kernel/system_call_event.h @@ -0,0 +1,8 @@ +#ifndef KERNEL_SYSTEM_CALL_EVENT_H +#define KERNEL_SYSTEM_CALL_EVENT_H + +#include "system_call.h" + +int sys_call_event_cb(uint32_t call_id, void * args_data, registers_t * regs); + +#endif // KERNEL_SYSTEM_CALL_EVENT_H diff --git a/src/kernel/include/kernel/system_call_io.h b/src/kernel/include/kernel/system_call_io.h index c64087d2..a881e448 100644 --- a/src/kernel/include/kernel/system_call_io.h +++ b/src/kernel/include/kernel/system_call_io.h @@ -3,6 +3,6 @@ #include "system_call.h" -int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs); +int sys_call_io_cb(uint32_t call_id, void * args_data, registers_t * regs); #endif // KERNEL_SYSTEM_CALL_IO_H diff --git a/src/kernel/include/kernel/system_call_mem.h b/src/kernel/include/kernel/system_call_mem.h index 7bc6e049..7cac2ab2 100644 --- a/src/kernel/include/kernel/system_call_mem.h +++ b/src/kernel/include/kernel/system_call_mem.h @@ -3,6 +3,6 @@ #include "system_call.h" -int sys_call_mem_cb(uint16_t int_no, void * args_data, registers_t * regs); +int sys_call_mem_cb(uint32_t call_id, void * args_data, registers_t * regs); #endif // KERNEL_SYSTEM_CALL_MEM_H diff --git a/src/kernel/include/kernel/system_call_proc.h b/src/kernel/include/kernel/system_call_proc.h index 276e07a3..65bd3a0a 100644 --- a/src/kernel/include/kernel/system_call_proc.h +++ b/src/kernel/include/kernel/system_call_proc.h @@ -3,6 +3,6 @@ #include "system_call.h" -int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs); +int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs); #endif // KERNEL_SYSTEM_CALL_PROC_H diff --git a/src/kernel/include/kernel/time.h b/src/kernel/include/kernel/time.h index a8bad034..0696a219 100644 --- a/src/kernel/include/kernel/time.h +++ b/src/kernel/include/kernel/time.h @@ -19,6 +19,7 @@ void time_init(uint32_t freq); */ int time_start_timer(uint32_t ticks); int time_start_timer_ns(uint32_t ns); +int time_start_timer_us(uint32_t us); int time_start_timer_ms(uint32_t ms); void time_stop_timer(int id); diff --git a/src/kernel/include/paging.h b/src/kernel/include/paging.h index 73cda471..ea80ae63 100644 --- a/src/kernel/include/paging.h +++ b/src/kernel/include/paging.h @@ -8,8 +8,9 @@ /** * @brief Setup paging called by kernel main. + * @return int 0 for success */ -void paging_init(); +int paging_init(); /** * @brief Map `paddr` to a temporary page and return the virtual address. @@ -30,8 +31,9 @@ void * paging_temp_map(uint32_t paddr); * until empty. * * @param paddr physical address to free + * @return int 0 for success */ -void paging_temp_free(uint32_t paddr); +int paging_temp_free(uint32_t paddr); /** * @brief Get count of free pages for temporary mapping. diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 7bb543a0..d40c17b8 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -30,42 +30,75 @@ typedef struct _handle { } handle_t; enum PROCESS_STATE { + /// Process struct is created but nothing is loaded PROCESS_STATE_STARTING = 0, + /// Resources are being allocated for the process PROCESS_STATE_LOADING, + /// Ready to start but not yet started PROCESS_STATE_LOADED, + /// Execution suspended, no events waited for PROCESS_STATE_SUSPENDED, + /// Execution suspended, waiting for event PROCESS_STATE_WAITING, - // PROCESS_STATE_WAITING_STDIN, + /// This is the curent active process running PROCESS_STATE_RUNNING, + /// Execution has finished, resources have not been freed PROCESS_STATE_DEAD, + /// Kernel error, resources have not been freed. User errors are noted in status_code PROCESS_STATE_ERROR, }; typedef struct _process { + /// Page directory physical address uint32_t cr3; + /// Process stack pointer uint32_t esp; + /// Kernel stack pointer? uint32_t esp0; + /// Process id uint32_t pid; + /// Virtual address of the next page to be allocated for the heap uint32_t next_heap_page; + /// Number of pages allocated to the stack uint32_t stack_page_count; + /// PID of parent process (0 is no parent) + uint32_t parent_pid; + // TODO heap & stack limits - char * filepath; - int argc; + /// String path to executable file on filesystem + char * filepath; + /// Number of arguments, at least 1 (for filename) + int argc; + /// Arguments to process, first arg is filename char ** argv; - int status_code; + /// Exit code after execution + int status_code; + /// Optional callback address for receiving signals from kernel signals_master_cb_t signals_callback; - arr_t io_handles; // array - ebus_t event_queue; - memory_t memory; - - uint32_t filter_event; + /// array of open io handles, access to io methods, state and driver + arr_t io_handles; // array + /// event bus for this process + // ebus_t event_queue; + /// Memory allocation from the kernel (for malloc in kernel instead of libc) + memory_t memory; + + /// Event type being waited on by process if state is PROCESS_STATE_WAITING + ebus_event_t filter_event; + /// Event matching filter_event if one is ready + ebus_event_t next_event; + /// Current state of process (eg. loading, running, waiting, dead, etc.) enum PROCESS_STATE state; + /// Array of circular buffers used to store data being sent to each handle. + /// If a buffee is filled it ... (tbd, drops input or pops oldest?) io_buffer_t * io_buffer; + + struct _process * next; + struct _process * prev; } process_t; /** @@ -154,6 +187,9 @@ int process_add_handle(process_t * proc, int id, int flags, io_device_t * device handle_t * process_get_handle(process_t * proc, int id); +int process_link(process_t * proc, process_t * next); +int process_unlink(process_t * proc); + /** * @brief Set the next PID value. All future PID's will be incremented from * here. diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h index 28e0f5ab..d9e95a36 100644 --- a/src/kernel/include/process_manager.h +++ b/src/kernel/include/process_manager.h @@ -5,11 +5,10 @@ #include #include "ebus.h" -#include "libc/datastruct/array.h" #include "process.h" typedef struct _proc_man { - arr_t task_list; // process_t * + process_t * first_task; process_t * foreground_task; } proc_man_t; @@ -24,7 +23,7 @@ int pm_remove_proc(proc_man_t * pm, int pid); int pm_set_foreground_proc(proc_man_t * pm, int pid); -int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event); +int pm_resume_process(proc_man_t * pm, int pid); // TODO move to scheduler process_t * pm_get_next(proc_man_t * pm); diff --git a/src/kernel/include/system_call.h b/src/kernel/include/system_call.h index a25bd4c7..5effd114 100644 --- a/src/kernel/include/system_call.h +++ b/src/kernel/include/system_call.h @@ -6,10 +6,10 @@ #include "cpu/isr.h" #include "defs.h" -typedef int (*sys_call_handler_t)(uint16_t interrupt_no, void * args_data, registers_t * regs); +typedef int (*sys_call_handler_t)(uint32_t call_id, void * args_data, registers_t * regs); void system_call_init(uint8_t isr_interrupt_no); -void system_call_register(uint8_t family, sys_call_handler_t handler); +void system_call_register(uint16_t family, sys_call_handler_t handler); #endif // SYSTEM_CALL_H diff --git a/src/kernel/src/drivers/ata.c b/src/kernel/src/drivers/ata.c index 525416d6..deb1d862 100644 --- a/src/kernel/src/drivers/ata.c +++ b/src/kernel/src/drivers/ata.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/ATA" + #include "drivers/ata.h" #include "cpu/isr.h" @@ -12,9 +14,6 @@ #include "libc/stdio.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/ATA" - // https://wiki.osdev.org/ATA_PIO_Mode #define MAX_RETRY 5000 diff --git a/src/kernel/src/drivers/keyboard.c b/src/kernel/src/drivers/keyboard.c index 781ef149..a260a1c5 100644 --- a/src/kernel/src/drivers/keyboard.c +++ b/src/kernel/src/drivers/keyboard.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/KEYBOARD" + #include "drivers/keyboard.h" #include @@ -10,9 +12,6 @@ #include "libc/stdio.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/KEYBOARD" - 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}; diff --git a/src/kernel/src/drivers/pit.c b/src/kernel/src/drivers/pit.c index 7e5d9c74..91e4aa2b 100644 --- a/src/kernel/src/drivers/pit.c +++ b/src/kernel/src/drivers/pit.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/PIT" + #include "drivers/pit.h" #include "cpu/isr.h" @@ -6,9 +8,6 @@ #include "kernel/panic.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/PIT" - #define PIT_CHANNEL_0_PORT 0x40 #define PIT_CHANNEL_1_PORT 0x41 #define PIT_CHANNEL_2_PORT 0x42 diff --git a/src/kernel/src/drivers/ram.c b/src/kernel/src/drivers/ram.c index 38e57972..ebb13ad7 100644 --- a/src/kernel/src/drivers/ram.c +++ b/src/kernel/src/drivers/ram.c @@ -1,12 +1,11 @@ +#define KLOG_SERVICE "DRIVER/RAM" + #include "drivers/ram.h" #include "cpu/mmu.h" #include "kernel/logs.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/RAM" - #define REGION_MAX_PAGE_COUNT 0x8000 #define REGION_MAX_SIZE (REGION_MAX_PAGE_COUNT * PAGE_SIZE) @@ -17,14 +16,14 @@ static ram_table_t * __region_table; static size_t __region_table_count; static void * __bitmask; -static int find_addr_entry(uint32_t addr, size_t * out_bit_i); -static int find_free_bit(const void * bitmask, size_t page_count); -static int find_free_region(); -static void set_bit_used(void * bitmask, size_t bit); -static void set_bit_free(void * bitmask, size_t bit); -static int is_bit_free(void * bitmask, size_t bit); -static void fill_bitmask(void * bitmask, size_t page_count); -static void add_memory_at(size_t start, uint64_t base, uint64_t length); +static int find_addr_entry(uint32_t addr, size_t * out_bit_i); +static int find_free_bit(const void * bitmask, size_t page_count); +static int find_free_region(); +static int set_bit_used(void * bitmask, size_t bit); +static int set_bit_free(void * bitmask, size_t bit); +static int is_bit_free(void * bitmask, size_t bit); +static int fill_bitmask(void * bitmask, size_t page_count); +static int add_memory_at(size_t start, uint64_t base, uint64_t length); int ram_init(ram_table_t * ram_table, void * bitmasks) { if (!ram_table) { @@ -211,7 +210,7 @@ int ram_page_free(uint32_t addr) { void * bitmask = __bitmask + PAGE_SIZE * region_i; if (is_bit_free(bitmask, bit_i)) { - KLOG_ERROR("Page %u in region %d for address 0x%XX is already free", bit_i, region_i, addr); + KLOG_ERROR("Page %u in region %d for address 0x%X is already free", bit_i, region_i, addr); return -1; } @@ -224,6 +223,14 @@ int ram_page_free(uint32_t addr) { } static int find_addr_entry(uint32_t addr, size_t * out_bit_i) { + if (!addr) { + KLOG_ERROR("Searching for null address"); + return -1; + } + if (!out_bit_i) { + KLOG_ERROR("Output pointer is null"); + return -1; + } for (size_t i = 0; i < __region_table_count; i++) { ram_table_entry_t * entry = &__region_table->entries[i]; @@ -237,10 +244,20 @@ static int find_addr_entry(uint32_t addr, size_t * out_bit_i) { } } + KLOG_ERROR("Failed to find entry for address %p", addr); + return -1; } static int find_free_bit(const void * bitmask, size_t page_count) { + if (!bitmask) { + KLOG_ERROR("Tried to find bitmask of null pointer"); + return -1; + } + if (!page_count) { + KLOG_WARNING("Trying to find free bit form 0 pages"); + return -1; + } const char * bitmask_data = bitmask; for (size_t i = 1; i < page_count; i++) { @@ -252,6 +269,8 @@ static int find_free_bit(const void * bitmask, size_t page_count) { } } + KLOG_ERROR("Failed to find free bit in bitmask %p", bitmask); + return -1; } @@ -264,28 +283,49 @@ static int find_free_region() { } } + KLOG_ERROR("Failed to find free region"); + return -1; } -static void set_bit_used(void * bitmask, size_t bit) { +static int set_bit_used(void * bitmask, size_t bit) { + if (!bitmask) { + KLOG_ERROR("Tried to set used bit of null bitmask"); + return -1; + } + char * bitmask_data = bitmask; size_t byte = bit / 8; bit = bit % 8; bitmask_data[byte] &= ~(1 << bit); + + return 0; } -static void set_bit_free(void * bitmask, size_t bit) { +static int set_bit_free(void * bitmask, size_t bit) { + if (!bitmask) { + KLOG_ERROR("Tried to set free bit of null bitmask"); + return -1; + } + char * bitmask_data = bitmask; size_t byte = bit / 8; bit = bit % 8; bitmask_data[byte] |= 1 << bit; + + return 0; } static int is_bit_free(void * bitmask, size_t bit) { + if (!bitmask) { + KLOG_ERROR("Tried to check if bit is used of null bitmask"); + return 0; + } + char * bitmask_data = bitmask; size_t byte = bit / 8; @@ -302,7 +342,16 @@ static int is_bit_free(void * bitmask, size_t bit) { * @param bitmask pointer to the bitmask * @param page_count number of pages in region including the bitmask page */ -static void fill_bitmask(void * bitmask, size_t page_count) { +static int fill_bitmask(void * bitmask, size_t page_count) { + if (!bitmask) { + KLOG_ERROR("Trying to fill bitmask of null pointer"); + return -1; + } + if (!page_count) { + KLOG_WARNING("Trying to fill bitmask for 0 pages"); + return -1; + } + unsigned char * bitmask_data = (unsigned char *)bitmask; size_t bytes = page_count / 8; @@ -322,9 +371,12 @@ static void fill_bitmask(void * bitmask, size_t page_count) { } bitmask_data[0] &= 0xfe; + + return 0; } -static void add_memory_at(size_t start, uint64_t base, uint64_t length) { +static int add_memory_at(size_t start, uint64_t base, uint64_t length) { + // TODO what are invalid inputs? size_t split_count = length / REGION_MAX_SIZE; for (size_t i = 0; i <= split_count; i++) { @@ -345,4 +397,6 @@ static void add_memory_at(size_t start, uint64_t base, uint64_t length) { base += REGION_MAX_SIZE; } + + return 0; } diff --git a/src/kernel/src/drivers/ramdisk.c b/src/kernel/src/drivers/ramdisk.c index bb2311e8..9f6ff26e 100644 --- a/src/kernel/src/drivers/ramdisk.c +++ b/src/kernel/src/drivers/ramdisk.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/RAMDISK" + #include "drivers/ramdisk.h" #include "kernel.h" @@ -6,9 +8,6 @@ #include "libc/proc.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/RAMDISK" - struct _ramdisk { int id; size_t size; diff --git a/src/kernel/src/drivers/rtc.c b/src/kernel/src/drivers/rtc.c index d0a2f1f9..87b6feb4 100644 --- a/src/kernel/src/drivers/rtc.c +++ b/src/kernel/src/drivers/rtc.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/RTC" + #include "drivers/rtc.h" #include @@ -6,9 +8,6 @@ #include "cpu/ports.h" #include "kernel/logs.h" -#undef SERVICE -#define SERVICE "DRIVER/RTC" - #define RTC_REG_PORT 0x70 #define RTC_DATA_PORT 0x71 diff --git a/src/kernel/src/drivers/serial.c b/src/kernel/src/drivers/serial.c index c9402ae3..b78c5e1d 100644 --- a/src/kernel/src/drivers/serial.c +++ b/src/kernel/src/drivers/serial.c @@ -6,6 +6,8 @@ // WARNING serial driver is used in logging, so be careful about where you log // so you don't get an infinite loop. +// TODO might need to disable interrupts while interacting with ports? + int serial_init(uint16_t port) { port_byte_out(port + 1, 0x00); // Disable all interrupts port_byte_out(port + 3, 0x80); // Enable DLAB (set baud rate divisor) diff --git a/src/kernel/src/drivers/tar.c b/src/kernel/src/drivers/tar.c index fa000c40..5fb822f8 100644 --- a/src/kernel/src/drivers/tar.c +++ b/src/kernel/src/drivers/tar.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/TAR" + #include "drivers/tar.h" #include @@ -9,9 +11,6 @@ #include "libc/stdio.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/TAR" - typedef struct { char filename[100]; char mode[8]; diff --git a/src/kernel/src/drivers/vga.c b/src/kernel/src/drivers/vga.c index 6ab46980..b98710c7 100644 --- a/src/kernel/src/drivers/vga.c +++ b/src/kernel/src/drivers/vga.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/VGA" + #include "drivers/vga.h" #include "cpu/ports.h" @@ -7,9 +9,6 @@ // WARNING vga driver was previously used in logging, so be careful using it for // log outputs. -#undef SERVICE -#define SERVICE "DRIVER/VGA" - #define REG_SCREEN_CTRL 0x3d4 #define REG_SCREEN_DATA 0x3d5 @@ -50,8 +49,8 @@ void vga_clear() { } void vga_put(int index, char c, unsigned char attr) { - // idk if this is too much - KLOG_TRACE("Put character 0x%X (%c) to index %d with attr 0x%X", c, c, index, attr); + // This is way to much + // KLOG_TRACE("Put character 0x%X (%c) to index %d with attr 0x%X", c, c, index, attr); index *= 2; __screen[index] = c; __screen[index + 1] = attr; diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index 9fe86bb8..c8e7e334 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -1,9 +1,12 @@ +#define KLOG_SERVICE "KERNEL/EXEC" + #include "exec.h" #include "cpu/mmu.h" #include "cpu/tss.h" #include "drivers/ram.h" #include "kernel.h" +#include "kernel/logs.h" #include "libc/memory.h" #include "libc/proc.h" #include "libc/stdio.h" @@ -17,32 +20,103 @@ static void proc_entry(); static int copy_args(process_t * proc, const char * filepath, int argc, char ** argv); int command_exec(uint8_t * buff, const char * filepath, size_t size, size_t argc, char ** argv) { + if (!buff) { + KLOG_ERROR("Tried to execute null buffer"); + return -1; + } + if (!filepath) { + KLOG_ERROR("Missing filepath"); + return -1; + } + if (!size) { + KLOG_WARNING("Buffer size is 0"); + } + if (argc && !argv) { + KLOG_ERROR("Missing argv"); + return -1; + } + process_t * proc = kmalloc(sizeof(process_t)); + if (!proc) { + KLOG_ERROR("Failed to malloc process_t"); + return -1; + } process_t * active = get_active_task(); if (process_create(proc)) { - puts("Failed to create process\n"); + KLOG_ERROR("Failed to create process"); + kfree(proc); return -1; } if (process_load_heap(proc, buff, size)) { - puts("Failed to load\n"); - process_free(proc); + KLOG_ERROR("Failed to load heap"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling load heap error"); + } + kfree(proc); return -1; } + KLOG_TRACE("Increasing stack by 1022 pages"); for (size_t i = 0; i < 1022; i++) { - process_grow_stack(proc); + if (process_grow_stack(proc)) { + KLOG_ERROR("Failed to add page %u", i); + if (process_free(proc)) { + KPANIC("Failed to free process while handling stack grow error"); + } + kfree(proc); + return -1; + } + } + + if (copy_args(proc, filepath, argc, argv)) { + KLOG_ERROR("Failed to copy args"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling copy args error"); + } + kfree(proc); + return -1; + } + + KLOG_TRACE("Setting process entrypoint to %p", proc_entry); + + if (process_set_entrypoint(proc, proc_entry)) { + KLOG_ERROR("Failed to set entrypoint"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling set entrypoint error"); + } + kfree(proc); + return -1; } - copy_args(proc, filepath, argc, argv); + KLOG_TRACE("Adding 32 pages"); - process_set_entrypoint(proc, proc_entry); - process_add_pages(proc, 32); - pm_add_proc(kernel_get_proc_man(), proc); + if (!process_add_pages(proc, 32)) { + KLOG_ERROR("Failed to add 32 pages"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling add 32 pages error"); + } + kfree(proc); + return -1; + } - if (pm_resume_process(kernel_get_proc_man(), proc->pid, 0)) { + if (pm_add_proc(kernel_get_proc_man(), proc)) { + KLOG_ERROR("Failed to add process to process manager"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling add process to process manager error"); + } + kfree(proc); + return -1; + } + + if (pm_resume_process(kernel_get_proc_man(), proc->pid)) { + KLOG_ERROR("Failed to resume process %u", proc->pid); + if (process_free(proc)) { + KPANIC("Failed to free process while handling resume error"); + } + kfree(proc); return -1; } @@ -60,30 +134,78 @@ static void proc_entry() { // TODO get start function pointer from elf + KLOG_TRACE("Entering process pid %u", proc->pid); + int res = fn(proc->argc, proc->argv); proc->status_code = res; + + KLOG_TRACE("Return from process pid %u with status %d", proc->pid, res); } static char * copy_string(const char * str) { + if (!str) { + KLOG_ERROR("Tried to copy null string"); + return 0; + } int len = kstrlen(str); char * new_str = kmalloc(len + 1); - kmemcpy(new_str, str, len + 1); + if (!new_str) { + KLOG_ERROR("Failed to malloc new string of length %d", len + 1); + return 0; + } + if (!kmemcpy(new_str, str, len + 1)) { + KLOG_ERROR("Failed to copy %u bytes in memory from %p to %p", len + 1, str, new_str); + return 0; + } return new_str; } static int copy_args(process_t * proc, const char * filepath, int argc, char ** argv) { - if (!proc || !filepath || !argv) { + if (!proc) { + KLOG_ERROR("Tried to copy args for null process"); + return -1; + } + if (!filepath) { + KLOG_ERROR("Missing filepath"); + return -1; + } + if (argc && !argv) { + KLOG_ERROR("Missing argv"); return -1; } proc->filepath = copy_string(filepath); - proc->argc = argc + 1; - proc->argv = kmalloc(sizeof(char *) * (argc + 1)); + if (!proc->filepath) { + KLOG_ERROR("Failed to copy filepath"); + return -1; + } + proc->argc = argc + 1; + proc->argv = kmalloc(sizeof(char *) * (argc + 1)); + if (!proc->argv) { + KLOG_ERROR("Failed to malloc process_t argv"); + kfree(proc->filepath); + return -1; + } - size_t len = kstrlen(filepath); proc->argv[0] = copy_string(filepath); + if (!proc->argv[0]) { + KLOG_ERROR("Failed to copy filepath to argv"); + kfree(proc->argv); + kfree(proc->filepath); + return -1; + } + for (int i = 0; i < argc; i++) { proc->argv[i + 1] = copy_string(argv[i]); + if (!proc->argv[i + 1]) { + KLOG_ERROR("Failed to copy arg %d", i); + for (int j = 0; j < i + 1; j++) { + kfree(proc->argv[i]); + } + kfree(proc->argv); + kfree(proc->filepath); + return -1; + } } return 0; diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 252e14af..4c2ff789 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -3,6 +3,7 @@ * * Documentation moved to design/boot_stages.md */ +#define KLOG_SERVICE "KERNEL" #include "kernel.h" @@ -15,6 +16,7 @@ #include "exec.h" #include "kernel/logs.h" #include "kernel/panic.h" +#include "kernel/system_call_event.h" #include "kernel/system_call_io.h" #include "kernel/system_call_mem.h" #include "kernel/system_call_proc.h" @@ -24,9 +26,6 @@ #include "libc/string.h" #include "libk/defs.h" -#undef SERVICE -#define SERVICE "KERNEL" - static kernel_t __kernel; extern _Noreturn void halt(void); @@ -103,30 +102,38 @@ void kernel_init() { static void setup_system_calls() { system_call_init(IRQ16); - system_call_register(SYS_INT_FAMILY_IO, sys_call_io_cb); - system_call_register(SYS_INT_FAMILY_MEM, sys_call_mem_cb); - system_call_register(SYS_INT_FAMILY_PROC, sys_call_proc_cb); + system_call_register(SYS_CALL_FAMILY_IO, sys_call_io_cb); + system_call_register(SYS_CALL_FAMILY_MEM, sys_call_mem_cb); + system_call_register(SYS_CALL_FAMILY_PROC, sys_call_proc_cb); + system_call_register(SYS_CALL_FAMILY_EVENT, sys_call_event_cb); } int kernel_exec(const char * filename, size_t argc, char ** argv) { + if (!filename) { + KLOG_ERROR("Missing filename"); + return -1; + } tar_stat_t stat; if (!tar_stat_file(kernel_get_tar(), filename, &stat)) { - puts("Failed to find file\n"); + KLOG_ERROR("Failed to find file %s to execute", filename); return -1; } uint8_t * buff = kmalloc(stat.size); if (!buff) { + KLOG_ERROR("Failed to malloc buffer of size %u", stat.size); return -1; } tar_fs_file_t * file = tar_file_open(kernel_get_tar(), filename); if (!file) { + KLOG_ERROR("Failed to open file %s", filename); kfree(buff); return -1; } if (!tar_file_read(file, buff, stat.size)) { + KLOG_ERROR("Failed to read from file %s", filename); tar_file_close(file); kfree(buff); return -1; @@ -135,6 +142,7 @@ int kernel_exec(const char * filename, size_t argc, char ** argv) { int pid = command_exec(buff, filename, stat.size, argc, argv); if (pid < 0) { + KLOG_ERROR("Failed to execute file %s", filename); tar_file_close(file); kfree(buff); return -1; @@ -159,8 +167,13 @@ ebus_t * get_kernel_ebus() { } void kernel_queue_event(ebus_event_t * event) { - ebus_push(&__kernel.event_queue, event); - pm_push_event(&__kernel.pm, event); + if (ebus_push(&__kernel.event_queue, event)) { + KLOG_ERROR("Failed to push event to kernel event queue"); + return; + } + if (pm_push_event(&__kernel.pm, event)) { + KLOG_ERROR("Failed to push event to process manager"); + } } disk_t * kernel_get_disk() { diff --git a/src/kernel/src/kernel/memory.c b/src/kernel/src/kernel/memory.c index 28727a4c..2b520f36 100644 --- a/src/kernel/src/kernel/memory.c +++ b/src/kernel/src/kernel/memory.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "KERNEL/MEMORY" + #include "kernel/memory.h" #include "kernel.h" @@ -5,9 +7,6 @@ #include "libc/memory.h" #include "paging.h" -#undef SERVICE -#define SERVICE "KERNEL/MEMORY" - static memory_t __memory; static size_t __next_heap_page; diff --git a/src/kernel/src/kernel/panic.c b/src/kernel/src/kernel/panic.c index b6fb441d..902aa07c 100644 --- a/src/kernel/src/kernel/panic.c +++ b/src/kernel/src/kernel/panic.c @@ -1,5 +1,7 @@ +#include "kernel/panic.h" + #include "drivers/vga.h" -#include "kernel.h" +#include "kernel/logs.h" NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int line) { vga_color(VGA_FG_WHITE | VGA_BG_RED); @@ -15,6 +17,7 @@ NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int li vga_puts(msg); } vga_cursor_hide(); + KLOG_ERROR("[KERNEL PANIC][%s]:%u %s", file, line, msg); halt(); } diff --git a/src/kernel/src/kernel/scheduler.c b/src/kernel/src/kernel/scheduler.c index fcffe9f0..a38e597a 100644 --- a/src/kernel/src/kernel/scheduler.c +++ b/src/kernel/src/kernel/scheduler.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SCHEDULER" + #include "kernel/scheduler.h" #include "ebus.h" @@ -26,7 +28,7 @@ int scheduler_run(scheduler_t * scheduler) { } if (cb_len(&get_kernel()->event_queue.queue) > 0) { - KLOGS_DEBUG("Scheduler", "There are %u events ready", cb_len(&get_kernel()->event_queue.queue)); + KLOG_DEBUG("There are %u events ready", cb_len(&get_kernel()->event_queue.queue)); ebus_event_t event; if (cb_pop(&get_kernel()->event_queue.queue, &event) < 0) { diff --git a/src/kernel/src/kernel/system_call_event.c b/src/kernel/src/kernel/system_call_event.c new file mode 100644 index 00000000..4a105dd1 --- /dev/null +++ b/src/kernel/src/kernel/system_call_event.c @@ -0,0 +1,116 @@ +#define KLOG_SERVICE "SYSCALL/EVENT" +// #define KLOG_LEVEL KERNEL_LOG_LEVEL_TRACE + +#include "kernel/system_call_event.h" + +#include + +#include "defs.h" +#include "drivers/vga.h" +#include "ebus.h" +#include "exec.h" +#include "kernel.h" +#include "kernel/logs.h" +#include "kernel/time.h" +#include "libc/proc.h" +#include "libc/stdio.h" +#include "libc/string.h" +#include "libk/defs.h" +#include "process.h" + +int sys_call_event_cb(uint32_t call_id, void * args_data, registers_t * regs) { + process_t * proc = get_current_process(); + + KLOG_TRACE("Call id 0x%X from pid %u", call_id, proc->pid); + + switch (call_id) { + default: { + KLOG_WARNING("Invalid call id 0x%X", call_id); + break; + } + + // Generic event pull, make another case block for more specific logic + case SYS_CALL_EVENT_PULL: { + struct _args { + int filter; + ebus_event_t * event_out; + } * args = (struct _args *)args_data; + + if (!args->filter) { + KLOG_WARNING("Event pul system call with no filter"); + return 1; + } + + proc->next_event.event_id = 0; + proc->filter_event.event_id = args->filter; + proc->state = PROCESS_STATE_WAITING; + + enable_interrupts(); + process_t * next = pm_get_next(kernel_get_proc_man()); + if (pm_resume_process(kernel_get_proc_man(), next->pid)) { + KPANIC("Failed to resume process"); + } + + // args->filter doesn't appear to be valid here, why not? + if (!(proc->next_event.event_id == proc->filter_event.event_id)) { + KPANIC("Tried to resume process but the event does not match filter"); + } + if (args->event_out) { + kmemcpy(args->event_out, &proc->next_event, sizeof(ebus_event_t)); + } + + proc->filter_event.event_id = 0; + proc->next_event.event_id = 0; + } break; + + case SYS_CALL_EVENT_TIME: { + enable_interrupts(); + process_t * next = pm_get_next(kernel_get_proc_man()); + if (pm_resume_process(kernel_get_proc_man(), next->pid)) { + KPANIC("Failed to resume process"); + } + + return time_s(); + } break; + + case SYS_CALL_EVENT_SLEEP: { + struct _args { + size_t ms; + size_t us; + } * args = (struct _args *)args_data; + + int timer_id = 0; + if (args->ms) { + KLOG_TRACE("Using millisecond sleep %u", args->ms); + timer_id = time_start_timer_ms(args->ms); + } + else { + KLOG_TRACE("Using microsecond sleep %u", args->us); + timer_id = time_start_timer_us(args->us); + } + + if (timer_id < 1) { + KLOG_WARNING("Failed to start timer of %u ms\n", args->ms); + return 1; + } + + proc->next_event.event_id = 0; + proc->next_event.timer.id = 0; + proc->next_event.timer.time = 0; + proc->filter_event.event_id = EBUS_EVENT_TIMER; + proc->filter_event.timer.id = timer_id; + proc->state = PROCESS_STATE_WAITING; + + do { + enable_interrupts(); + process_t * next = pm_get_next(kernel_get_proc_man()); + if (pm_resume_process(kernel_get_proc_man(), next->pid)) { + KPANIC("Failed to resume process"); + } + KLOG_TRACE("Back from timer %u", timer_id); + } while (proc->next_event.timer.id != timer_id); + } break; + } + + return 0; +} diff --git a/src/kernel/src/kernel/system_call_io.c b/src/kernel/src/kernel/system_call_io.c index 064d1b62..c6d3ba69 100644 --- a/src/kernel/src/kernel/system_call_io.c +++ b/src/kernel/src/kernel/system_call_io.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SYSCALL/IO" + #include "kernel/system_call_io.h" #include "drivers/vga.h" @@ -8,21 +10,18 @@ #include "libk/defs.h" #include "process.h" -#undef SERVICE -#define SERVICE "SYSCALL/IO" - -int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { +int sys_call_io_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); arr_t * io_handles = &proc->io_handles; - KLOG_TRACE("Call from pid %u interrupt number 0x%X", proc->pid, int_no); + KLOG_TRACE("Call id 0x%X from pid %u", call_id, proc->pid); - switch (int_no) { + switch (call_id) { default: { - KLOG_WARNING("Invalid interrupt number 0x%X", int_no); + KLOG_WARNING("Invalid call id 0x%X", call_id); break; } - case SYS_INT_IO_OPEN: { + case SYS_CALL_IO_OPEN: { struct _args { const char * path; const char * mode; @@ -40,7 +39,7 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { return process_add_handle(proc, -1, 0, d); } break; - // case SYS_INT_IO_CLOSE: { + // case SYS_CALL_IO_CLOSE: { // struct _args { // int handle; // } * args = (struct _args *)args_data; @@ -60,7 +59,7 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { // return 0; // } break; - case SYS_INT_IO_READ: { + case SYS_CALL_IO_READ: { struct _args { int handle; char * buff; @@ -104,7 +103,7 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { // return d->read_fn(d->data, args->buff, args->count, args->pos); } break; - case SYS_INT_IO_WRITE: { + case SYS_CALL_IO_WRITE: { struct _args { int handle; const char * buff; @@ -127,7 +126,7 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { return d->write_fn(d->device_data, args->buff, args->count, args->pos); } break; - case SYS_INT_IO_SIZE: { + case SYS_CALL_IO_SIZE: { struct _args { int handle; const char * buff; diff --git a/src/kernel/src/kernel/system_call_mem.c b/src/kernel/src/kernel/system_call_mem.c index 43ce7243..95de59eb 100644 --- a/src/kernel/src/kernel/system_call_mem.c +++ b/src/kernel/src/kernel/system_call_mem.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SYSCALL/MEMORY" + #include "kernel/system_call_mem.h" #include @@ -8,20 +10,17 @@ #include "memory_alloc.h" #include "process.h" -#undef SERVICE -#define SERVICE "SYSCALL/MEMORY" - -int sys_call_mem_cb(uint16_t int_no, void * args_data, registers_t * regs) { +int sys_call_mem_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); - KLOG_TRACE("Call from pid %u interrupt number 0x%X", proc->pid, int_no); + KLOG_TRACE("Call id 0x%X from pid %u", call_id, proc->pid); - switch (int_no) { + switch (call_id) { default: { - KLOG_WARNING("Invalid interrupt number 0x%X", int_no); + KLOG_WARNING("Invalid call id 0x%X", call_id); break; } - case SYS_INT_MEM_MALLOC: { + case SYS_CALL_MEM_MALLOC: { struct _args { size_t size; } * args = (struct _args *)args_data; @@ -29,7 +28,7 @@ int sys_call_mem_cb(uint16_t int_no, void * args_data, registers_t * regs) { return PTR2UINT(memory_alloc(&proc->memory, args->size)); } break; - case SYS_INT_MEM_REALLOC: { + case SYS_CALL_MEM_REALLOC: { struct _args { void * ptr; size_t size; @@ -38,7 +37,7 @@ int sys_call_mem_cb(uint16_t int_no, void * args_data, registers_t * regs) { return PTR2UINT(memory_realloc(&proc->memory, args->ptr, args->size)); } break; - case SYS_INT_MEM_FREE: { + case SYS_CALL_MEM_FREE: { struct _args { void * ptr; } * args = (struct _args *)args_data; diff --git a/src/kernel/src/kernel/system_call_proc.c b/src/kernel/src/kernel/system_call_proc.c index 60734136..a822da0a 100644 --- a/src/kernel/src/kernel/system_call_proc.c +++ b/src/kernel/src/kernel/system_call_proc.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SYSCALL/PROCESS" + #include "kernel/system_call_proc.h" #include @@ -14,24 +16,20 @@ #include "libk/defs.h" #include "process.h" -#undef SERVICE -#define SERVICE "SYSCALL/PROCESS" - -int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { +int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); - int res = 0; - KLOG_TRACE("Call from pid %u interrupt number 0x%X", proc->pid, int_no); + KLOG_TRACE("Call id 0x%X from pid %u", call_id, proc->pid); - switch (int_no) { + switch (call_id) { default: { - KLOG_WARNING("Invalid interrupt number 0x%X", int_no); + KLOG_WARNING("Invalid call id 0x%X", call_id); break; } // TODO this isn't fully updated with task switching - case SYS_INT_PROC_EXIT: { + case SYS_CALL_PROC_EXIT: { KLOG_DEBUG("System call proc exit"); struct _args { uint8_t code; @@ -51,7 +49,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { // TODO this isn't fully updated with task switching - case SYS_INT_PROC_ABORT: { + case SYS_CALL_PROC_ABORT: { KLOG_DEBUG("System call proc abort"); struct _args { uint8_t code; @@ -72,7 +70,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { KPANIC("Unexpected return from kernel_switch_task"); } break; - case SYS_INT_PROC_PANIC: { + case SYS_CALL_PROC_PANIC: { KLOG_DEBUG("System call proc panic"); struct _args { const char * msg; @@ -98,7 +96,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { } } break; - case SYS_INT_PROC_REG_SIG: { + case SYS_CALL_PROC_REG_SIG: { KLOG_DEBUG("System call proc sig"); struct _args { signals_master_cb_t cb; @@ -106,7 +104,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { tmp_register_signals_cb(args->cb); } break; - case SYS_INT_PROC_GETPID: { + case SYS_CALL_PROC_GETPID: { // KLOG_DEBUG("System call proc getpid"); process_t * p = get_current_process(); if (!p) { @@ -115,7 +113,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { return p->pid; } break; - case SYS_INT_PROC_QUEUE_EVENT: { + case SYS_CALL_PROC_QUEUE_EVENT: { // KLOG_DEBUG("System call proc queue event"); struct _args { ebus_event_t * event; @@ -131,46 +129,19 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { kernel_queue_event(args->event); } break; - case SYS_INT_PROC_YIELD: { - // KLOG_DEBUG("System call proc yield"); - struct _args { - int filter; - ebus_event_t * event_out; - } * args = (struct _args *)args_data; + case SYS_CALL_PROC_YIELD: { + proc->filter_event.event_id = 0; + proc->next_event.event_id = 0; + proc->state = PROCESS_STATE_SUSPENDED; - // TODO clear iret from stack? - 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()); - int has_event = 0; - if (ebus_queue_size(&next->event_queue) > 0) { - // KLOGS_DEBUG("SC_PROC", "Got %u events", ebus_queue_size(&next->event_queue)); - if (ebus_pop(&next->event_queue, args->event_out)) { - KPANIC("Yea, that didn't work"); - } - has_event = 1; - } - // KLOGS_DEBUG("SC_PROC", "Switching from process %u to %u", proc->pid, next->pid); - if (pm_resume_process(kernel_get_proc_man(), next->pid, 0)) { + process_t * next = pm_get_next(kernel_get_proc_man()); + if (pm_resume_process(kernel_get_proc_man(), next->pid)) { KPANIC("Failed to resume process"); } - - // TODO return 1 for event out - // 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 has_event; } break; - case SYS_INT_PROC_EXEC: { + case SYS_CALL_PROC_EXEC: { struct _args { const char * filename; size_t argc; @@ -181,7 +152,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { return kernel_exec(args->filename, args->argc, args->argv); } break; - case SYS_INT_PROC_SET_FOREGROUND: { + case SYS_CALL_PROC_SET_FOREGROUND: { struct _args { int pid; } * args = (struct _args *)args_data; diff --git a/src/kernel/src/kernel/time.c b/src/kernel/src/kernel/time.c index 72d32fa6..931c57f7 100644 --- a/src/kernel/src/kernel/time.c +++ b/src/kernel/src/kernel/time.c @@ -1,3 +1,4 @@ +#define KLOG_SERVICE "KERNEL/TIME" #include "kernel/time.h" #include "cpu/isr.h" @@ -9,9 +10,6 @@ #include "libc/proc.h" #include "libc/stdio.h" -#undef SERVICE -#define SERVICE "KERNEL/TIME" - // https://wiki.osdev.org/PIT #define BASE_FREQ 1193180 @@ -29,6 +27,7 @@ static arr_t __timers; // timer_t static void timer_callback(registers_t * regs) { __tick++; + // TODO is this is way too much KLOG_TRACE("Timer callback, next tick is %u", __tick); for (int i = 0; i < arr_size(&__timers); i++) { @@ -73,12 +72,16 @@ void time_init(uint32_t freq) { } int time_start_timer(uint32_t ticks) { + if (!ticks) { + KLOG_TRACE("Tried to start a timer of 0 ticks"); + return 0; + } timer_t t; t.id = __next_id++; t.count = ticks; if (arr_insert(&__timers, arr_size(&__timers), &t)) { KLOG_ERROR("Failed to insert into timers array"); - return -1; + return 0; } KLOG_DEBUG("Starting timer %d of %u ticks", t.id, t.count); return t.id; @@ -88,6 +91,10 @@ int time_start_timer_ns(uint32_t ns) { return time_start_timer(ns * __freq / 1000000000); } +int time_start_timer_us(uint32_t us) { + return time_start_timer(us * __freq / 1000000); +} + int time_start_timer_ms(uint32_t ms) { return time_start_timer(ms * __freq / 1000); } diff --git a/src/kernel/src/loader.c b/src/kernel/src/loader.c index 4925ca85..bd64a039 100644 --- a/src/kernel/src/loader.c +++ b/src/kernel/src/loader.c @@ -4,6 +4,7 @@ * * Documentation moved to design/boot_stages.md */ +#define KLOG_SERVICE "LOADER" #include @@ -26,9 +27,6 @@ #include "process.h" #include "process_manager.h" -#undef SERVICE -#define SERVICE "LOADER" - void kernel_init(); static void map_kernel_table(mmu_table_t * table); @@ -47,7 +45,8 @@ void __start() { serial_init(SERIAL_PORT_COM1); _libc_config_file_write_call(device_serial_write_raw); - kernel_log_set_level(KERNEL_LOG_LEVEL_DEBUG); + // THIS WAS REPLACED WITH KLOG_LEVEL MACRO + // kernel_log_set_level(KERNEL_LOG_LEVEL_DEBUG); // kernel_log_set_level(KERNEL_LOG_LEVEL_TRACE); KLOG_INFO("Loader Start"); @@ -187,22 +186,69 @@ static void id_map_page(mmu_table_t * table, size_t page) { } static char * copy_string(const char * str) { + if (!str) { + KLOG_ERROR("Tried to copy null string"); + return 0; + } int len = kstrlen(str); char * new_str = kmalloc(len + 1); - kmemcpy(new_str, str, len + 1); + if (!new_str) { + KLOG_ERROR("Failed to malloc new string of length %d", len + 1); + return 0; + } + if (!kmemcpy(new_str, str, len + 1)) { + KLOG_ERROR("Failed to copy %u bytes in memory from %p to %p", len + 1, str, new_str); + return 0; + } return new_str; } -static int copy_args(process_t * proc, const char * filepath, int argc, const char ** argv) { - if (!proc || !filepath || !argv) { +static int copy_args(process_t * proc, const char * filepath, int argc, char ** argv) { + if (!proc) { + KLOG_ERROR("Tried to copy args for null process"); + return -1; + } + if (!filepath) { + KLOG_ERROR("Missing filepath"); + return -1; + } + if (argc && !argv) { + KLOG_ERROR("Missing argv"); return -1; } proc->filepath = copy_string(filepath); - proc->argc = argc; - proc->argv = kmalloc(sizeof(char *) * argc); + if (!proc->filepath) { + KLOG_ERROR("Failed to copy filepath"); + return -1; + } + proc->argc = argc + 1; + proc->argv = kmalloc(sizeof(char *) * (argc + 1)); + if (!proc->argv) { + KLOG_ERROR("Failed to malloc process_t argv"); + kfree(proc->filepath); + return -1; + } + + proc->argv[0] = copy_string(filepath); + if (!proc->argv[0]) { + KLOG_ERROR("Failed to copy filepath to argv"); + kfree(proc->argv); + kfree(proc->filepath); + return -1; + } + for (int i = 0; i < argc; i++) { - proc->argv[i] = copy_string(argv[i]); + proc->argv[i + 1] = copy_string(argv[i]); + if (!proc->argv[i + 1]) { + KLOG_ERROR("Failed to copy arg %d", i); + for (int j = 0; j < i + 1; j++) { + kfree(proc->argv[i]); + } + kfree(proc->argv); + kfree(proc->filepath); + return -1; + } } return 0; @@ -223,11 +269,12 @@ static void proc_entry() { } static process_t * load_init() { + // TODO use exec code or replace this with exec version of copy args const char * filename = "init"; tar_stat_t stat; if (!tar_stat_file(kernel_get_tar(), filename, &stat)) { - KLOGS_ERROR("init", "Failed to find file\n"); + KLOG_ERROR("Failed to find file\n"); return 0; } @@ -251,21 +298,24 @@ static process_t * load_init() { process_t * proc = kmalloc(sizeof(process_t)); if (process_create(proc)) { - KLOGS_ERROR("init", "Failed to create process\n"); + KLOG_ERROR("Failed to create process for %s", filename); return 0; } if (process_load_heap(proc, buff, stat.size)) { - KLOGS_ERROR("init", "Failed to load\n"); + KLOG_ERROR("Failed to load %s", filename); process_free(proc); return 0; } for (size_t i = 0; i < 1022; i++) { - process_grow_stack(proc); + if (process_grow_stack(proc)) { + KLOG_ERROR("Failed to grow process stack"); + return 0; + } } - copy_args(proc, filename, 1, &filename); + copy_args(proc, filename, 0, 0); process_set_entrypoint(proc, proc_entry); process_add_pages(proc, 32); diff --git a/src/kernel/src/paging.c b/src/kernel/src/paging.c index 830a8b6e..482b4e38 100644 --- a/src/kernel/src/paging.c +++ b/src/kernel/src/paging.c @@ -1,6 +1,9 @@ +#define KLOG_SERVICE "KERNEL/PAGING" + #include "paging.h" #include "drivers/ram.h" +#include "kernel/logs.h" #include "libc/string.h" typedef struct { @@ -10,15 +13,28 @@ typedef struct { static page_user_t __temp_pages[VADDR_TMP_PAGE_COUNT]; -void paging_init() { - kmemset(__temp_pages, 0, sizeof(__temp_pages)); +int paging_init() { + if (!kmemset(__temp_pages, 0, sizeof(__temp_pages))) { + KLOG_ERROR("Failed to clear temp pages array"); + return -1; + } + + KLOG_DEBUG("Paging initialized"); + return 0; } void * paging_temp_map(uint32_t paddr) { - if (!paddr || paddr & MASK_FLAGS) { + if (!paddr) { + KLOG_ERROR("Trying to map physical address 0"); + return 0; + } + if (paddr & MASK_FLAGS) { + KLOG_ERROR("Trying to map misaligned physical address %p", paddr); return 0; } + KLOG_TRACE("Map temporary page for physical address %p", paddr); + // Return one if already exists for (size_t i = 0; i < VADDR_TMP_PAGE_COUNT; i++) { if (__temp_pages[i].addr == paddr) { @@ -38,7 +54,13 @@ void * paging_temp_map(uint32_t paddr) { mmu_table_t * table = (mmu_table_t *)VADDR_KERNEL_TABLE; uint32_t vaddr = PAGE2ADDR(table_i); - mmu_table_set(table, table_i, paddr, MMU_TABLE_RW); + + KLOG_TRACE("Mapping physical address %p to table index %u virtual address %p", paddr, table_i, vaddr); + + if (mmu_table_set(table, table_i, paddr, MMU_TABLE_RW)) { + KLOG_ERROR("Failed to set mmu table index %u to physical address %p", table_i, paddr); + return 0; + } mmu_flush_tlb(vaddr); return UINT2PTR(vaddr); } @@ -47,22 +69,37 @@ void * paging_temp_map(uint32_t paddr) { return 0; } -void paging_temp_free(uint32_t paddr) { - if (!paddr || paddr & MASK_FLAGS) { - return; +int paging_temp_free(uint32_t paddr) { + if (!paddr) { + KLOG_ERROR("Trying to free physical address 0"); + return -1; } + if (paddr & MASK_FLAGS) { + KLOG_ERROR("Trying to free misaligned physical address %p", paddr); + return -1; + } + + KLOG_TRACE("Free temporary page for physical address %p", paddr); for (size_t i = 0; i < VADDR_TMP_PAGE_COUNT; i++) { if (__temp_pages[i].addr == paddr) { - if (__temp_pages[i].count < 1) { - return; + if (!__temp_pages[i].count) { + KLOG_ERROR("Trying to free temp page %u which has count 0", i); + return -1; } __temp_pages[i].count--; - break; + uint32_t vaddr = PAGE2ADDR(i); + KLOG_TRACE("Freed temporary page %u with virtual address %p from physical address %p", i, vaddr, paddr); + + return 0; } } + + KLOG_ERROR("Failed to find mapping for physical address %u", paddr); + + return -1; } size_t paging_temp_available() { @@ -78,8 +115,14 @@ size_t paging_temp_available() { } int paging_id_map_range(size_t start, size_t end) { + if (start > end) { + KLOG_WARNING("Trying to map range with start %u after end %u", start, end); + return -1; + } + while (start <= end) { if (paging_id_map_page(start++)) { + // Error logged in paging_id_map_page return -1; } } @@ -89,6 +132,7 @@ int paging_id_map_range(size_t start, size_t end) { int paging_id_map_page(size_t page) { if (page >= MMU_TABLE_SIZE) { + KLOG_ERROR("Failed to identity map page %u", page); return -1; } @@ -100,16 +144,18 @@ int paging_id_map_page(size_t page) { int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { if (!dir) { + KLOG_ERROR("Trying to add page to null directory"); return -1; } - if (start > end) { - return 0; + KLOG_WARNING("Trying to add pages for range with start %u after end %u", start, end); + return -1; } uint32_t table_end = end / MMU_TABLE_SIZE; if (table_end >= MMU_DIR_SIZE) { + KLOG_WARNING("End %u is after last table end %u", end, MMU_DIR_SIZE * MMU_TABLE_SIZE); return -1; } @@ -118,7 +164,9 @@ int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { uint32_t addr = ram_page_alloc(); if (!addr) { - paging_remove_pages(dir, start, page_i - 1); + if (paging_remove_pages(dir, start, page_i - 1)) { + KLOG_ERROR("Failed to remove page from directory"); + } return -1; } @@ -128,8 +176,12 @@ int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { // Add table if needed if (!(mmu_dir_get_flags(dir, dir_i) & MMU_DIR_FLAG_PRESENT)) { if (paging_add_table(dir, dir_i)) { - paging_remove_pages(dir, start, page_i - 1); - ram_page_free(addr); + if (paging_remove_pages(dir, start, page_i - 1)) { + KLOG_ERROR("Failed to remove page from directory %p", dir); + } + if (ram_page_free(addr)) { + KLOG_ERROR("Failed to free ram page"); + } return -1; } } @@ -139,14 +191,25 @@ int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { mmu_table_t * table = paging_temp_map(table_addr); if (!table) { - paging_remove_pages(dir, start, page_i - 1); - paging_temp_free(table_addr); - ram_page_free(addr); + KLOG_ERROR("Failed to create temporary map for %p", table_addr); + if (paging_remove_pages(dir, start, page_i - 1)) { + KLOG_ERROR("Failed to remove page from directory %p", dir); + } + if (ram_page_free(addr)) { + KLOG_ERROR("Failed to free ram page"); + } return -1; } - mmu_table_set(table, table_i, addr, MMU_TABLE_RW); - paging_temp_free(table_addr); + // TODO should either be panic or log error and return? + if (mmu_table_set(table, table_i, addr, MMU_TABLE_RW)) { + KLOG_ERROR("Failed to set page table %p index %u to physical address %p", table, table_i, addr); + return -1; + } + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary page"); + return -1; + } } return 0; @@ -154,16 +217,18 @@ int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { int paging_remove_pages(mmu_dir_t * dir, size_t start, size_t end) { if (!dir) { + KLOG_ERROR("Trying to remove page from null directory"); return -1; } - if (start > end) { - return 0; + KLOG_WARNING("Trying to remove pages for range with start %u after end %u", start, end); + return -1; } uint32_t table_end = end / MMU_TABLE_SIZE; if (table_end >= MMU_DIR_SIZE) { + KLOG_WARNING("End %u is after last table end %u", end, MMU_TABLE_SIZE); return -1; } @@ -182,6 +247,7 @@ int paging_remove_pages(mmu_dir_t * dir, size_t start, size_t end) { mmu_table_t * table = paging_temp_map(table_addr); if (!table) { + KLOG_ERROR("Failed to create temporary map for %p", table_addr); return -1; } @@ -192,17 +258,32 @@ int paging_remove_pages(mmu_dir_t * dir, size_t start, size_t end) { uint32_t page_addr = mmu_table_get_addr(table, table_i); - mmu_table_set(table, table_i, 0, 0); + // TODO should either be panic or log error and return? + if (mmu_table_set(table, table_i, 0, 0)) { + KLOG_ERROR("Failed to clear page table %p index %u", table, table_i); + return -1; + } mmu_flush_tlb(PAGE2ADDR(page_i)); - ram_page_free(page_addr); - paging_temp_free(table_addr); + if (ram_page_free(page_addr)) { + KLOG_ERROR("Failed to free ram page"); + return -1; + } + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary mapping for table %p", table_addr); + return -1; + } } return 0; } int paging_add_table(mmu_dir_t * dir, size_t dir_i) { - if (!dir || dir_i >= MMU_DIR_SIZE) { + if (!dir) { + KLOG_ERROR("Trying to add table to null directory"); + return -1; + } + if (dir_i >= MMU_DIR_SIZE) { + KLOG_ERROR("Directory index %u is past directory end %p", dir_i, MMU_DIR_SIZE); return -1; } @@ -216,12 +297,20 @@ int paging_add_table(mmu_dir_t * dir, size_t dir_i) { mmu_table_t * table = paging_temp_map(addr); if (!table) { - ram_page_free(addr); + if (ram_page_free(addr)) { + KLOG_ERROR("Failed to free ram page"); + } return -1; } mmu_table_clear(table); - mmu_dir_set(dir, dir_i, addr, MMU_DIR_RW); + if (mmu_dir_set(dir, dir_i, addr, MMU_DIR_RW)) { + KLOG_ERROR("Failed to set page directory %p index %u to physical address %p", dir, dir_i, addr); + if (paging_temp_free(addr)) { + KLOG_ERROR("Failed to free temporary page"); + } + return -1; + } paging_temp_free(addr); } @@ -230,14 +319,28 @@ int paging_add_table(mmu_dir_t * dir, size_t dir_i) { } int paging_remove_table(mmu_dir_t * dir, size_t dir_i) { - if (!dir || dir_i >= MMU_DIR_SIZE) { + if (!dir) { + KLOG_ERROR("Trying to remove table from null directory"); + return -1; + } + if (dir_i >= MMU_DIR_SIZE) { + KLOG_ERROR("Directory index %u is past directory end %p", dir_i, MMU_DIR_SIZE); return -1; } if (mmu_dir_get_flags(dir, dir_i) & MMU_DIR_FLAG_PRESENT) { uint32_t addr = mmu_dir_get_addr(dir, dir_i); - mmu_dir_set(dir, dir_i, 0, 0); - ram_page_free(addr); + if (!addr) { + KLOG_ERROR("Failed to get address of table %u from directory %p", dir_i, dir); + return -1; + } + if (mmu_dir_set(dir, dir_i, 0, 0)) { + KLOG_ERROR("Failed to clear table %u from directory %p", dir_i, dir); + return -1; + } + if (ram_page_free(addr)) { + KLOG_ERROR("Failed to free ram page"); + } } return 0; diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 1f9fe9d9..6a24f2e0 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "KERNEL/PROCESS" + #include "process.h" #include "cpu/mmu.h" @@ -18,14 +20,19 @@ static uint32_t next_handle_id(); int process_create(process_t * proc) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); return -1; } - kmemset(proc, 0, sizeof(process_t)); + if (!kmemset(proc, 0, sizeof(process_t))) { + KLOG_ERROR("Failed to clear process struct"); + return -1; + } proc->cr3 = ram_page_alloc(); if (!proc->cr3) { + KLOG_ERROR("Failed to allocate ram page for process page directory"); return -1; } @@ -33,21 +40,33 @@ int process_create(process_t * proc) { mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { - ram_page_free(proc->cr3); + KLOG_ERROR("Failed to create temporary mapping for physical address %p", proc->cr3); + if (ram_page_free(proc->cr3)) { + KLOG_ERROR("Failed to free ram page %p for process page directory", proc->cr3); + } return -1; } uint32_t kernel_table_addr = mmu_dir_get_addr((mmu_dir_t *)VADDR_KERNEL_DIR, 0); + if (!kernel_table_addr) { + KLOG_ERROR("Failed to get physical address of kernel table"); + return -1; + } // Copy first page table from kernel page directory mmu_dir_clear(dir); - mmu_dir_set(dir, 0, kernel_table_addr, MMU_DIR_RW); + if (mmu_dir_set(dir, 0, kernel_table_addr, MMU_DIR_RW)) { + KLOG_ERROR("Failed to set kernel table address in process page directory %p", dir); + return -1; + } proc->esp = VADDR_USER_STACK; proc->esp0 = VADDR_ISR_STACK; // Allocate pages for ISR stack + first page of user stack if (paging_add_pages(dir, ADDR2PAGE(proc->esp), ADDR2PAGE(proc->esp0))) { + KLOG_ERROR("Failed to create pages for isr and user stacks"); + // Error logged in function, not logging here because we are already returning error paging_temp_free(proc->cr3); ram_page_free(proc->cr3); return -1; @@ -57,21 +76,30 @@ int process_create(process_t * proc) { proc->next_heap_page = ADDR2PAGE(VADDR_USER_MEM); proc->stack_page_count = 1; - paging_temp_free(proc->cr3); + // TODO parent process pid - if (arr_create(&proc->io_handles, 4, sizeof(handle_t))) { + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary page"); ram_page_free(proc->cr3); return -1; } - if (ebus_create(&proc->event_queue, 4096)) { - arr_free(&proc->io_handles); + if (arr_create(&proc->io_handles, 4, sizeof(handle_t))) { + KLOG_ERROR("Failed to create array for io handles"); ram_page_free(proc->cr3); return -1; } + // if (ebus_create(&proc->event_queue, 4096)) { + // KLOG_ERROR("Failed to create ebus for process event queue"); + // arr_free(&proc->io_handles); + // ram_page_free(proc->cr3); + // return -1; + // } + if (memory_init(&proc->memory, kernel_alloc_page)) { - ebus_free(&proc->event_queue); + KLOG_ERROR("Failed to initialize malloc for process"); + // ebus_free(&proc->event_queue); arr_free(&proc->io_handles); ram_page_free(proc->cr3); return -1; @@ -79,14 +107,16 @@ int process_create(process_t * proc) { proc->io_buffer = io_buffer_create(IO_BUFFER_SIZE); if (!proc->io_buffer) { - ebus_free(&proc->event_queue); + KLOG_ERROR("Failed to create io buffer"); + // ebus_free(&proc->event_queue); arr_free(&proc->io_handles); ram_page_free(proc->cr3); return -1; } if (open_stdio_handles(proc)) { - ebus_free(&proc->event_queue); + KLOG_ERROR("Failed to open stdio handles"); + // ebus_free(&proc->event_queue); arr_free(&proc->io_handles); ram_page_free(proc->cr3); io_buffer_free(proc->io_buffer); @@ -98,15 +128,17 @@ int process_create(process_t * proc) { int process_free(process_t * proc) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); return -1; } - ebus_free(&proc->event_queue); + // ebus_free(&proc->event_queue); arr_free(&proc->io_handles); mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to create temporary mapping for process pageing directory"); return -1; } @@ -120,6 +152,7 @@ int process_free(process_t * proc) { mmu_table_t * table = paging_temp_map(table_addr); if (!table) { + KLOG_ERROR("Failed to create temporary mapping for process page table"); paging_temp_free(proc->cr3); ram_page_free(proc->cr3); return -1; @@ -133,19 +166,40 @@ int process_free(process_t * proc) { } } - paging_temp_free(table_addr); - ram_page_free(table_addr); + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary map of process page table"); + return -1; + } + if (ram_page_free(table_addr)) { + KLOG_ERROR("Failed to free ram page for process page table"); + return -1; + } } // Free dir - paging_temp_free(proc->cr3); - ram_page_free(proc->cr3); + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary map of process page directory"); + return -1; + } + if (ram_page_free(proc->cr3)) { + KLOG_ERROR("Failed to free ram page for process page directory"); + return -1; + } return 0; } int process_set_entrypoint(process_t * proc, void * entrypoint) { - if (!proc || !entrypoint || proc->state >= PROCESS_STATE_SUSPENDED) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!entrypoint) { + KLOG_ERROR("Entrypoint is null pointer"); + return -1; + } + if (proc->state >= PROCESS_STATE_SUSPENDED) { + KLOG_ERROR("Process already started"); return -1; } @@ -157,23 +211,37 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to create temporary map for process page directory"); return -1; } uint32_t table_addr = mmu_dir_get_addr(dir, dir_i); + if (!table_addr) { + KLOG_ERROR("Failed to get physical address of process page directory"); + paging_temp_free(proc->cr3); + return -1; + } mmu_table_t * table = paging_temp_map(table_addr); if (!table) { + KLOG_ERROR("Failed to create temporary map for process page table"); paging_temp_free(proc->cr3); return -1; } uint32_t page_addr = mmu_table_get_addr(table, table_i); + if (!table_addr) { + KLOG_ERROR("Failed to get physical address of process page"); + paging_temp_free(table_addr); + paging_temp_free(proc->cr3); + return -1; + } uint32_t * stack = paging_temp_map(page_addr); if (!stack) { + KLOG_ERROR("Failed to create temporary map for process stack page"); paging_temp_free(table_addr); paging_temp_free(proc->cr3); return -1; @@ -182,9 +250,18 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { 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); + if (paging_temp_free(page_addr)) { + KLOG_ERROR("Failed to free temporary map for process stack page"); + return -1; + } + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary map for process page table"); + return -1; + } + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary map for process page directory"); + return -1; + } proc->esp -= (5 * 4) - 1; @@ -192,7 +269,16 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { } int process_resume(process_t * proc, const ebus_event_t * event) { - if (!proc || proc->state < PROCESS_STATE_LOADED || proc->state >= PROCESS_STATE_DEAD) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (proc->state < PROCESS_STATE_LOADED) { + KLOG_ERROR("Process not yet loaded"); + return -1; + } + if (proc->state >= PROCESS_STATE_DEAD) { + KLOG_ERROR("Process is dead"); return -1; } @@ -200,9 +286,20 @@ int process_resume(process_t * proc, const ebus_event_t * event) { if (!active_before) { KPANIC("Failed to find active task"); } - active_before->state = PROCESS_STATE_SUSPENDED; + + if (active_before->state == PROCESS_STATE_RUNNING) { + KLOG_TRACE("Setting state of active process %u to suspended", active_before->pid); + active_before->state = PROCESS_STATE_SUSPENDED; + } + else { + KLOG_TRACE("Skip updating active process %u status because it's not running, got %u", active_before->pid, active_before->state); + } + + KLOG_TRACE("Setting process state for pid %u to SUSPENDED", active_before->pid); proc->state = PROCESS_STATE_RUNNING; + KLOG_TRACE("Setting process state for pid %u to RUNNING", proc->pid); + switch_task(proc); // Call this again because we are a new process now @@ -213,26 +310,37 @@ int process_resume(process_t * proc, const ebus_event_t * event) { } void * process_add_pages(process_t * proc, size_t count) { - if (!proc || !count) { + if (!proc) { + KLOG_ERROR("Tried to add page to null process"); + return 0; + } + if (!count) { + KLOG_WARNING("Add page count is 0"); return 0; } if (proc->next_heap_page + count >= MMU_DIR_SIZE * MMU_TABLE_SIZE) { + KLOG_ERROR("Cannot allocate %u pages after %u, will exceed max size of %d", count, proc->next_heap_page, MMU_DIR_SIZE * MMU_TABLE_SIZE); return 0; } mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to map a temporary page for pid %u page dir", proc->pid); return 0; } if (paging_add_pages(dir, proc->next_heap_page, proc->next_heap_page + count)) { + KLOG_ERROR("Failed to add %u pages to pid %u", count, proc->pid); paging_temp_free(proc->cr3); return 0; } - paging_temp_free(proc->cr3); + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary page for process page directory"); + return 0; + } void * ptr = UINT2PTR(PAGE2ADDR(proc->next_heap_page)); proc->next_heap_page += count; @@ -242,38 +350,55 @@ void * process_add_pages(process_t * proc, size_t count) { int process_grow_stack(process_t * proc) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); return -1; } mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to create temporary map of process page directory"); return -1; } size_t new_stack_page_i = MMU_DIR_SIZE * MMU_TABLE_SIZE - proc->stack_page_count - 1; if (paging_add_pages(dir, new_stack_page_i, new_stack_page_i)) { + KLOG_ERROR("Failed to add pages fo process stack"); paging_temp_free(proc->cr3); return -1; } - proc->stack_page_count--; + proc->stack_page_count++; - paging_temp_free(proc->cr3); + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary map of process page dir"); + return -1; + } return 0; } int process_load_heap(process_t * proc, const char * buff, size_t size) { - if (!proc || !buff || !size) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!buff) { + KLOG_ERROR("Trying to load heap from null buffer"); + return -1; + } + if (!size) { + KLOG_ERROR("Trying to load empty buffer"); return -1; } + KLOG_TRACE("Setting process pid %u state to LOADING", proc->pid); proc->state = PROCESS_STATE_LOADING; size_t page_count = ADDR2PAGE(size); if (size & MASK_FLAGS) { + KLOG_TRACE("Increasing page count by 1 to align with page boundary"); page_count++; } @@ -281,28 +406,43 @@ int process_load_heap(process_t * proc, const char * buff, size_t size) { void * heap_alloc = process_add_pages(proc, page_count); if (!heap_alloc) { + KLOG_ERROR("Failed to allocate pages for process pid %u heap", proc->pid); return -1; } mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to create temporary mapping of process page directory"); return -1; } for (size_t i = 0; i < page_count; i++) { - uint32_t table_addr = mmu_dir_get_addr(dir, (heap_start + i) / MMU_TABLE_SIZE); - mmu_table_t * table = paging_temp_map(table_addr); + uint32_t table_addr = mmu_dir_get_addr(dir, (heap_start + i) / MMU_TABLE_SIZE); + if (!table_addr) { + KLOG_ERROR("Failed to get physical address of process pid %u page table", proc->pid); + paging_temp_free(proc->cr3); + return -1; + } + mmu_table_t * table = paging_temp_map(table_addr); if (!table) { + KLOG_ERROR("Failed to create temporary mapping of process pid %u page table %p", proc->pid, table_addr); paging_temp_free(proc->cr3); return -1; } - uint32_t addr = mmu_table_get_addr(table, (heap_start + i) % MMU_TABLE_SIZE); - void * tmp_page = paging_temp_map(addr); + uint32_t addr = mmu_table_get_addr(table, (heap_start + i) % MMU_TABLE_SIZE); + if (!table_addr) { + KLOG_ERROR("Failed to get physical address of process pid %u page table", proc->pid); + paging_temp_free(table_addr); + paging_temp_free(proc->cr3); + return -1; + } + void * tmp_page = paging_temp_map(addr); if (!tmp_page) { + KLOG_ERROR("Failed to create temporary map of process pid %u page %p", proc->pid, addr); paging_temp_free(table_addr); paging_temp_free(proc->cr3); return -1; @@ -316,19 +456,34 @@ int process_load_heap(process_t * proc, const char * buff, size_t size) { kmemcpy(tmp_page, &buff[i * PAGE_SIZE], to_copy); - paging_temp_free(addr); - paging_temp_free(table_addr); + if (paging_temp_free(addr)) { + KLOG_ERROR("Failed to free temporary map of process pid %u page"); + return -1; + } + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary map of process pid %u page table"); + return -1; + } } - paging_temp_free(proc->cr3); + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary map of process pid %u page directory"); + return -1; + } + KLOG_TRACE("Setting process pid %u state to LOADED", proc->pid); proc->state = PROCESS_STATE_LOADED; return 0; } handle_t * process_get_handle(process_t * proc, int id) { - if (!proc || id < 0) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return 0; + } + if (id < 0) { + KLOG_ERROR("id must be >= 0, got %d", id); return 0; } @@ -340,11 +495,18 @@ handle_t * process_get_handle(process_t * proc, int id) { } } + KLOG_ERROR("Failed to find handle %d for process pid %u", id, proc->pid); + return 0; } int process_add_handle(process_t * proc, int id, int flags, io_device_t * device) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!device) { + KLOG_ERROR("Devices is a null pointer"); return -1; } @@ -359,7 +521,7 @@ int process_add_handle(process_t * proc, int id, int flags, io_device_t * device }; if (arr_insert(&proc->io_handles, arr_size(&proc->io_handles), &h)) { - KLOGS_ERROR("process", "Could not add new handle to process"); + KLOG_ERROR("Could not add new handle to process"); return -1; } @@ -368,6 +530,7 @@ int process_add_handle(process_t * proc, int id, int flags, io_device_t * device static int open_stdio_handles(process_t * proc) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); return -1; } @@ -375,14 +538,14 @@ static int open_stdio_handles(process_t * proc) { // process_add_handle returns handle id if (process_add_handle(proc, 1, DEVICE_IO_FLAG_WRITE, device_screen_open()) < 0) { - KLOGS_ERROR("process", "Failed to create stdout handle"); + KLOG_ERROR("Failed to create stdout handle"); return -1; } handle_t * h = arr_at(&proc->io_handles, 0); if (process_add_handle(proc, 2, DEVICE_IO_FLAG_WRITE, device_screen_open()) < 0) { - KLOGS_ERROR("process", "Failed to create stderr handle"); + KLOG_ERROR("Failed to create stderr handle"); return -1; } @@ -393,6 +556,48 @@ static int open_stdio_handles(process_t * proc) { return 0; } +int process_link(process_t * proc, process_t * next) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!next) { + KLOG_ERROR("Next process struct is null pointer"); + return -1; + } + if (proc->next && proc->next->prev != proc) { + KLOG_ERROR("proc has a bad link, next does not link back to proc"); + return -1; + } + + next->prev = proc; + next->next = proc->next; + + proc->next->prev = next; + proc->next = next; + + return 0; +} + +int process_unlink(process_t * proc) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!proc->prev || !proc->next) { + KLOG_ERROR("Process struct is not linked"); + return -1; + } + + proc->prev->next = proc->next; + proc->next->prev = proc->prev; + + proc->next = 0; + proc->prev = 0; + + return 0; +} + static uint32_t __pid; static uint32_t next_pid() { diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 0d4c1140..7f4bf13d 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -1,3 +1,6 @@ +#define KLOG_SERVICE "KERNEL/PROCESS_MANAGER" +// #define KLOG_LEVEL KLOG_LEVEL_TRACE + #include "process_manager.h" #include "drivers/keyboard.h" @@ -7,16 +10,14 @@ #include "libc/stdio.h" #include "libc/string.h" -static int pid_arr_index(arr_t * arr, int pid); - int pm_create(proc_man_t * pm) { if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); return -1; } - kmemset(pm, 0, sizeof(proc_man_t)); - - if (arr_create(&pm->task_list, 4, sizeof(process_t *))) { + if (!kmemset(pm, 0, sizeof(proc_man_t))) { + KLOG_ERROR("Failed to clear process manager struct"); return -1; } @@ -24,200 +25,250 @@ int pm_create(proc_man_t * pm) { } process_t * pm_find_pid(proc_man_t * pm, int pid) { - if (!pm || pid < 0) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); return 0; } - - int i = pid_arr_index(&pm->task_list, pid); - if (i < 0) { + if (pid < 0) { + KLOG_WARNING("Find takes a pid >= 0, got %d", pid); return 0; } + if (!pm->first_task) { + KLOG_WARNING("No processes exist in process manager, can't find pid %d", pid); + return 0; + } + + if (pm->foreground_task && pm->foreground_task->pid == pid) { + return pm->foreground_task; + } + + process_t * proc = pm->first_task; + if (proc->pid == pid) { + return proc; + } - process_t * proc; - arr_get(&pm->task_list, i, &proc); + do { + if (proc->pid == pid) { + return proc; + } - return proc; + proc = proc->next; + } while (proc != pm->first_task); + + return 0; } int pm_add_proc(proc_man_t * pm, process_t * proc) { - if (!pm || !proc) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); return -1; } - - if (arr_insert(&pm->task_list, arr_size(&pm->task_list), &proc)) { + if (!proc) { + KLOG_ERROR("Process struct is a null pointer"); return -1; } + if (!pm->first_task) { + KLOG_INFO("Assigning first process to be %u", proc->pid); + pm->first_task = proc; + pm->foreground_task = proc; + + // Link to self + proc->next = proc; + proc->prev = proc; + return 0; + } + + if (pm_find_pid(pm, proc->pid)) { + KLOG_WARNING("Tried to add process %u to manager, already added", proc->pid); + return 0; + } + + process_t * prev = pm->first_task->prev; + KLOG_TRACE("Using process %u as previous to first task %u", prev->pid, pm->first_task->pid); + + prev->next = proc; + pm->first_task->prev = proc; + + proc->next = pm->first_task; + proc->prev = prev; + + process_t * p = pm->first_task; + do { + KLOG_TRACE("Link %u n %u p %u", p->pid, p->next->pid, p->prev->pid); + p = p->next; + } while (p != pm->first_task); return 0; } int pm_remove_proc(proc_man_t * pm, int pid) { - if (!pm || pid < 0) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); + return -1; + } + if (pid < 0) { + KLOG_WARNING("Remove process takes a pid >= 0, got %d", pid); return -1; } if (pid == get_active_task()->pid) { + KLOG_ERROR("Trying to remove active task pid %d", pid); return -1; } - int i = pid_arr_index(&pm->task_list, pid); - if (i < 0 || arr_remove(&pm->task_list, i, 0)) { + process_t * proc = pm_find_pid(pm, pid); + if (!proc) { + KLOG_ERROR("Failed to find process for pid %u", pid); + return -1; + } + + if (proc == pm->first_task) { + KLOG_ERROR("Cannot remove first process"); + return -1; + } + + if (proc == pm->foreground_task) { + KLOG_ERROR("Cannot remove foreground process"); return -1; } - return -1; + return process_unlink(proc); } int pm_set_foreground_proc(proc_man_t * pm, int pid) { - if (!pm || pid < 0) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); + return -1; + } + if (pid < 0) { + KLOG_WARNING("Set foreground process takes a pid >= 0, got %d", pid); return -1; } process_t * proc = pm_find_pid(pm, pid); if (!proc) { + KLOG_ERROR("Failed to find process for pid %d", pid); return -1; } pm->foreground_task = proc; - return -1; + return 0; } -int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { +int pm_resume_process(proc_man_t * pm, int pid) { if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); + return -1; + } + if (pid < 0) { + KLOG_WARNING("Set foreground process takes a pid >= 0, got %d", pid); return -1; } + // TODO event is not used process_t * proc = pm_find_pid(pm, pid); if (!proc) { + KLOG_ERROR("Failed to find process for pid %d", pid); return -1; } - return process_resume(proc, event); + if (proc->filter_event.event_id) { + // TODO assert next_event has an event of the correct type + // TODO push to process next_event instead of event_queue + // TODO clear next_event before resuming process + // TODO does process state need updating? - probably not + } + + return process_resume(proc, 0); } process_t * pm_get_next(proc_man_t * pm) { if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); 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; - } + process_t * proc = pm->foreground_task->next; - KLOGS_TRACE("pm", "PID %u is state %x", proc->pid, proc->state); + // KLOG_TRACE("Start looking for next process"); - // if (proc->state == PROCESS_STATE_WAITING_STDIN) { - // KLOGS_DEBUG("pm", "Process waiting for stdin"); - // if (io_buffer_length(proc->io_buffer) > 0) { - // KLOGS_DEBUG("pm", "Process is waiting for stdin and has %u ready", io_buffer_length(proc->io_buffer)); - // return proc; - // } - // } + do { + // KLOG_TRACE("Looking at pid %u in state %u to see if it's ready", proc->pid, proc->state); - if (proc->state == PROCESS_STATE_WAITING && ebus_queue_size(&proc->event_queue) > 0) { - ebus_event_t event; - if (ebus_peek(&proc->event_queue, &event) > 0) { - proc->state = PROCESS_STATE_SUSPENDED; + if (PROCESS_STATE_LOADED <= proc->state <= PROCESS_STATE_DEAD) { + if (!proc->filter_event.event_id) { + // KLOG_TRACE("Process %u has no filter event, so it's ready", proc->pid); + return proc; + } + // This handles the above case but is split for trace log + if (proc->filter_event.event_id == proc->next_event.event_id) { + KLOG_TRACE("Process %u has ready event %u", proc->pid, proc->next_event.event_id); + return proc; } + // KLOG_TRACE("Process %u is not ready, waiting for %u", proc->pid, proc->filter_event.event_id); } - - if (proc->state == PROCESS_STATE_LOADED || proc->state == PROCESS_STATE_SUSPENDED || proc->state == PROCESS_STATE_RUNNING) { - return proc; + else { + // KLOG_TRACE("Process with pid %u is not alive", proc->pid); } - i++; - } + // KLOG_TRACE("Going to next process %u, fg is %u", proc->next->pid, pm->foreground_task->pid); + proc = proc->next; + } while (proc != pm->foreground_task->next); - process_t * active = get_active_task(); - if (PROCESS_STATE_LOADED <= active->state <= PROCESS_STATE_DEAD) { - return active; - } + // KLOG_TRACE("Finish looking for next process"); - KPANIC("Process Loop!"); + if (PROCESS_STATE_LOADED <= proc->state <= PROCESS_STATE_DEAD) { + // KLOG_TRACE("Next process is the foreground process with pid %u", proc->pid); + return proc; + } - return 0; + KPANIC("Could not find process to resume"); } -static int pid_arr_index(arr_t * arr, int pid) { - if (!arr) { +int pm_push_event(proc_man_t * pm, ebus_event_t * event) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); 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; - } + if (!event) { + KLOG_ERROR("Event is a null pointer"); + return -1; } - - return -1; -} - -int pm_push_event(proc_man_t * pm, ebus_event_t * event) { - if (!pm || !event) { + if (!event->event_id) { + KLOG_ERROR("Event id must be non-zero"); return -1; } - if (event->event_id = EBUS_EVENT_KEY) { - process_t * foreground = pm->foreground_task; + KLOG_TRACE("Start push event %u", event->event_id); - KLOGS_TRACE("pm", "Foreground is %u", foreground->pid); + process_t * proc = pm->first_task; - // if (event->key.event == KEY_EVENT_PRESS) { - // if (io_buffer_push(foreground->io_buffer, event->key.c)) { - // KLOGS_WARNING("pm", "Failed to push key into io buffer"); - // return -1; - // } - // KLOGS_TRACE("pm", "IO buffer is size %u", io_buffer_length(foreground->io_buffer)); - // } - - if (ebus_push(&foreground->event_queue, event)) { - return -1; - } - } - else { - process_t * active = get_active_task(); - - for (size_t i = 0; i < arr_size(&pm->task_list); i++) { - process_t * proc; - arr_get(&pm->task_list, i, &proc); - - if (proc->pid == active->pid) { - continue; + do { + if (proc->filter_event.event_id == event->event_id) { + KLOG_TRACE("Push event %u to %u", event->event_id, proc->pid); + if (proc->next_event.event_id) { + KLOG_WARNING("Replacing event %u with %u for process %u", proc->next_event.event_id, event->event_id, proc->pid); } + kmemcpy(&proc->next_event, event, sizeof(ebus_event_t)); - if (proc->state <= PROCESS_STATE_LOADED || proc->state >= PROCESS_STATE_DEAD) { - continue; + if (event->event_id == EBUS_EVENT_KEY) { + KLOG_TRACE("Push scancode 0x%x results in 0x%x", event->key.scancode, proc->next_event.key.scancode); } - if (proc->filter_event == event->event_id) { - KLOGS_DEBUG("pm", "Process %u was waiting for %u and got it", proc->pid, proc->filter_event); - if (ebus_push(&proc->event_queue, event)) { - return -1; - } - - if (proc->state == PROCESS_STATE_WAITING) { - proc->state = PROCESS_STATE_SUSPENDED; - } + if (proc->state == PROCESS_STATE_WAITING) { + KLOG_TRACE("Setting process state to suspended for pid %u", proc->pid); + proc->state = PROCESS_STATE_SUSPENDED; } } - } + else { + KLOG_TRACE("Event %u did not match pid %u waiting on %u", event->event_id, proc->pid, proc->filter_event.event_id); + } + + proc = proc->next; + } while (proc != pm->first_task); + + KLOG_TRACE("Finish push event %u", event->event_id); + return 0; } diff --git a/src/kernel/src/system_call.c b/src/kernel/src/system_call.c index c393634b..8f65020e 100644 --- a/src/kernel/src/system_call.c +++ b/src/kernel/src/system_call.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SYSCALL" + #include "system_call.h" #include "cpu/isr.h" @@ -11,9 +13,6 @@ #include "libk/defs.h" #include "process.h" -#undef SERVICE -#define SERVICE "SYSCALL" - #define MAX_CALLBACKS 0x100 static sys_call_handler_t __callbacks[MAX_CALLBACKS]; @@ -30,7 +29,7 @@ void system_call_init(uint8_t isr_interrupt_no) { KLOG_DEBUG("Initialized system calls"); } -void system_call_register(uint8_t family, sys_call_handler_t handler) { +void system_call_register(uint16_t family, sys_call_handler_t handler) { KLOG_DEBUG("Registering handler for family 0x%02X", family); if (family >= MAX_CALLBACKS) { KLOG_ERROR("Cannot register handler for family 0x%02X, must be < 0x%X", family, MAX_CALLBACKS); @@ -42,12 +41,14 @@ void system_call_register(uint8_t family, sys_call_handler_t handler) { static void callback(registers_t * regs) { uint32_t res = 0; - uint16_t int_no = regs->eax & 0xffff; - uint8_t family = (regs->eax >> 8) & 0xff; + uint32_t call_id = regs->eax; + uint16_t family = (regs->eax >> 16); + + KLOG_TRACE("Received system call 0x%X", call_id); // if (family != 0x01 && family != 0x10) { // process_t * proc = get_current_process(); - // KLOG_DEBUG("Got system call 0x%04x from PID %u", (int)int_no, proc->pid); + // KLOG_DEBUG("Got system call 0x%04x from PID %u", (int)call_id, proc->pid); // } void * args_data = UINT2PTR(regs->ebx); @@ -55,10 +56,10 @@ static void callback(registers_t * regs) { sys_call_handler_t handler = __callbacks[family]; if (handler) { - res = handler(int_no, args_data, regs); + res = handler(call_id, args_data, regs); } else { - KLOG_ERROR("Failed to find handler for interrupt 0x%04X", int_no); + KLOG_ERROR("Failed to find handler for system call 0x%04X", call_id); PANIC("UNKNOWN INTERRUPT"); } diff --git a/src/libc/include/libc/time.h b/src/libc/include/libc/time.h new file mode 100644 index 00000000..c0c54d3a --- /dev/null +++ b/src/libc/include/libc/time.h @@ -0,0 +1,10 @@ +#ifndef LIBC_TIME_H +#define LIBC_TIME_H + +#include + +size_t time(void); +void sleep(size_t ms); +void usleep(size_t us); + +#endif // LIBC_TIME_H diff --git a/src/libc/src/proc.c b/src/libc/src/proc.c index 935fd90f..9a6b155b 100644 --- a/src/libc/src/proc.c +++ b/src/libc/src/proc.c @@ -21,11 +21,11 @@ void queue_event(ebus_event_t * event) { } int pull_event(int filter, ebus_event_t * event_out) { - return _sys_yield(filter, event_out); + return _sys_event_pull(filter, event_out); } void yield() { - _sys_yield(0, 0); + _sys_yield(); } int proc_open(const char * filename, size_t argc, char ** argv) { diff --git a/src/libc/src/time.c b/src/libc/src/time.c new file mode 100644 index 00000000..7980317c --- /dev/null +++ b/src/libc/src/time.c @@ -0,0 +1,16 @@ +#include "libc/time.h" + +#include "ebus.h" +#include "libk/sys_call.h" + +size_t time() { + return _sys_event_time(); +} + +void sleep(size_t ms) { + _sys_event_sleep(ms, 0); +} + +void usleep(size_t us) { + _sys_event_sleep(0, us); +} diff --git a/src/libk/include/libk/defs.h b/src/libk/include/libk/defs.h index de930f01..5feabd95 100644 --- a/src/libk/include/libk/defs.h +++ b/src/libk/include/libk/defs.h @@ -1,47 +1,57 @@ #ifndef LIBK_DEFS_H #define LIBK_DEFS_H -#define SYS_INT_FAMILY_IO 0x01 -#define SYS_INT_FAMILY_MEM 0x02 -#define SYS_INT_FAMILY_PROC 0x03 -#define SYS_INT_FAMILY_STDIO 0x10 -#define SYS_INT_FAMILY_IO_FILE 0x11 -#define SYS_INT_FAMILY_IO_DIR 0x12 - -#define SYS_INT_IO_OPEN 0x0100 -#define SYS_INT_IO_CLOSE 0x0101 -#define SYS_INT_IO_READ 0x0102 -#define SYS_INT_IO_WRITE 0x0103 -#define SYS_INT_IO_SIZE 0x0104 - -#define SYS_INT_MEM_MALLOC 0x0200 -#define SYS_INT_MEM_REALLOC 0x0201 -#define SYS_INT_MEM_FREE 0x0202 - -#define SYS_INT_PROC_EXIT 0x0300 -#define SYS_INT_PROC_ABORT 0x0301 -#define SYS_INT_PROC_PANIC 0x0302 -#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_PROC_EXEC 0x0307 -#define SYS_INT_PROC_SET_FOREGROUND 0x0308 - -// #define SYS_INT_STDIO_PUTC 0x1000 -// #define SYS_INT_STDIO_PUTS 0x1001 - -// #define SYS_INT_IO_FILE_OPEN 0x1101 -// #define SYS_INT_IO_FILE_CLOSE 0x1102 -// #define SYS_INT_IO_FILE_READ 0x1103 -// #define SYS_INT_IO_FILE_WRITE 0x1104 -// #define SYS_INT_IO_FILE_SEEK 0x1105 -// #define SYS_INT_IO_FILE_TELL 0x1106 - -// #define SYS_INT_IO_DIR_OPEN 0x1201 -// #define SYS_INT_IO_DIR_CLOSE 0x1202 -// #define SYS_INT_IO_DIR_READ 0x1203 -// #define SYS_INT_IO_DIR_SEEK 0x1205 -// #define SYS_INT_IO_DIR_TELL 0x1206 +#define SYS_CALL_FAMILY_IO 0x01 +#define SYS_CALL_FAMILY_MEM 0x02 +#define SYS_CALL_FAMILY_PROC 0x03 +#define SYS_CALL_FAMILY_EVENT 0x04 +#define SYS_CALL_FAMILY_STDIO 0x10 +#define SYS_CALL_FAMILY_IO_FILE 0x11 +#define SYS_CALL_FAMILY_IO_DIR 0x12 + +#define SYS_CALL_IO_OPEN ((SYS_CALL_FAMILY_IO << 16) | 0x0001) +#define SYS_CALL_IO_CLOSE ((SYS_CALL_FAMILY_IO << 16) | 0x0002) +#define SYS_CALL_IO_READ ((SYS_CALL_FAMILY_IO << 16) | 0x0003) +#define SYS_CALL_IO_WRITE ((SYS_CALL_FAMILY_IO << 16) | 0x0004) +#define SYS_CALL_IO_SIZE ((SYS_CALL_FAMILY_IO << 16) | 0x0005) + +#define SYS_CALL_MEM_MALLOC ((SYS_CALL_FAMILY_MEM << 16) | 0x0001) +#define SYS_CALL_MEM_REALLOC ((SYS_CALL_FAMILY_MEM << 16) | 0x0002) +#define SYS_CALL_MEM_FREE ((SYS_CALL_FAMILY_MEM << 16) | 0x0003) + +#define SYS_CALL_PROC_EXIT ((SYS_CALL_FAMILY_PROC << 16) | 0x0001) +#define SYS_CALL_PROC_ABORT ((SYS_CALL_FAMILY_PROC << 16) | 0x0002) +#define SYS_CALL_PROC_PANIC ((SYS_CALL_FAMILY_PROC << 16) | 0x0003) +#define SYS_CALL_PROC_REG_SIG ((SYS_CALL_FAMILY_PROC << 16) | 0x0004) +#define SYS_CALL_PROC_GETPID ((SYS_CALL_FAMILY_PROC << 16) | 0x0005) +#define SYS_CALL_PROC_QUEUE_EVENT ((SYS_CALL_FAMILY_PROC << 16) | 0x0006) +#define SYS_CALL_PROC_YIELD ((SYS_CALL_FAMILY_PROC << 16) | 0x0007) +#define SYS_CALL_PROC_EXEC ((SYS_CALL_FAMILY_PROC << 16) | 0x0008) +#define SYS_CALL_PROC_SET_FOREGROUND ((SYS_CALL_FAMILY_PROC << 16) | 0x0009) + +#define SYS_CALL_PROC_LIST_OPEN +#define SYS_CALL_PROC_LIST_CLOSE +#define SYS_CALL_PROC_LIST_READ +#define SYS_CALL_PROC_LIST_ + +#define SYS_CALL_EVENT_PULL ((SYS_CALL_FAMILY_EVENT << 16) | 0x0001) +#define SYS_CALL_EVENT_TIME ((SYS_CALL_FAMILY_EVENT << 16) | 0x0002) +#define SYS_CALL_EVENT_SLEEP ((SYS_CALL_FAMILY_EVENT << 16) | 0x0003) + +// #define SYS_CALL_STDIO_PUTC 0x1000 +// #define SYS_CALL_STDIO_PUTS 0x1001 + +// #define SYS_CALL_IO_FILE_OPEN 0x1101 +// #define SYS_CALL_IO_FILE_CLOSE 0x1102 +// #define SYS_CALL_IO_FILE_READ 0x1103 +// #define SYS_CALL_IO_FILE_WRITE 0x1104 +// #define SYS_CALL_IO_FILE_SEEK 0x1105 +// #define SYS_CALL_IO_FILE_TELL 0x1106 + +// #define SYS_CALL_IO_DIR_OPEN 0x1201 +// #define SYS_CALL_IO_DIR_CLOSE 0x1202 +// #define SYS_CALL_IO_DIR_READ 0x1203 +// #define SYS_CALL_IO_DIR_SEEK 0x1205 +// #define SYS_CALL_IO_DIR_TELL 0x1206 #endif // LIBK_DEFS_H diff --git a/src/libk/include/libk/sys_call.h b/src/libk/include/libk/sys_call.h index 9abef2ea..bafeafb3 100644 --- a/src/libk/include/libk/sys_call.h +++ b/src/libk/include/libk/sys_call.h @@ -33,7 +33,12 @@ 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); +void _sys_yield(void); int _sys_proc_set_foreground(int pid); +int _sys_event_pull(int filter, ebus_event_t * event_out); + +size_t _sys_event_time(void); +void _sys_event_sleep(size_t ms, size_t us); + #endif // LIBK_SYS_CALL_H diff --git a/src/libk/src/sys_call.c b/src/libk/src/sys_call.c index 332ec7e1..68d1c65d 100644 --- a/src/libk/src/sys_call.c +++ b/src/libk/src/sys_call.c @@ -8,76 +8,88 @@ #define UINT2PTR(UINT) ((void *)(UINT)) #define LUINT2PTR(UINT) UINT2PTR((uint32_t)(UINT)) -extern int send_call(uint32_t int_no, ...); -extern NO_RETURN void send_call_noret(uint32_t int_no, ...); +extern int send_call(uint32_t call_id, ...); +extern NO_RETURN void send_call_noret(uint32_t call_id, ...); int _sys_io_open(const char * path, const char * mode) { - return send_call(SYS_INT_IO_OPEN, path, mode); + return send_call(SYS_CALL_IO_OPEN, path, mode); } int _sys_io_close(int handle) { - return send_call(SYS_INT_IO_CLOSE, handle); + return send_call(SYS_CALL_IO_CLOSE, handle); } int _sys_io_read(int handle, char * buff, size_t count, size_t pos) { - return send_call(SYS_INT_IO_READ, handle, buff, count, pos); + return send_call(SYS_CALL_IO_READ, handle, buff, count, pos); } int _sys_io_write(int handle, const char * buff, size_t count, size_t pos) { - return send_call(SYS_INT_IO_WRITE, handle, buff, count, pos); + return send_call(SYS_CALL_IO_WRITE, handle, buff, count, pos); } int _sys_io_size(int handle) { - return send_call(SYS_INT_IO_SIZE, handle); + return send_call(SYS_CALL_IO_SIZE, handle); } void * _sys_mem_malloc(size_t size) { - return UINT2PTR(send_call(SYS_INT_MEM_MALLOC, size)); + return UINT2PTR(send_call(SYS_CALL_MEM_MALLOC, size)); } void * _sys_mem_realloc(void * ptr, size_t size) { - return UINT2PTR(send_call(SYS_INT_MEM_REALLOC, ptr, size)); + return UINT2PTR(send_call(SYS_CALL_MEM_REALLOC, ptr, size)); } void _sys_mem_free(void * ptr) { - send_call(SYS_INT_MEM_FREE, ptr); + send_call(SYS_CALL_MEM_FREE, ptr); } void _sys_proc_exit(uint8_t code) { // _sys_puts("libk: Proc exit\n"); - send_call_noret(SYS_INT_PROC_EXIT, code); + send_call_noret(SYS_CALL_PROC_EXIT, code); } void _sys_proc_abort(uint8_t code, const char * msg) { // _sys_puts("libk: Proc abort\n"); - send_call_noret(SYS_INT_PROC_ABORT, code, msg); + send_call_noret(SYS_CALL_PROC_ABORT, code, msg); } void _sys_proc_panic(const char * msg, const char * file, unsigned int line) { // _sys_puts("libk: Proc panic\n"); - send_call_noret(SYS_INT_PROC_PANIC, msg, file, line); + send_call_noret(SYS_CALL_PROC_PANIC, msg, file, line); } int _sys_proc_getpid(void) { - return send_call(SYS_INT_PROC_GETPID); + return send_call(SYS_CALL_PROC_GETPID); } void _sys_register_signals(void * callback) { - send_call(SYS_INT_PROC_REG_SIG, callback); + send_call(SYS_CALL_PROC_REG_SIG, callback); } void _sys_queue_event(ebus_event_t * event) { - send_call(SYS_INT_PROC_QUEUE_EVENT, event); + send_call(SYS_CALL_PROC_QUEUE_EVENT, event); } -int _sys_yield(int filter, ebus_event_t * event_out) { - return send_call(SYS_INT_PROC_YIELD, filter, event_out); +void _sys_yield() { + send_call(SYS_CALL_PROC_YIELD); } int _sys_proc_exec(const char * filename, int argc, char ** argv) { - return send_call(SYS_INT_PROC_EXEC, filename, argc, argv); + return send_call(SYS_CALL_PROC_EXEC, filename, argc, argv); } int _sys_proc_set_foreground(int pid) { - return send_call(SYS_INT_PROC_SET_FOREGROUND, pid); + return send_call(SYS_CALL_PROC_SET_FOREGROUND, pid); +} + +int _sys_event_pull(int filter, ebus_event_t * event_out) { + return send_call(SYS_CALL_EVENT_PULL, filter, event_out); +} + +size_t _sys_event_time() { + return send_call(SYS_CALL_EVENT_TIME); +} + +void _sys_event_sleep(size_t ms, size_t us) { + send_call(SYS_CALL_EVENT_SLEEP, ms, us); } diff --git a/tests/src/kernel/test_paging.cpp b/tests/src/kernel/test_paging.cpp index affb0970..6e098666 100644 --- a/tests/src/kernel/test_paging.cpp +++ b/tests/src/kernel/test_paging.cpp @@ -167,7 +167,7 @@ TEST_F(Paging, paging_add_pages_InvalidParameters) { EXPECT_NE(0, paging_add_pages(0, 1, 2)); // Start is after end - EXPECT_EQ(0, paging_add_pages(&dir, 2, 1)); + EXPECT_NE(0, paging_add_pages(&dir, 2, 1)); // End past dir EXPECT_NE(0, paging_add_pages(&dir, 1, MMU_DIR_SIZE * MMU_TABLE_SIZE)); @@ -239,7 +239,7 @@ TEST_F(Paging, paging_remove_pages_InvalidParameters) { EXPECT_NE(0, paging_remove_pages(0, 1, 2)); // Start past end - EXPECT_EQ(0, paging_remove_pages(&dir, 2, 1)); + EXPECT_NE(0, paging_remove_pages(&dir, 2, 1)); // End Past Dir EXPECT_NE(0, paging_remove_pages(&dir, 1, MMU_DIR_SIZE * MMU_TABLE_SIZE)); diff --git a/tests/src/mocks/include/libk/sys_call.mock.h b/tests/src/mocks/include/libk/sys_call.mock.h index 4dab349f..ee2ed5be 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, ebus_event_t *); +DECLARE_FAKE_VOID_FUNC(_sys_yield); 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/paging.mock.h b/tests/src/mocks/include/paging.mock.h index 6c65b3ed..6ac36b8b 100644 --- a/tests/src/mocks/include/paging.mock.h +++ b/tests/src/mocks/include/paging.mock.h @@ -8,9 +8,9 @@ extern "C" { #include "fff.h" #include "paging.h" -DECLARE_FAKE_VOID_FUNC(paging_init); +DECLARE_FAKE_VALUE_FUNC(int, paging_init); DECLARE_FAKE_VALUE_FUNC(void *, paging_temp_map, uint32_t); -DECLARE_FAKE_VOID_FUNC(paging_temp_free, uint32_t); +DECLARE_FAKE_VALUE_FUNC(int, paging_temp_free, uint32_t); DECLARE_FAKE_VALUE_FUNC(size_t, paging_temp_available); DECLARE_FAKE_VALUE_FUNC(int, paging_id_map_range, size_t, size_t); DECLARE_FAKE_VALUE_FUNC(int, paging_id_map_page, size_t); diff --git a/tests/src/mocks/src/libk.mock.c b/tests/src/mocks/src/libk.mock.c index d1f712d7..5a1ff578 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, ebus_event_t *); +DEFINE_FAKE_VOID_FUNC(_sys_yield); DEFINE_FAKE_VALUE_FUNC(size_t, _sys_putc, char); DEFINE_FAKE_VALUE_FUNC(size_t, _sys_puts, const char *); diff --git a/tests/src/mocks/src/paging.mock.c b/tests/src/mocks/src/paging.mock.c index fa9a7769..33ba921e 100644 --- a/tests/src/mocks/src/paging.mock.c +++ b/tests/src/mocks/src/paging.mock.c @@ -1,9 +1,9 @@ #include "paging.mock.h" -DEFINE_FAKE_VOID_FUNC(paging_init); +DEFINE_FAKE_VALUE_FUNC(int, paging_init); DEFINE_FAKE_VALUE_FUNC(void *, paging_temp_map, uint32_t); -DEFINE_FAKE_VOID_FUNC(paging_temp_free, uint32_t); +DEFINE_FAKE_VALUE_FUNC(int, paging_temp_free, uint32_t); DEFINE_FAKE_VALUE_FUNC(size_t, paging_temp_available); DEFINE_FAKE_VALUE_FUNC(int, paging_id_map_range, size_t, size_t); DEFINE_FAKE_VALUE_FUNC(int, paging_id_map_page, size_t);