From 590252bd5e761823e799dc44166d11a7f5447e99 Mon Sep 17 00:00:00 2001 From: Richard Mitsuk Lavitt Date: Fri, 15 Jan 2021 14:33:38 -0600 Subject: [PATCH 1/5] fixed grammar in a couple of awkward error messages --- src/crypto/rx/Rx_linux.cpp | 2 +- src/crypto/rx/Rx_win.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto/rx/Rx_linux.cpp b/src/crypto/rx/Rx_linux.cpp index 34a097bb9..6228825b6 100644 --- a/src/crypto/rx/Rx_linux.cpp +++ b/src/crypto/rx/Rx_linux.cpp @@ -275,7 +275,7 @@ bool xmrig::Rx::msrInit(const RxConfig &config, const std::vector &th const uint64_t ts = Chrono::steadyMSecs(); if (wrmsr(preset, threads, config.cacheQoS(), config.rdmsr())) { - LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for \"%s\" preset has been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, config.msrPresetName(), Chrono::steadyMSecs() - ts); + LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for \"%s\" preset have been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, config.msrPresetName(), Chrono::steadyMSecs() - ts); return true; } diff --git a/src/crypto/rx/Rx_win.cpp b/src/crypto/rx/Rx_win.cpp index 77e7c9b4f..d131822f7 100644 --- a/src/crypto/rx/Rx_win.cpp +++ b/src/crypto/rx/Rx_win.cpp @@ -123,7 +123,7 @@ static HANDLE wrmsr_install_driver() hService = OpenServiceW(hManager, SERVICE_NAME, SERVICE_ALL_ACCESS); if (hService) { - LOG_WARN(CLEAR "%s" YELLOW("service ") YELLOW_BOLD("WinRing0_1_2_0") YELLOW(" is already exists"), tag); + LOG_WARN(CLEAR "%s" YELLOW("service ") YELLOW_BOLD("WinRing0_1_2_0") YELLOW(" already exists"), tag); SERVICE_STATUS status; const auto rc = QueryServiceStatus(hService, &status); From c48e2e6af8ec16350f95b3871967cd8a9bfdce7e Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 22 Jan 2021 23:50:25 +0700 Subject: [PATCH 2/5] Added new class Msr. --- cmake/randomx.cmake | 15 +- src/crypto/rx/RxConfig.h | 2 +- src/hw/msr/Msr.cpp | 70 +++++++++ src/hw/msr/Msr.h | 61 ++++++++ src/{crypto/rx => hw}/msr/MsrItem.cpp | 14 +- src/{crypto/rx => hw}/msr/MsrItem.h | 15 +- src/hw/msr/Msr_linux.cpp | 86 +++++++++++ src/hw/msr/Msr_win.cpp | 204 ++++++++++++++++++++++++++ 8 files changed, 438 insertions(+), 29 deletions(-) create mode 100644 src/hw/msr/Msr.cpp create mode 100644 src/hw/msr/Msr.h rename src/{crypto/rx => hw}/msr/MsrItem.cpp (69%) rename src/{crypto/rx => hw}/msr/MsrItem.h (70%) create mode 100644 src/hw/msr/Msr_linux.cpp create mode 100644 src/hw/msr/Msr_win.cpp diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index 5d44e05fc..56c8cc18d 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -100,13 +100,20 @@ if (WITH_RANDOMX) message("-- WITH_MSR=ON") if (XMRIG_OS_WIN) - list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_win.cpp) + list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_win.cpp src/hw/msr/Msr_win.cpp) elseif (XMRIG_OS_LINUX) - list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_linux.cpp) + list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_linux.cpp src/hw/msr/Msr_linux.cpp) endif() - list(APPEND HEADERS_CRYPTO src/crypto/rx/msr/MsrItem.h) - list(APPEND SOURCES_CRYPTO src/crypto/rx/msr/MsrItem.cpp) + list(APPEND HEADERS_CRYPTO + src/hw/msr/Msr.h + src/hw/msr/MsrItem.h + ) + + list(APPEND SOURCES_CRYPTO + src/hw/msr/Msr.cpp + src/hw/msr/MsrItem.cpp + ) else() remove_definitions(/DXMRIG_FEATURE_MSR) remove_definitions(/DXMRIG_FIX_RYZEN) diff --git a/src/crypto/rx/RxConfig.h b/src/crypto/rx/RxConfig.h index fb3a656d4..78d2f9649 100644 --- a/src/crypto/rx/RxConfig.h +++ b/src/crypto/rx/RxConfig.h @@ -30,7 +30,7 @@ #ifdef XMRIG_FEATURE_MSR -# include "crypto/rx/msr/MsrItem.h" +# include "hw/msr/MsrItem.h" #endif diff --git a/src/hw/msr/Msr.cpp b/src/hw/msr/Msr.cpp new file mode 100644 index 000000000..68c60e6ed --- /dev/null +++ b/src/hw/msr/Msr.cpp @@ -0,0 +1,70 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "hw/msr/Msr.h" +#include "base/io/log/Log.h" + + +namespace xmrig { + + +static const char *kTag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr "); +static std::weak_ptr instance; + + +} // namespace xmrig + + + +const char *xmrig::Msr::tag() +{ + return kTag; +} + + + +std::shared_ptr xmrig::Msr::get() +{ + auto msr = instance.lock(); + if (!msr) { + msr = std::make_shared(); + instance = msr; + } + + if (msr->isAvailable()) { + return msr; + } + + return {}; +} + + +xmrig::MsrItem xmrig::Msr::read(uint32_t reg, int32_t cpu, bool verbose) const +{ + uint64_t value = 0; + if (rdmsr(reg, cpu, value)) { + return { reg, value }; + } + + if (verbose) { + LOG_WARN("%s " YELLOW_BOLD("cannot read MSR 0x%08" PRIx32), tag(), reg); + } + + return {}; +} diff --git a/src/hw/msr/Msr.h b/src/hw/msr/Msr.h new file mode 100644 index 000000000..5f325a251 --- /dev/null +++ b/src/hw/msr/Msr.h @@ -0,0 +1,61 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_MSR_H +#define XMRIG_MSR_H + + +#include "base/tools/Object.h" +#include "hw/msr/MsrItem.h" + + +#include + + +namespace xmrig +{ + + +class MsrPrivate; + + +class Msr +{ +public: + XMRIG_DISABLE_COPY_MOVE(Msr) + + Msr(); + ~Msr(); + + static const char *tag(); + static std::shared_ptr get(); + + bool isAvailable() const; + MsrItem read(uint32_t reg, int32_t cpu = -1, bool verbose = true) const; + +private: + bool rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const; + + MsrPrivate *d_ptr = nullptr; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_MSR_H */ diff --git a/src/crypto/rx/msr/MsrItem.cpp b/src/hw/msr/MsrItem.cpp similarity index 69% rename from src/crypto/rx/msr/MsrItem.cpp rename to src/hw/msr/MsrItem.cpp index 4c8e7f2af..eac88f0cb 100644 --- a/src/crypto/rx/msr/MsrItem.cpp +++ b/src/hw/msr/MsrItem.cpp @@ -1,14 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2019 XMR-Stak , - * Copyright 2018 Lee Clagett - * Copyright 2018-2019 tevador - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +17,7 @@ */ -#include "crypto/rx/msr/MsrItem.h" +#include "hw/msr/MsrItem.h" #include "3rdparty/rapidjson/document.h" diff --git a/src/crypto/rx/msr/MsrItem.h b/src/hw/msr/MsrItem.h similarity index 70% rename from src/crypto/rx/msr/MsrItem.h rename to src/hw/msr/MsrItem.h index b14fda3b6..ad3c9d393 100644 --- a/src/crypto/rx/msr/MsrItem.h +++ b/src/hw/msr/MsrItem.h @@ -1,14 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2019 XMR-Stak , - * Copyright 2018 Lee Clagett - * Copyright 2018-2019 tevador - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,9 +31,6 @@ namespace xmrig { -class RxDataset; - - class MsrItem { public: diff --git a/src/hw/msr/Msr_linux.cpp b/src/hw/msr/Msr_linux.cpp new file mode 100644 index 000000000..02a29c72f --- /dev/null +++ b/src/hw/msr/Msr_linux.cpp @@ -0,0 +1,86 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "hw/msr/Msr.h" +#include "3rdparty/fmt/core.h" +#include "base/io/log/Log.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace xmrig { + + +class MsrPrivate +{ +public: + bool available = true; +}; + + +} // namespace xmrig + + +xmrig::Msr::Msr() : d_ptr(new MsrPrivate()) +{ + if (system("/sbin/modprobe msr allow_writes=on > /dev/null 2>&1") != 0) { + LOG_WARN("%s " YELLOW_BOLD("msr kernel module is not available"), Msr::tag()); + + d_ptr->available = false; + } +} + + +xmrig::Msr::~Msr() +{ + delete d_ptr; +} + + +bool xmrig::Msr::isAvailable() const +{ + return d_ptr->available; +} + + +bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const +{ + const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? 0 : cpu); + const int fd = open(name.c_str(), O_RDONLY); + + if (fd < 0) { + return false; + } + + const bool success = pread(fd, &value, sizeof value, reg) == sizeof value; + close(fd); + + return success; +} diff --git a/src/hw/msr/Msr_win.cpp b/src/hw/msr/Msr_win.cpp new file mode 100644 index 000000000..d055785cd --- /dev/null +++ b/src/hw/msr/Msr_win.cpp @@ -0,0 +1,204 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "hw/msr/Msr.h" +#include "base/io/log/Log.h" + + +#include +#include +#include + + +#define SERVICE_NAME L"WinRing0_1_2_0" +#define IOCTL_READ_MSR CTL_CODE(40000, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +namespace xmrig { + + +static const wchar_t *kServiceName = SERVICE_NAME; + + +class MsrPrivate +{ +public: + bool uninstall() + { + if (driver != INVALID_HANDLE_VALUE) { + CloseHandle(driver); + } + + if (!service) { + return true; + } + + bool result = true; + + if (!reuse) { + SERVICE_STATUS serviceStatus; + + if (!ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus)) { + result = false; + } + + if (!DeleteService(service)) { + LOG_ERR("%s " RED("failed to remove WinRing0 driver, error %u"), Msr::tag(), GetLastError()); + result = false; + } + } + + CloseServiceHandle(service); + service = nullptr; + + return result; + } + + + bool reuse = false; + HANDLE driver = INVALID_HANDLE_VALUE; + SC_HANDLE manager = nullptr; + SC_HANDLE service = nullptr; +}; + + +} // namespace xmrig + + +xmrig::Msr::Msr() : d_ptr(new MsrPrivate()) +{ + DWORD err = 0; + + d_ptr->manager = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); + if (!d_ptr->manager) { + if ((err = GetLastError()) == ERROR_ACCESS_DENIED) { + LOG_WARN("%s " YELLOW_BOLD("to access MSR registers Administrator privileges required."), tag()); + } + else { + LOG_ERR("%s " RED("failed to open service control manager, error %u"), tag(), err); + } + + return; + } + + std::vector dir; + + do { + dir.resize(dir.empty() ? MAX_PATH : dir.size() * 2); + GetModuleFileNameW(nullptr, dir.data(), dir.size()); + err = GetLastError(); + } while (err == ERROR_INSUFFICIENT_BUFFER); + + if (err != ERROR_SUCCESS) { + LOG_ERR("%s " RED("failed to get path to driver, error %u"), tag(), err); + return; + } + + for (auto it = dir.end() - 1; it != dir.begin(); --it) { + if ((*it == L'\\') || (*it == L'/')) { + ++it; + *it = L'\0'; + break; + } + } + + const std::wstring path = std::wstring(dir.data()) + L"WinRing0x64.sys"; + + d_ptr->service = OpenServiceW(d_ptr->manager, kServiceName, SERVICE_ALL_ACCESS); + if (d_ptr->service) { + LOG_WARN("%s " YELLOW("service ") YELLOW_BOLD("WinRing0_1_2_0") YELLOW(" already exists"), tag()); + + SERVICE_STATUS status; + const auto rc = QueryServiceStatus(d_ptr->service, &status); + + if (rc) { + DWORD dwBytesNeeded = 0; + + QueryServiceConfigA(d_ptr->service, nullptr, 0, &dwBytesNeeded); + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + std::vector buffer(dwBytesNeeded); + auto config = reinterpret_cast(buffer.data()); + + if (QueryServiceConfigA(d_ptr->service, config, buffer.size(), &dwBytesNeeded)) { + LOG_INFO("%s " YELLOW("service path: ") YELLOW_BOLD("\"%s\""), tag(), config->lpBinaryPathName); + } + } + } + + if (rc && status.dwCurrentState == SERVICE_RUNNING) { + d_ptr->reuse = true; + } + else if (!d_ptr->uninstall()) { + return; + } + } + + if (!d_ptr->reuse) { + d_ptr->service = CreateServiceW(d_ptr->manager, kServiceName, kServiceName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr); + if (!d_ptr->service) { + LOG_ERR("%s " RED("failed to install WinRing0 driver, error %u"), tag(), GetLastError()); + + return; + } + + if (!StartService(d_ptr->service, 0, nullptr)) { + err = GetLastError(); + if (err != ERROR_SERVICE_ALREADY_RUNNING) { + if (err == ERROR_FILE_NOT_FOUND) { + LOG_ERR("%s " RED("failed to start WinRing0 driver: ") RED_BOLD("\"WinRing0x64.sys not found\""), tag()); + } + else { + LOG_ERR("%s " RED("failed to start WinRing0 driver, error %u"), tag(), err); + } + + d_ptr->uninstall(); + + return; + } + } + } + + d_ptr->driver = CreateFileW(L"\\\\.\\" SERVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (d_ptr->driver == INVALID_HANDLE_VALUE) { + LOG_ERR("%s " RED("failed to connect to WinRing0 driver, error %u"), tag(), GetLastError());; + } +} + + +xmrig::Msr::~Msr() +{ + d_ptr->uninstall(); + + delete d_ptr; +} + + +bool xmrig::Msr::isAvailable() const +{ + return d_ptr->driver != INVALID_HANDLE_VALUE; +} + + +bool xmrig::Msr::rdmsr(uint32_t reg, int32_t, uint64_t &value) const +{ + DWORD size = 0; + + return DeviceIoControl(d_ptr->driver, IOCTL_READ_MSR, ®, sizeof(reg), &value, sizeof(value), &size, nullptr) != 0; +} From b9d813c40303425387b92158d2b1213b745e0aef Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 23 Jan 2021 00:27:56 +0700 Subject: [PATCH 3/5] Move Ryzen related fixes to RxFix class. --- cmake/randomx.cmake | 13 ++++- src/crypto/randomx/jit_compiler_x86.cpp | 8 +-- src/crypto/rx/Rx.cpp | 14 ++++- src/crypto/rx/Rx.h | 9 +-- src/crypto/rx/RxFix.h | 42 ++++++++++++++ src/crypto/rx/RxFix_linux.cpp | 71 ++++++++++++++++++++++++ src/crypto/rx/RxFix_win.cpp | 74 +++++++++++++++++++++++++ src/crypto/rx/Rx_linux.cpp | 41 -------------- src/crypto/rx/Rx_win.cpp | 45 --------------- 9 files changed, 215 insertions(+), 102 deletions(-) create mode 100644 src/crypto/rx/RxFix.h create mode 100644 src/crypto/rx/RxFix_linux.cpp create mode 100644 src/crypto/rx/RxFix_win.cpp diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index 56c8cc18d..83c8e5b3a 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -100,12 +100,21 @@ if (WITH_RANDOMX) message("-- WITH_MSR=ON") if (XMRIG_OS_WIN) - list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_win.cpp src/hw/msr/Msr_win.cpp) + list(APPEND SOURCES_CRYPTO + src/crypto/rx/Rx_win.cpp + src/hw/msr/Msr_win.cpp + src/crypto/rx/RxFix_win.cpp + ) elseif (XMRIG_OS_LINUX) - list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_linux.cpp src/hw/msr/Msr_linux.cpp) + list(APPEND SOURCES_CRYPTO + src/crypto/rx/Rx_linux.cpp + src/hw/msr/Msr_linux.cpp + src/crypto/rx/RxFix_linux.cpp + ) endif() list(APPEND HEADERS_CRYPTO + src/crypto/rx/RxFix.h src/hw/msr/Msr.h src/hw/msr/MsrItem.h ) diff --git a/src/crypto/randomx/jit_compiler_x86.cpp b/src/crypto/randomx/jit_compiler_x86.cpp index 8c3145b2a..17227c34f 100644 --- a/src/crypto/randomx/jit_compiler_x86.cpp +++ b/src/crypto/randomx/jit_compiler_x86.cpp @@ -1,7 +1,7 @@ /* Copyright (c) 2018-2020, tevador -Copyright (c) 2019-2020, SChernykh -Copyright (c) 2019-2020, XMRig , +Copyright (c) 2019-2021, SChernykh +Copyright (c) 2019-2021, XMRig , All rights reserved. @@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "crypto/rx/Profiler.h" #ifdef XMRIG_FIX_RYZEN -# include "crypto/rx/Rx.h" +# include "crypto/rx/RxFix.h" #endif #ifdef _MSC_VER @@ -427,7 +427,7 @@ namespace randomx { } # ifdef XMRIG_FIX_RYZEN - xmrig::Rx::setMainLoopBounds(mainLoopBounds); + xmrig::RxFix::setMainLoopBounds(mainLoopBounds); # endif memcpy(code + prologueSize - 48, &pcfg.eMask, sizeof(pcfg.eMask)); diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index 40d3c6129..99ca6b0ad 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2018-2019 tevador - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,11 @@ #include "crypto/randomx/aes_hash.hpp" +#ifdef XMRIG_FIX_RYZEN +# include "crypto/rx/RxFix.h" +#endif + + namespace xmrig { @@ -104,7 +109,10 @@ bool xmrig::Rx::init(const T &seed, const RxConfig &config, const CpuConfig &cpu } if (!osInitialized) { - setupMainLoopExceptionFrame(); +# ifdef XMRIG_FIX_RYZEN + RxFix::setupMainLoopExceptionFrame(); +# endif + if (!cpu.isHwAES()) { SelectSoftAESImpl(cpu.threads().get(seed.algorithm()).count()); } diff --git a/src/crypto/rx/Rx.h b/src/crypto/rx/Rx.h index 42bd0c156..a93f7449f 100644 --- a/src/crypto/rx/Rx.h +++ b/src/crypto/rx/Rx.h @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2018-2019 tevador - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,10 +52,6 @@ public: template static bool init(const T &seed, const RxConfig &config, const CpuConfig &cpu); template static bool isReady(const T &seed); -# ifdef XMRIG_FIX_RYZEN - static void setMainLoopBounds(const std::pair& bounds); -# endif - # ifdef XMRIG_FEATURE_MSR static bool isMSR(); # else @@ -65,7 +61,6 @@ public: private: static bool msrInit(const RxConfig &config, const std::vector& threads); static void msrDestroy(); - static void setupMainLoopExceptionFrame(); }; diff --git a/src/crypto/rx/RxFix.h b/src/crypto/rx/RxFix.h new file mode 100644 index 000000000..66d2e7d9a --- /dev/null +++ b/src/crypto/rx/RxFix.h @@ -0,0 +1,42 @@ +/* XMRig + * Copyright (c) 2018-2019 tevador + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_RXFIX_H +#define XMRIG_RXFIX_H + + +#include + + +namespace xmrig +{ + + +class RxFix +{ +public: + static void setMainLoopBounds(const std::pair &bounds); + static void setupMainLoopExceptionFrame(); +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_RXFIX_H */ diff --git a/src/crypto/rx/RxFix_linux.cpp b/src/crypto/rx/RxFix_linux.cpp new file mode 100644 index 000000000..1a3743c73 --- /dev/null +++ b/src/crypto/rx/RxFix_linux.cpp @@ -0,0 +1,71 @@ +/* XMRig + * Copyright (c) 2018-2019 tevador + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "crypto/rx/RxFix.h" +#include "base/io/log/Log.h" + + +#include +#include +#include + + +namespace xmrig { + + +static thread_local std::pair mainLoopBounds = { nullptr, nullptr }; + + +static void MainLoopHandler(int sig, siginfo_t *info, void *ucontext) +{ + ucontext_t *ucp = (ucontext_t*) ucontext; + + LOG_VERBOSE(YELLOW_BOLD("%s at %p"), (sig == SIGSEGV) ? "SIGSEGV" : "SIGILL", ucp->uc_mcontext.gregs[REG_RIP]); + + void* p = reinterpret_cast(ucp->uc_mcontext.gregs[REG_RIP]); + const std::pair& loopBounds = mainLoopBounds; + + if ((loopBounds.first <= p) && (p < loopBounds.second)) { + ucp->uc_mcontext.gregs[REG_RIP] = reinterpret_cast(loopBounds.second); + } + else { + abort(); + } +} + + +} // namespace xmrig + + + +void xmrig::RxFix::setMainLoopBounds(const std::pair &bounds) +{ + mainLoopBounds = bounds; +} + + +void xmrig::RxFix::setupMainLoopExceptionFrame() +{ + struct sigaction act = {}; + act.sa_sigaction = MainLoopHandler; + act.sa_flags = SA_RESTART | SA_SIGINFO; + sigaction(SIGSEGV, &act, nullptr); + sigaction(SIGILL, &act, nullptr); +} diff --git a/src/crypto/rx/RxFix_win.cpp b/src/crypto/rx/RxFix_win.cpp new file mode 100644 index 000000000..75538be4d --- /dev/null +++ b/src/crypto/rx/RxFix_win.cpp @@ -0,0 +1,74 @@ +/* XMRig + * Copyright (c) 2018-2019 tevador + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "crypto/rx/RxFix.h" +#include "base/io/log/Log.h" + + +#include + + +namespace xmrig { + + +static thread_local std::pair mainLoopBounds = { nullptr, nullptr }; + + +static LONG WINAPI MainLoopHandler(_EXCEPTION_POINTERS *ExceptionInfo) +{ + if (ExceptionInfo->ExceptionRecord->ExceptionCode == 0xC0000005) { + const char* accessType; + switch (ExceptionInfo->ExceptionRecord->ExceptionInformation[0]) { + case 0: accessType = "read"; break; + case 1: accessType = "write"; break; + case 8: accessType = "DEP violation"; break; + default: accessType = "unknown"; break; + } + LOG_VERBOSE(YELLOW_BOLD("[THREAD %u] Access violation at 0x%p: %s at address 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionAddress, accessType, ExceptionInfo->ExceptionRecord->ExceptionInformation[1]); + } + else { + LOG_VERBOSE(YELLOW_BOLD("[THREAD %u] Exception 0x%08X at 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); + } + + void* p = reinterpret_cast(ExceptionInfo->ContextRecord->Rip); + const std::pair& loopBounds = mainLoopBounds; + + if ((loopBounds.first <= p) && (p < loopBounds.second)) { + ExceptionInfo->ContextRecord->Rip = reinterpret_cast(loopBounds.second); + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + + +} // namespace xmrig + + +void xmrig::RxFix::setMainLoopBounds(const std::pair &bounds) +{ + mainLoopBounds = bounds; +} + + +void xmrig::RxFix::setupMainLoopExceptionFrame() +{ + AddVectoredExceptionHandler(1, MainLoopHandler); +} diff --git a/src/crypto/rx/Rx_linux.cpp b/src/crypto/rx/Rx_linux.cpp index 6228825b6..e73980026 100644 --- a/src/crypto/rx/Rx_linux.cpp +++ b/src/crypto/rx/Rx_linux.cpp @@ -37,8 +37,6 @@ #include #include #include -#include -#include namespace xmrig { @@ -235,33 +233,6 @@ static bool wrmsr(const MsrItems& preset, const std::vector& threads, } -#ifdef XMRIG_FIX_RYZEN -static thread_local std::pair mainLoopBounds = { nullptr, nullptr }; - -static void MainLoopHandler(int sig, siginfo_t *info, void *ucontext) -{ - ucontext_t *ucp = (ucontext_t*) ucontext; - - LOG_VERBOSE(YELLOW_BOLD("%s at %p"), (sig == SIGSEGV) ? "SIGSEGV" : "SIGILL", ucp->uc_mcontext.gregs[REG_RIP]); - - void* p = reinterpret_cast(ucp->uc_mcontext.gregs[REG_RIP]); - const std::pair& loopBounds = mainLoopBounds; - - if ((loopBounds.first <= p) && (p < loopBounds.second)) { - ucp->uc_mcontext.gregs[REG_RIP] = reinterpret_cast(loopBounds.second); - } - else { - abort(); - } -} - -void Rx::setMainLoopBounds(const std::pair& bounds) -{ - mainLoopBounds = bounds; -} -#endif - - } // namespace xmrig @@ -299,15 +270,3 @@ void xmrig::Rx::msrDestroy() LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts); } } - - -void xmrig::Rx::setupMainLoopExceptionFrame() -{ -# ifdef XMRIG_FIX_RYZEN - struct sigaction act = {}; - act.sa_sigaction = MainLoopHandler; - act.sa_flags = SA_RESTART | SA_SIGINFO; - sigaction(SIGSEGV, &act, nullptr); - sigaction(SIGILL, &act, nullptr); -# endif -} diff --git a/src/crypto/rx/Rx_win.cpp b/src/crypto/rx/Rx_win.cpp index d131822f7..36e13819b 100644 --- a/src/crypto/rx/Rx_win.cpp +++ b/src/crypto/rx/Rx_win.cpp @@ -348,43 +348,6 @@ static bool wrmsr(const MsrItems &preset, const std::vector& threads, } -#ifdef XMRIG_FIX_RYZEN -static thread_local std::pair mainLoopBounds = { nullptr, nullptr }; - -static LONG WINAPI MainLoopHandler(_EXCEPTION_POINTERS *ExceptionInfo) -{ - if (ExceptionInfo->ExceptionRecord->ExceptionCode == 0xC0000005) { - const char* accessType; - switch (ExceptionInfo->ExceptionRecord->ExceptionInformation[0]) { - case 0: accessType = "read"; break; - case 1: accessType = "write"; break; - case 8: accessType = "DEP violation"; break; - default: accessType = "unknown"; break; - } - LOG_VERBOSE(YELLOW_BOLD("[THREAD %u] Access violation at 0x%p: %s at address 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionAddress, accessType, ExceptionInfo->ExceptionRecord->ExceptionInformation[1]); - } - else { - LOG_VERBOSE(YELLOW_BOLD("[THREAD %u] Exception 0x%08X at 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); - } - - void* p = reinterpret_cast(ExceptionInfo->ContextRecord->Rip); - const std::pair& loopBounds = mainLoopBounds; - - if ((loopBounds.first <= p) && (p < loopBounds.second)) { - ExceptionInfo->ContextRecord->Rip = reinterpret_cast(loopBounds.second); - return EXCEPTION_CONTINUE_EXECUTION; - } - - return EXCEPTION_CONTINUE_SEARCH; -} - -void Rx::setMainLoopBounds(const std::pair& bounds) -{ - mainLoopBounds = bounds; -} -#endif - - } // namespace xmrig @@ -421,11 +384,3 @@ void xmrig::Rx::msrDestroy() LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts); } } - - -void xmrig::Rx::setupMainLoopExceptionFrame() -{ -# ifdef XMRIG_FIX_RYZEN - AddVectoredExceptionHandler(1, MainLoopHandler); -# endif -} From 9dae559b73726b53469bd67a1b8b341c2927565f Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 23 Jan 2021 23:23:39 +0700 Subject: [PATCH 4/5] Added RxMsr class. --- cmake/randomx.cmake | 8 +- src/backend/cpu/interfaces/ICpuInfo.h | 11 +- src/backend/cpu/platform/BasicCpuInfo.cpp | 9 +- src/backend/cpu/platform/BasicCpuInfo.h | 61 ++-- src/backend/cpu/platform/HwlocCpuInfo.cpp | 24 +- src/backend/cpu/platform/HwlocCpuInfo.h | 6 +- src/crypto/rx/Rx.cpp | 45 +-- src/crypto/rx/Rx.h | 4 - src/crypto/rx/RxMsr.cpp | 184 +++++++++++ src/crypto/rx/RxMsr.h | 53 +++ src/crypto/rx/Rx_linux.cpp | 272 --------------- src/crypto/rx/Rx_win.cpp | 386 ---------------------- src/hw/msr/Msr.cpp | 18 + src/hw/msr/Msr.h | 8 + src/hw/msr/MsrItem.h | 5 + src/hw/msr/Msr_linux.cpp | 34 +- src/hw/msr/Msr_win.cpp | 53 ++- 17 files changed, 435 insertions(+), 746 deletions(-) create mode 100644 src/crypto/rx/RxMsr.cpp create mode 100644 src/crypto/rx/RxMsr.h delete mode 100644 src/crypto/rx/Rx_linux.cpp delete mode 100644 src/crypto/rx/Rx_win.cpp diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index 83c8e5b3a..976f11862 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -101,25 +101,25 @@ if (WITH_RANDOMX) if (XMRIG_OS_WIN) list(APPEND SOURCES_CRYPTO - src/crypto/rx/Rx_win.cpp - src/hw/msr/Msr_win.cpp src/crypto/rx/RxFix_win.cpp + src/hw/msr/Msr_win.cpp ) elseif (XMRIG_OS_LINUX) list(APPEND SOURCES_CRYPTO - src/crypto/rx/Rx_linux.cpp - src/hw/msr/Msr_linux.cpp src/crypto/rx/RxFix_linux.cpp + src/hw/msr/Msr_linux.cpp ) endif() list(APPEND HEADERS_CRYPTO src/crypto/rx/RxFix.h + src/crypto/rx/RxMsr.h src/hw/msr/Msr.h src/hw/msr/MsrItem.h ) list(APPEND SOURCES_CRYPTO + src/crypto/rx/RxMsr.cpp src/hw/msr/Msr.cpp src/hw/msr/MsrItem.cpp ) diff --git a/src/backend/cpu/interfaces/ICpuInfo.h b/src/backend/cpu/interfaces/ICpuInfo.h index b772a92c4..7a8887239 100644 --- a/src/backend/cpu/interfaces/ICpuInfo.h +++ b/src/backend/cpu/interfaces/ICpuInfo.h @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -86,18 +86,21 @@ public: inline constexpr static bool is64bit() { return false; } # endif + virtual Arch arch() const = 0; virtual Assembly::Id assembly() const = 0; virtual bool has(Flag feature) const = 0; virtual bool hasAES() const = 0; virtual bool hasAVX() const = 0; virtual bool hasAVX2() const = 0; virtual bool hasBMI2() const = 0; + virtual bool hasCatL3() const = 0; virtual bool hasOneGbPages() const = 0; virtual bool hasXOP() const = 0; - virtual bool hasCatL3() const = 0; virtual bool isVM() const = 0; + virtual bool jccErratum() const = 0; virtual const char *backend() const = 0; virtual const char *brand() const = 0; + virtual const std::vector &units() const = 0; virtual CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const = 0; virtual MsrMod msrMod() const = 0; virtual rapidjson::Value toJSON(rapidjson::Document &doc) const = 0; @@ -108,8 +111,6 @@ public: virtual size_t packages() const = 0; virtual size_t threads() const = 0; virtual Vendor vendor() const = 0; - virtual Arch arch() const = 0; - virtual bool jccErratum() const = 0; }; diff --git a/src/backend/cpu/platform/BasicCpuInfo.cpp b/src/backend/cpu/platform/BasicCpuInfo.cpp index 2a4dc829d..bcf77e927 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.cpp +++ b/src/backend/cpu/platform/BasicCpuInfo.cpp @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2017-2019 XMR-Stak , - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -190,6 +190,11 @@ xmrig::BasicCpuInfo::BasicCpuInfo() : m_flags.set(FLAG_CAT_L3, has_cat_l3()); m_flags.set(FLAG_VM, is_vm()); + m_units.resize(m_threads); + for (int32_t i = 0; i < static_cast(m_threads); ++i) { + m_units[i] = i; + } + # ifdef XMRIG_FEATURE_ASM if (hasAES()) { char vendor[13] = { 0 }; diff --git a/src/backend/cpu/platform/BasicCpuInfo.h b/src/backend/cpu/platform/BasicCpuInfo.h index edf119a2e..88760bac8 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.h +++ b/src/backend/cpu/platform/BasicCpuInfo.h @@ -1,12 +1,7 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2019 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig + * Copyright (c) 2017-2019 XMR-Stak , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,34 +40,36 @@ protected: CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override; rapidjson::Value toJSON(rapidjson::Document &doc) const override; - inline Assembly::Id assembly() const override { return m_assembly; } - inline bool has(Flag flag) const override { return m_flags.test(flag); } - inline bool hasAES() const override { return has(FLAG_AES); } - inline bool hasAVX() const override { return has(FLAG_AVX); } - inline bool hasAVX2() const override { return has(FLAG_AVX2); } - inline bool hasBMI2() const override { return has(FLAG_BMI2); } - inline bool hasOneGbPages() const override { return has(FLAG_PDPE1GB); } - inline bool hasXOP() const override { return has(FLAG_XOP); } - inline bool hasCatL3() const override { return has(FLAG_CAT_L3); } - inline bool isVM() const override { return has(FLAG_VM); } - inline const char *brand() const override { return m_brand; } - inline MsrMod msrMod() const override { return m_msrMod; } - inline size_t cores() const override { return 0; } - inline size_t L2() const override { return 0; } - inline size_t L3() const override { return 0; } - inline size_t nodes() const override { return 0; } - inline size_t packages() const override { return 1; } - inline size_t threads() const override { return m_threads; } - inline Vendor vendor() const override { return m_vendor; } - inline Arch arch() const override { return m_arch; } - inline bool jccErratum() const override { return m_jccErratum; } + inline Arch arch() const override { return m_arch; } + inline Assembly::Id assembly() const override { return m_assembly; } + inline bool has(Flag flag) const override { return m_flags.test(flag); } + inline bool hasAES() const override { return has(FLAG_AES); } + inline bool hasAVX() const override { return has(FLAG_AVX); } + inline bool hasAVX2() const override { return has(FLAG_AVX2); } + inline bool hasBMI2() const override { return has(FLAG_BMI2); } + inline bool hasCatL3() const override { return has(FLAG_CAT_L3); } + inline bool hasOneGbPages() const override { return has(FLAG_PDPE1GB); } + inline bool hasXOP() const override { return has(FLAG_XOP); } + inline bool isVM() const override { return has(FLAG_VM); } + inline bool jccErratum() const override { return m_jccErratum; } + inline const char *brand() const override { return m_brand; } + inline const std::vector &units() const override { return m_units; } + inline MsrMod msrMod() const override { return m_msrMod; } + inline size_t cores() const override { return 0; } + inline size_t L2() const override { return 0; } + inline size_t L3() const override { return 0; } + inline size_t nodes() const override { return 0; } + inline size_t packages() const override { return 1; } + inline size_t threads() const override { return m_threads; } + inline Vendor vendor() const override { return m_vendor; } protected: - char m_brand[64 + 6]{}; - size_t m_threads; - Vendor m_vendor = VENDOR_UNKNOWN; Arch m_arch = ARCH_UNKNOWN; bool m_jccErratum = false; + char m_brand[64 + 6]{}; + size_t m_threads; + std::vector m_units; + Vendor m_vendor = VENDOR_UNKNOWN; private: # ifndef XMRIG_ARM diff --git a/src/backend/cpu/platform/HwlocCpuInfo.cpp b/src/backend/cpu/platform/HwlocCpuInfo.cpp index 6a6841246..8b1c4536b 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.cpp +++ b/src/backend/cpu/platform/HwlocCpuInfo.cpp @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -170,7 +170,8 @@ xmrig::HwlocCpuInfo::HwlocCpuInfo() findCache(root, 2, 3, [this](hwloc_obj_t found) { this->m_cache[found->attr->cache.depth] += found->attr->cache.size; }); - m_threads = countByType(m_topology, HWLOC_OBJ_PU); + setThreads(countByType(m_topology, HWLOC_OBJ_PU)); + m_cores = countByType(m_topology, HWLOC_OBJ_CORE); m_nodes = std::max(hwloc_bitmap_weight(hwloc_topology_get_complete_nodeset(m_topology)), 1); m_packages = countByType(m_topology, HWLOC_OBJ_PACKAGE); @@ -395,3 +396,20 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith } # endif } + + +void xmrig::HwlocCpuInfo::setThreads(size_t threads) +{ + m_threads = threads; + + if (m_units.size() != m_threads) { + m_units.resize(m_threads); + } + + hwloc_obj_t pu = nullptr; + size_t i = 0; + + while ((pu = hwloc_get_next_obj_by_type(m_topology, HWLOC_OBJ_PU, pu)) != nullptr) { + m_units[i++] = static_cast(pu->os_index); + } +} diff --git a/src/backend/cpu/platform/HwlocCpuInfo.h b/src/backend/cpu/platform/HwlocCpuInfo.h index 6a07a0374..69b67a305 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.h +++ b/src/backend/cpu/platform/HwlocCpuInfo.h @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -66,7 +66,7 @@ protected: private: CpuThreads allThreads(const Algorithm &algorithm, uint32_t limit) const; void processTopLevelCache(hwloc_obj_t obj, const Algorithm &algorithm, CpuThreads &threads, size_t limit) const; - + void setThreads(size_t threads); static uint32_t m_features; diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index 99ca6b0ad..a485b382f 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -27,8 +27,9 @@ #include "crypto/randomx/aes_hash.hpp" -#ifdef XMRIG_FIX_RYZEN +#ifdef XMRIG_FEATURE_MSR # include "crypto/rx/RxFix.h" +# include "crypto/rx/RxMsr.h" #endif @@ -39,8 +40,6 @@ class RxPrivate; static bool osInitialized = false; -static bool msrInitialized = false; -static bool msrEnabled = false; static RxPrivate *d_ptr = nullptr; @@ -70,9 +69,9 @@ xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId) void xmrig::Rx::destroy() { - if (osInitialized) { - msrDestroy(); - } +# ifdef XMRIG_FEATURE_MSR + RxMsr::destroy(); +# endif delete d_ptr; @@ -90,11 +89,9 @@ template bool xmrig::Rx::init(const T &seed, const RxConfig &config, const CpuConfig &cpu) { if (seed.algorithm().family() != Algorithm::RANDOM_X) { - if (msrInitialized) { - msrDestroy(); - msrInitialized = false; - msrEnabled = false; - } +# ifdef XMRIG_FEATURE_MSR + RxMsr::destroy(); +# endif return true; } @@ -103,10 +100,11 @@ bool xmrig::Rx::init(const T &seed, const RxConfig &config, const CpuConfig &cpu randomx_set_huge_pages_jit(cpu.isHugePagesJit()); randomx_set_optimized_dataset_init(config.initDatasetAVX2()); - if (!msrInitialized) { - msrEnabled = msrInit(config, cpu.threads().get(seed.algorithm()).data()); - msrInitialized = true; +# ifdef XMRIG_FEATURE_MSR + if (!RxMsr::isInitialized()) { + RxMsr::init(config, cpu.threads().get(seed.algorithm()).data()); } +# endif if (!osInitialized) { # ifdef XMRIG_FIX_RYZEN @@ -139,24 +137,7 @@ bool xmrig::Rx::isReady(const T &seed) #ifdef XMRIG_FEATURE_MSR bool xmrig::Rx::isMSR() { - return msrEnabled; -} -#else -bool xmrig::Rx::msrInit(const RxConfig &, const std::vector &) -{ - return false; -} - - -void xmrig::Rx::msrDestroy() -{ -} -#endif - - -#ifndef XMRIG_FIX_RYZEN -void xmrig::Rx::setupMainLoopExceptionFrame() -{ + return RxMsr::isEnabled(); } #endif diff --git a/src/crypto/rx/Rx.h b/src/crypto/rx/Rx.h index a93f7449f..af8047062 100644 --- a/src/crypto/rx/Rx.h +++ b/src/crypto/rx/Rx.h @@ -57,10 +57,6 @@ public: # else static constexpr bool isMSR() { return false; } # endif - -private: - static bool msrInit(const RxConfig &config, const std::vector& threads); - static void msrDestroy(); }; diff --git a/src/crypto/rx/RxMsr.cpp b/src/crypto/rx/RxMsr.cpp new file mode 100644 index 000000000..6083e9b33 --- /dev/null +++ b/src/crypto/rx/RxMsr.cpp @@ -0,0 +1,184 @@ +/* XMRig + * Copyright (c) 2018-2019 tevador + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "crypto/rx/RxMsr.h" +#include "backend/cpu/Cpu.h" +#include "backend/cpu/CpuThread.h" +#include "base/io/log/Log.h" +#include "base/tools/Chrono.h" +#include "crypto/rx/RxConfig.h" +#include "hw/msr/Msr.h" + + +#include +#include + + +namespace xmrig { + + +bool RxMsr::m_enabled = false; +bool RxMsr::m_initialized = false; + + +static MsrItems items; + + +#ifdef XMRIG_OS_WIN +static constexpr inline int32_t get_cpu(int32_t) { return -1; } +#else +static constexpr inline int32_t get_cpu(int32_t cpu) { return cpu; } +#endif + + +static bool wrmsr(const MsrItems &preset, const std::vector &threads, bool cache_qos, bool save) +{ + auto msr = Msr::get(); + if (!msr) { + return false; + } + + if (save) { + items.reserve(preset.size()); + + for (const auto &i : preset) { + auto item = msr->read(i.reg()); + if (!item.isValid()) { + items.clear(); + + return false; + } + + LOG_VERBOSE("%s " CYAN_BOLD("0x%08" PRIx32) CYAN(":0x%016" PRIx64) CYAN_BOLD(" -> 0x%016" PRIx64), Msr::tag(), i.reg(), item.value(), MsrItem::maskedValue(item.value(), i.value(), i.mask())); + + items.emplace_back(item); + } + } + + // Which CPU cores will have access to the full L3 cache + std::set cacheEnabled; + bool cacheQoSDisabled = threads.empty(); + + if (cache_qos) { + const auto &units = Cpu::info()->units(); + + for (const auto &t : threads) { + const auto affinity = static_cast(t.affinity()); + + // If some thread has no affinity or wrong affinity, disable cache QoS + if (affinity < 0 || std::find(units.begin(), units.end(), affinity) == units.end()) { + cacheQoSDisabled = true; + + LOG_WARN("%s " YELLOW_BOLD("cache QoS can only be enabled when all mining threads have affinity set"), Msr::tag()); + break; + } + + cacheEnabled.insert(affinity); + } + } + + return msr->write([&msr, &preset, cache_qos, &cacheEnabled, cacheQoSDisabled](int32_t cpu) { + for (const auto &item : preset) { + if (!msr->write(item, get_cpu(cpu))) { + return false; + } + } + + if (!cache_qos) { + return true; + } + + // Assign Class Of Service 0 to current CPU core (default, full L3 cache available) + if (cacheQoSDisabled || cacheEnabled.count(cpu)) { + return msr->write(0xC8F, 0, get_cpu(cpu)); + } + + // Disable L3 cache for Class Of Service 1 + if (!msr->write(0xC91, 0, get_cpu(cpu))) { + // Some CPUs don't let set it to all zeros + if (!msr->write(0xC91, 1, get_cpu(cpu))) { + return false; + } + } + + // Assign Class Of Service 1 to current CPU core + return msr->write(0xC8F, 1ULL << 32, get_cpu(cpu)); + }); +} + + +} // namespace xmrig + + +bool xmrig::RxMsr::init(const RxConfig &config, const std::vector &threads) +{ + if (isInitialized()) { + return isEnabled(); + } + + m_initialized = true; + m_enabled = false; + + const auto &preset = config.msrPreset(); + if (preset.empty()) { + return false; + } + + const uint64_t ts = Chrono::steadyMSecs(); + bool cache_qos = config.cacheQoS(); + + if (cache_qos && !Cpu::info()->hasCatL3()) { + if (!threads.empty()) { + LOG_WARN("%s " YELLOW_BOLD("this CPU doesn't support cat_l3, cache QoS is unavailable"), Msr::tag()); + } + + cache_qos = false; + } + + if ((m_enabled = wrmsr(preset, threads, cache_qos, config.rdmsr()))) { + LOG_NOTICE("%s " GREEN_BOLD("register values for \"%s\" preset have been set successfully") BLACK_BOLD(" (%" PRIu64 " ms)"), Msr::tag(), config.msrPresetName(), Chrono::steadyMSecs() - ts); + } + else { + LOG_ERR("%s " RED_BOLD("FAILED TO APPLY MSR MOD, HASHRATE WILL BE LOW"), Msr::tag()); + } + + return isEnabled(); +} + + +void xmrig::RxMsr::destroy() +{ + if (!isInitialized()) { + return; + } + + m_initialized = false; + m_enabled = false; + + if (items.empty()) { + return; + } + + const uint64_t ts = Chrono::steadyMSecs(); + + if (!wrmsr(items, std::vector(), true, false)) { + LOG_ERR("%s " RED_BOLD("failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)")), Msr::tag(), Chrono::steadyMSecs() - ts); + } +} diff --git a/src/crypto/rx/RxMsr.h b/src/crypto/rx/RxMsr.h new file mode 100644 index 000000000..870e298cb --- /dev/null +++ b/src/crypto/rx/RxMsr.h @@ -0,0 +1,53 @@ +/* XMRig + * Copyright (c) 2018-2019 tevador + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_RXMSR_H +#define XMRIG_RXMSR_H + + +#include + + +namespace xmrig +{ + + +class CpuThread; +class RxConfig; + + +class RxMsr +{ +public: + static inline bool isEnabled() { return m_enabled; } + static inline bool isInitialized() { return m_initialized; } + + static bool init(const RxConfig &config, const std::vector &threads); + static void destroy(); + +private: + static bool m_enabled; + static bool m_initialized; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_RXMSR_H */ diff --git a/src/crypto/rx/Rx_linux.cpp b/src/crypto/rx/Rx_linux.cpp deleted file mode 100644 index e73980026..000000000 --- a/src/crypto/rx/Rx_linux.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* XMRig - * Copyright (c) 2018-2019 tevador - * Copyright (c) 2000 Transmeta Corporation - * Copyright (c) 2004-2008 H. Peter Anvin - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "crypto/rx/Rx.h" -#include "backend/cpu/Cpu.h" -#include "backend/cpu/CpuThread.h" -#include "base/io/log/Log.h" -#include "base/tools/Chrono.h" -#include "crypto/rx/RxConfig.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace xmrig { - - -static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " "; -static MsrItems savedState; - - -static inline int dir_filter(const struct dirent *dirp) -{ - return isdigit(dirp->d_name[0]) ? 1 : 0; -} - - -bool rdmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t &value) -{ - char msr_file_name[64]{}; - - sprintf(msr_file_name, "/dev/cpu/%u/msr", cpu); - int fd = open(msr_file_name, O_RDONLY); - if (fd < 0) { - return false; - } - - const bool success = pread(fd, &value, sizeof value, reg) == sizeof value; - - close(fd); - - return success; -} - - -static MsrItem rdmsr(uint32_t reg) -{ - uint64_t value = 0; - if (!rdmsr_on_cpu(reg, 0, value)) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot read MSR 0x%08" PRIx32, tag, reg); - - return {}; - } - - return { reg, value }; -} - - -static uint64_t get_masked_value(uint64_t old_value, uint64_t new_value, uint64_t mask) -{ - return (new_value & mask) | (old_value & ~mask); -} - - -static bool wrmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t value, uint64_t mask) -{ - // If a bit in mask is set to 1, use new value, otherwise use old value - if (mask != MsrItem::kNoMask) { - uint64_t old_value; - if (rdmsr_on_cpu(reg, cpu, old_value)) { - value = get_masked_value(old_value, value, mask); - } - } - - char msr_file_name[64]{}; - - sprintf(msr_file_name, "/dev/cpu/%u/msr", cpu); - int fd = open(msr_file_name, O_WRONLY); - if (fd < 0) { - return false; - } - - const bool success = pwrite(fd, &value, sizeof value, reg) == sizeof value; - - close(fd); - - return success; -} - - -template -static bool wrmsr_on_all_cpus(uint32_t reg, uint64_t value, uint64_t mask, T&& callback) -{ - struct dirent **namelist; - int dir_entries = scandir("/dev/cpu", &namelist, dir_filter, 0); - int errors = 0; - - while (dir_entries--) { - if (!callback(reg, strtoul(namelist[dir_entries]->d_name, nullptr, 10), value, mask)) { - ++errors; - } - - free(namelist[dir_entries]); - } - - free(namelist); - - if (errors) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, tag, reg, value); - } - - return errors == 0; -} - - -static bool wrmsr_modprobe() -{ - if (system("/sbin/modprobe msr allow_writes=on > /dev/null 2>&1") != 0) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "msr kernel module is not available", tag); - - return false; - } - - return true; -} - - -static bool wrmsr(const MsrItems& preset, const std::vector& threads, bool cache_qos, bool save) -{ - if (!wrmsr_modprobe()) { - return false; - } - - if (save) { - for (const auto &i : preset) { - auto item = rdmsr(i.reg()); - LOG_VERBOSE(CLEAR "%s" CYAN_BOLD("0x%08" PRIx32) CYAN(":0x%016" PRIx64) CYAN_BOLD(" -> 0x%016" PRIx64), tag, i.reg(), item.value(), get_masked_value(item.value(), i.value(), i.mask())); - - if (item.isValid()) { - savedState.emplace_back(item); - } - } - } - - for (const auto &i : preset) { - if (!wrmsr_on_all_cpus(i.reg(), i.value(), i.mask(), [](uint32_t reg, uint32_t cpu, uint64_t value, uint64_t mask) { return wrmsr_on_cpu(reg, cpu, value, mask); })) { - return false; - } - } - - const uint32_t n = Cpu::info()->threads(); - - // Which CPU cores will have access to the full L3 cache - std::vector cacheEnabled(n, false); - bool cacheQoSDisabled = threads.empty(); - - for (const CpuThread& t : threads) { - // If some thread has no affinity or wrong affinity, disable cache QoS - if ((t.affinity() < 0) || (t.affinity() >= n)) { - cacheQoSDisabled = true; - if (cache_qos) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "Cache QoS can only be enabled when all mining threads have affinity set", tag); - } - break; - } - - cacheEnabled[t.affinity()] = true; - } - - if (cache_qos && !Cpu::info()->hasCatL3()) { - if (!threads.empty()) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "This CPU doesn't support cat_l3, cache QoS is unavailable", tag); - } - cache_qos = false; - } - - bool result = true; - - if (cache_qos) { - result = wrmsr_on_all_cpus(0xC8F, 0, MsrItem::kNoMask, [&cacheEnabled, cacheQoSDisabled](uint32_t, uint32_t cpu, uint64_t, uint64_t) { - if (cacheQoSDisabled || (cpu >= cacheEnabled.size()) || cacheEnabled[cpu]) { - // Assign Class Of Service 0 to current CPU core (default, full L3 cache available) - if (!wrmsr_on_cpu(0xC8F, cpu, 0, MsrItem::kNoMask)) { - return false; - } - } - else { - // Disable L3 cache for Class Of Service 1 - if (!wrmsr_on_cpu(0xC91, cpu, 0, MsrItem::kNoMask)) { - // Some CPUs don't let set it to all zeros - if (!wrmsr_on_cpu(0xC91, cpu, 1, MsrItem::kNoMask)) { - return false; - } - } - - // Assign Class Of Service 1 to current CPU core - if (!wrmsr_on_cpu(0xC8F, cpu, 1ULL << 32, MsrItem::kNoMask)) { - return false; - } - } - return true; - }); - } - - return result; -} - - -} // namespace xmrig - - -bool xmrig::Rx::msrInit(const RxConfig &config, const std::vector &threads) -{ - const auto &preset = config.msrPreset(); - if (preset.empty()) { - return false; - } - - const uint64_t ts = Chrono::steadyMSecs(); - - if (wrmsr(preset, threads, config.cacheQoS(), config.rdmsr())) { - LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for \"%s\" preset have been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, config.msrPresetName(), Chrono::steadyMSecs() - ts); - - return true; - } - - - LOG_ERR(CLEAR "%s" RED_BOLD_S "FAILED TO APPLY MSR MOD, HASHRATE WILL BE LOW", tag); - - return false; -} - - -void xmrig::Rx::msrDestroy() -{ - if (savedState.empty()) { - return; - } - - const uint64_t ts = Chrono::steadyMSecs(); - - if (!wrmsr(savedState, std::vector(), true, false)) { - LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts); - } -} diff --git a/src/crypto/rx/Rx_win.cpp b/src/crypto/rx/Rx_win.cpp deleted file mode 100644 index 36e13819b..000000000 --- a/src/crypto/rx/Rx_win.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* XMRig - * Copyright (c) 2018-2019 tevador - * Copyright (c) 2000 Transmeta Corporation - * Copyright (c) 2004-2008 H. Peter Anvin - * Copyright (c) 2007-2009 hiyohiyo , - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "crypto/rx/Rx.h" -#include "backend/cpu/Cpu.h" -#include "backend/cpu/CpuThread.h" -#include "base/io/log/Log.h" -#include "base/kernel/Platform.h" -#include "base/tools/Chrono.h" -#include "crypto/rx/RxConfig.h" - - -#include -#include -#include -#include - - -#define SERVICE_NAME L"WinRing0_1_2_0" - - -namespace xmrig { - - -static bool reuseDriver = false; -static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " "; -static MsrItems savedState; - - -static SC_HANDLE hManager; -static SC_HANDLE hService; - - -static bool wrmsr_uninstall_driver() -{ - if (!hService) { - return true; - } - - bool result = true; - - if (!reuseDriver) { - SERVICE_STATUS serviceStatus; - - if (!ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus)) { - result = false; - } - - if (!DeleteService(hService)) { - LOG_ERR(CLEAR "%s" RED_S "failed to remove WinRing0 driver, error %u", tag, GetLastError()); - result = false; - } - } - - CloseServiceHandle(hService); - hService = nullptr; - - return result; -} - - -static HANDLE wrmsr_install_driver() -{ - DWORD err = 0; - - hManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); - if (!hManager) { - err = GetLastError(); - - if (err == ERROR_ACCESS_DENIED) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "to write MSR registers Administrator privileges required.", tag); - } - else { - LOG_ERR(CLEAR "%s" RED_S "failed to open service control manager, error %u", tag, err); - } - - return nullptr; - } - - std::vector dir; - dir.resize(MAX_PATH); - do { - dir.resize(dir.size() * 2); - GetModuleFileNameW(nullptr, dir.data(), dir.size()); - err = GetLastError(); - } while (err == ERROR_INSUFFICIENT_BUFFER); - - if (err != ERROR_SUCCESS) { - LOG_ERR(CLEAR "%s" RED_S "failed to get path to driver, error %u", tag, err); - return nullptr; - } - - for (auto it = dir.end() - 1; it != dir.begin(); --it) { - if ((*it == L'\\') || (*it == L'/')) { - ++it; - *it = L'\0'; - break; - } - } - - std::wstring driverPath = dir.data(); - driverPath += L"WinRing0x64.sys"; - - hService = OpenServiceW(hManager, SERVICE_NAME, SERVICE_ALL_ACCESS); - if (hService) { - LOG_WARN(CLEAR "%s" YELLOW("service ") YELLOW_BOLD("WinRing0_1_2_0") YELLOW(" already exists"), tag); - - SERVICE_STATUS status; - const auto rc = QueryServiceStatus(hService, &status); - - if (rc) { - DWORD dwBytesNeeded; - - QueryServiceConfigA(hService, nullptr, 0, &dwBytesNeeded); - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - std::vector buffer(dwBytesNeeded); - auto config = reinterpret_cast(buffer.data()); - - if (QueryServiceConfigA(hService, config, buffer.size(), &dwBytesNeeded)) { - LOG_INFO(CLEAR "%s" YELLOW("service path: ") YELLOW_BOLD("\"%s\""), tag, config->lpBinaryPathName); - } - } - } - - if (rc && status.dwCurrentState == SERVICE_RUNNING) { - reuseDriver = true; - } - else if (!wrmsr_uninstall_driver()) { - return nullptr; - } - } - - if (!reuseDriver) { - hService = CreateServiceW(hManager, SERVICE_NAME, SERVICE_NAME, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, driverPath.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr); - if (!hService) { - LOG_ERR(CLEAR "%s" RED_S "failed to install WinRing0 driver, error %u", tag, GetLastError()); - - return nullptr; - } - - if (!StartService(hService, 0, nullptr)) { - err = GetLastError(); - if (err != ERROR_SERVICE_ALREADY_RUNNING) { - if (err == ERROR_FILE_NOT_FOUND) { - LOG_ERR(CLEAR "%s" RED("failed to start WinRing0 driver: ") RED_BOLD("\"WinRing0x64.sys not found\""), tag); - } - else { - LOG_ERR(CLEAR "%s" RED_S "failed to start WinRing0 driver, error %u", tag, err); - } - - wrmsr_uninstall_driver(); - - return nullptr; - } - } - } - - HANDLE hDriver = CreateFileW(L"\\\\.\\" SERVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (!hDriver) { - LOG_ERR(CLEAR "%s" RED_S "failed to connect to WinRing0 driver, error %u", tag, GetLastError()); - - return nullptr; - } - - return hDriver; -} - - -#define IOCTL_READ_MSR CTL_CODE(40000, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS) - - -static bool rdmsr(HANDLE driver, uint32_t reg, uint64_t &value) -{ - DWORD size = 0; - - return DeviceIoControl(driver, IOCTL_READ_MSR, ®, sizeof(reg), &value, sizeof(value), &size, nullptr) != 0; -} - - -static MsrItem rdmsr(HANDLE driver, uint32_t reg) -{ - uint64_t value = 0; - if (!rdmsr(driver, reg, value)) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot read MSR 0x%08" PRIx32, tag, reg); - - return {}; - } - - return { reg, value }; -} - - -static uint64_t get_masked_value(uint64_t old_value, uint64_t new_value, uint64_t mask) -{ - return (new_value & mask) | (old_value & ~mask); -} - - -static bool wrmsr(HANDLE driver, uint32_t reg, uint64_t value, uint64_t mask) -{ - struct { - uint32_t reg = 0; - uint32_t value[2]{}; - } input; - - static_assert(sizeof(input) == 12, "Invalid struct size for WinRing0 driver"); - - // If a bit in mask is set to 1, use new value, otherwise use old value - if (mask != MsrItem::kNoMask) { - uint64_t old_value; - if (rdmsr(driver, reg, old_value)) { - value = get_masked_value(old_value, value, mask); - } - } - - input.reg = reg; - *(reinterpret_cast(input.value)) = value; - - DWORD output; - DWORD k; - - if (!DeviceIoControl(driver, IOCTL_WRITE_MSR, &input, sizeof(input), &output, sizeof(output), &k, nullptr)) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, tag, reg, value); - - return false; - } - - return true; -} - - -static bool wrmsr(const MsrItems &preset, const std::vector& threads, bool cache_qos, bool save) -{ - bool success = true; - - HANDLE driver = wrmsr_install_driver(); - if (!driver) { - wrmsr_uninstall_driver(); - - if (hManager) { - CloseServiceHandle(hManager); - } - - return false; - } - - if (save) { - for (const auto &i : preset) { - auto item = rdmsr(driver, i.reg()); - LOG_VERBOSE(CLEAR "%s" CYAN_BOLD("0x%08" PRIx32) CYAN(":0x%016" PRIx64) CYAN_BOLD(" -> 0x%016" PRIx64), tag, i.reg(), item.value(), get_masked_value(item.value(), i.value(), i.mask())); - - if (item.isValid()) { - savedState.emplace_back(item); - } - } - } - - const uint32_t n = Cpu::info()->threads(); - - // Which CPU cores will have access to the full L3 cache - std::vector cacheEnabled(n, false); - bool cacheQoSDisabled = threads.empty(); - - for (const CpuThread& t : threads) { - // If some thread has no affinity or wrong affinity, disable cache QoS - if ((t.affinity() < 0) || (t.affinity() >= n)) { - cacheQoSDisabled = true; - if (cache_qos) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "Cache QoS can only be enabled when all mining threads have affinity set", tag); - } - break; - } - - cacheEnabled[t.affinity()] = true; - } - - if (cache_qos && !Cpu::info()->hasCatL3()) { - if (!threads.empty()) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "This CPU doesn't support cat_l3, cache QoS is unavailable", tag); - } - cache_qos = false; - } - - std::thread wrmsr_thread([n, driver, &preset, &cacheEnabled, cache_qos, cacheQoSDisabled, &success]() { - for (uint32_t i = 0; i < n; ++i) { - if (!Platform::setThreadAffinity(i)) { - continue; - } - - for (const auto &i : preset) { - success &= wrmsr(driver, i.reg(), i.value(), i.mask()); - } - - if (cache_qos) { - if (cacheQoSDisabled || cacheEnabled[i]) { - // Assign Class Of Service 0 to current CPU core (default, full L3 cache available) - success &= wrmsr(driver, 0xC8F, 0, MsrItem::kNoMask); - } - else { - // Disable L3 cache for Class Of Service 1 - if (!wrmsr(driver, 0xC91, 0, MsrItem::kNoMask)) { - // Some CPUs don't let set it to all zeros - if (!wrmsr(driver, 0xC91, 1, MsrItem::kNoMask)) { - success = false; - } - } - - // Assign Class Of Service 1 to current CPU core - success &= wrmsr(driver, 0xC8F, 1ULL << 32, MsrItem::kNoMask); - } - } - - if (!success) { - break; - } - } - }); - - wrmsr_thread.join(); - - CloseHandle(driver); - - wrmsr_uninstall_driver(); - CloseServiceHandle(hManager); - - return success; -} - - -} // namespace xmrig - - -bool xmrig::Rx::msrInit(const RxConfig &config, const std::vector& threads) -{ - const auto &preset = config.msrPreset(); - if (preset.empty()) { - return false; - } - - const uint64_t ts = Chrono::steadyMSecs(); - - if (wrmsr(preset, threads, config.cacheQoS(), config.rdmsr())) { - LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for \"%s\" preset has been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, config.msrPresetName(), Chrono::steadyMSecs() - ts); - - return true; - } - - LOG_ERR(CLEAR "%s" RED_BOLD_S "FAILED TO APPLY MSR MOD, HASHRATE WILL BE LOW", tag); - - return false; -} - - -void xmrig::Rx::msrDestroy() -{ - if (savedState.empty()) { - return; - } - - const uint64_t ts = Chrono::steadyMSecs(); - - if (!wrmsr(savedState, std::vector(), true, false)) { - LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts); - } -} diff --git a/src/hw/msr/Msr.cpp b/src/hw/msr/Msr.cpp index 68c60e6ed..1fed87760 100644 --- a/src/hw/msr/Msr.cpp +++ b/src/hw/msr/Msr.cpp @@ -55,6 +55,24 @@ std::shared_ptr xmrig::Msr::get() } +bool xmrig::Msr::write(uint32_t reg, uint64_t value, int32_t cpu, uint64_t mask, bool verbose) +{ + if (mask != MsrItem::kNoMask) { + uint64_t old_value; + if (rdmsr(reg, cpu, old_value)) { + value = MsrItem::maskedValue(old_value, value, mask); + } + } + + const bool result = wrmsr(reg, value, cpu); + if (!result && verbose) { + LOG_WARN("%s " YELLOW_BOLD("cannot set MSR 0x%08" PRIx32 " to 0x%016" PRIx64), tag(), reg, value); + } + + return result; +} + + xmrig::MsrItem xmrig::Msr::read(uint32_t reg, int32_t cpu, bool verbose) const { uint64_t value = 0; diff --git a/src/hw/msr/Msr.h b/src/hw/msr/Msr.h index 5f325a251..3bd88dd56 100644 --- a/src/hw/msr/Msr.h +++ b/src/hw/msr/Msr.h @@ -24,6 +24,7 @@ #include "hw/msr/MsrItem.h" +#include #include @@ -39,17 +40,24 @@ class Msr public: XMRIG_DISABLE_COPY_MOVE(Msr) + using Callback = std::function; + Msr(); ~Msr(); static const char *tag(); static std::shared_ptr get(); + inline bool write(const MsrItem &item, int32_t cpu = -1, bool verbose = true) { return write(item.reg(), item.value(), cpu, item.mask(), verbose); } + bool isAvailable() const; + bool write(uint32_t reg, uint64_t value, int32_t cpu = -1, uint64_t mask = MsrItem::kNoMask, bool verbose = true); + bool write(Callback &&callback); MsrItem read(uint32_t reg, int32_t cpu = -1, bool verbose = true) const; private: bool rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const; + bool wrmsr(uint32_t reg, uint64_t value, int32_t cpu); MsrPrivate *d_ptr = nullptr; }; diff --git a/src/hw/msr/MsrItem.h b/src/hw/msr/MsrItem.h index ad3c9d393..00c0416ae 100644 --- a/src/hw/msr/MsrItem.h +++ b/src/hw/msr/MsrItem.h @@ -46,6 +46,11 @@ public: inline uint64_t value() const { return m_value; } inline uint64_t mask() const { return m_mask; } + static inline uint64_t maskedValue(uint64_t old_value, uint64_t new_value, uint64_t mask) + { + return (new_value & mask) | (old_value & ~mask); + } + rapidjson::Value toJSON(rapidjson::Document &doc) const; String toString() const; diff --git a/src/hw/msr/Msr_linux.cpp b/src/hw/msr/Msr_linux.cpp index 02a29c72f..9053c32f1 100644 --- a/src/hw/msr/Msr_linux.cpp +++ b/src/hw/msr/Msr_linux.cpp @@ -19,6 +19,7 @@ #include "hw/msr/Msr.h" #include "3rdparty/fmt/core.h" +#include "backend/cpu/Cpu.h" #include "base/io/log/Log.h" @@ -31,8 +32,6 @@ #include #include #include -#include -#include namespace xmrig { @@ -70,6 +69,20 @@ bool xmrig::Msr::isAvailable() const } +bool xmrig::Msr::write(Callback &&callback) +{ + const auto &units = Cpu::info()->units(); + + for (int32_t pu : units) { + if (!callback(pu)) { + return false; + } + } + + return true; +} + + bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const { const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? 0 : cpu); @@ -84,3 +97,20 @@ bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const return success; } + + +bool xmrig::Msr::wrmsr(uint32_t reg, uint64_t value, int32_t cpu) +{ + const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? 0 : cpu); + int fd = open(name.c_str(), O_WRONLY); + + if (fd < 0) { + return false; + } + + const bool success = pwrite(fd, &value, sizeof value, reg) == sizeof value; + + close(fd); + + return success; +} diff --git a/src/hw/msr/Msr_win.cpp b/src/hw/msr/Msr_win.cpp index d055785cd..654f67783 100644 --- a/src/hw/msr/Msr_win.cpp +++ b/src/hw/msr/Msr_win.cpp @@ -18,10 +18,13 @@ #include "hw/msr/Msr.h" +#include "backend/cpu/Cpu.h" #include "base/io/log/Log.h" +#include "base/kernel/Platform.h" #include +#include #include #include @@ -196,9 +199,57 @@ bool xmrig::Msr::isAvailable() const } -bool xmrig::Msr::rdmsr(uint32_t reg, int32_t, uint64_t &value) const +bool xmrig::Msr::write(Callback &&callback) { + const auto &units = Cpu::info()->units(); + bool success = false; + + std::thread thread([&callback, &units, &success]() { + for (int32_t pu : units) { + if (!Platform::setThreadAffinity(pu)) { + continue; + } + + if (!callback(pu)) { + return; + } + } + + success = true; + }); + + thread.join(); + + return success; +} + + +bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const +{ + assert(cpu < 0); + DWORD size = 0; return DeviceIoControl(d_ptr->driver, IOCTL_READ_MSR, ®, sizeof(reg), &value, sizeof(value), &size, nullptr) != 0; } + + +bool xmrig::Msr::wrmsr(uint32_t reg, uint64_t value, int32_t cpu) +{ + assert(cpu < 0); + + struct { + uint32_t reg = 0; + uint32_t value[2]{}; + } input; + + static_assert(sizeof(input) == 12, "Invalid struct size for WinRing0 driver"); + + input.reg = reg; + *(reinterpret_cast(input.value)) = value; + + DWORD output; + DWORD k; + + return DeviceIoControl(d_ptr->driver, IOCTL_WRITE_MSR, &input, sizeof(input), &output, sizeof(output), &k, nullptr) != 0; +} From 672f6df6c1d02951dc0e95cd19f03bec4646e8da Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 24 Jan 2021 02:23:27 +0700 Subject: [PATCH 5/5] Fixed Cache QoS restore on exit where it not supported. --- src/crypto/rx/RxMsr.cpp | 15 +++++++-------- src/crypto/rx/RxMsr.h | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/crypto/rx/RxMsr.cpp b/src/crypto/rx/RxMsr.cpp index 6083e9b33..171579e9c 100644 --- a/src/crypto/rx/RxMsr.cpp +++ b/src/crypto/rx/RxMsr.cpp @@ -34,6 +34,7 @@ namespace xmrig { +bool RxMsr::m_cacheQoS = false; bool RxMsr::m_enabled = false; bool RxMsr::m_initialized = false; @@ -142,17 +143,15 @@ bool xmrig::RxMsr::init(const RxConfig &config, const std::vector &th } const uint64_t ts = Chrono::steadyMSecs(); - bool cache_qos = config.cacheQoS(); + m_cacheQoS = config.cacheQoS(); - if (cache_qos && !Cpu::info()->hasCatL3()) { - if (!threads.empty()) { - LOG_WARN("%s " YELLOW_BOLD("this CPU doesn't support cat_l3, cache QoS is unavailable"), Msr::tag()); - } + if (m_cacheQoS && !Cpu::info()->hasCatL3()) { + LOG_WARN("%s " YELLOW_BOLD("this CPU doesn't support cat_l3, cache QoS is unavailable"), Msr::tag()); - cache_qos = false; + m_cacheQoS = false; } - if ((m_enabled = wrmsr(preset, threads, cache_qos, config.rdmsr()))) { + if ((m_enabled = wrmsr(preset, threads, m_cacheQoS, config.rdmsr()))) { LOG_NOTICE("%s " GREEN_BOLD("register values for \"%s\" preset have been set successfully") BLACK_BOLD(" (%" PRIu64 " ms)"), Msr::tag(), config.msrPresetName(), Chrono::steadyMSecs() - ts); } else { @@ -178,7 +177,7 @@ void xmrig::RxMsr::destroy() const uint64_t ts = Chrono::steadyMSecs(); - if (!wrmsr(items, std::vector(), true, false)) { + if (!wrmsr(items, std::vector(), m_cacheQoS, false)) { LOG_ERR("%s " RED_BOLD("failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)")), Msr::tag(), Chrono::steadyMSecs() - ts); } } diff --git a/src/crypto/rx/RxMsr.h b/src/crypto/rx/RxMsr.h index 870e298cb..8e1bf9547 100644 --- a/src/crypto/rx/RxMsr.h +++ b/src/crypto/rx/RxMsr.h @@ -42,6 +42,7 @@ public: static void destroy(); private: + static bool m_cacheQoS; static bool m_enabled; static bool m_initialized; };