diff options
author | Anton Kling <anton@kling.gg> | 2023-11-28 20:07:50 +0100 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2023-11-28 20:07:50 +0100 |
commit | 636858dbbd48ed9f5073793b46740302aa202f43 (patch) | |
tree | cf976c2b5a61ba055f0877317afdaf6e871df80e | |
parent | 89dc5dd5ba1e9cfe7a8975086c1d5638f8fbbac5 (diff) |
Kernel: Add basic IPC and move to microkernel design.
The IPC design is currently a WIP and is nowhere near complete
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/cpu/syscall.c | 55 | ||||
-rw-r--r-- | kernel/includes/syscalls.h | 5 | ||||
-rw-r--r-- | kernel/ipc.c | 95 | ||||
-rw-r--r-- | kernel/ipc.h | 26 | ||||
-rw-r--r-- | kernel/libc/exit/assert.c | 4 | ||||
-rw-r--r-- | kernel/libc/include/assert.h | 8 | ||||
-rw-r--r-- | kernel/sched/scheduler.c | 14 | ||||
-rw-r--r-- | kernel/sched/scheduler.h | 4 | ||||
-rw-r--r-- | kernel/syscalls/ipc.c | 18 | ||||
-rw-r--r-- | userland/libc/include/syscall.h | 5 |
11 files changed, 214 insertions, 22 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 0778cb3..a36e84c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,6 +1,6 @@ CC="i686-sb-gcc" AS="i686-sb-as" -OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o +OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o ipc.o syscalls/ipc.o CFLAGS = -O3 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL INCLUDE=-I./includes/ -I../include/ -I./libc/include/ diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c index 9aecc42..5fd6828 100644 --- a/kernel/cpu/syscall.c +++ b/kernel/cpu/syscall.c @@ -114,24 +114,45 @@ int syscall_openpty(SYS_OPENPTY_PARAMS *args) { } void (*syscall_functions[])() = { - (void(*))syscall_open, (void(*))syscall_read, - (void(*))syscall_write, (void(*))syscall_pread, - (void(*))syscall_pwrite, (void(*))syscall_fork, - (void(*))syscall_exec, (void(*))syscall_getpid, - (void(*))syscall_exit, (void(*))syscall_wait, - (void(*))syscall_brk, (void(*))syscall_sbrk, - (void(*))syscall_pipe, (void(*))syscall_dup2, - (void(*))syscall_close, (void(*))syscall_openpty, - (void(*))syscall_poll, (void(*))syscall_mmap, - (void(*))syscall_accept, (void(*))syscall_bind, - (void(*))syscall_socket, (void(*))syscall_shm_open, - (void(*))syscall_ftruncate, (void(*))syscall_stat, - (void(*))syscall_msleep, (void(*))syscall_uptime, - (void(*))syscall_mkdir, (void(*))syscall_recvfrom, - (void(*))syscall_sendto, (void(*))syscall_kill, - (void(*))syscall_sigaction, (void(*))syscall_chdir, - (void(*))syscall_getcwd, (void(*))syscall_isatty, + (void(*))syscall_open, + (void(*))syscall_read, + (void(*))syscall_write, + (void(*))syscall_pread, + (void(*))syscall_pwrite, + (void(*))syscall_fork, + (void(*))syscall_exec, + (void(*))syscall_getpid, + (void(*))syscall_exit, + (void(*))syscall_wait, + (void(*))syscall_brk, + (void(*))syscall_sbrk, + (void(*))syscall_pipe, + (void(*))syscall_dup2, + (void(*))syscall_close, + (void(*))syscall_openpty, + (void(*))syscall_poll, + (void(*))syscall_mmap, + (void(*))syscall_accept, + (void(*))syscall_bind, + (void(*))syscall_socket, + (void(*))syscall_shm_open, + (void(*))syscall_ftruncate, + (void(*))syscall_stat, + (void(*))syscall_msleep, + (void(*))syscall_uptime, + (void(*))syscall_mkdir, + (void(*))syscall_recvfrom, + (void(*))syscall_sendto, + (void(*))syscall_kill, + (void(*))syscall_sigaction, + (void(*))syscall_chdir, + (void(*))syscall_getcwd, + (void(*))syscall_isatty, (void(*))syscall_randomfill, + (void(*))syscall_ipc_register_endpoint, + (void(*))syscall_ipc_read, + (void(*))syscall_ipc_write, + (void(*))syscall_ipc_write_to_process, }; void syscall_function_handler(u32 eax, u32 arg1, u32 arg2, u32 arg3, u32 arg4, diff --git a/kernel/includes/syscalls.h b/kernel/includes/syscalls.h index 7b2a966..46218ce 100644 --- a/kernel/includes/syscalls.h +++ b/kernel/includes/syscalls.h @@ -8,6 +8,11 @@ #include <typedefs.h> #include <types.h> +int syscall_ipc_register_endpoint(u32 endpoint); +int syscall_ipc_read(u8 *buffer, u32 length, u32 *sender_pid); +int syscall_ipc_write(int ipc_id, u8 *buffer, u32 length); +int syscall_ipc_write_to_process(int pid, u8 *buffer, u32 length); + typedef struct SYS_ACCEPT_PARAMS { int socket; struct sockaddr *address; diff --git a/kernel/ipc.c b/kernel/ipc.c new file mode 100644 index 0000000..3422cc7 --- /dev/null +++ b/kernel/ipc.c @@ -0,0 +1,95 @@ +#include <assert.h> +#include <ipc.h> +#include <math.h> +#include <sched/scheduler.h> +#include <stdbool.h> +#include <string.h> + +struct IpcEndpoint { + u8 in_use; + u32 pid; +}; + +struct IpcEndpoint ipc_endpoints[100]; + +bool ipc_register_endpoint(u32 endpoint) { + if (endpoint >= 100) + return false; + if (ipc_endpoints[endpoint].in_use) + return false; + ipc_endpoints[endpoint].in_use = 1; + ipc_endpoints[endpoint].pid = get_current_task()->pid; + return true; +} + +bool ipc_endpoint_to_pid(u32 endpoint, u32 *pid) { + if (endpoint >= 100) + return false; + if (!ipc_endpoints[endpoint].in_use) + return false; + *pid = ipc_endpoints[endpoint].pid; + return true; +} + +int ipc_get_mailbox(u32 id, struct IpcMailbox **out) { + process_t *p; + if (!get_task_from_pid(id, &p)) + return 0; + *out = &p->ipc_mailbox; + return 1; +} + +int ipc_read(u8 *buffer, u32 length, u32 *sender_pid) { + struct IpcMailbox *handler = &get_current_task()->ipc_mailbox; + + u32 read_ptr = handler->read_ptr; + struct IpcMessage *ipc_message = NULL; + for (;;) { + ipc_message = &handler->data[read_ptr]; + if (!ipc_message->is_used) { + asm("sti"); + continue; + } + break; + } + ipc_message->is_used = 0; + // TODO: Verify sender_pid is a valid address + if (sender_pid) + *sender_pid = ipc_message->sender_pid; + + u32 len = min(length, ipc_message->size); + memcpy(buffer, ipc_message->buffer, len); + + // Update read_ptr + read_ptr++; + if (read_ptr >= IPC_NUM_DATA) + read_ptr = 0; + handler->read_ptr = read_ptr; + return len; +} + +int ipc_write_to_process(int pid, u8 *buffer, u32 length) { + struct IpcMailbox *handler; + assert(ipc_get_mailbox(pid, &handler)); + + u32 write_ptr = handler->write_ptr; + struct IpcMessage *ipc_message = &handler->data[write_ptr]; + ipc_message->is_used = 1; + u32 len = min(IPC_BUFFER_SIZE, length); + ipc_message->sender_pid = get_current_task()->pid; + ipc_message->size = len; + memcpy(ipc_message->buffer, buffer, len); + + // Update write_ptr + write_ptr++; + if (write_ptr >= IPC_NUM_DATA) + write_ptr = 0; + handler->write_ptr = write_ptr; + return len; +} + +int ipc_write(int endpoint, u8 *buffer, u32 length) { + u32 pid; + assert(ipc_endpoint_to_pid(endpoint, &pid)); + return ipc_write_to_process(pid, buffer, length); +} diff --git a/kernel/ipc.h b/kernel/ipc.h new file mode 100644 index 0000000..cfa9e6d --- /dev/null +++ b/kernel/ipc.h @@ -0,0 +1,26 @@ +#ifndef IPC_H +#define IPC_H +#include <stdbool.h> +#include <typedefs.h> + +#define IPC_BUFFER_SIZE 4096 +#define IPC_NUM_DATA 32 + +struct IpcMessage { + u8 is_used; + u32 sender_pid; + u32 size; + u8 buffer[IPC_BUFFER_SIZE]; +}; + +struct IpcMailbox { + u32 read_ptr; + u32 write_ptr; + struct IpcMessage data[IPC_NUM_DATA]; +}; + +bool ipc_register_endpoint(u32 endpoint); +int ipc_write_to_process(int pid, u8 *buffer, u32 length); +int ipc_write(int ipc_id, u8 *buffer, u32 length); +int ipc_read(u8 *buffer, u32 length, u32 *sender_pid); +#endif diff --git a/kernel/libc/exit/assert.c b/kernel/libc/exit/assert.c index b48773a..3351249 100644 --- a/kernel/libc/exit/assert.c +++ b/kernel/libc/exit/assert.c @@ -1,12 +1,12 @@ #include <assert.h> #include <log.h> #include <stdio.h> -#include <log.h> -void aFailed(char *f, int l) { +__attribute__((__noreturn__)) void aFailed(char *f, int l) { kprintf("Assert failed\n"); kprintf("%s : %d\n", f, l); dump_backtrace(10); + asm("hlt"); for (;;) ; } diff --git a/kernel/libc/include/assert.h b/kernel/libc/include/assert.h index 90a0be4..d6525f0 100644 --- a/kernel/libc/include/assert.h +++ b/kernel/libc/include/assert.h @@ -1,10 +1,16 @@ #include <log.h> #include <stdio.h> +// This infinite loop is needed for GCC to understand that +// aFailed does not return. No clue why the attribute does +// help solve the issue. #define assert(expr) \ { \ - if (!(expr)) \ + if (!(expr)) { \ aFailed(__FILE__, __LINE__); \ + for (;;) \ + ; \ + } \ } #define ASSERT_BUT_FIXME_PROPOGATE(expr) \ diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c index 7d13277..ccc5956 100644 --- a/kernel/sched/scheduler.c +++ b/kernel/sched/scheduler.c @@ -17,7 +17,19 @@ u32 next_pid = 0; extern u32 read_eip(void); -process_t *get_current_task(void) { return current_task; } +process_t *get_current_task(void) { + return current_task; +} + +bool get_task_from_pid(u32 pid, process_t **out) { + for (process_t *tmp = ready_queue; tmp; tmp = tmp->next) { + if (tmp->pid == pid) { + *out = tmp; + return true; + } + } + return false; +} void set_signal_handler(int sig, void (*handler)(int)) { if (sig >= 20 || sig < 0) diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h index f57a319..17e5d56 100644 --- a/kernel/sched/scheduler.h +++ b/kernel/sched/scheduler.h @@ -3,8 +3,10 @@ #include <fs/ext2.h> #include <fs/vfs.h> #include <halts.h> +#include <ipc.h> #include <mmu.h> #include <signal.h> +#include <stdbool.h> #define MAX_PATH 256 #define KEYBOARD_HALT 0 @@ -41,6 +43,7 @@ struct Process { u32 signal_handler_stack; void *signal_handlers[20]; PageDirectory *cr3; + struct IpcMailbox ipc_mailbox; vfs_fd_t *file_descriptors[100]; vfs_inode_t *read_halt_inode[100]; vfs_inode_t *write_halt_inode[100]; @@ -59,6 +62,7 @@ struct Process { int dead; }; +bool get_task_from_pid(u32 pid, process_t **out); process_t *get_current_task(void); int get_free_fd(process_t *p, int allocate); void free_process(void); diff --git a/kernel/syscalls/ipc.c b/kernel/syscalls/ipc.c new file mode 100644 index 0000000..b6947d1 --- /dev/null +++ b/kernel/syscalls/ipc.c @@ -0,0 +1,18 @@ +#include <ipc.h> +#include <syscalls.h> + +int syscall_ipc_register_endpoint(u32 id) { + return ipc_register_endpoint(id); +} + +int syscall_ipc_read(u8 *buffer, u32 length, u32 *sender_pid) { + return ipc_read(buffer, length, sender_pid); +} + +int syscall_ipc_write_to_process(int pid, u8 *buffer, u32 length) { + return ipc_write_to_process(pid, buffer, length); +} + +int syscall_ipc_write(int endpoint, u8 *buffer, u32 length) { + return ipc_write(endpoint, buffer, length); +} diff --git a/userland/libc/include/syscall.h b/userland/libc/include/syscall.h index 7a3b50d..b50c061 100644 --- a/userland/libc/include/syscall.h +++ b/userland/libc/include/syscall.h @@ -41,6 +41,11 @@ #define SYS_ISATTY 33 #define SYS_RANDOMFILL 34 +#define SYS_IPC_REGISTER_ENDPOINT 35 +#define SYS_IPC_READ 36 +#define SYS_IPC_WRITE 37 +#define SYS_IPC_WRITE_TO_PROCESS 38 + int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx, uint32_t esi, uint32_t edi); int s_syscall(int sys); |