Skip to content

Commit

Permalink
Kernel+LibSystem: Add a 4th syscall argument
Browse files Browse the repository at this point in the history
Let's allow passing 4 function arguments to a syscall. The 4th argument
goes into ESI or RSI.
  • Loading branch information
awesomekling committed Jul 25, 2021
1 parent 9b78ae5 commit deff554
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 8 deletions.
11 changes: 11 additions & 0 deletions Kernel/API/Syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

}
Expand Down
4 changes: 3 additions & 1 deletion Kernel/Arch/x86/RegisterState.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
15 changes: 8 additions & 7 deletions Kernel/Syscall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@ 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()
{
register_user_callable_interrupt_handler(syscall_vector, syscall_asm_entry);
}

#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;
Expand All @@ -101,15 +101,15 @@ 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();
auto& process = current_thread->process();
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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down
5 changes: 5 additions & 0 deletions Userland/Libraries/LibSystem/syscall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
6 changes: 6 additions & 0 deletions Userland/Libraries/LibSystem/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

0 comments on commit deff554

Please sign in to comment.