浏览代码

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.
Andreas Kling 4 年之前
父节点
当前提交
deff554096

+ 11 - 0
Kernel/API/Syscall.h

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

+ 3 - 1
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
     }
 

+ 8 - 7
Kernel/Syscall.cpp

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

+ 5 - 0
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);
+}
 }

+ 6 - 0
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