Remove kstuff mount hook toggling

This commit is contained in:
Roman Tarasov committed 2026-09-11 23:41:49 +03:00
1 parent 2424c98ed4
commit 7bf0a6efaf
3 files changed
+15 -146

No files matched your search

-11
View File
@@ -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.
+2 -6
View File
@@ -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",
+13 -129
View File
@@ -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;