@@ -390,191 +390,206 @@ uint64_t ForkGuest(FEXCore::Core::InternalThreadState* Thread, FEXCore::Core::Cp
390390 }
391391}
392392
393- void RegisterThread (FEX::HLE::SyscallHandler* Handler) {
394- using namespace FEXCore ::IR;
395-
396- REGISTER_SYSCALL_IMPL (rt_sigreturn, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
397- FEX::HLE::_SyscallHandler->GetSignalDelegator ()->HandleSignalHandlerReturn (true );
398- FEX_UNREACHABLE;
399- });
400-
401- REGISTER_SYSCALL_IMPL (fork, ([](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
402- FEX::HLE::clone3_args args {.Type = TypeOfClone::TYPE_CLONE2,
403- .args = {
404- .flags = 0 ,
405- .pidfd = 0 ,
406- .child_tid = 0 ,
407- .parent_tid = 0 ,
408- .exit_signal = SIGCHLD,
409- .stack = 0 ,
410- .stack_size = 0 ,
411- .tls = 0 ,
412- .set_tid = 0 ,
413- .set_tid_size = 0 ,
414- .cgroup = 0 ,
415- }};
416-
417- return ForkGuest (Frame->Thread , Frame, &args);
418- }));
419-
420- REGISTER_SYSCALL_IMPL (vfork, ([](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
421- FEX::HLE::clone3_args args {.Type = TypeOfClone::TYPE_CLONE2,
422- .args = {
423- .flags = CLONE_VFORK,
424- .pidfd = 0 ,
425- .child_tid = 0 ,
426- .parent_tid = 0 ,
427- .exit_signal = SIGCHLD,
428- .stack = 0 ,
429- .stack_size = 0 ,
430- .tls = 0 ,
431- .set_tid = 0 ,
432- .set_tid_size = 0 ,
433- .cgroup = 0 ,
434- }};
435-
436- return ForkGuest (Frame->Thread , Frame, &args);
437- }));
438-
439- REGISTER_SYSCALL_IMPL (getpgrp, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
440- uint64_t Result = ::getpgrp ();
441- SYSCALL_ERRNO ();
442- });
443-
444- REGISTER_SYSCALL_IMPL (clone3, ([](FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::kernel_clone3_args* cl_args, size_t size) -> uint64_t {
445- FEX::HLE::clone3_args args {};
446- args.Type = TypeOfClone::TYPE_CLONE3;
447- memcpy (&args.args , cl_args, std::min (sizeof (FEX::HLE::kernel_clone3_args), size));
448- return CloneHandler (Frame, &args);
449- }));
450-
451- REGISTER_SYSCALL_IMPL (exit, [](FEXCore::Core::CpuStateFrame* Frame, int status) -> uint64_t {
452- // TLS/DTV teardown is something FEX can't control. Disable glibc checking when we leave a pthread.
453- // Since this thread is hard stopping, we can't track the TLS/DTV teardown in FEX's thread handling.
454- FEXCore::Allocator::YesIKnowImNotSupposedToUseTheGlibcAllocator::HardDisable ();
455- auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState (Frame);
456-
457- if (ThreadObject->ThreadInfo .clear_child_tid ) {
458- auto Addr = std::atomic_ref<int32_t >(*ThreadObject->ThreadInfo .clear_child_tid );
459- Addr.store (0 );
460- syscall (SYSCALL_DEF (futex), ThreadObject->ThreadInfo .clear_child_tid , FUTEX_WAKE, ~0ULL , 0 , 0 , 0 );
461- }
393+ using namespace FEXCore ::IR;
462394
463- ThreadObject->StatusCode = status;
395+ auto rt_sigreturn (FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
396+ FEX::HLE::_SyscallHandler->GetSignalDelegator ()->HandleSignalHandlerReturn (true );
397+ FEX_UNREACHABLE;
398+ }
464399
465- FEX::HLE::_SyscallHandler->UninstallTLSState (ThreadObject);
400+ auto fork (FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
401+ FEX::HLE::clone3_args args {.Type = TypeOfClone::TYPE_CLONE2,
402+ .args = {
403+ .flags = 0 ,
404+ .pidfd = 0 ,
405+ .child_tid = 0 ,
406+ .parent_tid = 0 ,
407+ .exit_signal = SIGCHLD,
408+ .stack = 0 ,
409+ .stack_size = 0 ,
410+ .tls = 0 ,
411+ .set_tid = 0 ,
412+ .set_tid_size = 0 ,
413+ .cgroup = 0 ,
414+ }};
415+
416+ return ForkGuest (Frame->Thread , Frame, &args);
417+ }
466418
467- if (ThreadObject->ExecutionThread ) {
468- // If this is a pthread based execution thread, then there is more work to be done.
469- // Delegate final deletion and cleanup to the pthreads Thread management.
470- FEX::LinuxEmulation::Threads::LongjumpDeallocateAndExit (ThreadObject, status);
471- } else {
472- FEX::HLE::_SyscallHandler->TM .DestroyThread (ThreadObject, true );
473- FEX::LinuxEmulation::Threads::DeallocateStackObjectAndExit (nullptr , status);
474- }
475- // This will never be reached
476- std::terminate ();
477- });
478-
479- REGISTER_SYSCALL_IMPL (prctl,
480- [](FEXCore::Core::CpuStateFrame* Frame, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4,
481- unsigned long arg5) -> uint64_t {
482- uint64_t Result {};
419+ auto vfork (FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
420+ FEX::HLE::clone3_args args {.Type = TypeOfClone::TYPE_CLONE2,
421+ .args = {
422+ .flags = CLONE_VFORK,
423+ .pidfd = 0 ,
424+ .child_tid = 0 ,
425+ .parent_tid = 0 ,
426+ .exit_signal = SIGCHLD,
427+ .stack = 0 ,
428+ .stack_size = 0 ,
429+ .tls = 0 ,
430+ .set_tid = 0 ,
431+ .set_tid_size = 0 ,
432+ .cgroup = 0 ,
433+ }};
434+
435+ return ForkGuest (Frame->Thread , Frame, &args);
436+ }
437+
438+ auto getpgrp (FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
439+ uint64_t Result = ::getpgrp ();
440+ SYSCALL_ERRNO ();
441+ }
442+
443+ auto clone3 (FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::kernel_clone3_args* cl_args, size_t size) -> uint64_t {
444+ FEX::HLE::clone3_args args {};
445+ args.Type = TypeOfClone::TYPE_CLONE3;
446+ memcpy (&args.args , cl_args, std::min (sizeof (FEX::HLE::kernel_clone3_args), size));
447+ return CloneHandler (Frame, &args);
448+ }
449+
450+ auto exit (FEXCore::Core::CpuStateFrame* Frame, int status) -> uint64_t {
451+ // TLS/DTV teardown is something FEX can't control. Disable glibc checking when we leave a pthread.
452+ // Since this thread is hard stopping, we can't track the TLS/DTV teardown in FEX's thread handling.
453+ FEXCore::Allocator::YesIKnowImNotSupposedToUseTheGlibcAllocator::HardDisable ();
454+ auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState (Frame);
455+
456+ if (ThreadObject->ThreadInfo .clear_child_tid ) {
457+ auto Addr = std::atomic_ref<int32_t >(*ThreadObject->ThreadInfo .clear_child_tid );
458+ Addr.store (0 );
459+ syscall (SYSCALL_DEF (futex), ThreadObject->ThreadInfo .clear_child_tid , FUTEX_WAKE, ~0ULL , 0 , 0 , 0 );
460+ }
461+
462+ ThreadObject->StatusCode = status;
463+
464+ FEX::HLE::_SyscallHandler->UninstallTLSState (ThreadObject);
465+
466+ if (ThreadObject->ExecutionThread ) {
467+ // If this is a pthread based execution thread, then there is more work to be done.
468+ // Delegate final deletion and cleanup to the pthreads Thread management.
469+ FEX::LinuxEmulation::Threads::LongjumpDeallocateAndExit (ThreadObject, status);
470+ } else {
471+ FEX::HLE::_SyscallHandler->TM .DestroyThread (ThreadObject, true );
472+ FEX::LinuxEmulation::Threads::DeallocateStackObjectAndExit (nullptr , status);
473+ }
474+ // This will never be reached
475+ std::terminate ();
476+ }
477+
478+ auto prctl (FEXCore::Core::CpuStateFrame* Frame, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
479+ -> uint64_t {
480+ uint64_t Result {};
483481#ifndef PR_GET_AUXV
484482#define PR_GET_AUXV 0x41555856
485483#endif
486- switch (option) {
487- case PR_SET_SECCOMP: {
488- uint32_t Operation {};
489- if (arg2 == SECCOMP_MODE_STRICT) Operation = SECCOMP_SET_MODE_STRICT;
490- if (arg2 == SECCOMP_MODE_FILTER) Operation = SECCOMP_SET_MODE_FILTER;
491-
492- return FEX::HLE::_SyscallHandler->SeccompEmulator .Handle (Frame, Operation, 0 , reinterpret_cast <void *>(arg3));
493- }
494- case PR_GET_SECCOMP: return FEX::HLE::_SyscallHandler->SeccompEmulator .GetSeccomp (Frame);
495- case PR_GET_AUXV: {
496- if (arg4 || arg5) {
497- return -EINVAL;
498- }
499-
500- void * addr = reinterpret_cast <void *>(arg2);
501- size_t UserSize = reinterpret_cast <size_t >(arg3);
502-
503- const auto auxv = FEX::HLE::_SyscallHandler->GetCodeLoader ()->GetAuxv ();
504- const auto auxvBase = auxv.address ;
505- const auto auxvSize = auxv.size ;
506- size_t MinSize = std::min (auxvSize, UserSize);
507-
508- memcpy (addr, reinterpret_cast <void *>(auxvBase), MinSize);
509-
510- // Returns the size of auxv without truncation.
511- return auxvSize;
512- }
513- default : Result = ::prctl (option, arg2, arg3, arg4, arg5); break ;
514- }
515- SYSCALL_ERRNO ();
516- });
517-
518- REGISTER_SYSCALL_IMPL (arch_prctl, [](FEXCore::Core::CpuStateFrame* Frame, int code, unsigned long addr) -> uint64_t {
519- uint64_t Result {};
520- switch (code) {
521- case 0x1001 : // ARCH_SET_GS
522- if (addr >= SyscallHandler::TASK_MAX_64BIT) {
523- // Ignore a non-canonical address
524- return -EPERM;
525- }
526- Frame->State .gs_cached = addr;
527- Result = 0 ;
528- break ;
529- case 0x1002 : // ARCH_SET_FS
530- if (addr >= SyscallHandler::TASK_MAX_64BIT) {
531- // Ignore a non-canonical address
532- return -EPERM;
533- }
534- Frame->State .fs_cached = addr;
535- Result = 0 ;
536- break ;
537- case 0x1003 : // ARCH_GET_FS
538- *reinterpret_cast <uint64_t *>(addr) = Frame->State .fs_cached ;
539- Result = 0 ;
540- break ;
541- case 0x1004 : // ARCH_GET_GS
542- *reinterpret_cast <uint64_t *>(addr) = Frame->State .gs_cached ;
543- Result = 0 ;
544- break ;
545- case 0x3001 : // ARCH_CET_STATUS
546- Result = -EINVAL; // We don't support CET, return EINVAL
547- break ;
548- case 0x1011 : // ARCH_GET_CPUID
549- return 1 ;
550- break ;
551- case 0x1012 : // ARCH_SET_CPUID
552- return -ENODEV; // Claim we don't support faulting on CPUID
553- break ;
554- default :
555- LogMan::Msg::EFmt (" Unknown prctl: 0x{:x}" , code);
556- Result = -EINVAL;
557- break ;
484+ switch (option) {
485+ case PR_SET_SECCOMP: {
486+ uint32_t Operation {};
487+ if (arg2 == SECCOMP_MODE_STRICT) {
488+ Operation = SECCOMP_SET_MODE_STRICT;
489+ }
490+ if (arg2 == SECCOMP_MODE_FILTER) {
491+ Operation = SECCOMP_SET_MODE_FILTER;
492+ }
493+
494+ return FEX::HLE::_SyscallHandler->SeccompEmulator .Handle (Frame, Operation, 0 , reinterpret_cast <void *>(arg3));
495+ }
496+ case PR_GET_SECCOMP: return FEX::HLE::_SyscallHandler->SeccompEmulator .GetSeccomp (Frame);
497+ case PR_GET_AUXV: {
498+ if (arg4 || arg5) {
499+ return -EINVAL;
558500 }
559- SYSCALL_ERRNO ();
560- });
561501
562- REGISTER_SYSCALL_IMPL (set_tid_address, [](FEXCore::Core::CpuStateFrame* Frame, int * tidptr) -> uint64_t {
563- auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState (Frame);
564- ThreadObject->ThreadInfo .clear_child_tid = tidptr;
565- return ThreadObject->ThreadInfo .TID ;
566- });
502+ void * addr = reinterpret_cast <void *>(arg2);
503+ size_t UserSize = reinterpret_cast <size_t >(arg3);
567504
568- REGISTER_SYSCALL_IMPL (exit_group, [](FEXCore::Core::CpuStateFrame* Frame, int status) -> uint64_t {
569- Frame->Thread ->CTX ->FlushAndCloseCodeMap ();
505+ const auto auxv = FEX::HLE::_SyscallHandler->GetCodeLoader ()->GetAuxv ();
506+ const auto auxvBase = auxv.address ;
507+ const auto auxvSize = auxv.size ;
508+ size_t MinSize = std::min (auxvSize, UserSize);
570509
571- // Save telemetry if we're exiting.
572- FEX::HLE::_SyscallHandler->GetSignalDelegator ()->SaveTelemetry ();
573- FEX::HLE::_SyscallHandler->TM .CleanupForExit ();
510+ memcpy (addr, reinterpret_cast <void *>(auxvBase), MinSize);
574511
575- syscall (SYSCALL_DEF (exit_group), status);
576- // This will never be reached
577- std::terminate ();
578- });
512+ // Returns the size of auxv without truncation.
513+ return auxvSize;
514+ }
515+ default : Result = ::prctl (option, arg2, arg3, arg4, arg5); break ;
516+ }
517+ SYSCALL_ERRNO ();
518+ }
519+
520+ auto arch_prctl (FEXCore::Core::CpuStateFrame* Frame, int code, unsigned long addr) -> uint64_t {
521+ uint64_t Result {};
522+ switch (code) {
523+ case 0x1001 : // ARCH_SET_GS
524+ if (addr >= SyscallHandler::TASK_MAX_64BIT) {
525+ // Ignore a non-canonical address
526+ return -EPERM;
527+ }
528+ Frame->State .gs_cached = addr;
529+ Result = 0 ;
530+ break ;
531+ case 0x1002 : // ARCH_SET_FS
532+ if (addr >= SyscallHandler::TASK_MAX_64BIT) {
533+ // Ignore a non-canonical address
534+ return -EPERM;
535+ }
536+ Frame->State .fs_cached = addr;
537+ Result = 0 ;
538+ break ;
539+ case 0x1003 : // ARCH_GET_FS
540+ *reinterpret_cast <uint64_t *>(addr) = Frame->State .fs_cached ;
541+ Result = 0 ;
542+ break ;
543+ case 0x1004 : // ARCH_GET_GS
544+ *reinterpret_cast <uint64_t *>(addr) = Frame->State .gs_cached ;
545+ Result = 0 ;
546+ break ;
547+ case 0x3001 : // ARCH_CET_STATUS
548+ Result = -EINVAL; // We don't support CET, return EINVAL
549+ break ;
550+ case 0x1011 : // ARCH_GET_CPUID
551+ return 1 ;
552+ break ;
553+ case 0x1012 : // ARCH_SET_CPUID
554+ return -ENODEV; // Claim we don't support faulting on CPUID
555+ break ;
556+ default :
557+ LogMan::Msg::EFmt (" Unknown prctl: 0x{:x}" , code);
558+ Result = -EINVAL;
559+ break ;
560+ }
561+ SYSCALL_ERRNO ();
562+ }
563+
564+ auto set_tid_address (FEXCore::Core::CpuStateFrame* Frame, int * tidptr) -> uint64_t {
565+ auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState (Frame);
566+ ThreadObject->ThreadInfo .clear_child_tid = tidptr;
567+ return ThreadObject->ThreadInfo .TID ;
568+ }
569+
570+ auto exit_group (FEXCore::Core::CpuStateFrame* Frame, int status) -> uint64_t {
571+ Frame->Thread ->CTX ->FlushAndCloseCodeMap ();
572+
573+ // Save telemetry if we're exiting.
574+ FEX::HLE::_SyscallHandler->GetSignalDelegator ()->SaveTelemetry ();
575+ FEX::HLE::_SyscallHandler->TM .CleanupForExit ();
576+
577+ syscall (SYSCALL_DEF (exit_group), status);
578+ // This will never be reached
579+ std::terminate ();
580+ }
581+
582+
583+ void RegisterThread (FEX::HLE::SyscallHandler* Handler) {
584+ REGISTER_SYSCALL_IMPL (rt_sigreturn, rt_sigreturn);
585+ REGISTER_SYSCALL_IMPL (fork, fork);
586+ REGISTER_SYSCALL_IMPL (vfork, vfork);
587+ REGISTER_SYSCALL_IMPL (getpgrp, getpgrp);
588+ REGISTER_SYSCALL_IMPL (clone3, clone3);
589+ REGISTER_SYSCALL_IMPL (exit, exit);
590+ REGISTER_SYSCALL_IMPL (prctl, prctl);
591+ REGISTER_SYSCALL_IMPL (arch_prctl, arch_prctl);
592+ REGISTER_SYSCALL_IMPL (set_tid_address, set_tid_address);
593+ REGISTER_SYSCALL_IMPL (exit_group, exit_group);
579594}
580595} // namespace FEX::HLE
0 commit comments