diff --git a/Scripts/StructPackVerifier.py b/Scripts/StructPackVerifier.py index 782f64934..372acd6de 100755 --- a/Scripts/StructPackVerifier.py +++ b/Scripts/StructPackVerifier.py @@ -651,6 +651,7 @@ def main(): "-I/usr/x86_64-linux-gnu/include/", "-O2", "--target=x86_64-linux-unknown", + "-D_M_X86_64", ] args_aarch64 = [ @@ -658,6 +659,7 @@ def main(): "-I/usr/aarch64-linux-gnu/include/", "-O2", "--target=aarch64-linux-unknown", + "-D_M_ARM_64", ] args_x86_win32 = [ @@ -686,11 +688,13 @@ def main(): args_x86_32 = FindClangArguments(args_x86_32) args_x86_64 = FindClangArguments(args_x86_64) args_aarch64 = FindClangArguments(args_aarch64) + args_x86_win32 = FindClangArguments(args_x86_win32) args_x86_win64 = FindClangArguments(args_x86_win64) Arch_x86_32 = ArchDB("x86_32") Arch_x86_64 = ArchDB("x86_64") + Arch_aarch64 = ArchDB("aarch64") Arch_x86_win32 = ArchDB("win32") Arch_x86_win64 = ArchDB("win64") diff --git a/Source/Tests/LinuxSyscalls/CMakeLists.txt b/Source/Tests/LinuxSyscalls/CMakeLists.txt index 72404d7d9..5f617921d 100644 --- a/Source/Tests/LinuxSyscalls/CMakeLists.txt +++ b/Source/Tests/LinuxSyscalls/CMakeLists.txt @@ -45,6 +45,7 @@ add_library(LinuxEmulation STATIC Syscalls/Key.cpp Syscalls/Memory.cpp Syscalls/Msg.cpp + Syscalls/Namespace.cpp Syscalls/Sched.cpp Syscalls/Semaphore.cpp Syscalls/SHM.cpp @@ -70,6 +71,7 @@ set(HEADERS_TO_VERIFY x32/Ioctl/input.h x86_32 # This needs to match structs to 32bit structs x32/Ioctl/sockios.h x86_32 # This needs to match structs to 32bit structs x32/Ioctl/joystick.h x86_32 # This needs to match structs to 32bit structs + x64/Types.h x86_64 # This needs to match structs to 64bit structs ) list(LENGTH HEADERS_TO_VERIFY ARG_COUNT) diff --git a/Source/Tests/LinuxSyscalls/Syscalls.h b/Source/Tests/LinuxSyscalls/Syscalls.h index 05c3a2351..f617be78a 100644 --- a/Source/Tests/LinuxSyscalls/Syscalls.h +++ b/Source/Tests/LinuxSyscalls/Syscalls.h @@ -17,7 +17,6 @@ $end_info$ #include #include -#include #include #include @@ -45,6 +44,7 @@ class SignalDelegator; void RegisterKey(); void RegisterMemory(); void RegisterMsg(); + void RegisterNamespace(FEX::HLE::SyscallHandler *const Handler); void RegisterNuma(); void RegisterSched(); void RegisterSemaphore(); @@ -250,27 +250,6 @@ struct FunctionToLambda { } }; -struct FEX_PACKED epoll_event_x86 { - uint32_t events; - epoll_data_t data; - - epoll_event_x86() = delete; - - operator struct epoll_event() const { - epoll_event event{}; - event.events = events; - event.data = data; - return event; - } - - epoll_event_x86(struct epoll_event event) { - events = event.events; - data = event.data; - } -}; -static_assert(std::is_trivial::value, "Needs to be trivial"); -static_assert(sizeof(epoll_event_x86) == 12, "Incorrect size"); - struct open_how { uint64_t flags; uint64_t mode; diff --git a/Source/Tests/LinuxSyscalls/Syscalls/FD.cpp b/Source/Tests/LinuxSyscalls/Syscalls/FD.cpp index 59636b760..8920edcc0 100644 --- a/Source/Tests/LinuxSyscalls/Syscalls/FD.cpp +++ b/Source/Tests/LinuxSyscalls/Syscalls/FD.cpp @@ -235,17 +235,6 @@ namespace FEX::HLE { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL(timerfd_settime, [](FEXCore::Core::CpuStateFrame *Frame, int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) -> uint64_t { - // Flags don't need remapped - uint64_t Result = ::timerfd_settime(fd, flags, new_value, old_value); - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL(timerfd_gettime, [](FEXCore::Core::CpuStateFrame *Frame, int fd, struct itimerspec *curr_value) -> uint64_t { - uint64_t Result = ::timerfd_gettime(fd, curr_value); - SYSCALL_ERRNO(); - }); - REGISTER_SYSCALL_IMPL(eventfd, [](FEXCore::Core::CpuStateFrame *Frame, uint32_t count) -> uint64_t { uint64_t Result = ::syscall(SYS_eventfd2, count, 0); SYSCALL_ERRNO(); diff --git a/Source/Tests/LinuxSyscalls/Syscalls/Key.cpp b/Source/Tests/LinuxSyscalls/Syscalls/Key.cpp index 5528d2d31..5d30b951b 100644 --- a/Source/Tests/LinuxSyscalls/Syscalls/Key.cpp +++ b/Source/Tests/LinuxSyscalls/Syscalls/Key.cpp @@ -5,6 +5,7 @@ $end_info$ */ #include "Tests/LinuxSyscalls/Syscalls.h" +#include "Tests/LinuxSyscalls/Types.h" #include "Tests/LinuxSyscalls/x64/Syscalls.h" #include "Tests/LinuxSyscalls/x32/Syscalls.h" @@ -14,12 +15,12 @@ $end_info$ namespace FEX::HLE { void RegisterKey() { - REGISTER_SYSCALL_IMPL(add_key, [](FEXCore::Core::CpuStateFrame *Frame, const char *type, const char *description, const void *payload, size_t plen, int32_t /*key_serial_t*/ keyring) -> uint64_t { + REGISTER_SYSCALL_IMPL(add_key, [](FEXCore::Core::CpuStateFrame *Frame, const char *type, const char *description, const void *payload, size_t plen, key_serial_t keyring) -> uint64_t { uint64_t Result = syscall(SYS_add_key, type, description, payload, plen, keyring); SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL(request_key, [](FEXCore::Core::CpuStateFrame *Frame, const char *type, const char *description, const char *callout_info, int32_t /*key_serial_t*/ dest_keyring) -> uint64_t { + REGISTER_SYSCALL_IMPL(request_key, [](FEXCore::Core::CpuStateFrame *Frame, const char *type, const char *description, const char *callout_info, key_serial_t dest_keyring) -> uint64_t { uint64_t Result = syscall(SYS_request_key, type, description, callout_info, dest_keyring); SYSCALL_ERRNO(); }); diff --git a/Source/Tests/LinuxSyscalls/Syscalls/Namespace.cpp b/Source/Tests/LinuxSyscalls/Syscalls/Namespace.cpp new file mode 100644 index 000000000..69a7e2d30 --- /dev/null +++ b/Source/Tests/LinuxSyscalls/Syscalls/Namespace.cpp @@ -0,0 +1,71 @@ +/* +$info$ +tags: LinuxSyscalls|syscalls-shared +$end_info$ +*/ + +#include "Tests/LinuxSyscalls/Syscalls.h" +#include "Tests/LinuxSyscalls/Syscalls/Thread.h" +#include "Tests/LinuxSyscalls/x64/Syscalls.h" +#include "Tests/LinuxSyscalls/x32/Syscalls.h" + +#include +#include +#include + +namespace SignalDelegator { + struct GuestSigAction; +} + + +namespace FEX::HLE { + void RegisterNamespace(FEX::HLE::SyscallHandler *const Handler) { + if (Handler->GetHostKernelVersion() >= FEX::HLE::SyscallHandler::KernelVersion(5, 1, 0)) { + REGISTER_SYSCALL_IMPL(open_tree, [](FEXCore::Core::CpuStateFrame *Frame, int dfd, const char *filename, unsigned int flags) -> uint64_t { + uint64_t Result = ::syscall(SYS_open_tree, dfd, filename, flags); + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL(move_mount, [](FEXCore::Core::CpuStateFrame *Frame, int from_dfd, const char *from_pathname, int to_dfd, const char *to_pathname, unsigned int flags) -> uint64_t { + uint64_t Result = ::syscall(SYS_move_mount, from_dfd, from_pathname, to_dfd, to_pathname, flags); + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL(fsopen, [](FEXCore::Core::CpuStateFrame *Frame, int dfd, const char *path, unsigned int flags) -> uint64_t { + uint64_t Result = ::syscall(SYS_fsopen, dfd, path, flags); + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL(fsconfig, [](FEXCore::Core::CpuStateFrame *Frame, int fd, unsigned int cmd, const char *key, const void *value, int aux) -> uint64_t { + uint64_t Result = ::syscall(SYS_fsconfig, fd, cmd, key, value, aux); + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL(fspick, [](FEXCore::Core::CpuStateFrame *Frame, int dfd, const char *path, unsigned int flags) -> uint64_t { + uint64_t Result = ::syscall(SYS_fspick, dfd, path, flags); + SYSCALL_ERRNO(); + }); + } + else { + REGISTER_SYSCALL_IMPL(open_tree, UnimplementedSyscallSafe); + REGISTER_SYSCALL_IMPL(move_mount, UnimplementedSyscallSafe); + REGISTER_SYSCALL_IMPL(fsopen, UnimplementedSyscallSafe); + REGISTER_SYSCALL_IMPL(fsconfig, UnimplementedSyscallSafe); + REGISTER_SYSCALL_IMPL(fsmount, UnimplementedSyscallSafe); + REGISTER_SYSCALL_IMPL(fspick, UnimplementedSyscallSafe); + } + +#ifndef SYS_mount_setattr +#define SYS_mount_setattr 442 +#endif + if (Handler->GetHostKernelVersion() >= FEX::HLE::SyscallHandler::KernelVersion(5, 12, 0)) { + REGISTER_SYSCALL_IMPL(mount_setattr, [](FEXCore::Core::CpuStateFrame *Frame, int dfd, const char *path, unsigned int flags, void *uattr, size_t usize) -> uint64_t { + uint64_t Result = ::syscall(SYS_mount_setattr, dfd, path, flags, uattr, usize); + SYSCALL_ERRNO(); + }); + } + else { + REGISTER_SYSCALL_IMPL(mount_setattr, UnimplementedSyscallSafe); + } + } +} diff --git a/Source/Tests/LinuxSyscalls/Syscalls/Signals.cpp b/Source/Tests/LinuxSyscalls/Syscalls/Signals.cpp index 7b3d137a5..f64b926d9 100644 --- a/Source/Tests/LinuxSyscalls/Syscalls/Signals.cpp +++ b/Source/Tests/LinuxSyscalls/Syscalls/Signals.cpp @@ -56,12 +56,14 @@ namespace FEX::HLE { SYSCALL_ERRNO(); }); + // XXX: siginfo_t definitely isn't correct for 32-bit REGISTER_SYSCALL_IMPL(rt_tgsigqueueinfo, [](FEXCore::Core::CpuStateFrame *Frame, pid_t tgid, pid_t tid, int sig, siginfo_t *info) -> uint64_t { uint64_t Result = ::syscall(SYS_rt_tgsigqueueinfo, tgid, tid, sig, info); SYSCALL_ERRNO(); }); if (Handler->IsHostKernelVersionAtLeast(5, 1, 0)) { + // XXX: siginfo_t definitely isn't correct for 32-bit REGISTER_SYSCALL_IMPL(pidfd_send_signal, [](FEXCore::Core::CpuStateFrame *Frame, int pidfd, int sig, siginfo_t *info, unsigned int flags) -> uint64_t { uint64_t Result = ::syscall(SYS_pidfd_send_signal, pidfd, sig, info, flags); SYSCALL_ERRNO(); diff --git a/Source/Tests/LinuxSyscalls/Syscalls/Time.cpp b/Source/Tests/LinuxSyscalls/Syscalls/Time.cpp index aa44cd1e0..68c28b56f 100644 --- a/Source/Tests/LinuxSyscalls/Syscalls/Time.cpp +++ b/Source/Tests/LinuxSyscalls/Syscalls/Time.cpp @@ -24,21 +24,6 @@ namespace FEX::HLE { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL(time, [](FEXCore::Core::CpuStateFrame *Frame, time_t *tloc) -> uint64_t { - uint64_t Result = ::time(tloc); - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL(times, [](FEXCore::Core::CpuStateFrame *Frame, struct tms *buf) -> uint64_t { - uint64_t Result = ::times(buf); - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL(utime, [](FEXCore::Core::CpuStateFrame *Frame, char* filename, const struct utimbuf* times) -> uint64_t { - uint64_t Result = ::utime(filename, times); - SYSCALL_ERRNO(); - }); - REGISTER_SYSCALL_IMPL(adjtimex, [](FEXCore::Core::CpuStateFrame *Frame, struct timex *buf) -> uint64_t { uint64_t Result = ::adjtimex(buf); SYSCALL_ERRNO(); diff --git a/Source/Tests/LinuxSyscalls/Syscalls/Timer.cpp b/Source/Tests/LinuxSyscalls/Syscalls/Timer.cpp index f7609adbe..3a096008c 100644 --- a/Source/Tests/LinuxSyscalls/Syscalls/Timer.cpp +++ b/Source/Tests/LinuxSyscalls/Syscalls/Timer.cpp @@ -5,6 +5,7 @@ $end_info$ */ #include "Tests/LinuxSyscalls/Syscalls.h" +#include "Tests/LinuxSyscalls/Types.h" #include "Tests/LinuxSyscalls/x64/Syscalls.h" #include "Tests/LinuxSyscalls/x32/Syscalls.h" @@ -24,27 +25,17 @@ namespace FEX::HLE { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL(timer_create, [](FEXCore::Core::CpuStateFrame *Frame, clockid_t clockid, struct sigevent *sevp, timer_t *timerid) -> uint64_t { + REGISTER_SYSCALL_IMPL(timer_create, [](FEXCore::Core::CpuStateFrame *Frame, clockid_t clockid, struct sigevent *sevp, kernel_timer_t *timerid) -> uint64_t { uint64_t Result = ::syscall(SYS_timer_create, clockid, sevp, timerid); SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL(timer_settime, [](FEXCore::Core::CpuStateFrame *Frame, timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) -> uint64_t { - uint64_t Result = ::syscall(SYS_timer_settime, timerid, flags, new_value, old_value); - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL(timer_gettime, [](FEXCore::Core::CpuStateFrame *Frame, timer_t timerid, struct itimerspec *curr_value) -> uint64_t { - uint64_t Result = ::syscall(SYS_timer_gettime, timerid, curr_value); - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL(timer_getoverrun, [](FEXCore::Core::CpuStateFrame *Frame, timer_t timerid) -> uint64_t { + REGISTER_SYSCALL_IMPL(timer_getoverrun, [](FEXCore::Core::CpuStateFrame *Frame, kernel_timer_t timerid) -> uint64_t { uint64_t Result = ::syscall(SYS_timer_getoverrun, timerid); SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL(timer_delete, [](FEXCore::Core::CpuStateFrame *Frame, timer_t timerid) -> uint64_t { + REGISTER_SYSCALL_IMPL(timer_delete, [](FEXCore::Core::CpuStateFrame *Frame, kernel_timer_t timerid) -> uint64_t { uint64_t Result = ::syscall(SYS_timer_delete, timerid); SYSCALL_ERRNO(); }); diff --git a/Source/Tests/LinuxSyscalls/Types.h b/Source/Tests/LinuxSyscalls/Types.h new file mode 100644 index 000000000..9169ad118 --- /dev/null +++ b/Source/Tests/LinuxSyscalls/Types.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include +#include + +namespace FEX::HLE { +using key_serial_t = int32_t; +using kernel_timer_t = int32_t; + +struct FEX_PACKED epoll_event_x86 { + uint32_t events; + epoll_data_t data; + + epoll_event_x86() = delete; + + operator struct epoll_event() const { + epoll_event event{}; + event.events = events; + event.data = data; + return event; + } + + epoll_event_x86(struct epoll_event event) { + events = event.events; + data = event.data; + } +}; +static_assert(std::is_trivial::value, "Needs to be trivial"); +static_assert(sizeof(epoll_event_x86) == 12, "Incorrect size"); + + +} diff --git a/Source/Tests/LinuxSyscalls/x32/EPoll.cpp b/Source/Tests/LinuxSyscalls/x32/EPoll.cpp index ba651dc5e..623b0db8d 100644 --- a/Source/Tests/LinuxSyscalls/x32/EPoll.cpp +++ b/Source/Tests/LinuxSyscalls/x32/EPoll.cpp @@ -6,6 +6,7 @@ $end_info$ */ #include "Tests/LinuxSyscalls/Syscalls.h" +#include "Tests/LinuxSyscalls/Types.h" #include "Tests/LinuxSyscalls/x32/Syscalls.h" #include "Tests/LinuxSyscalls/x32/Types.h" @@ -26,7 +27,7 @@ namespace FEXCore::Core { namespace FEX::HLE::x32 { void RegisterEpoll(FEX::HLE::SyscallHandler *const Handler) { - REGISTER_SYSCALL_IMPL_X32(epoll_wait, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, compat_ptr events, int maxevents, int timeout) -> uint64_t { + REGISTER_SYSCALL_IMPL_X32(epoll_wait, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, compat_ptr events, int maxevents, int timeout) -> uint64_t { std::vector Events(std::max(0, maxevents)); uint64_t Result = ::syscall(SYS_epoll_pwait, epfd, Events.data(), maxevents, timeout, nullptr); @@ -38,7 +39,7 @@ namespace FEX::HLE::x32 { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL_X32(epoll_ctl, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, int op, int fd, compat_ptr event) -> uint64_t { + REGISTER_SYSCALL_IMPL_X32(epoll_ctl, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, int op, int fd, compat_ptr event) -> uint64_t { struct epoll_event Event = *event; uint64_t Result = ::syscall(SYS_epoll_ctl, epfd, op, fd, &Event); if (Result != -1) { @@ -47,7 +48,7 @@ namespace FEX::HLE::x32 { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL_X32(epoll_pwait, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, compat_ptr events, int maxevent, int timeout, const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { + REGISTER_SYSCALL_IMPL_X32(epoll_pwait, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, compat_ptr events, int maxevent, int timeout, const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { std::vector Events(std::max(0, maxevent)); uint64_t Result = ::syscall(SYS_epoll_pwait, @@ -71,7 +72,7 @@ namespace FEX::HLE::x32 { #ifndef SYS_epoll_pwait2 #define SYS_epoll_pwait2 354 #endif - REGISTER_SYSCALL_IMPL_X32(epoll_pwait2, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, compat_ptr events, int maxevent, compat_ptr timeout, const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { + REGISTER_SYSCALL_IMPL_X32(epoll_pwait2, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, compat_ptr events, int maxevent, compat_ptr timeout, const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { std::vector Events(std::max(0, maxevent)); struct timespec tp64{}; diff --git a/Source/Tests/LinuxSyscalls/x32/FD.cpp b/Source/Tests/LinuxSyscalls/x32/FD.cpp index 4132864db..cb52237c7 100644 --- a/Source/Tests/LinuxSyscalls/x32/FD.cpp +++ b/Source/Tests/LinuxSyscalls/x32/FD.cpp @@ -736,6 +736,41 @@ namespace FEX::HLE::x32 { SYSCALL_ERRNO(); }); + REGISTER_SYSCALL_IMPL_X32(timerfd_settime, [](FEXCore::Core::CpuStateFrame *Frame, + int fd, + int flags, + const FEX::HLE::x32::old_itimerspec32 *new_value, + FEX::HLE::x32::old_itimerspec32 *old_value) -> uint64_t { + struct itimerspec new_value_host{}; + struct itimerspec old_value_host{}; + struct itimerspec *old_value_host_p{}; + + new_value_host = *new_value; + if (old_value) { + old_value_host_p = &old_value_host; + } + + // Flags don't need remapped + uint64_t Result = ::timerfd_settime(fd, flags, &new_value_host, old_value_host_p); + + if (Result != -1 && old_value) { + *old_value = old_value_host; + } + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL_X32(timerfd_gettime, [](FEXCore::Core::CpuStateFrame *Frame, int fd, FEX::HLE::x32::old_itimerspec32 *curr_value) -> uint64_t { + struct itimerspec Host{}; + + uint64_t Result = ::timerfd_gettime(fd, &Host); + + if (Result != -1) { + *curr_value = Host; + } + + SYSCALL_ERRNO(); + }); + REGISTER_SYSCALL_IMPL_X32(pselect6_time64, [](FEXCore::Core::CpuStateFrame *Frame, int nfds, fd_set32 *readfds, fd_set32 *writefds, fd_set32 *exceptfds, struct timespec *timeout, compat_ptr sigmaskpack) -> uint64_t { fd_set Host_readfds; fd_set Host_writefds; diff --git a/Source/Tests/LinuxSyscalls/x32/Syscalls.cpp b/Source/Tests/LinuxSyscalls/x32/Syscalls.cpp index 7b86eddc4..ea29b51e7 100644 --- a/Source/Tests/LinuxSyscalls/x32/Syscalls.cpp +++ b/Source/Tests/LinuxSyscalls/x32/Syscalls.cpp @@ -684,6 +684,7 @@ public: FEX::HLE::RegisterKey(); FEX::HLE::RegisterMemory(); FEX::HLE::RegisterMsg(); + FEX::HLE::RegisterNamespace(this); FEX::HLE::RegisterSched(); FEX::HLE::RegisterSemaphore(); FEX::HLE::RegisterSHM(); diff --git a/Source/Tests/LinuxSyscalls/x32/Time.cpp b/Source/Tests/LinuxSyscalls/x32/Time.cpp index e3b8a5fc4..d0394bf33 100644 --- a/Source/Tests/LinuxSyscalls/x32/Time.cpp +++ b/Source/Tests/LinuxSyscalls/x32/Time.cpp @@ -15,6 +15,7 @@ $end_info$ #include #include #include +#include ARG_TO_STR(FEX::HLE::x32::compat_ptr, "%lx") @@ -25,6 +26,39 @@ namespace FEXCore::Core { namespace FEX::HLE::x32 { void RegisterTime() { + + REGISTER_SYSCALL_IMPL_X32(time, [](FEXCore::Core::CpuStateFrame *Frame, FEX::HLE::x32::old_time32_t *tloc) -> uint64_t { + time_t Host{}; + uint64_t Result = ::time(&Host); + + if (tloc) { + // On 32-bit this truncates + *tloc = (FEX::HLE::x32::old_time32_t)Host; + } + + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL_X32(times, [](FEXCore::Core::CpuStateFrame *Frame, struct FEX::HLE::x32::compat_tms *buf) -> uint64_t { + struct tms Host{}; + uint64_t Result = ::times(&Host); + if (buf) { + *buf = Host; + } + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL_X32(utime, [](FEXCore::Core::CpuStateFrame *Frame, char* filename, const FEX::HLE::x32::old_utimbuf32* times) -> uint64_t { + struct utimbuf Host{}; + struct utimbuf *Host_p{}; + if (times) { + Host = *times; + Host_p = &Host; + } + uint64_t Result = ::utime(filename, Host_p); + SYSCALL_ERRNO(); + }); + REGISTER_SYSCALL_IMPL_X32(gettimeofday, [](FEXCore::Core::CpuStateFrame *Frame, timeval32 *tv, struct timezone *tz) -> uint64_t { struct timeval tv64{}; struct timeval *tv_ptr{}; diff --git a/Source/Tests/LinuxSyscalls/x32/Timer.cpp b/Source/Tests/LinuxSyscalls/x32/Timer.cpp index d307019e4..a0bdf6edb 100644 --- a/Source/Tests/LinuxSyscalls/x32/Timer.cpp +++ b/Source/Tests/LinuxSyscalls/x32/Timer.cpp @@ -5,6 +5,7 @@ $end_info$ */ #include "Tests/LinuxSyscalls/Syscalls.h" +#include "Tests/LinuxSyscalls/Types.h" #include "Tests/LinuxSyscalls/x32/Syscalls.h" #include "Tests/LinuxSyscalls/x32/Types.h" @@ -20,12 +21,42 @@ namespace FEXCore::Core { namespace FEX::HLE::x32 { void RegisterTimer() { - REGISTER_SYSCALL_IMPL_X32(timer_settime64, [](FEXCore::Core::CpuStateFrame *Frame, timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) -> uint64_t { + REGISTER_SYSCALL_IMPL_X32(timer_settime, [](FEXCore::Core::CpuStateFrame *Frame, + kernel_timer_t timerid, + int flags, + const FEX::HLE::x32::old_itimerspec32 *new_value, + FEX::HLE::x32::old_itimerspec32 *old_value) -> uint64_t { + itimerspec new_value_host{}; + itimerspec old_value_host{}; + itimerspec *old_value_host_p{}; + + new_value_host = *new_value; + if (old_value) { + old_value_host_p = &old_value_host; + } + uint64_t Result = ::syscall(SYS_timer_settime, timerid, flags, &new_value_host, old_value_host_p); + if (Result != -1 && old_value) { + *old_value = old_value_host; + } + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL_X32(timer_gettime, [](FEXCore::Core::CpuStateFrame *Frame, + kernel_timer_t timerid, + FEX::HLE::x32::old_itimerspec32 *curr_value) -> uint64_t { + itimerspec curr_value_host{}; + uint64_t Result = ::syscall(SYS_timer_gettime, timerid, curr_value_host); + *curr_value = curr_value_host; + SYSCALL_ERRNO(); + }); + + + REGISTER_SYSCALL_IMPL_X32(timer_settime64, [](FEXCore::Core::CpuStateFrame *Frame, kernel_timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) -> uint64_t { uint64_t Result = ::syscall(SYS_timer_settime, timerid, flags, new_value, old_value); SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL_X32(timer_gettime64, [](FEXCore::Core::CpuStateFrame *Frame, timer_t timerid, struct itimerspec *curr_value) -> uint64_t { + REGISTER_SYSCALL_IMPL_X32(timer_gettime64, [](FEXCore::Core::CpuStateFrame *Frame, kernel_timer_t timerid, struct itimerspec *curr_value) -> uint64_t { uint64_t Result = ::syscall(SYS_timer_gettime, timerid, curr_value); SYSCALL_ERRNO(); }); diff --git a/Source/Tests/LinuxSyscalls/x32/Types.h b/Source/Tests/LinuxSyscalls/x32/Types.h index 23aafe336..a9a26e33f 100644 --- a/Source/Tests/LinuxSyscalls/x32/Types.h +++ b/Source/Tests/LinuxSyscalls/x32/Types.h @@ -18,9 +18,13 @@ $end_info$ #include #include #include +#include #include #include #include +#include + +#include "Tests/LinuxSyscalls/Types.h" namespace FEX::HLE::x32 { @@ -39,6 +43,8 @@ using compat_nlink_t = uint16_t; using compat_uid_t = uint16_t; using compat_gid_t = uint16_t; using compat_old_sigset_t = uint32_t; +using old_time32_t = int32_t; +using compat_clock_t = int32_t; // Can't use using with aligned attributes, clang doesn't honour it typedef FEX_ALIGNED(4) uint64_t compat_uint64_t; @@ -832,4 +838,81 @@ GuestSigAction_32 { static_assert(std::is_trivial::value, "Needs to be trivial"); static_assert(sizeof(GuestSigAction_32) == 20, "Incorrect size"); +struct +FEX_ANNOTATE("alias-x86_32-tms") +FEX_ANNOTATE("fex-match") +compat_tms { + compat_clock_t tms_utime; + compat_clock_t tms_stime; + compat_clock_t tms_cutime; + compat_clock_t tms_cstime; + + compat_tms() = delete; + operator tms() const { + tms val{}; + val.tms_utime = tms_utime; + val.tms_stime = tms_stime; + val.tms_cutime = tms_cutime; + val.tms_cstime = tms_cstime; + return val; + } + compat_tms(struct tms val) { + tms_utime = val.tms_utime; + tms_stime = val.tms_stime; + tms_cutime = val.tms_cutime; + tms_cstime = val.tms_cstime; + } +}; + +static_assert(std::is_trivial::value, "Needs to be trivial"); +static_assert(sizeof(compat_tms) == 16, "Incorrect size"); + +struct +FEX_ANNOTATE("alias-x86_32-utimbuf") +FEX_ANNOTATE("fex-match") +old_utimbuf32 { + old_time32_t actime; + old_time32_t modtime; + + old_utimbuf32() = delete; + operator utimbuf() const { + utimbuf val{}; + val.actime = actime; + val.modtime = modtime; + return val; + } + + old_utimbuf32(struct utimbuf val) { + actime = val.actime; + modtime = val.modtime; + } +}; + +static_assert(std::is_trivial::value, "Needs to be trivial"); +static_assert(sizeof(old_utimbuf32) == 8, "Incorrect size"); + +struct +FEX_ANNOTATE("alias-x86_32-itimerspec") +FEX_ANNOTATE("fex-match") +old_itimerspec32 { + timespec32 it_interval; + timespec32 it_value; + + old_itimerspec32() = delete; + operator itimerspec() const { + itimerspec val{}; + val.it_interval = it_interval; + val.it_value = it_value; + return val; + } + + old_itimerspec32(struct itimerspec val) + : it_interval { val.it_interval } + , it_value { val.it_value } { + } +}; + +static_assert(std::is_trivial::value, "Needs to be trivial"); +static_assert(sizeof(old_itimerspec32) == 16, "Incorrect size"); + } diff --git a/Source/Tests/LinuxSyscalls/x64/EPoll.cpp b/Source/Tests/LinuxSyscalls/x64/EPoll.cpp index 5585106e8..8d7c54bf6 100644 --- a/Source/Tests/LinuxSyscalls/x64/EPoll.cpp +++ b/Source/Tests/LinuxSyscalls/x64/EPoll.cpp @@ -6,7 +6,9 @@ $end_info$ */ #include "Tests/LinuxSyscalls/Syscalls.h" +#include "Tests/LinuxSyscalls/Types.h" #include "Tests/LinuxSyscalls/x64/Syscalls.h" +#include "Tests/LinuxSyscalls/x64/Types.h" #include #include @@ -23,7 +25,7 @@ namespace FEXCore::Core { namespace FEX::HLE::x64 { void RegisterEpoll(FEX::HLE::SyscallHandler *const Handler) { - REGISTER_SYSCALL_IMPL_X64(epoll_wait, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, epoll_event_x86 *events, int maxevents, int timeout) -> uint64_t { + REGISTER_SYSCALL_IMPL_X64(epoll_wait, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, FEX::HLE::epoll_event_x86 *events, int maxevents, int timeout) -> uint64_t { std::vector Events(std::max(0, maxevents)); uint64_t Result = ::syscall(SYS_epoll_pwait, epfd, Events.data(), maxevents, timeout, nullptr, 8); @@ -35,7 +37,7 @@ namespace FEX::HLE::x64 { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL_X64(epoll_ctl, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, int op, int fd, epoll_event_x86 *event) -> uint64_t { + REGISTER_SYSCALL_IMPL_X64(epoll_ctl, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, int op, int fd, FEX::HLE::epoll_event_x86 *event) -> uint64_t { struct epoll_event Event; struct epoll_event *EventPtr{}; if (event) { @@ -49,7 +51,7 @@ namespace FEX::HLE::x64 { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL_X64(epoll_pwait, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, epoll_event_x86 *events, int maxevent, int timeout, const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { + REGISTER_SYSCALL_IMPL_X64(epoll_pwait, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, FEX::HLE::epoll_event_x86 *events, int maxevent, int timeout, const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { std::vector Events(std::max(0, maxevent)); uint64_t Result = ::syscall(SYS_epoll_pwait, @@ -73,7 +75,7 @@ namespace FEX::HLE::x64 { #ifndef SYS_epoll_pwait2 #define SYS_epoll_pwait2 354 #endif - REGISTER_SYSCALL_IMPL_X64(epoll_pwait2, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, epoll_event_x86 *events, int maxevent, timespec *timeout, const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { + REGISTER_SYSCALL_IMPL_X64(epoll_pwait2, [](FEXCore::Core::CpuStateFrame *Frame, int epfd, FEX::HLE::epoll_event_x86 *events, int maxevent, timespec *timeout, const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { std::vector Events(std::max(0, maxevent)); uint64_t Result = ::syscall(SYS_epoll_pwait2, diff --git a/Source/Tests/LinuxSyscalls/x64/FD.cpp b/Source/Tests/LinuxSyscalls/x64/FD.cpp index 39ee64c47..3d63dea6c 100644 --- a/Source/Tests/LinuxSyscalls/x64/FD.cpp +++ b/Source/Tests/LinuxSyscalls/x64/FD.cpp @@ -7,10 +7,10 @@ $end_info$ #include "Tests/LinuxSyscalls/FileManagement.h" #include "Tests/LinuxSyscalls/Syscalls.h" #include "Tests/LinuxSyscalls/x64/Syscalls.h" +#include "Tests/LinuxSyscalls/x64/Types.h" #include -#include #include #include #include @@ -20,60 +20,12 @@ $end_info$ #include #include #include +#include #include #include #include namespace FEX::HLE::x64 { - struct FEX_PACKED guest_stat { - __kernel_ulong_t st_dev; - __kernel_ulong_t st_ino; - __kernel_ulong_t st_nlink; - - unsigned int st_mode; - unsigned int st_uid; - unsigned int st_gid; - unsigned int __pad0; - __kernel_ulong_t st_rdev; - __kernel_long_t st_size; - __kernel_long_t st_blksize; - __kernel_long_t st_blocks; /* Number 512-byte blocks allocated. */ - - __kernel_ulong_t st_atime_; - __kernel_ulong_t st_atime_nsec; - __kernel_ulong_t st_mtime_; - __kernel_ulong_t st_mtime_nsec; - __kernel_ulong_t st_ctime_; - __kernel_ulong_t st_ctime_nsec; - __kernel_long_t __unused[3]; - }; - - static void CopyStat(guest_stat *guest, struct stat *host) { -#define COPY(x) guest->x = host->x - COPY(st_dev); - COPY(st_ino); - COPY(st_nlink); - - COPY(st_mode); - COPY(st_uid); - COPY(st_gid); - - COPY(st_rdev); - COPY(st_size); - COPY(st_blksize); - COPY(st_blocks); - - guest->st_atime_ = host->st_atim.tv_sec; - guest->st_atime_nsec = host->st_atim.tv_nsec; - - guest->st_mtime_ = host->st_mtime; - guest->st_mtime_nsec = host->st_mtim.tv_nsec; - - guest->st_ctime_ = host->st_ctime; - guest->st_ctime_nsec = host->st_ctim.tv_nsec; -#undef COPY - } - void RegisterFD() { REGISTER_SYSCALL_IMPL_X64(poll, [](FEXCore::Core::CpuStateFrame *Frame, struct pollfd *fds, nfds_t nfds, int timeout) -> uint64_t { uint64_t Result = ::poll(fds, nfds, timeout); @@ -119,29 +71,29 @@ namespace FEX::HLE::x64 { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL_X64(stat, [](FEXCore::Core::CpuStateFrame *Frame, const char *pathname, guest_stat *buf) -> uint64_t { + REGISTER_SYSCALL_IMPL_X64(stat, [](FEXCore::Core::CpuStateFrame *Frame, const char *pathname, FEX::HLE::x64::guest_stat *buf) -> uint64_t { struct stat host_stat; uint64_t Result = FEX::HLE::_SyscallHandler->FM.Stat(pathname, &host_stat); if (Result != -1) { - CopyStat(buf, &host_stat); + *buf = host_stat; } SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL_X64(fstat, [](FEXCore::Core::CpuStateFrame *Frame, int fd, guest_stat *buf) -> uint64_t { + REGISTER_SYSCALL_IMPL_X64(fstat, [](FEXCore::Core::CpuStateFrame *Frame, int fd, FEX::HLE::x64::guest_stat *buf) -> uint64_t { struct stat host_stat; uint64_t Result = ::fstat(fd, &host_stat); if (Result != -1) { - CopyStat(buf, &host_stat); + *buf = host_stat; } SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL_X64(lstat, [](FEXCore::Core::CpuStateFrame *Frame, const char *path, guest_stat *buf) -> uint64_t { + REGISTER_SYSCALL_IMPL_X64(lstat, [](FEXCore::Core::CpuStateFrame *Frame, const char *path, FEX::HLE::x64::guest_stat *buf) -> uint64_t { struct stat host_stat; uint64_t Result = FEX::HLE::_SyscallHandler->FM.Lstat(path, &host_stat); if (Result != -1) { - CopyStat(buf, &host_stat); + *buf = host_stat; } SYSCALL_ERRNO(); }); @@ -161,11 +113,11 @@ namespace FEX::HLE::x64 { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL_X64(newfstatat, [](FEXCore::Core::CpuStateFrame *Frame, int dirfd, const char *pathname, guest_stat *buf, int flag) -> uint64_t { + REGISTER_SYSCALL_IMPL_X64(newfstatat, [](FEXCore::Core::CpuStateFrame *Frame, int dirfd, const char *pathname, FEX::HLE::x64::guest_stat *buf, int flag) -> uint64_t { struct stat host_stat; uint64_t Result = FEX::HLE::_SyscallHandler->FM.NewFSStatAt(dirfd, pathname, &host_stat, flag); if (Result != -1) { - CopyStat(buf, &host_stat); + *buf = host_stat; } SYSCALL_ERRNO(); }); @@ -299,5 +251,16 @@ namespace FEX::HLE::x64 { uint64_t Result = ::fallocate(fd, mode, offset, len); SYSCALL_ERRNO(); }); + + REGISTER_SYSCALL_IMPL_X64(timerfd_settime, [](FEXCore::Core::CpuStateFrame *Frame, int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) -> uint64_t { + // Flags don't need remapped + uint64_t Result = ::timerfd_settime(fd, flags, new_value, old_value); + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL_X64(timerfd_gettime, [](FEXCore::Core::CpuStateFrame *Frame, int fd, struct itimerspec *curr_value) -> uint64_t { + uint64_t Result = ::timerfd_gettime(fd, curr_value); + SYSCALL_ERRNO(); + }); } } diff --git a/Source/Tests/LinuxSyscalls/x64/Syscalls.cpp b/Source/Tests/LinuxSyscalls/x64/Syscalls.cpp index 7180fcffb..f9b30e46f 100644 --- a/Source/Tests/LinuxSyscalls/x64/Syscalls.cpp +++ b/Source/Tests/LinuxSyscalls/x64/Syscalls.cpp @@ -107,6 +107,7 @@ namespace FEX::HLE::x64 { FEX::HLE::RegisterKey(); FEX::HLE::RegisterMemory(); FEX::HLE::RegisterMsg(); + FEX::HLE::RegisterNamespace(this); FEX::HLE::RegisterSched(); FEX::HLE::RegisterSemaphore(); FEX::HLE::RegisterSHM(); diff --git a/Source/Tests/LinuxSyscalls/x64/Time.cpp b/Source/Tests/LinuxSyscalls/x64/Time.cpp index e59e30ed2..f74c0ca4e 100644 --- a/Source/Tests/LinuxSyscalls/x64/Time.cpp +++ b/Source/Tests/LinuxSyscalls/x64/Time.cpp @@ -5,6 +5,7 @@ $end_info$ */ #include "Tests/LinuxSyscalls/Syscalls.h" +#include "Tests/LinuxSyscalls/Types.h" #include "Tests/LinuxSyscalls/x64/Syscalls.h" #include @@ -19,6 +20,21 @@ $end_info$ namespace FEX::HLE::x64 { void RegisterTime() { + REGISTER_SYSCALL_IMPL_X64(time, [](FEXCore::Core::CpuStateFrame *Frame, time_t *tloc) -> uint64_t { + uint64_t Result = ::time(tloc); + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL_X64(times, [](FEXCore::Core::CpuStateFrame *Frame, struct tms *buf) -> uint64_t { + uint64_t Result = ::times(buf); + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL_X64(utime, [](FEXCore::Core::CpuStateFrame *Frame, char* filename, const struct utimbuf* times) -> uint64_t { + uint64_t Result = ::utime(filename, times); + SYSCALL_ERRNO(); + }); + REGISTER_SYSCALL_IMPL_X64(gettimeofday, [](FEXCore::Core::CpuStateFrame *Frame, struct timeval *tv, struct timezone *tz) -> uint64_t { uint64_t Result = ::gettimeofday(tv, tz); SYSCALL_ERRNO(); @@ -68,6 +84,16 @@ namespace FEX::HLE::x64 { uint64_t Result = ::setitimer(which, new_value, old_value); SYSCALL_ERRNO(); }); + + REGISTER_SYSCALL_IMPL_X64(timer_settime, [](FEXCore::Core::CpuStateFrame *Frame, kernel_timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) -> uint64_t { + uint64_t Result = ::syscall(SYS_timer_settime, timerid, flags, new_value, old_value); + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL_X64(timer_gettime, [](FEXCore::Core::CpuStateFrame *Frame, kernel_timer_t timerid, struct itimerspec *curr_value) -> uint64_t { + uint64_t Result = ::syscall(SYS_timer_gettime, timerid, curr_value); + SYSCALL_ERRNO(); + }); } } diff --git a/Source/Tests/LinuxSyscalls/x64/Types.h b/Source/Tests/LinuxSyscalls/x64/Types.h index 979a1cc9b..c1e0b79ef 100644 --- a/Source/Tests/LinuxSyscalls/x64/Types.h +++ b/Source/Tests/LinuxSyscalls/x64/Types.h @@ -6,8 +6,12 @@ $end_info$ #pragma once +#include + +#include #include #include +#include #include namespace FEX::HLE::x64 { @@ -112,4 +116,89 @@ using __time_t = time_t; static_assert(std::is_trivial::value, "Needs to be trivial"); static_assert(sizeof(FEX::HLE::x64::semun) == 8, "Incorrect size"); + + struct + FEX_ANNOTATE("fex-match") + FEX_PACKED + guest_stat { + __kernel_ulong_t st_dev; + __kernel_ulong_t st_ino; + __kernel_ulong_t st_nlink; + + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad0; + __kernel_ulong_t st_rdev; + __kernel_long_t st_size; + __kernel_long_t st_blksize; + __kernel_long_t st_blocks; /* Number 512-byte blocks allocated. */ + + __kernel_ulong_t st_atime_; + __kernel_ulong_t st_atime_nsec; + __kernel_ulong_t st_mtime_; + __kernel_ulong_t st_mtime_nsec; + __kernel_ulong_t st_ctime_; + __kernel_ulong_t st_ctime_nsec; + __kernel_long_t __unused[3]; + + guest_stat() = delete; + operator struct stat() const { + struct stat val{}; +#define COPY(x) val.x = x + COPY(st_dev); + COPY(st_ino); + COPY(st_nlink); + + COPY(st_mode); + COPY(st_uid); + COPY(st_gid); + + COPY(st_rdev); + COPY(st_size); + COPY(st_blksize); + COPY(st_blocks); + + val.st_atim.tv_sec = st_atime_; + val.st_atim.tv_nsec = st_atime_nsec; + + val.st_mtim.tv_sec = st_mtime_; + val.st_mtim.tv_nsec = st_mtime_nsec; + + val.st_ctim.tv_sec = st_ctime_; + val.st_ctim.tv_nsec= st_ctime_nsec; +#undef COPY + return val; + } + + guest_stat(struct stat val) { +#define COPY(x) x = val.x + COPY(st_dev); + COPY(st_ino); + COPY(st_nlink); + + COPY(st_mode); + COPY(st_uid); + COPY(st_gid); + + COPY(st_rdev); + COPY(st_size); + COPY(st_blksize); + COPY(st_blocks); + + st_atime_ = val.st_atim.tv_sec; + st_atime_nsec = val.st_atim.tv_nsec; + + st_mtime_ = val.st_mtime; + st_mtime_nsec = val.st_mtim.tv_nsec; + + st_ctime_ = val.st_ctime; + st_ctime_nsec = val.st_ctim.tv_nsec; +#undef COPY + } + }; + + // Original definition in `arch/x86/include/uapi/asm/stat.h` for future excavation + static_assert(std::is_trivial::value, "Needs to be trivial"); + static_assert(sizeof(FEX::HLE::x64::guest_stat) == 144, "Incorrect size"); }