Kernel+LibSystem: Add a 4th syscall argument

Let's allow passing 4 function arguments to a syscall. The 4th argument
goes into ESI or RSI.
This commit is contained in:
Andreas Kling 2021-07-24 02:15:07 +02:00
parent 9b78ae5149
commit deff554096
Notes: sideshowbarker 2024-07-18 08:22:19 +09:00
5 changed files with 33 additions and 8 deletions

View file

@ -531,6 +531,17 @@ inline uintptr_t invoke(Function function, T1 arg1, T2 arg2, T3 arg3)
: "memory");
return result;
}
template<typename T1, typename T2, typename T3, typename T4>
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
}

View file

@ -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
}

View file

@ -80,7 +80,7 @@ NEVER_INLINE NAKED void syscall_asm_entry()
namespace Syscall {
static KResultOr<FlatPtr> handle(RegisterState&, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3);
static KResultOr<FlatPtr> 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<FlatPtr> (Process::*Handler)(FlatPtr, FlatPtr, FlatPtr);
typedef KResultOr<FlatPtr> (Process::*Handler)(FlatPtr, FlatPtr, FlatPtr, FlatPtr);
typedef KResultOr<FlatPtr> (Process::*HandlerWithRegisterState)(RegisterState&);
struct HandlerMetadata {
Handler handler;
@ -101,7 +101,7 @@ static const HandlerMetadata s_syscall_table[] = {
};
#undef __ENUMERATE_SYSCALL
KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3)
KResultOr<FlatPtr> 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<FlatPtr> 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<FlatPtr> 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());

View file

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

View file

@ -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