diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 6377d384798..30b07a03693 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -531,6 +531,17 @@ inline uintptr_t invoke(Function function, T1 arg1, T2 arg2, T3 arg3) : "memory"); return result; } + +template +inline uintptr_t invoke(Function function, T1 arg1, T2 arg2, T3 arg3, T4 arg4) +{ + uintptr_t result; + asm volatile("int $0x82" + : "=a"(result) + : "a"(function), "d"((uintptr_t)arg1), "c"((uintptr_t)arg2), "b"((uintptr_t)arg3), "S"((uintptr_t)arg4) + : "memory"); + return result; +} #endif } diff --git a/Kernel/Arch/x86/RegisterState.h b/Kernel/Arch/x86/RegisterState.h index b92fd38b66d..21e9fe13cdc 100644 --- a/Kernel/Arch/x86/RegisterState.h +++ b/Kernel/Arch/x86/RegisterState.h @@ -104,18 +104,20 @@ struct [[gnu::packed]] RegisterState { #endif } - void capture_syscall_params(FlatPtr& function, FlatPtr& arg1, FlatPtr& arg2, FlatPtr& arg3) const + void capture_syscall_params(FlatPtr& function, FlatPtr& arg1, FlatPtr& arg2, FlatPtr& arg3, FlatPtr& arg4) const { #if ARCH(I386) function = eax; arg1 = edx; arg2 = ecx; arg3 = ebx; + arg4 = esi; #else function = rax; arg1 = rdx; arg2 = rcx; arg3 = rbx; + arg4 = rsi; #endif } diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 41dceadcb4f..ae32b62d94c 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -80,7 +80,7 @@ NEVER_INLINE NAKED void syscall_asm_entry() namespace Syscall { -static KResultOr handle(RegisterState&, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3); +static KResultOr handle(RegisterState&, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3, FlatPtr arg4); UNMAP_AFTER_INIT void initialize() { @@ -88,7 +88,7 @@ UNMAP_AFTER_INIT void initialize() } #pragma GCC diagnostic ignored "-Wcast-function-type" -typedef KResultOr (Process::*Handler)(FlatPtr, FlatPtr, FlatPtr); +typedef KResultOr (Process::*Handler)(FlatPtr, FlatPtr, FlatPtr, FlatPtr); typedef KResultOr (Process::*HandlerWithRegisterState)(RegisterState&); struct HandlerMetadata { Handler handler; @@ -101,7 +101,7 @@ static const HandlerMetadata s_syscall_table[] = { }; #undef __ENUMERATE_SYSCALL -KResultOr handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3) +KResultOr handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3, FlatPtr arg4) { VERIFY_INTERRUPTS_ENABLED(); auto current_thread = Thread::current(); @@ -109,7 +109,7 @@ KResultOr handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F current_thread->did_syscall(); if (function >= Function::__Count) { - dbgln("Unknown syscall {} requested ({:p}, {:p}, {:p})", function, arg1, arg2, arg3); + dbgln("Unknown syscall {} requested ({:p}, {:p}, {:p}, {:p})", function, arg1, arg2, arg3, arg4); return ENOSYS; } @@ -153,7 +153,7 @@ KResultOr handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F auto handler = (HandlerWithRegisterState)syscall_metadata.handler; result = (process.*(handler))(regs); } else { - result = (process.*(syscall_metadata.handler))(arg1, arg2, arg3); + result = (process.*(syscall_metadata.handler))(arg1, arg2, arg3, arg4); } return result; @@ -207,9 +207,10 @@ NEVER_INLINE void syscall_handler(TrapFrame* trap) FlatPtr arg1; FlatPtr arg2; FlatPtr arg3; - regs.capture_syscall_params(function, arg1, arg2, arg3); + FlatPtr arg4; + regs.capture_syscall_params(function, arg1, arg2, arg3, arg4); - auto result = Syscall::handle(regs, function, arg1, arg2, arg3); + auto result = Syscall::handle(regs, function, arg1, arg2, arg3, arg4); if (result.is_error()) { regs.set_return_reg(result.error()); diff --git a/Userland/Libraries/LibSystem/syscall.cpp b/Userland/Libraries/LibSystem/syscall.cpp index 4801b1bf12c..e04121d7905 100644 --- a/Userland/Libraries/LibSystem/syscall.cpp +++ b/Userland/Libraries/LibSystem/syscall.cpp @@ -28,4 +28,9 @@ uintptr_t syscall3(uintptr_t function, uintptr_t arg0, uintptr_t arg1, uintptr_t { return Syscall::invoke((Syscall::Function)function, arg0, arg1, arg2); } + +uintptr_t syscall4(uintptr_t function, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) +{ + return Syscall::invoke((Syscall::Function)function, arg0, arg1, arg2, arg3); +} } diff --git a/Userland/Libraries/LibSystem/syscall.h b/Userland/Libraries/LibSystem/syscall.h index ac9f38cb55d..a6cdabb227f 100644 --- a/Userland/Libraries/LibSystem/syscall.h +++ b/Userland/Libraries/LibSystem/syscall.h @@ -15,6 +15,7 @@ uintptr_t syscall0(uintptr_t function); uintptr_t syscall1(uintptr_t function, uintptr_t arg0); uintptr_t syscall2(uintptr_t function, uintptr_t arg0, uintptr_t arg1); uintptr_t syscall3(uintptr_t function, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2); +uintptr_t syscall4(uintptr_t function, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3); } #ifdef __cplusplus @@ -39,4 +40,9 @@ inline uintptr_t syscall(auto function, auto arg0, auto arg1, auto arg2) return syscall3((uintptr_t)function, (uintptr_t)arg0, (uintptr_t)arg1, (uintptr_t)arg2); } +inline uintptr_t syscall(auto function, auto arg0, auto arg1, auto arg2, auto arg3) +{ + return syscall4((uintptr_t)function, (uintptr_t)arg0, (uintptr_t)arg1, (uintptr_t)arg2, (uintptr_t)arg3); +} + #endif