mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 20:00:46 +02:00
FEXGetConfig: Support the ability to get TSO emulation facts
Allows a nice way to get information about how TSO emulation is occuring on the individual's hardware. In particular, the more subtle details around the implementation rather than just a hard on or off toggle.
This commit is contained in:
1 file changed
+159
@@ -12,6 +12,99 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
namespace {
|
||||
struct TSOEmulationFacts {
|
||||
bool LSE {}, LSE2 {};
|
||||
bool HardwareTSO {};
|
||||
bool LRCPC1 {}, LRCPC2 {}, LRCPC3 {};
|
||||
};
|
||||
|
||||
#ifdef _M_ARM_64
|
||||
bool CheckForHardwareTSO() {
|
||||
// We need to check if these are defined or not. This is a very fresh feature.
|
||||
#ifndef PR_GET_MEM_MODEL
|
||||
#define PR_GET_MEM_MODEL 0x6d4d444c
|
||||
#endif
|
||||
#ifndef PR_SET_MEM_MODEL
|
||||
#define PR_SET_MEM_MODEL 0x4d4d444c
|
||||
#endif
|
||||
#ifndef PR_SET_MEM_MODEL_DEFAULT
|
||||
#define PR_SET_MEM_MODEL_DEFAULT 0
|
||||
#endif
|
||||
#ifndef PR_SET_MEM_MODEL_TSO
|
||||
#define PR_SET_MEM_MODEL_TSO 1
|
||||
#endif
|
||||
// Check to see if this is supported.
|
||||
auto Result = prctl(PR_GET_MEM_MODEL, 0, 0, 0, 0);
|
||||
if (Result == -1) {
|
||||
// Unsupported, early exit.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Result == PR_SET_MEM_MODEL_DEFAULT) {
|
||||
// Try to set the TSO mode if we are currently default.
|
||||
Result = prctl(PR_SET_MEM_MODEL, PR_SET_MEM_MODEL_TSO, 0, 0, 0);
|
||||
if (Result == 0) {
|
||||
Result = prctl(PR_SET_MEM_MODEL, PR_SET_MEM_MODEL_DEFAULT, 0, 0, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
enum ISAR0_FIELDS {
|
||||
LSE = 20,
|
||||
};
|
||||
|
||||
enum ISAR1_FIELDS {
|
||||
LRCPC = 20,
|
||||
};
|
||||
|
||||
enum MMFR2_FIELDS {
|
||||
AT = 32,
|
||||
};
|
||||
|
||||
constexpr static uint32_t IDFIELDMASK = 0b1111;
|
||||
uint64_t GetISAR0() {
|
||||
uint64_t Result {};
|
||||
asm("mrs %0, ID_AA64ISAR0_EL1;" : "=r"(Result));
|
||||
return Result;
|
||||
}
|
||||
|
||||
uint64_t GetISAR1() {
|
||||
uint64_t Result {};
|
||||
asm("mrs %0, ID_AA64ISAR1_EL1;" : "=r"(Result));
|
||||
return Result;
|
||||
}
|
||||
|
||||
uint64_t GetMMFR2() {
|
||||
uint64_t Result {};
|
||||
asm("mrs %0, ID_AA64MMFR2_EL1;" : "=r"(Result));
|
||||
return Result;
|
||||
}
|
||||
|
||||
TSOEmulationFacts GetTSOEmulationFacts() {
|
||||
const auto ISAR0 = GetISAR0();
|
||||
const auto ISAR1 = GetISAR1();
|
||||
const auto MMFR2 = GetMMFR2();
|
||||
|
||||
return {
|
||||
.LSE = ((ISAR0 >> ISAR0_FIELDS::LSE) & IDFIELDMASK) >= 0b0010,
|
||||
.LSE2 = ((MMFR2 >> MMFR2_FIELDS::AT) & IDFIELDMASK) >= 0b0001,
|
||||
.HardwareTSO = CheckForHardwareTSO(),
|
||||
.LRCPC1 = ((ISAR1 >> ISAR1_FIELDS::LRCPC) & IDFIELDMASK) >= 0b0001,
|
||||
.LRCPC2 = ((ISAR1 >> ISAR1_FIELDS::LRCPC) & IDFIELDMASK) >= 0b0010,
|
||||
.LRCPC3 = ((ISAR1 >> ISAR1_FIELDS::LRCPC) & IDFIELDMASK) >= 0b0011,
|
||||
};
|
||||
}
|
||||
#else
|
||||
TSOEmulationFacts GetTSOEmulationFacts() {
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv, char** envp) {
|
||||
FEXCore::Config::Initialize();
|
||||
@@ -30,6 +123,8 @@ int main(int argc, char** argv, char** envp) {
|
||||
|
||||
Parser.add_option("--current-rootfs").action("store_true").help("Print the directory that contains the FEX rootfs. Mounted in the case of squashfs");
|
||||
|
||||
Parser.add_option("--tso-emulation-info").action("store_true").help("Print how FEX is emulating the x86-TSO memory model.");
|
||||
|
||||
Parser.add_option("--version").action("store_true").help("Print the installed FEX-Emu version");
|
||||
|
||||
optparse::Values Options = Parser.parse_args(argc, argv);
|
||||
@@ -71,5 +166,69 @@ int main(int argc, char** argv, char** envp) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Options.is_set_by_user("tso_emulation_info")) {
|
||||
auto TSOFacts = GetTSOEmulationFacts();
|
||||
const char* GPRMemoryTSOEmulation {};
|
||||
const char* MemcpyMemoryTSOEmulation {};
|
||||
const char* VectorMemoryTSOEmulation {};
|
||||
const char* UnalignedMemoryLoadStoreTSOEmulation {};
|
||||
|
||||
if (TSOFacts.HardwareTSO) {
|
||||
GPRMemoryTSOEmulation = "\e[32mHardware TSO\e[0m";
|
||||
} else if (TSOFacts.LRCPC3) {
|
||||
GPRMemoryTSOEmulation = "\e[32mLRCPC3\e[0m";
|
||||
} else if (TSOFacts.LRCPC2) {
|
||||
GPRMemoryTSOEmulation = "\e[32mLRCPC2\e[0m";
|
||||
} else if (TSOFacts.LRCPC1) {
|
||||
GPRMemoryTSOEmulation = "\e[32mLRCPC\e[0m";
|
||||
} else {
|
||||
GPRMemoryTSOEmulation = "\e[31mAtomics\e[0m";
|
||||
}
|
||||
|
||||
// Memcpy only uses Hardware TSO, LRCPC, and Atomics.
|
||||
if (TSOFacts.HardwareTSO) {
|
||||
MemcpyMemoryTSOEmulation = "\e[32mHardware TSO\e[0m";
|
||||
} else if (TSOFacts.LRCPC1) {
|
||||
MemcpyMemoryTSOEmulation = "\e[32mLRCPC\e[0m";
|
||||
} else {
|
||||
MemcpyMemoryTSOEmulation = "\e[31mAtomics\e[0m";
|
||||
}
|
||||
|
||||
if (TSOFacts.HardwareTSO) {
|
||||
VectorMemoryTSOEmulation = "\e[32mHardware TSO\e[0m";
|
||||
} else if (TSOFacts.LRCPC3) {
|
||||
VectorMemoryTSOEmulation = "\e[32mLRCPC3\e[0m";
|
||||
} else {
|
||||
VectorMemoryTSOEmulation = "\e[31mHalf-Barriers\e[0m";
|
||||
}
|
||||
|
||||
if (TSOFacts.HardwareTSO) {
|
||||
UnalignedMemoryLoadStoreTSOEmulation = "\e[32mHardware TSO\e[0m";
|
||||
} else {
|
||||
UnalignedMemoryLoadStoreTSOEmulation = "\e[31mHalf-Barriers\e[0m";
|
||||
}
|
||||
|
||||
fprintf(stdout, "Hardware Features:\n");
|
||||
fprintf(stdout, "\tMemory atomics emulation method: %s\n", TSOFacts.LSE ? "\e[32mLSE\e[0m" : "\e[31mLL/SC\e[0m");
|
||||
fprintf(stdout, "\tUnaligned atomic memory granularity: %s\n", TSOFacts.LSE2 ? "\e[32m16-byte\e[0m" : "\e[31mNatural alignment\e[0m");
|
||||
///< TODO: Once TME is supported by hardware this can change.
|
||||
fprintf(stdout, "\tUnaligned memory atomic emulation: %s\n", TSOFacts.LSE ? "\e[31mTearing CAS loops\e[0m" : "\e[31mTearing LL/SC loops\e[0m");
|
||||
fprintf(stdout, "\tUnaligned memory loadstore emulation: %s\n", UnalignedMemoryLoadStoreTSOEmulation);
|
||||
fprintf(stdout, "\tGPR memory model emulation: %s\n", GPRMemoryTSOEmulation);
|
||||
fprintf(stdout, "\tMemcpy memory model emulation: %s\n", MemcpyMemoryTSOEmulation);
|
||||
fprintf(stdout, "\tVector memory model emulation: %s\n", VectorMemoryTSOEmulation);
|
||||
|
||||
FEX_CONFIG_OPT(TSOEnabled, TSOENABLED);
|
||||
FEX_CONFIG_OPT(MemcpySetTSOEnabled, MEMCPYSETTSOENABLED);
|
||||
FEX_CONFIG_OPT(VectorTSOEnabled, VECTORTSOENABLED);
|
||||
FEX_CONFIG_OPT(HalfBarrierTSOEnabled, HALFBARRIERTSOENABLED);
|
||||
|
||||
fprintf(stdout, "\nConfiguration:\n");
|
||||
fprintf(stdout, "\tTSO Emulation: %s\n", TSOEnabled() ? "Enabled" : "Disabled");
|
||||
fprintf(stdout, "\tMemcpy TSO Emulation: %s\n", TSOEnabled() && MemcpySetTSOEnabled() ? "Enabled" : "Disabled");
|
||||
fprintf(stdout, "\tVector TSO Emulation: %s\n", TSOEnabled() && VectorTSOEnabled() ? "Enabled" : "Disabled");
|
||||
fprintf(stdout, "\tHalf-barrier unaligned TSO emulation: %s\n", TSOEnabled() && HalfBarrierTSOEnabled() ? "Enabled" : "Disabled");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user