From 00c55e9688d2e3752cdf39f65e2f24cd9b20c406 Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Sun, 12 Oct 2025 17:47:29 +0200 Subject: [PATCH] Add option to build without (read/write)(fs/gs)base instructions (#111) --- CMakeLists.txt | 5 +++++ rpcsx/thread.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f446a2cf9..bbd3d4c58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,11 @@ option(WITHOUT_OPENGL "Disable OpenGL" OFF) option(WITHOUT_OPENGLEW "Disable OpenGLEW" OFF) option(WITHOUT_OPENAL "Disable OpenAL" OFF) option(COMPILE_FFMPEG "Compile FFmpeg" ON) +option(USE_FS_GS_SYSCALL "Use the arch_prctl syscall to interact with fsbase and gsbase instead of x86 instructions. Used for compatibility with some systems, but comes at a performance cost." OFF) + +if(USE_FS_GS_SYSCALL) + add_definitions(-DUSE_FS_GS_SYSCALL) +endif() # rpcs3 options option(USE_NATIVE_INSTRUCTIONS "USE_NATIVE_INSTRUCTIONS makes rpcs3 compile with -march=native, which is useful for local builds, but not good for packages." ON) diff --git a/rpcsx/thread.cpp b/rpcsx/thread.cpp index 1b26de1c0..efea0816d 100644 --- a/rpcsx/thread.cpp +++ b/rpcsx/thread.cpp @@ -39,9 +39,16 @@ static auto setContext = [] { static __attribute__((no_stack_protector)) void handleSigSys(int sig, siginfo_t *info, void *ucontext) { +#ifndef USE_FS_GS_SYSCALL if (auto hostFs = _readgsbase_u64()) { _writefsbase_u64(hostFs); } +#else + uint64_t hostFs = 0; + if (syscall(SYS_arch_prctl, ARCH_GET_GS, &hostFs) == 0 && hostFs) { + syscall(SYS_arch_prctl, ARCH_SET_FS, hostFs); + } +#endif // rx::printStackTrace(reinterpret_cast(ucontext), // rx::thread::g_current, 1); @@ -58,7 +65,11 @@ handleSigSys(int sig, siginfo_t *info, void *ucontext) { thread = orbis::g_currentThread; thread->context = prevContext; +#ifndef USE_FS_GS_SYSCALL _writefsbase_u64(thread->fsBase); +#else + syscall(SYS_arch_prctl, ARCH_SET_FS, thread->fsBase); +#endif } __attribute__((no_stack_protector)) static void @@ -149,7 +160,11 @@ handleSigUser(int sig, siginfo_t *info, void *ucontext) { } if (inGuestCode) { +#ifndef USE_FS_GS_SYSCALL _writefsbase_u64(thread->fsBase); +#else + syscall(SYS_arch_prctl, ARCH_SET_FS, thread->fsBase); +#endif } } @@ -389,6 +404,7 @@ void rx::thread::setupThisThread() { void rx::thread::invoke(orbis::Thread *thread) { orbis::g_currentThread = thread; +#ifndef USE_FS_GS_SYSCALL std::uint64_t hostFs = _readfsbase_u64(); _writegsbase_u64(hostFs); @@ -397,4 +413,15 @@ void rx::thread::invoke(orbis::Thread *thread) { ::setContext(context->uc_mcontext); _writefsbase_u64(hostFs); +#else + std::uint64_t hostFs; + syscall(SYS_arch_prctl, ARCH_GET_FS, &hostFs); + syscall(SYS_arch_prctl, ARCH_SET_GS, hostFs); + + syscall(SYS_arch_prctl, ARCH_SET_FS, thread->fsBase); + auto context = reinterpret_cast(thread->context); + + ::setContext(context->uc_mcontext); + syscall(SYS_arch_prctl, ARCH_SET_FS, hostFs); +#endif }