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);