From 2f9b8b6fc9c36d8d8906709014a0cdf7711ad032 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 7 Apr 2026 03:43:35 +0300 Subject: [PATCH] Kernel/LibC: Rework userspace syscall interface Kernel syscall API no longer zeros all unused argument registers and libc now uses inlined syscall macro internally. This significantly cleans up generated code for basic syscall wrapper functions. --- kernel/include/kernel/API/Syscall.h | 68 +++++++++------------- kernel/include/kernel/IDT.h | 2 +- kernel/kernel/Syscall.cpp | 1 + userspace/libraries/LibC/CMakeLists.txt | 2 +- userspace/libraries/LibC/include/unistd.h | 16 +++++ userspace/libraries/LibC/unistd.cpp | 17 +----- userspace/programs/DynamicLoader/main.cpp | 8 +-- userspace/programs/DynamicLoader/utils.cpp | 1 + userspace/programs/DynamicLoader/utils.h | 18 +++--- 9 files changed, 66 insertions(+), 67 deletions(-) diff --git a/kernel/include/kernel/API/Syscall.h b/kernel/include/kernel/API/Syscall.h index ba12a3bf..a6ce0ae3 100644 --- a/kernel/include/kernel/API/Syscall.h +++ b/kernel/include/kernel/API/Syscall.h @@ -1,44 +1,34 @@ #pragma once -#include -#include -#include -#include +#include -namespace Kernel -{ - - ALWAYS_INLINE long syscall(int syscall, uintptr_t arg1 = 0, uintptr_t arg2 = 0, uintptr_t arg3 = 0, uintptr_t arg4 = 0, uintptr_t arg5 = 0) - { - long ret; -#if ARCH(x86_64) - register uintptr_t r10 asm("r10") = arg3; - register uintptr_t r8 asm( "r8") = arg4; - register uintptr_t r9 asm( "r9") = arg5; - asm volatile( - "syscall" - : "=a"(ret) - , "+D"(syscall) - , "+S"(arg1) - , "+d"(arg2) - , "+r"(r10) - , "+r"(r8) - , "+r"(r9) - :: "rcx", "r11", "memory"); -#elif ARCH(i686) - asm volatile( - "int %[irq]" - : "=a"(ret) - : [irq]"i"(static_cast(IRQ_SYSCALL)) // WTF GCC 15 - , "a"(syscall) - , "b"(arg1) - , "c"(arg2) - , "d"(arg3) - , "S"(arg4) - , "D"(arg5) - : "memory"); +#if defined(__x86_64__) + #define _kas_instruction "syscall" + #define _kas_result rax + #define _kas_arguments rdi, rsi, rdx, r10, r8, r9 + #define _kas_globbers rcx, rdx, rdi, rsi, r8, r9, r10, r11 +#elif defined(__i686__) + #define _kas_instruction "int $0xF0" + #define _kas_result eax + #define _kas_arguments eax, ebx, ecx, edx, esi, edi + #define _kas_globbers #endif - return ret; - } -} +#define _kas_argument_var(index, value) register long _kas_a##index asm(_ban_stringify(_ban_get(index, _kas_arguments))) = (long)value; +#define _kas_dummy_var(index, value) register long _kas_d##index asm(#value); +#define _kas_input(index, _) "r"(_kas_a##index) +#define _kas_output(index, _) , "=r"(_kas_d##index) +#define _kas_globber(_, value) #value + +#define _kas_syscall(...) ({ \ + register long _kas_ret asm(_ban_stringify(_kas_result)); \ + _ban_for_each(_kas_argument_var, __VA_ARGS__) \ + _ban_for_each(_kas_dummy_var, _kas_globbers) \ + asm volatile( \ + _kas_instruction \ + : "=r"(_kas_ret) _ban_for_each(_kas_output, _kas_globbers) \ + : _ban_for_each_comma(_kas_input, __VA_ARGS__) \ + : "cc", "memory"); \ + (void)_kas_a0; /* require 1 argument */ \ + _kas_ret; \ + }) diff --git a/kernel/include/kernel/IDT.h b/kernel/include/kernel/IDT.h index 3da72577..594a540d 100644 --- a/kernel/include/kernel/IDT.h +++ b/kernel/include/kernel/IDT.h @@ -20,7 +20,7 @@ namespace Kernel constexpr uint8_t IRQ_MSI_BASE = 0x80; constexpr uint8_t IRQ_MSI_END = 0xF0; #if ARCH(i686) - constexpr uint8_t IRQ_SYSCALL = 0xF0; + constexpr uint8_t IRQ_SYSCALL = 0xF0; // hard coded in kernel/API/Syscall.h #endif constexpr uint8_t IRQ_IPI = 0xF1; constexpr uint8_t IRQ_TIMER = 0xF2; diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 469d734e..79008278 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -7,6 +7,7 @@ #include #include +#include #define DUMP_ALL_SYSCALLS 0 #define DUMP_LONG_SYSCALLS 0 diff --git a/userspace/libraries/LibC/CMakeLists.txt b/userspace/libraries/LibC/CMakeLists.txt index ec8e6bf2..b2338b72 100644 --- a/userspace/libraries/LibC/CMakeLists.txt +++ b/userspace/libraries/LibC/CMakeLists.txt @@ -74,7 +74,7 @@ set(LIBC_SOURCES ) add_library(objlibc OBJECT ${LIBC_SOURCES}) -target_compile_definitions(objlibc PRIVATE __arch=${BANAN_ARCH}) +target_compile_definitions(objlibc PRIVATE __arch=${BANAN_ARCH} __is_libc) target_compile_options(objlibc PRIVATE -O2 -g -Wstack-usage=512 -fno-exceptions -fno-rtti -fpic) target_compile_options(objlibc PUBLIC -Wall -Wextra -Werror -Wno-error=stack-usage=) diff --git a/userspace/libraries/LibC/include/unistd.h b/userspace/libraries/LibC/include/unistd.h index 71c7a25e..2acc98f7 100644 --- a/userspace/libraries/LibC/include/unistd.h +++ b/userspace/libraries/LibC/include/unistd.h @@ -608,6 +608,22 @@ char* getpass(const char* prompt); long syscall(long syscall, ...); +#ifdef __is_libc +#include +#include +#define _syscall(...) ({ \ + long _ret = -ERESTART; \ + while (_ret == -ERESTART) \ + _ret = _kas_syscall(__VA_ARGS__); \ + if (_ret < 0) { \ + errno = -_ret; \ + _ret = -1; \ + } \ + _ret; \ + }) +#define syscall _syscall +#endif + extern char** environ; __END_DECLS diff --git a/userspace/libraries/LibC/unistd.cpp b/userspace/libraries/LibC/unistd.cpp index ba7da6bf..2c10f553 100644 --- a/userspace/libraries/LibC/unistd.cpp +++ b/userspace/libraries/LibC/unistd.cpp @@ -254,32 +254,21 @@ void _exit(int status) ASSERT_NOT_REACHED(); } +#undef syscall long syscall(long syscall, ...) { va_list args; va_start(args, syscall); - uintptr_t arg1 = va_arg(args, uintptr_t); uintptr_t arg2 = va_arg(args, uintptr_t); uintptr_t arg3 = va_arg(args, uintptr_t); uintptr_t arg4 = va_arg(args, uintptr_t); uintptr_t arg5 = va_arg(args, uintptr_t); - va_end(args); - long ret; - do - ret = Kernel::syscall(syscall, arg1, arg2, arg3, arg4, arg5); - while (ret == -ERESTART); - - if (ret < 0) - { - errno = -ret; - return -1; - } - - return ret; + return _syscall(syscall, arg1, arg2, arg3, arg4, arg5); } +#define syscall _syscall int close(int fd) { diff --git a/userspace/programs/DynamicLoader/main.cpp b/userspace/programs/DynamicLoader/main.cpp index 95ba5298..0638b584 100644 --- a/userspace/programs/DynamicLoader/main.cpp +++ b/userspace/programs/DynamicLoader/main.cpp @@ -223,14 +223,14 @@ constexpr uintptr_t SYM_NOT_FOUND = -1; static void lock_global_lock() { - const pthread_t tid = syscall<>(SYS_PTHREAD_SELF); + const pthread_t tid = syscall(SYS_PTHREAD_SELF); pthread_t expected = 0; while (!s_global_locker.compare_exchange(expected, tid)) { if (expected == tid) break; - syscall<>(SYS_YIELD); + syscall(SYS_YIELD); expected = 0; } @@ -1393,7 +1393,7 @@ static void initialize_tls(MasterTLS master_tls) .master_tls_module_count = master_tls.module_count, .dynamic_tls = s_dynamic_tls, .cleanup_stack = nullptr, - .id = static_cast(syscall<>(SYS_PTHREAD_SELF)), + .id = static_cast(syscall(SYS_PTHREAD_SELF)), .errno_ = 0, .cancel_type = PTHREAD_CANCEL_DEFERRED, .cancel_state = PTHREAD_CANCEL_ENABLE, @@ -1565,7 +1565,7 @@ static void load_dynamic_tls(LoadedElf& elf) int expected = 0; while (!BAN::atomic_compare_exchange(s_dynamic_tls->lock, expected, 1)) { - syscall<>(SYS_YIELD); + syscall(SYS_YIELD); expected = 0; } diff --git a/userspace/programs/DynamicLoader/utils.cpp b/userspace/programs/DynamicLoader/utils.cpp index f6e46136..ebd13f73 100644 --- a/userspace/programs/DynamicLoader/utils.cpp +++ b/userspace/programs/DynamicLoader/utils.cpp @@ -2,6 +2,7 @@ #include #include +#include #include void print(int fd, const char* buffer) diff --git a/userspace/programs/DynamicLoader/utils.h b/userspace/programs/DynamicLoader/utils.h index c8fdb975..8e802a4c 100644 --- a/userspace/programs/DynamicLoader/utils.h +++ b/userspace/programs/DynamicLoader/utils.h @@ -1,10 +1,18 @@ #pragma once #include + +#include // make sure syscall function is declared before defining it + +#include #include -#include -#include +#define syscall(...) ({ \ + long _ret = -ERESTART; \ + while (_ret == -ERESTART) \ + _ret = _kas_syscall(__VA_ARGS__); \ + _ret; \ + }) template inline constexpr T min(T a, T b) @@ -18,12 +26,6 @@ inline constexpr T max(T a, T b) return a > b ? a : b; } -template requires (sizeof...(Ts) <= 5) && ((BAN::is_integral_v || BAN::is_pointer_v) && ...) -inline auto syscall(long syscall, Ts... args) -{ - return Kernel::syscall(syscall, (uintptr_t)args...); -} - void print(int fd, const char* buffer); [[noreturn]] void print_error_and_exit(const char* message, int error);