From a4b39d1b081cecd077dabb16717dfba15e10d25b Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Aug 2024 04:57:40 +0300 Subject: [PATCH 1/4] Implement basic system info detection on macos using sysctl --- .../CPU/Backends/AArch64/AArch64Common.cpp | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp index 765c9f7e04cc..93349842899b 100644 --- a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp +++ b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp @@ -6,6 +6,7 @@ namespace aarch64 { +#if !defined(__APPLE__) struct cpu_entry_t { u32 vendor; @@ -194,4 +195,87 @@ namespace aarch64 result += suffix; return result; } +#else + // Sysctl wrappers. Maybe should be moved somewhere else later. + static std::pair cli_exec(const std::string_view& command) + { + std::array buffer; // iobuf for stdout + std::string result; // accumulated output + int exit_code = -1; + + // Invoke command, stream result over pipe + FILE* pipe = ::popen(command.data(), "r"); + if (!pipe) + { + return { exit_code, result }; + } + + // Accumulate stdout buffer + while (true) + { + memset(buffer.data(), 0, buffer.size()); + if (!::fgets(buffer.data(), buffer.size(), pipe)) + { + break; + } + result += buffer.data(); + } + + // Grab exit code. This is not really definitive but should be good enough to detect problems. + exit_code = ::pclose(pipe); + + // Return the output and exit code + return { exit_code, result }; + } + + static std::string sysctl_s(const std::string_view& variable_name) + { + const auto command = fmt::format("sysctl -n %s", variable_name); + const auto [exit_code, result] = cli_exec(command); + + if (exit_code != 0) + { + return {}; + } + + return fmt::trim(result, "\n\t "); + } + + static u64 sysctl_u64(const std::string_view& variable_name) + { + const auto value = sysctl_s(variable_name); + if (value.empty()) + { + return umax; + } + return std::stoull(value, nullptr, 16); + } + + // We can get the brand name from sysctl directly + // Once we have windows implemented, we should probably separate the different OS-dependent bits to avoid clutter + std::string get_cpu_brand() + { + const auto brand = sysctl_s("machdep.cpu.brand_string"); + if (brand.empty()) + { + return "Unidentified CPU"; + } + + // Parse extra core information (P and E cores) + if (sysctl_u64("hw.nperflevels") < 2) + { + return brand; + } + + u64 pcores = sysctl_u64("hw.perflevel0.physicalcpu"); + u64 ecores = sysctl_u64("hw.perflevel1.physicalcpu"); + + if (sysctl_s("hw.perflevel0.name") == "Efficiency") + { + std::swap(ecores, pcores); + } + + return fmt::format("%s (%lluP+%lluE)", brand, pcores, ecores); + } +#endif } From 9045d023f61690063a724cc741dc3250b91b52e6 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Aug 2024 15:39:05 +0300 Subject: [PATCH 2/4] Use sysctlbyname --- .../CPU/Backends/AArch64/AArch64Common.cpp | 58 ++++++------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp index 93349842899b..f12b77d0c050 100644 --- a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp +++ b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.cpp @@ -4,6 +4,10 @@ #include #include +#if defined(__APPLE__) +#include +#endif + namespace aarch64 { #if !defined(__APPLE__) @@ -196,59 +200,35 @@ namespace aarch64 return result; } #else - // Sysctl wrappers. Maybe should be moved somewhere else later. - static std::pair cli_exec(const std::string_view& command) + static std::string sysctl_s(const std::string_view& variable_name) { - std::array buffer; // iobuf for stdout - std::string result; // accumulated output - int exit_code = -1; - - // Invoke command, stream result over pipe - FILE* pipe = ::popen(command.data(), "r"); - if (!pipe) + // Determine required buffer size + size_t length = 0; + if (sysctlbyname(variable_name.data(), nullptr, &length, nullptr, 0) == -1) { - return { exit_code, result }; + return ""; } - // Accumulate stdout buffer - while (true) + // Allocate space for the variable. + std::vector text(length + 1); + text[length] = 0; + if (sysctlbyname(variable_name.data(), text.data(), &length, nullptr, 0) == -1) { - memset(buffer.data(), 0, buffer.size()); - if (!::fgets(buffer.data(), buffer.size(), pipe)) - { - break; - } - result += buffer.data(); + return ""; } - // Grab exit code. This is not really definitive but should be good enough to detect problems. - exit_code = ::pclose(pipe); - - // Return the output and exit code - return { exit_code, result }; - } - - static std::string sysctl_s(const std::string_view& variable_name) - { - const auto command = fmt::format("sysctl -n %s", variable_name); - const auto [exit_code, result] = cli_exec(command); - - if (exit_code != 0) - { - return {}; - } - - return fmt::trim(result, "\n\t "); + return text.data(); } static u64 sysctl_u64(const std::string_view& variable_name) { - const auto value = sysctl_s(variable_name); - if (value.empty()) + u64 value = 0; + size_t data_len = sizeof(value); + if (sysctlbyname(variable_name.data(), &value, &data_len, nullptr, 0) == -1) { return umax; } - return std::stoull(value, nullptr, 16); + return value; } // We can get the brand name from sysctl directly From 72df6ddbc9d876e425ae47b11a88d93572feed7f Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Aug 2024 20:38:02 +0300 Subject: [PATCH 3/4] macos - Fix crash when running native arm64 LLVM --- Utilities/JITLLVM.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Utilities/JITLLVM.cpp b/Utilities/JITLLVM.cpp index a28ee2580fb1..0a1038f61ed3 100644 --- a/Utilities/JITLLVM.cpp +++ b/Utilities/JITLLVM.cpp @@ -517,7 +517,7 @@ std::string jit_compiler::triple1() #elif defined(__APPLE__) && defined(ARCH_X64) return llvm::Triple::normalize("x86_64-unknown-linux-gnu"); #elif defined(__APPLE__) && defined(ARCH_ARM64) - return llvm::Triple::normalize("aarch64-unknown-linux-gnu"); + return llvm::Triple::normalize("aarch64-unknown-linux-android"); // Set environment to android to reserve x18 #else return llvm::Triple::normalize(llvm::sys::getProcessTriple()); #endif @@ -532,7 +532,7 @@ std::string jit_compiler::triple2() #elif defined(__APPLE__) && defined(ARCH_X64) return llvm::Triple::normalize("x86_64-unknown-linux-gnu"); #elif defined(__APPLE__) && defined(ARCH_ARM64) - return llvm::Triple::normalize("aarch64-unknown-linux-gnu"); + return llvm::Triple::normalize("aarch64-unknown-linux-android"); // Set environment to android to reserve x18 #else return llvm::Triple::normalize(llvm::sys::getProcessTriple()); #endif From 8e49e6cdfa18cb06be1201078f7cf2d1c453ac88 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Aug 2024 20:51:58 +0300 Subject: [PATCH 4/4] Fix crash in JIT when compiling LLVM blocks --- Utilities/JITASM.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Utilities/JITASM.cpp b/Utilities/JITASM.cpp index aebfbcd272bf..b1d227fc1565 100644 --- a/Utilities/JITASM.cpp +++ b/Utilities/JITASM.cpp @@ -185,8 +185,13 @@ static u8* add_jit_memory(usz size, usz align) if (olda != newa) [[unlikely]] { #ifndef CAN_OVERCOMMIT - // Commit more memory - utils::memory_commit(pointer + olda, newa - olda, Prot); + // Commit more memory. + // NOTE: Calling memory commit in parallel on the same addresses can throw a permission error. + { + static std::mutex mcommit_lock; + std::lock_guard lock(mcommit_lock); + utils::memory_commit(pointer + olda, newa - olda, Prot); + } #endif // Acknowledge committed memory Ctr.atomic_op([&](u64& ctr)