diff --git a/daemon/gamemode-context.c b/daemon/gamemode-context.c index 864e7bc..3ef7596 100644 --- a/daemon/gamemode-context.c +++ b/daemon/gamemode-context.c @@ -91,6 +91,8 @@ struct GameModeContext { uint32_t last_cpu_energy_uj; uint32_t last_igpu_energy_uj; + long initial_split_lock_mitigate; + /* Reaper control */ struct { pthread_t thread; @@ -114,6 +116,7 @@ static void game_mode_context_enter(GameModeContext *self); static void game_mode_context_leave(GameModeContext *self); static char *game_mode_context_find_exe(pid_t pid); static void game_mode_execute_scripts(char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX], int timeout); +static int game_mode_disable_splitlock(GameModeContext *self, bool disable); static void start_reaper_thread(GameModeContext *self) { @@ -151,6 +154,8 @@ void game_mode_context_init(GameModeContext *self) /* Initialise the current CPU info */ game_mode_initialise_cpu(self->config, &self->cpu); + self->initial_split_lock_mitigate = -1; + pthread_rwlock_init(&self->rwlock, NULL); /* Get the reaper thread going */ @@ -202,6 +207,57 @@ void game_mode_context_destroy(GameModeContext *self) pthread_rwlock_destroy(&self->rwlock); } +static int game_mode_disable_splitlock(GameModeContext *self, bool disable) +{ + if (!config_get_disable_splitlock(self->config)) + return 0; + + long value_num = self->initial_split_lock_mitigate; + char value_str[40]; + + if (disable) { + FILE *f = fopen("/proc/sys/kernel/split_lock_mitigate", "r"); + if (f == NULL) { + if (errno == ENOENT) + return 0; + + LOG_ERROR("Couldn't open /proc/sys/kernel/split_lock_mitigate : %s\n", strerror(errno)); + return 1; + } + + if (fgets(value_str, sizeof value_str, f) == NULL) { + LOG_ERROR("Couldn't read from /proc/sys/kernel/split_lock_mitigate : %s\n", strerror(errno)); + fclose(f); + return 1; + } + + self->initial_split_lock_mitigate = strtol (value_str, NULL, 10); + fclose(f); + + value_num = 0; + if (self->initial_split_lock_mitigate == value_num) + return 0; + } + + if (value_num == -1) + return 0; + + sprintf(value_str, "%ld", value_num); + + const char *const exec_args[] = { + "pkexec", LIBEXECDIR "/procsysctl", "split_lock_mitigate", value_str, NULL, + }; + + LOG_MSG("Requesting update of split_lock_mitigate to %s\n", value_str); + int ret = run_external_process(exec_args, NULL, -1); + if (ret != 0) { + LOG_ERROR("Failed to update split_lock_mitigate\n"); + return ret; + } + + return 0; +} + static int game_mode_set_governor(GameModeContext *self, enum GameModeGovernor gov) { if (self->current_govenor == gov) { @@ -369,6 +425,8 @@ static void game_mode_context_enter(GameModeContext *self) if (config_get_inhibit_screensaver(self->config)) game_mode_inhibit_screensaver(true); + game_mode_disable_splitlock(self, true); + /* Apply GPU optimisations by first getting the current values, and then setting the target */ game_mode_get_gpu(self->stored_gpu); game_mode_apply_gpu(self->target_gpu); @@ -404,6 +462,8 @@ static void game_mode_context_leave(GameModeContext *self) if (config_get_inhibit_screensaver(self->config)) game_mode_inhibit_screensaver(false); + game_mode_disable_splitlock(self, false); + game_mode_set_governor(self, GAME_MODE_GOVERNOR_DEFAULT); game_mode_disable_igpu_optimization(self);