Emu: enable JIT write mode in SPRX Loader on Apple Silicon

The SPRX Loader thread spawned in Emulator::Load() invokes
ppu_initialize() and ppu_precompile(), both of which write into the
PPU JIT code cache. On AArch64 Apple Silicon, MAP_JIT pages default
to execute mode for newly created threads, so any write into the
cache from this thread segfaults before the game can boot.

Reproducible on a clean RPCS3 0.0.40-19340 boot of Red Dead
Redemption (BLUS30418) on macOS arm64: the emulator crashes ~12s
into boot with "Segfault writing location 0x300010000" originating
from the {SPRX Loader} thread, never reaching the title screen.

Mirror the W^X handling already used by the PPU thread's
ppu_cmd::initialize handler in PPUThread.cpp: enable write mode at
thread entry and pair it with an RAII guard so execute mode is
restored on every exit path (normal return, early-exit on
Emu.IsStopped(), exception). No effect on x86_64 or non-Apple
ARM64 builds (entire block is inside #ifdef __APPLE__).
This commit is contained in:
AurisDSP 2026-05-08 23:20:24 -04:00
parent 4312221498
commit a0b2485c07

View File

@ -1835,6 +1835,17 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
g_fxo->init<named_thread>("SPRX Loader"sv, [this, dir_queue, is_fast = m_precompilation_option.is_fast]() mutable
{
#ifdef __APPLE__
// Apple Silicon W^X: SPRX Loader writes JIT code via ppu_initialize().
// Without entering write mode, writes to MAP_JIT pages segfault.
pthread_jit_write_protect_np(false);
// RAII guard so execute mode is restored on every exit path
// (return, exception, etc.).
struct jit_write_guard {
~jit_write_guard() { pthread_jit_write_protect_np(true); }
} _jit_guard;
#endif
std::vector<ppu_module<lv2_obj>*> mod_list;
if (auto& _main = *ensure(g_fxo->try_get<main_ppu_module<lv2_obj>>()); !_main.path.empty())