diff --git a/Utilities/sysinfo.cpp b/Utilities/sysinfo.cpp index 921dc7c2f0..cfe2c06d22 100644 --- a/Utilities/sysinfo.cpp +++ b/Utilities/sysinfo.cpp @@ -33,8 +33,13 @@ bool utils::has_avx2() bool utils::has_rtm() { - // Check RTM and MPX extensions in order to filter out TSX on Haswell CPUs - static const bool g_value = get_cpuid(0, 0)[0] >= 0x7 && (get_cpuid(7, 0)[1] & 0x4800) == 0x4800; + static const bool g_value = get_cpuid(0, 0)[0] >= 0x7 && (get_cpuid(7, 0)[1] & 0x800) == 0x800; + return g_value; +} + +bool utils::has_mpx() +{ + static const bool g_value = get_cpuid(0, 0)[0] >= 0x7 && (get_cpuid(7, 0)[1] & 0x4000) == 0x4000; return g_value; } @@ -114,6 +119,10 @@ std::string utils::get_system_info() if (has_rtm()) { result += " | TSX"; + if (!has_mpx()) + { + result += " disabled by default"; + } } return result; diff --git a/Utilities/sysinfo.h b/Utilities/sysinfo.h index dce29c77ba..88ca019964 100644 --- a/Utilities/sysinfo.h +++ b/Utilities/sysinfo.h @@ -37,6 +37,8 @@ namespace utils bool has_rtm(); + bool has_mpx(); + bool has_512(); bool has_xop(); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 5f6b09c3f4..ef2525af0b 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -38,13 +38,15 @@ #include "Utilities/GDBDebugServer.h" +#include "Utilities/sysinfo.h" + #if defined(_WIN32) || defined(HAVE_VULKAN) #include "Emu/RSX/VK/VulkanAPI.h" #endif cfg_root g_cfg; -bool g_use_rtm = utils::has_rtm(); +bool g_use_rtm; std::string g_cfg_defaults; @@ -222,6 +224,22 @@ inline void fmt_class_string::format(std::string& out, u64 arg) }); } +template <> +void fmt_class_string::format(std::string& out, u64 arg) +{ + format_enum(out, arg, [](tsx_usage value) + { + switch (value) + { + case tsx_usage::disabled: return "Disabled"; + case tsx_usage::enabled: return "Enabled"; + case tsx_usage::forced: return "Forced"; + } + + return unknown; + }); +} + void Emulator::Init() { if (!g_tty) @@ -626,6 +644,13 @@ void Emulator::Load(bool add_only) #endif LOG_NOTICE(LOADER, "Used configuration:\n%s\n", g_cfg.to_string()); + + // Set RTM usage + g_use_rtm = utils::has_rtm() && ((utils::has_mpx() && g_cfg.core.enable_TSX == tsx_usage::enabled) || g_cfg.core.enable_TSX == tsx_usage::forced); + if (g_use_rtm && !utils::has_mpx()) + { + LOG_WARNING(GENERAL, "TSX forced by User"); + } // Load patches from different locations fxm::check_unlocked()->append(fs::get_config_dir() + "data/" + m_title_id + "/patch.yml"); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 3d42cd0bd4..c10473fe31 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -155,6 +155,13 @@ enum class detail_level high, }; +enum class tsx_usage +{ + disabled, + enabled, + forced, +}; + enum CellNetCtlState : s32; enum CellSysutilLang : s32; @@ -326,6 +333,7 @@ struct cfg_root : cfg::node cfg::_bool spu_accurate_putlluc{this, "Accurate PUTLLUC", false}; cfg::_bool spu_verification{this, "SPU Verification", true}; // Should be enabled cfg::_bool spu_cache{this, "SPU Cache", true}; + cfg::_enum enable_TSX{this, "Enable TSX", tsx_usage::enabled}; // Enable TSX. Forcing this on Haswell/Broadwell CPUs should be used carefully cfg::_enum lib_loading{this, "Lib Loader", lib_loading_type::liblv2only}; cfg::_bool hook_functions{this, "Hook static functions"}; diff --git a/rpcs3/Json/tooltips.json b/rpcs3/Json/tooltips.json index c4dac37e3a..49f6d28ea5 100644 --- a/rpcs3/Json/tooltips.json +++ b/rpcs3/Json/tooltips.json @@ -37,6 +37,7 @@ "debug": { "ppuDebug": "Never use this.", "spuDebug": "Never use this.", + "enableTSX": "Enable usage of TSX instructions.\nNeeds to be forced on some Haswell or Broadwell CPUs.\nForcing this on older Hardware can lead to system instability, use it with caution.", "readColor": "Never use this.", "dumpDepth": "Never use this.", "readDepth": "Never use this.", diff --git a/rpcs3/rpcs3qt/emu_settings.h b/rpcs3/rpcs3qt/emu_settings.h index b9031e8811..594452899d 100644 --- a/rpcs3/rpcs3qt/emu_settings.h +++ b/rpcs3/rpcs3qt/emu_settings.h @@ -37,6 +37,7 @@ public: PPUDebug, SPUDebug, MaxLLVMThreads, + EnableTSX, // Graphics Renderer, @@ -205,6 +206,7 @@ private: { PPUDebug, { "Core", "PPU Debug"}}, { SPUDebug, { "Core", "SPU Debug"}}, { MaxLLVMThreads, { "Core", "Max LLVM Compile Threads"}}, + { EnableTSX, { "Core", "Enable TSX"}}, // Graphics Tab { Renderer, { "Video", "Renderer"}}, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 540c1c2b8f..be5d4876b4 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -20,6 +20,7 @@ #include "stdafx.h" #include "Emu/System.h" #include "Crypto/unself.h" +#include "Utilities/sysinfo.h" #include #include @@ -1079,6 +1080,40 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: xemu_settings->EnhanceCheckBox(ui->spuDebug, emu_settings::SPUDebug); SubscribeTooltip(ui->spuDebug, json_debug["spuDebug"].toString()); + + if (utils::has_rtm()) + { + xemu_settings->EnhanceComboBox(ui->enableTSX, emu_settings::EnableTSX); + SubscribeTooltip(ui->enableTSX, json_debug["enableTSX"].toString()); + + static const QString tsx_forced = qstr(fmt::format("%s", tsx_usage::forced)); + static const QString tsx_default = qstr(xemu_settings->GetSettingDefault(emu_settings::EnableTSX)); + + // connect the toogled signal so that the stateChanged signal in EnhanceCheckBox can be prevented + connect(ui->enableTSX, &QComboBox::currentTextChanged, [this](const QString& text) + { + if (text == tsx_forced && !utils::has_mpx() && QMessageBox::No == QMessageBox::critical(this, tr("Haswell/Broadwell TSX Warning"), tr( + R"( +

+ RPCS3 has detected you are using TSX functions on a Haswell or Broadwell CPU.
+ Intel has deactivated these functions in newer Microcode revisions, since they can lead to unpredicted behaviour.
+ That means using TSX may break games or even damage your data.
+ We recommend to disable this feature and update your computer BIOS.

+ Do you wish to use TSX anyway? +

+ )" + ), QMessageBox::Yes, QMessageBox::No)) + { + // Reset if the messagebox was answered with no. This prevents the currentIndexChanged signal in EnhanceComboBox + ui->enableTSX->setCurrentText(tsx_default); + } + }); + } + else + { + ui->label_enableTSX->setHidden(true); + ui->enableTSX->setHidden(true); + } // // Layout fix for High Dpi diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index d85ad08d69..106e73904b 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -6,8 +6,8 @@ 0 0 - 752 - 519 + 849 + 615 @@ -36,7 +36,7 @@ - 7 + 0 @@ -1969,6 +1969,16 @@ + + + + Enable TSX: + + + + + +