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; +}