From fd8a0175d9912b8798f76613796369d94a0b4d6b Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 22:39:56 +0100 Subject: [PATCH] Add a syscall infrastructure (our baby program can print to the console now!) --- apps/app.asm | 13 +++++++++++++ kernel/CMakeLists.txt | 5 ++++- kernel/src/arch/x86_64/CPU.asm | 2 +- kernel/src/arch/x86_64/CPU.cpp | 8 ++++---- kernel/src/sys/Syscall.cpp | 18 ++++++++++++++++++ kernel/src/sys/Syscall.h | 16 ++++++++++++++++ kernel/src/sys/console_print.cpp | 12 ++++++++++++ kernel/src/sys/exit.cpp | 7 +++++++ luna/include/luna/Syscall.h | 12 ++++++++++++ 9 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 kernel/src/sys/Syscall.cpp create mode 100644 kernel/src/sys/Syscall.h create mode 100644 kernel/src/sys/console_print.cpp create mode 100644 kernel/src/sys/exit.cpp create mode 100644 luna/include/luna/Syscall.h diff --git a/apps/app.asm b/apps/app.asm index 56062887..a0dffce7 100644 --- a/apps/app.asm +++ b/apps/app.asm @@ -1,4 +1,17 @@ section .text global _start _start: + mov rax, 1 + mov rdi, message int 42h + mov rax, 1 + mov rdi, message2 + int 42h + mov rax, 0 + int 42h + +section .rodata +message: + db "Hello!", 0xa, 0 +message2: + db "I am an app", 0xa, 0 diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 7e9e5db4..d8498225 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -15,6 +15,9 @@ set(SOURCES src/thread/Spinlock.cpp src/thread/Thread.cpp src/thread/Scheduler.cpp + src/sys/Syscall.cpp + src/sys/exit.cpp + src/sys/console_print.cpp src/InitRD.cpp src/ELF.cpp ) @@ -82,4 +85,4 @@ target_include_directories(moon PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/gen) target_link_options(moon PRIVATE LINKER:-T ${CMAKE_CURRENT_LIST_DIR}/moon.ld -nostdlib -nodefaultlibs) -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/moon" DESTINATION ${LUNA_ROOT}/initrd/boot) \ No newline at end of file +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/moon" DESTINATION ${LUNA_ROOT}/initrd/boot) diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index 00b58b7e..364a7367 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -188,4 +188,4 @@ ISR_ERROR 21 ; control-protection exception (#CP) ; ISR 22-31 reserved IRQ 32, 0 ; timer interrupt IRQ 33, 0 ; keyboard interrupt -ISR 66 ; user exit +ISR 66 ; system call diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 8dca8b89..72289888 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -4,6 +4,7 @@ #include "arch/x86_64/CPU.h" #include "arch/x86_64/IO.h" #include "memory/MemoryManager.h" +#include "sys/Syscall.h" #include "thread/Scheduler.h" #include #include @@ -107,11 +108,10 @@ extern "C" void arch_interrupt_entry(Registers* regs) scancode_queue.try_push(scancode); pic_eoi(regs); } - else if (regs->isr == 66) // Exit!! + else if (regs->isr == 66) // System call { - kdbgln("exiting from user task!!"); - Scheduler::current()->state = ThreadState::Dying; - kernel_yield(); + SyscallArgs args = { regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8, regs->r9 }; + regs->rax = (u64)invoke_syscall(regs, args, regs->rax); } else { diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp new file mode 100644 index 00000000..d45552aa --- /dev/null +++ b/kernel/src/sys/Syscall.cpp @@ -0,0 +1,18 @@ +#include "sys/Syscall.h" +#include + +syscall_func_t syscalls[] = { +#undef __enumerate +#define __enumerate(name) sys_##name, + enumerate_syscalls(__enumerate) +#undef __enumerate +}; + +i64 invoke_syscall(Registers* regs, SyscallArgs args, u64 syscall) +{ + if (syscall >= Syscalls::__count) { return -ENOSYS; } + + auto rc = syscalls[syscall](regs, args); + if (rc.has_error()) return -rc.error(); + return (i64)rc.value(); +} diff --git a/kernel/src/sys/Syscall.h b/kernel/src/sys/Syscall.h new file mode 100644 index 00000000..15b69505 --- /dev/null +++ b/kernel/src/sys/Syscall.h @@ -0,0 +1,16 @@ +#pragma once +#include "arch/CPU.h" +#include +#include + +typedef u64 SyscallArgs[6]; + +typedef Result (*syscall_func_t)(Registers*, SyscallArgs); + +// Invoked by the architecture-dependent system call entry point. +i64 invoke_syscall(Registers*, SyscallArgs, u64 syscall); + +#undef __enumerate +#define __enumerate(name) extern Result sys_##name(Registers*, SyscallArgs); +enumerate_syscalls(__enumerate) +#undef __enumerate diff --git a/kernel/src/sys/console_print.cpp b/kernel/src/sys/console_print.cpp new file mode 100644 index 00000000..b112c5b2 --- /dev/null +++ b/kernel/src/sys/console_print.cpp @@ -0,0 +1,12 @@ +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include "video/TextConsole.h" + +Result sys_console_print(Registers*, SyscallArgs args) +{ + if (!MemoryManager::validate_userspace_string(args[0])) return err(EFAULT); + + TextConsole::print((char*)args[0]); + + return { 0 }; +} diff --git a/kernel/src/sys/exit.cpp b/kernel/src/sys/exit.cpp new file mode 100644 index 00000000..adc591c1 --- /dev/null +++ b/kernel/src/sys/exit.cpp @@ -0,0 +1,7 @@ +#include "sys/Syscall.h" +#include "thread/Scheduler.h" + +Result sys_exit(Registers*, SyscallArgs) +{ + kernel_exit(); +} diff --git a/luna/include/luna/Syscall.h b/luna/include/luna/Syscall.h new file mode 100644 index 00000000..30551cfa --- /dev/null +++ b/luna/include/luna/Syscall.h @@ -0,0 +1,12 @@ +#pragma once + +#define enumerate_syscalls(_e) _e(exit) _e(console_print) + +enum Syscalls +{ +#undef __enumerate +#define __enumerate(name) SYS_##name, + enumerate_syscalls(__enumerate) +#undef __enumerate + __count +};