mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 09:51:57 -05:00
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:
parent
9b78ae5149
commit
deff554096
5 changed files with 33 additions and 8 deletions
|
@ -531,6 +531,17 @@ inline uintptr_t invoke(Function function, T1 arg1, T2 arg2, T3 arg3)
|
||||||
: "memory");
|
: "memory");
|
||||||
return result;
|
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
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,18 +104,20 @@ struct [[gnu::packed]] RegisterState {
|
||||||
#endif
|
#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)
|
#if ARCH(I386)
|
||||||
function = eax;
|
function = eax;
|
||||||
arg1 = edx;
|
arg1 = edx;
|
||||||
arg2 = ecx;
|
arg2 = ecx;
|
||||||
arg3 = ebx;
|
arg3 = ebx;
|
||||||
|
arg4 = esi;
|
||||||
#else
|
#else
|
||||||
function = rax;
|
function = rax;
|
||||||
arg1 = rdx;
|
arg1 = rdx;
|
||||||
arg2 = rcx;
|
arg2 = rcx;
|
||||||
arg3 = rbx;
|
arg3 = rbx;
|
||||||
|
arg4 = rsi;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ NEVER_INLINE NAKED void syscall_asm_entry()
|
||||||
|
|
||||||
namespace Syscall {
|
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()
|
UNMAP_AFTER_INIT void initialize()
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ UNMAP_AFTER_INIT void initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
#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&);
|
typedef KResultOr<FlatPtr> (Process::*HandlerWithRegisterState)(RegisterState&);
|
||||||
struct HandlerMetadata {
|
struct HandlerMetadata {
|
||||||
Handler handler;
|
Handler handler;
|
||||||
|
@ -101,7 +101,7 @@ static const HandlerMetadata s_syscall_table[] = {
|
||||||
};
|
};
|
||||||
#undef __ENUMERATE_SYSCALL
|
#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();
|
VERIFY_INTERRUPTS_ENABLED();
|
||||||
auto current_thread = Thread::current();
|
auto current_thread = Thread::current();
|
||||||
|
@ -109,7 +109,7 @@ KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F
|
||||||
current_thread->did_syscall();
|
current_thread->did_syscall();
|
||||||
|
|
||||||
if (function >= Function::__Count) {
|
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;
|
return ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F
|
||||||
auto handler = (HandlerWithRegisterState)syscall_metadata.handler;
|
auto handler = (HandlerWithRegisterState)syscall_metadata.handler;
|
||||||
result = (process.*(handler))(regs);
|
result = (process.*(handler))(regs);
|
||||||
} else {
|
} else {
|
||||||
result = (process.*(syscall_metadata.handler))(arg1, arg2, arg3);
|
result = (process.*(syscall_metadata.handler))(arg1, arg2, arg3, arg4);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -207,9 +207,10 @@ NEVER_INLINE void syscall_handler(TrapFrame* trap)
|
||||||
FlatPtr arg1;
|
FlatPtr arg1;
|
||||||
FlatPtr arg2;
|
FlatPtr arg2;
|
||||||
FlatPtr arg3;
|
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()) {
|
if (result.is_error()) {
|
||||||
regs.set_return_reg(result.error());
|
regs.set_return_reg(result.error());
|
||||||
|
|
|
@ -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);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ uintptr_t syscall0(uintptr_t function);
|
||||||
uintptr_t syscall1(uintptr_t function, uintptr_t arg0);
|
uintptr_t syscall1(uintptr_t function, uintptr_t arg0);
|
||||||
uintptr_t syscall2(uintptr_t function, uintptr_t arg0, uintptr_t arg1);
|
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 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
|
#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);
|
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
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue