diff --git a/CHANGELOG.md b/CHANGELOG.md index f3777102..5d4ed0e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v5.3.0 +- [#1414](https://github.com/xmrig/xmrig/pull/1414) Added native MSR support for Windows, by using signed **WinRing0 driver** (© 2007-2009 OpenLibSys.org). +- Added new [MSR documentation](https://xmrig.com/docs/miner/randomx-optimization-guide/msr). + # v5.2.1 - [#1408](https://github.com/xmrig/xmrig/pull/1408) Added RandomX boost script for Linux (if you don't like run miner with root privileges). - Added support for [AMD Ryzen MSR registers](https://www.reddit.com/r/MoneroMining/comments/e962fu/9526_hs_on_ryzen_7_3700x_xmrig_520_1gb_pages_msr/) (Linux only). diff --git a/CMakeLists.txt b/CMakeLists.txt index b65d5337..b990d67d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,3 +209,8 @@ endif() add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB} ${ARGON2_LIBRARY}) + +if (WIN32) + add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/bin/WinRing0/WinRing0x64.sys" $) +endif() diff --git a/bin/WinRing0/LICENSE b/bin/WinRing0/LICENSE new file mode 100644 index 00000000..f34a6e96 --- /dev/null +++ b/bin/WinRing0/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2007-2009 OpenLibSys.org. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/bin/WinRing0/WinRing0x64.sys b/bin/WinRing0/WinRing0x64.sys new file mode 100644 index 00000000..197c255a Binary files /dev/null and b/bin/WinRing0/WinRing0x64.sys differ diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index 74f4048e..18939970 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -79,7 +79,9 @@ if (WITH_RANDOMX) ) endif() - if (XMRIG_OS_LINUX AND NOT XMRIG_ARM) + if (WIN32) + list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_windows.cpp) + elseif (XMRIG_OS_LINUX AND NOT XMRIG_ARM) list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_linux.cpp) endif() else() diff --git a/scripts/enable_1gb_pages.sh b/scripts/enable_1gb_pages.sh new file mode 100755 index 00000000..16d889f1 --- /dev/null +++ b/scripts/enable_1gb_pages.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e + +# https://xmrig.com/docs/miner/hugepages#onegb-huge-pages + +sysctl -w vm.nr_hugepages=$(nproc) + +for i in $(find /sys/devices/system/node/node* -maxdepth 0 -type d); +do + echo 3 > "$i/hugepages/hugepages-1048576kB/nr_hugepages"; +done + +echo "1GB pages successfully enabled" \ No newline at end of file diff --git a/src/base/io/log/Log.h b/src/base/io/log/Log.h index cfd3c3a3..c7e0c3f4 100644 --- a/src/base/io/log/Log.h +++ b/src/base/io/log/Log.h @@ -83,6 +83,7 @@ private: #define WHITE_BOLD_S CSI "1;37m" // actually white #define GREEN_BG_BOLD_S CSI "42;1m" +#define YELLOW_BG_BOLD_S CSI "43;1m" #define BLUE_BG_S CSI "44m" #define BLUE_BG_BOLD_S CSI "44;1m" #define MAGENTA_BG_S CSI "45m" @@ -109,6 +110,7 @@ private: #define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR #define GREEN_BG_BOLD(x) GREEN_BG_BOLD_S x CLEAR +#define YELLOW_BG_BOLD(x) YELLOW_BG_BOLD_S x CLEAR #define BLUE_BG(x) BLUE_BG_S x CLEAR #define BLUE_BG_BOLD(x) BLUE_BG_BOLD_S x CLEAR #define MAGENTA_BG(x) MAGENTA_BG_S x CLEAR diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index f6685fbf..8ee611f9 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -115,7 +115,7 @@ void xmrig::Rx::init(IRxListener *listener) } -#if !defined(XMRIG_OS_LINUX) || defined(XMRIG_ARM) +#if (!defined(XMRIG_OS_LINUX) && !defined(_WIN32)) || defined(XMRIG_ARM) void xmrig::Rx::osInit(const RxConfig &) { } diff --git a/src/crypto/rx/Rx_linux.cpp b/src/crypto/rx/Rx_linux.cpp index 782467a7..98d343f4 100644 --- a/src/crypto/rx/Rx_linux.cpp +++ b/src/crypto/rx/Rx_linux.cpp @@ -28,12 +28,13 @@ #include "crypto/rx/Rx.h" -#include "backend/common/Tags.h" #include "backend/cpu/Cpu.h" #include "base/io/log/Log.h" +#include "base/tools/Chrono.h" #include "crypto/rx/RxConfig.h" +#include #include #include #include @@ -47,6 +48,18 @@ namespace xmrig { +enum MsrMod : uint32_t { + MSR_MOD_NONE, + MSR_MOD_RYZEN, + MSR_MOD_INTEL, + MSR_MOD_MAX +}; + + +static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " "; +static const std::array modNames = { nullptr, "Ryzen", "Intel" }; + + static inline int dir_filter(const struct dirent *dirp) { return isdigit(dirp->d_name[0]) ? 1 : 0; @@ -88,7 +101,7 @@ static bool wrmsr_on_all_cpus(uint32_t reg, uint64_t value) free(namelist); if (errors) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, rx_tag(), reg, value); + LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, tag, reg, value); } return errors == 0; @@ -98,7 +111,7 @@ static bool wrmsr_on_all_cpus(uint32_t reg, uint64_t value) static bool wrmsr_modprobe() { if (system("/sbin/modprobe msr > /dev/null 2>&1") != 0) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "msr kernel module is not available", rx_tag()); + LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "msr kernel module is not available", tag); return false; } @@ -116,16 +129,33 @@ void xmrig::Rx::osInit(const RxConfig &config) return; } - if (Cpu::info()->assembly() == Assembly::RYZEN && wrmsr_modprobe()) { - wrmsr_on_all_cpus(0xC0011022, 0x510000); - wrmsr_on_all_cpus(0xC001102b, 0x1808cc16); - wrmsr_on_all_cpus(0xC0011020, 0); - wrmsr_on_all_cpus(0xC0011021, 0x40); + MsrMod mod = MSR_MOD_NONE; + if (Cpu::info()->assembly() == Assembly::RYZEN) { + mod = MSR_MOD_RYZEN; + } + else if (Cpu::info()->vendor() == ICpuInfo::VENDOR_INTEL) { + mod = MSR_MOD_INTEL; + } + if (mod == MSR_MOD_NONE) { return; } - if (Cpu::info()->vendor() == ICpuInfo::VENDOR_INTEL && wrmsr_modprobe()) { + const uint64_t ts = Chrono::steadyMSecs(); + + if (!wrmsr_modprobe()) { + return; + } + + if (mod == MSR_MOD_RYZEN) { + wrmsr_on_all_cpus(0xC0011020, 0); + wrmsr_on_all_cpus(0xC0011021, 0x40); + wrmsr_on_all_cpus(0xC0011022, 0x510000); + wrmsr_on_all_cpus(0xC001102b, 0x1808cc16); + } + else if (mod == MSR_MOD_INTEL) { wrmsr_on_all_cpus(0x1a4, config.wrmsr()); } + + LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for %s has been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, modNames[mod], Chrono::steadyMSecs() - ts); } diff --git a/src/crypto/rx/Rx_windows.cpp b/src/crypto/rx/Rx_windows.cpp new file mode 100644 index 00000000..a12030e4 --- /dev/null +++ b/src/crypto/rx/Rx_windows.cpp @@ -0,0 +1,255 @@ +/* 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 2000 Transmeta Corporation + * Copyright 2004-2008 H. Peter Anvin + * Copyright 2007-2009 hiyohiyo , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 "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 { + + +enum MsrMod : uint32_t { + MSR_MOD_NONE, + MSR_MOD_RYZEN, + MSR_MOD_INTEL, + MSR_MOD_MAX +}; + + +static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " "; +static const std::array modNames = { nullptr, "Ryzen", "Intel" }; + + +static SC_HANDLE hManager; +static SC_HANDLE hService; + + +static bool wrmsr_uninstall_driver() +{ + if (!hService) { + return true; + } + + bool result = true; + SERVICE_STATUS serviceStatus; + + if (!ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus)) { + LOG_ERR(CLEAR "%s" RED_S "failed to stop WinRing0 driver, error %u", tag, GetLastError()); + 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(); 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 && !wrmsr_uninstall_driver()) { + return nullptr; + } + + 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) { + LOG_ERR(CLEAR "%s" RED_S "failed to start WinRing0 driver, error %u", tag, err); + + CloseServiceHandle(hService); + hService = nullptr; + + 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_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +static bool wrmsr(HANDLE hDriver, uint32_t reg, uint64_t value) { + struct { + uint32_t reg = 0; + uint32_t value[2]{}; + } input; + + static_assert(sizeof(input) == 12, "Invalid struct size for WinRing0 driver"); + + input.reg = reg; + *((uint64_t*)input.value) = value; + + DWORD output; + DWORD k; + + if (!DeviceIoControl(hDriver, 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; +} + + +} // namespace xmrig + + +void xmrig::Rx::osInit(const RxConfig &config) +{ + if ((config.wrmsr() < 0) || !ICpuInfo::isX64()) { + return; + } + + MsrMod mod = MSR_MOD_NONE; + if (Cpu::info()->assembly() == Assembly::RYZEN) { + mod = MSR_MOD_RYZEN; + } + else if (Cpu::info()->vendor() == ICpuInfo::VENDOR_INTEL) { + mod = MSR_MOD_INTEL; + } + + if (mod == MSR_MOD_NONE) { + return; + } + + const uint64_t ts = Chrono::steadyMSecs(); + + HANDLE hDriver = wrmsr_install_driver(); + if (!hDriver) { + wrmsr_uninstall_driver(); + + if (hManager) { + CloseServiceHandle(hManager); + } + + return; + } + + std::thread wrmsr_thread([hDriver, mod, &config]() { + for (uint32_t i = 0, n = Cpu::info()->threads(); i < n; ++i) { + Platform::setThreadAffinity(i); + + if (mod == MSR_MOD_RYZEN) { + wrmsr(hDriver, 0xC0011020, 0); + wrmsr(hDriver, 0xC0011021, 0x40); + wrmsr(hDriver, 0xC0011022, 0x510000); + wrmsr(hDriver, 0xC001102b, 0x1808cc16); + } + else if (mod == MSR_MOD_INTEL) { + wrmsr(hDriver, 0x1a4, config.wrmsr()); + } + } + }); + + wrmsr_thread.join(); + + CloseHandle(hDriver); + + wrmsr_uninstall_driver(); + CloseServiceHandle(hManager); + + LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for %s has been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, modNames[mod], Chrono::steadyMSecs() - ts); +} diff --git a/src/version.h b/src/version.h index a17ed41e..74d47b4f 100644 --- a/src/version.h +++ b/src/version.h @@ -28,15 +28,15 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig miner" -#define APP_VERSION "5.2.1" +#define APP_VERSION "5.3.0-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "miner" #define APP_VER_MAJOR 5 -#define APP_VER_MINOR 2 -#define APP_VER_PATCH 1 +#define APP_VER_MINOR 3 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1920)