diff --git a/include/sm_kstuff.h b/include/sm_kstuff.h index 6f39bee..23f33b9 100644 --- a/include/sm_kstuff.h +++ b/include/sm_kstuff.h @@ -7,14 +7,6 @@ #define SM_KSTUFF_KEKCALL_CHECK UINT64_C(0xffffffff00000027) #define SM_KSTUFF_KEKCALL_REMOTE_SYSCALL UINT64_C(0x500000027) -#define SM_KSTUFF_KEKCALL_RUNTIME_HOOK_CONTROL UINT64_C(0x800000027) - -#define SM_KSTUFF_RUNTIME_HOOK_ENABLE UINT64_C(1) -#define SM_KSTUFF_RUNTIME_HOOK_DISABLE UINT64_C(2) -#define SM_KSTUFF_RUNTIME_HOOK_NMOUNT (UINT64_C(1) << 0) -#define SM_KSTUFF_RUNTIME_HOOK_UNMOUNT (UINT64_C(1) << 1) -#define SM_KSTUFF_RUNTIME_HOOK_MOUNT_UNMOUNT \ - (SM_KSTUFF_RUNTIME_HOOK_NMOUNT | SM_KSTUFF_RUNTIME_HOOK_UNMOUNT) // Resolve firmware-specific kstuff sysentvec addresses and initialize state. void sm_kstuff_init(void); @@ -40,9 +32,6 @@ void sm_kstuff_game_on_exec(pid_t pid, const char *title_id, uint32_t app_id, // Preserve kstuff state across an ExitSpawn/LoadExec process replacement. bool sm_kstuff_game_handoff(pid_t old_pid, pid_t new_pid, const char *title_id, uint32_t app_id); -// Resume mount syscall hooks as soon as the tracked process exits. The broader -// per-application state remains available for a possible ExitSpawn handoff. -void sm_kstuff_game_process_on_exit(pid_t pid); // Publish an AppFocus change for processing on the lifecycle/kstuff thread. void sm_kstuff_note_app_focus(uint32_t app_id); // Return the next wake deadline in monotonic microseconds, or 0 when idle. diff --git a/src/sm_game_lifecycle.c b/src/sm_game_lifecycle.c index aea42e3..4c88303 100644 --- a/src/sm_game_lifecycle.c +++ b/src/sm_game_lifecycle.c @@ -762,13 +762,9 @@ static void handle_game_exit(pid_t pid) { // Match the 1.6 fakelib lifetime: release the overlay as soon as this PID // exits. Keeping common/lib covered can leave the old sandbox busy and // prevent it from being removed during ExitSpawn. - // ShellCore and application-level KStuff ownership remain pending and may - // still be handed to a replacement PID of the same title/app. Mount hooks, - // however, belong to the process lifetime: resume them now so ShellCore's - // exit cleanup is intercepted even if the sandbox cannot be removed. A - // replacement NOTE_EXEC pauses them again in sm_kstuff_game_handoff(). + // ShellCore/KStuff ownership remains pending and may still be handed to a + // replacement PID of the same title/app. sm_fakelib_game_on_exit(pid); - sm_kstuff_game_process_on_exit(pid); log_debug(" [GAME] process exited, awaiting same-app handoff: %s " "pid=%ld app_id=0x%08X", diff --git a/src/sm_kstuff.c b/src/sm_kstuff.c index 864120a..8645886 100644 --- a/src/sm_kstuff.c +++ b/src/sm_kstuff.c @@ -39,9 +39,6 @@ typedef struct { bool restore_on_empty; bool sleep_pause_restore; bool current_app_focus_valid; - bool mount_hooks_restore_needed; - bool mount_hooks_control_unavailable; - pid_t mount_hooks_game_pid; uint32_t current_app_focus_id; uint64_t restore_retry_us; kstuff_game_entry_t game; @@ -59,94 +56,6 @@ static uint32_t get_pause_delay_seconds_for_title(const char *title_id, uint32_t *autopause_delay_out, bool *autopause_delay_valid_out); static void restore_kstuff_if_needed(const char *reason); -static void restore_game_mount_hooks_if_idle(const char *reason); -static void shutdown_kstuff_game_automation(const char *reason); - -static int control_runtime_syscall_hooks(uint64_t command, uint64_t mask, - uint64_t *enabled_mask_out) { - register uint64_t r10 __asm__("r10") = 0; - register uint64_t r8 __asm__("r8") = 0; - register uint64_t r9 __asm__("r9") = 0; - uint64_t result; - unsigned char is_error; - - __asm__ __volatile__("syscall" - : "=a"(result), "=@ccc"(is_error), "+r"(r10), - "+r"(r8), "+r"(r9) - : "a"(SM_KSTUFF_KEKCALL_RUNTIME_HOOK_CONTROL), - "D"(command), "S"(mask), "d"(UINT64_C(0)) - : "rcx", "r11", "memory"); - - if (is_error) - return (int)result; - if (enabled_mask_out) - *enabled_mask_out = result; - return 0; -} - -static bool set_game_mount_hooks_paused(bool pause, const char *reason) { - if (g_kstuff.mount_hooks_control_unavailable) - return false; - - if (!sm_kstuff_is_loaded()) { - log_debug(" [KSTUFF] cannot %s nmount/unmount interception: kstuff is " - "not currently callable", - pause ? "pause" : "resume"); - return false; - } - - uint64_t enabled_mask = 0; - int rc = control_runtime_syscall_hooks( - pause ? SM_KSTUFF_RUNTIME_HOOK_DISABLE - : SM_KSTUFF_RUNTIME_HOOK_ENABLE, - SM_KSTUFF_RUNTIME_HOOK_MOUNT_UNMOUNT, &enabled_mask); - if (rc != 0) { - if (rc == ENOSYS) { - g_kstuff.mount_hooks_control_unavailable = true; - log_debug(" [KSTUFF] nmount/unmount runtime control is unavailable; " - "update ps5-kstuff"); - } else { - log_debug(" [KSTUFF] failed to %s nmount/unmount interception: %s", - pause ? "pause" : "resume", strerror(rc)); - } - return false; - } - - bool desired_state = - pause ? (enabled_mask & SM_KSTUFF_RUNTIME_HOOK_MOUNT_UNMOUNT) == 0 - : (enabled_mask & SM_KSTUFF_RUNTIME_HOOK_MOUNT_UNMOUNT) == - SM_KSTUFF_RUNTIME_HOOK_MOUNT_UNMOUNT; - if (!desired_state) { - log_debug(" [KSTUFF] nmount/unmount %s returned unexpected status " - "0x%llX", - pause ? "pause" : "resume", - (unsigned long long)enabled_mask); - return false; - } - - log_debug(" [KSTUFF] nmount/unmount interception %s (%s)", - pause ? "paused" : "resumed", reason ? reason : "game state"); - return true; -} - -static void note_game_for_mount_hooks(pid_t pid, const char *reason) { - if (pid <= 0) - return; - g_kstuff.mount_hooks_game_pid = pid; - if (!g_kstuff.mount_hooks_restore_needed && - set_game_mount_hooks_paused(true, reason)) { - g_kstuff.mount_hooks_restore_needed = true; - } -} - -static void restore_game_mount_hooks_if_idle(const char *reason) { - if (g_kstuff.mount_hooks_game_pid > 0 || - !g_kstuff.mount_hooks_restore_needed) { - return; - } - if (set_game_mount_hooks_paused(false, reason)) - g_kstuff.mount_hooks_restore_needed = false; -} bool sm_kstuff_is_loaded(void) { register uint64_t r10 __asm__("r10") = 0; @@ -568,7 +477,7 @@ static void apply_kstuff_config_reload(void) { sm_mdbg_game_shutdown(); if (!runtime_config().kstuff_game_auto_toggle) { - shutdown_kstuff_game_automation("config reload"); + sm_kstuff_game_shutdown(); return; } @@ -676,7 +585,6 @@ static void restore_kstuff_if_needed(const char *reason) { reason ? reason : "no reason", g_kstuff.game.active ? ", pending delay for another tracked game" : ""); - restore_game_mount_hooks_if_idle(reason); } else { log_debug(" [KSTUFF] failed to auto-resume (%s)", reason ? reason : "no reason"); @@ -885,14 +793,11 @@ bool sm_kstuff_game_feature_enabled(void) { void sm_kstuff_game_on_exec(pid_t pid, const char *title_id, uint32_t app_id, uint64_t exec_time_us) { - if (!sm_kstuff_game_feature_enabled()) { - note_game_for_mount_hooks(pid, "game launch"); + if (!sm_kstuff_game_feature_enabled()) return; - } if (g_kstuff.game.active) { if (g_kstuff.game.pid == pid) { - note_game_for_mount_hooks(pid, "game launch"); log_debug(" [KSTUFF] already tracking pid=%ld for %s", (long)pid, title_id); return; @@ -908,10 +813,6 @@ void sm_kstuff_game_on_exec(pid_t pid, const char *title_id, uint32_t app_id, finish_tracked_game_clear("tracked game handoff"); } - // A previous tracked title may have disabled the entire sysentvec. Restore - // that state first, then apply the narrower nmount/unmount pause. - note_game_for_mount_hooks(pid, "game launch"); - if (is_kstuff_pause_disabled_for_title(title_id)) { log_debug(" [KSTUFF] auto-pause disabled by config for %s pid=%ld " "app_id=0x%08X", title_id, (long)pid, app_id); @@ -952,8 +853,6 @@ bool sm_kstuff_game_handoff(pid_t old_pid, pid_t new_pid, title_id[0] == '\0') { return false; } - note_game_for_mount_hooks(new_pid, "game process handoff"); - if (!g_kstuff.game.active || g_kstuff.game.pid != old_pid || strcmp(g_kstuff.game.title_id, title_id) != 0) { // Config may have enabled tracking while the old process was pending, or @@ -981,26 +880,17 @@ void sm_kstuff_note_app_focus(uint32_t app_id) { atomic_store(&g_pending_app_focus_valid, true); } -void sm_kstuff_game_process_on_exit(pid_t pid) { - if (g_kstuff.mount_hooks_game_pid != pid) +void sm_kstuff_game_on_exit(pid_t pid) { + if (!g_kstuff.game.active || g_kstuff.game.pid != pid) return; - g_kstuff.mount_hooks_game_pid = 0; - restore_game_mount_hooks_if_idle("game process exit"); -} - -void sm_kstuff_game_on_exit(pid_t pid) { - if (g_kstuff.game.active && g_kstuff.game.pid == pid) { - bool restore_needed = tracked_game_requires_restore(); - sm_mdbg_game_on_exit(pid); - log_debug(" [KSTUFF] game stopped: %s pid=%ld", - g_kstuff.game.title_id, (long)pid); - memset(&g_kstuff.game, 0, sizeof(g_kstuff.game)); - if (restore_needed) - finish_tracked_game_clear("tracked game exit"); - } - - sm_kstuff_game_process_on_exit(pid); + bool restore_needed = tracked_game_requires_restore(); + sm_mdbg_game_on_exit(pid); + log_debug(" [KSTUFF] game stopped: %s pid=%ld", + g_kstuff.game.title_id, (long)pid); + memset(&g_kstuff.game, 0, sizeof(g_kstuff.game)); + if (restore_needed) + finish_tracked_game_clear("tracked game exit"); } void sm_kstuff_game_poll(bool process_active) { @@ -1018,7 +908,7 @@ void sm_kstuff_game_poll(bool process_active) { maybe_apply_kstuff_pause_for_slot(&g_kstuff.game); } -static void shutdown_kstuff_game_automation(const char *reason) { +void sm_kstuff_game_shutdown(void) { bool restore_needed = tracked_game_requires_restore(); if (restore_needed && !g_kstuff.sleep_pause_restore && runtime_sleep_mode_active() && should_stop_requested()) { @@ -1033,16 +923,10 @@ static void shutdown_kstuff_game_automation(const char *reason) { memset(&g_kstuff.game, 0, sizeof(g_kstuff.game)); if (restore_needed) { mark_restore_needed(); - restore_kstuff_if_needed(reason); + restore_kstuff_if_needed("watcher shutdown"); } } -void sm_kstuff_game_shutdown(void) { - shutdown_kstuff_game_automation("watcher shutdown"); - g_kstuff.mount_hooks_game_pid = 0; - restore_game_mount_hooks_if_idle("watcher shutdown"); -} - void sm_kstuff_sleep_enter(void) { bool was_enabled = false; bool fully_disabled = false;