diff --git a/CHANGELOG.md b/CHANGELOG.md index 708d712e..b9f51507 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# v6.8.0 +- [#2052](https://github.com/xmrig/xmrig/pull/2052) Added DMI/SMBIOS reader. + - Added information about memory modules on the miner startup and for online benchmark. + - Added new HTTP API endpoint: `GET /2/dmi`. + - Added new command line option `--no-dmi` or config option `"dmi"`. + - Added new CMake option `-DWITH_DMI=OFF`. +- [#2057](https://github.com/xmrig/xmrig/pull/2057) Improved MSR subsystem code quality. +- [#2058](https://github.com/xmrig/xmrig/pull/2058) RandomX JIT x86: removed unnecessary instructions. + # v6.7.2 - [#2039](https://github.com/xmrig/xmrig/pull/2039) Fixed solo mining. diff --git a/CMakeLists.txt b/CMakeLists.txt index 88280c0f..e30fcc85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ option(WITH_PROFILING "Enable profiling for developers" OFF) option(WITH_SSE4_1 "Enable SSE 4.1 for Blake2" ON) option(WITH_BENCHMARK "Enable builtin RandomX benchmark and stress test" ON) option(WITH_SECURE_JIT "Enable secure access to JIT memory" OFF) +option(WITH_DMI "Enable DMI/SMBIOS reader" ON) option(BUILD_STATIC "Build static binary" OFF) option(ARM_TARGET "Force use specific ARM target 8 or 7" 0) @@ -178,7 +179,7 @@ else() endif() add_definitions(-DXMRIG_MINER_PROJECT -DXMRIG_JSON_SINGLE_LINE_ARRAY) -add_definitions(-D__STDC_FORMAT_MACROS -DUNICODE) +add_definitions(-D__STDC_FORMAT_MACROS -DUNICODE -D_FILE_OFFSET_BITS=64) find_package(UV REQUIRED) @@ -207,6 +208,9 @@ if (WITH_EMBEDDED_CONFIG) add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG) endif() +include(src/hw/api/api.cmake) +include(src/hw/dmi/dmi.cmake) + include_directories(src) include_directories(src/3rdparty) include_directories(${UV_INCLUDE_DIR}) diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index a4cb4208..28b578ee 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -106,13 +106,29 @@ 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/RxFix_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/RxFix_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/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 + ) else() remove_definitions(/DXMRIG_FEATURE_MSR) remove_definitions(/DXMRIG_FIX_RYZEN) diff --git a/src/Summary.cpp b/src/Summary.cpp index ebaeb356..eaee89bf 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2019 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig + * Copyright 2018-2021 SChernykh + * Copyright 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,6 +39,11 @@ #include "version.h" +#ifdef XMRIG_FEATURE_DMI +# include "hw/dmi/DmiReader.h" +#endif + + #ifdef XMRIG_ALGO_RANDOMX # include "crypto/rx/RxConfig.h" #endif @@ -71,7 +76,7 @@ inline static const char *asmName(Assembly::Id assembly) #endif -static void print_memory(Config *config) +static void print_pages(const Config *config) { Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", "HUGE PAGES", config->cpu().isHugePages() ? (VirtualMemory::isHugepagesAvailable() ? kHugepagesSupported : RED_BOLD("unavailable")) : RED_BOLD("disabled")); @@ -87,7 +92,7 @@ static void print_memory(Config *config) } -static void print_cpu(Config *) +static void print_cpu(const Config *) { const auto info = Cpu::info(); @@ -116,7 +121,7 @@ static void print_cpu(Config *) } -static void print_memory() +static void print_memory(const Config *config) { constexpr size_t oneGiB = 1024U * 1024U * 1024U; const auto freeMem = static_cast(uv_get_free_memory()); @@ -124,16 +129,49 @@ static void print_memory() const double percent = freeMem > 0 ? ((totalMem - freeMem) / totalMem * 100.0) : 100.0; - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%.1f/%.1f GB") BLACK_BOLD(" (%.0f%%)"), + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%.1f/%.1f") CYAN(" GB") BLACK_BOLD(" (%.0f%%)"), "MEMORY", (totalMem - freeMem) / oneGiB, totalMem / oneGiB, percent ); + +# ifdef XMRIG_FEATURE_DMI + if (!config->isDMI()) { + return; + } + + DmiReader reader; + if (!reader.read()) { + return; + } + + const bool vm = Cpu::info()->isVM(); + + for (const auto &memory : reader.memory()) { + if (!memory.isValid()) { + continue; + } + + if (memory.size()) { + Log::print(WHITE_BOLD(" %-13s") "%s: " CYAN_BOLD("%" PRIu64) CYAN(" GB ") WHITE_BOLD("%s @ %" PRIu64 " MHz ") BLACK_BOLD("%s"), + "", memory.slot().data(), memory.size() / oneGiB, memory.type(), memory.speed() / 1000000ULL, memory.product().data()); + } + else if (!vm) { + Log::print(WHITE_BOLD(" %-13s") "%s: " BLACK_BOLD(""), "", memory.slot().data()); + } + } + + const auto &board = vm ? reader.system() : reader.board(); + + if (board.isValid()) { + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") " - " WHITE_BOLD("%s"), "MOTHERBOARD", board.vendor().data(), board.product().data()); + } +# endif } -static void print_threads(Config *config) +static void print_threads(const Config *config) { Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s%d%%"), "DONATE", @@ -175,14 +213,16 @@ static void print_commands(Config *) void xmrig::Summary::print(Controller *controller) { - controller->config()->printVersions(); - print_memory(controller->config()); - print_cpu(controller->config()); - print_memory(); - print_threads(controller->config()); - controller->config()->pools().print(); + const auto config = controller->config(); - print_commands(controller->config()); + config->printVersions(); + print_pages(config); + print_cpu(config); + print_memory(config); + print_threads(config); + config->pools().print(); + + print_commands(config); } diff --git a/src/Summary.h b/src/Summary.h index 4317d13e..0b03f675 100644 --- a/src/Summary.h +++ b/src/Summary.h @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 diff --git a/src/backend/cpu/interfaces/ICpuInfo.h b/src/backend/cpu/interfaces/ICpuInfo.h index b772a92c..7a888723 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 98ca3fad..b25a3d9f 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 edf119a2..88760bac 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/BasicCpuInfo_arm.cpp b/src/backend/cpu/platform/BasicCpuInfo_arm.cpp index 84d2c57f..318928cd 100644 --- a/src/backend/cpu/platform/BasicCpuInfo_arm.cpp +++ b/src/backend/cpu/platform/BasicCpuInfo_arm.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 @@ -50,6 +50,11 @@ extern String cpu_name_arm(); xmrig::BasicCpuInfo::BasicCpuInfo() : m_threads(std::thread::hardware_concurrency()) { + m_units.resize(m_threads); + for (int32_t i = 0; i < static_cast(m_threads); ++i) { + m_units[i] = i; + } + # ifdef XMRIG_ARMv8 memcpy(m_brand, "ARMv8", 5); # else diff --git a/src/backend/cpu/platform/HwlocCpuInfo.cpp b/src/backend/cpu/platform/HwlocCpuInfo.cpp index 83f7e5d8..0cff8b64 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 @@ -125,8 +125,6 @@ static inline bool isCacheExclusive(hwloc_obj_t obj) xmrig::HwlocCpuInfo::HwlocCpuInfo() { - m_threads = 0; - hwloc_topology_init(&m_topology); hwloc_topology_load(m_topology); @@ -170,7 +168,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); @@ -277,10 +276,8 @@ xmrig::CpuThreads xmrig::HwlocCpuInfo::allThreads(const Algorithm &algorithm, ui CpuThreads threads; threads.reserve(m_threads); - hwloc_obj_t pu = nullptr; - - while ((pu = hwloc_get_next_obj_by_type(m_topology, HWLOC_OBJ_PU, pu)) != nullptr) { - threads.add(pu->os_index, 0); + for (const int32_t pu : m_units) { + threads.add(pu, 0); } if (threads.isEmpty()) { @@ -401,3 +398,24 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith } # endif } + + +void xmrig::HwlocCpuInfo::setThreads(size_t threads) +{ + if (!threads) { + return; + } + + 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 6a07a037..69b67a30 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/base/api/Api.cpp b/src/base/api/Api.cpp index 89e61593..3a71fd9c 100644 --- a/src/base/api/Api.cpp +++ b/src/base/api/Api.cpp @@ -1,12 +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-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 diff --git a/src/base/api/Api.h b/src/base/api/Api.h index 0ee9ca6a..f412a317 100644 --- a/src/base/api/Api.h +++ b/src/base/api/Api.h @@ -1,12 +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-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 @@ -31,7 +25,6 @@ #include "base/kernel/interfaces/IBaseListener.h" -#include "base/tools/Object.h" #include "base/tools/String.h" diff --git a/src/base/api/interfaces/IApiListener.h b/src/base/api/interfaces/IApiListener.h index bbf153a6..71ee9c76 100644 --- a/src/base/api/interfaces/IApiListener.h +++ b/src/base/api/interfaces/IApiListener.h @@ -1,10 +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 2016-2018 XMRig + * Copyright 2018-2021 SChernykh + * Copyright 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 @@ -24,6 +20,9 @@ #define XMRIG_IAPILISTENER_H +#include "base/tools/Object.h" + + namespace xmrig { @@ -33,6 +32,9 @@ class IApiRequest; class IApiListener { public: + XMRIG_DISABLE_COPY_MOVE(IApiListener) + + IApiListener() = default; virtual ~IApiListener() = default; # ifdef XMRIG_FEATURE_API diff --git a/src/base/api/interfaces/IApiRequest.h b/src/base/api/interfaces/IApiRequest.h index c05e513e..35fb27d5 100644 --- a/src/base/api/interfaces/IApiRequest.h +++ b/src/base/api/interfaces/IApiRequest.h @@ -1,12 +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-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 +21,7 @@ #include "3rdparty/rapidjson/fwd.h" +#include "base/tools/Object.h" namespace xmrig { @@ -38,6 +33,8 @@ class String; class IApiRequest { public: + XMRIG_DISABLE_COPY_MOVE(IApiRequest) + enum Method { METHOD_DELETE, METHOD_GET, @@ -67,7 +64,8 @@ public: }; - virtual ~IApiRequest() = default; + IApiRequest() = default; + virtual ~IApiRequest() = default; virtual bool accept() = 0; virtual bool hasParseError() const = 0; diff --git a/src/base/kernel/interfaces/IBaseListener.h b/src/base/kernel/interfaces/IBaseListener.h index 1f212369..80120ab8 100644 --- a/src/base/kernel/interfaces/IBaseListener.h +++ b/src/base/kernel/interfaces/IBaseListener.h @@ -1,12 +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-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 @@ -26,6 +20,9 @@ #define XMRIG_IBASELISTENER_H +#include "base/tools/Object.h" + + namespace xmrig { @@ -35,7 +32,10 @@ class Config; class IBaseListener { public: - virtual ~IBaseListener() = default; + XMRIG_DISABLE_COPY_MOVE(IBaseListener) + + IBaseListener() = default; + virtual ~IBaseListener() = default; virtual void onConfigChanged(Config *config, Config *previousConfig) = 0; }; diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 7b75843e..5baf0334 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 @@ -84,6 +84,7 @@ public: BenchSeedKey = 1046, BenchHashKey = 1047, BenchTokenKey = 1048, + DmiKey = 1049, // xmrig common CPUPriorityKey = 1021, diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index ef9a829a..31e113fd 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 @@ -134,7 +134,7 @@ void xmrig::Pools::load(const IJsonReader &reader) m_data.clear(); # ifdef XMRIG_FEATURE_BENCHMARK - m_benchmark = std::shared_ptr(BenchConfig::create(reader.getObject(BenchConfig::kBenchmark))); + m_benchmark = std::shared_ptr(BenchConfig::create(reader.getObject(BenchConfig::kBenchmark), reader.getBool("dmi", true))); if (m_benchmark) { m_data.emplace_back(m_benchmark); diff --git a/src/base/net/stratum/Pools.h b/src/base/net/stratum/Pools.h index 477ce211..7fa6ec9d 100644 --- a/src/base/net/stratum/Pools.h +++ b/src/base/net/stratum/Pools.h @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 diff --git a/src/base/net/stratum/benchmark/BenchClient.cpp b/src/base/net/stratum/benchmark/BenchClient.cpp index c81f4010..0e1093a1 100644 --- a/src/base/net/stratum/benchmark/BenchClient.cpp +++ b/src/base/net/stratum/benchmark/BenchClient.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 @@ -34,6 +34,10 @@ #include "base/tools/Cvt.h" #include "version.h" +#ifdef XMRIG_FEATURE_DMI +# include "hw/dmi/DmiReader.h" +#endif + xmrig::BenchClient::BenchClient(const std::shared_ptr &benchmark, IClientListener* listener) : m_listener(listener), @@ -336,6 +340,15 @@ void xmrig::BenchClient::send(Request request) doc.AddMember("steady_ready_ts", m_readyTime, allocator); doc.AddMember("cpu", Cpu::toJSON(doc), allocator); +# ifdef XMRIG_FEATURE_DMI + if (m_benchmark->isDMI()) { + DmiReader reader; + if (reader.read()) { + doc.AddMember("dmi", reader.toJSON(doc), allocator); + } + } +# endif + FetchRequest req(HTTP_POST, m_ip, BenchConfig::kApiPort, "/1/benchmark", doc, BenchConfig::kApiTLS, true); fetch(tag(), std::move(req), m_httpListener); } diff --git a/src/base/net/stratum/benchmark/BenchClient.h b/src/base/net/stratum/benchmark/BenchClient.h index 018bceaa..7eac1ee8 100644 --- a/src/base/net/stratum/benchmark/BenchClient.h +++ b/src/base/net/stratum/benchmark/BenchClient.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 diff --git a/src/base/net/stratum/benchmark/BenchConfig.cpp b/src/base/net/stratum/benchmark/BenchConfig.cpp index 2e02755a..c81e0c17 100644 --- a/src/base/net/stratum/benchmark/BenchConfig.cpp +++ b/src/base/net/stratum/benchmark/BenchConfig.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 @@ -52,8 +52,9 @@ const char *BenchConfig::kApiHost = "127.0.0.1"; } // namespace xmrig -xmrig::BenchConfig::BenchConfig(uint32_t size, const String &id, const rapidjson::Value &object) : +xmrig::BenchConfig::BenchConfig(uint32_t size, const String &id, const rapidjson::Value &object, bool dmi) : m_algorithm(Json::getString(object, kAlgo)), + m_dmi(dmi), m_submit(Json::getBool(object, kSubmit)), m_id(id), m_seed(Json::getString(object, kSeed)), @@ -72,7 +73,7 @@ xmrig::BenchConfig::BenchConfig(uint32_t size, const String &id, const rapidjson } -xmrig::BenchConfig *xmrig::BenchConfig::create(const rapidjson::Value &object) +xmrig::BenchConfig *xmrig::BenchConfig::create(const rapidjson::Value &object, bool dmi) { if (!object.IsObject() || object.ObjectEmpty()) { return nullptr; @@ -85,7 +86,7 @@ xmrig::BenchConfig *xmrig::BenchConfig::create(const rapidjson::Value &object) return nullptr; } - return new BenchConfig(size, id, object); + return new BenchConfig(size, id, object, dmi); } diff --git a/src/base/net/stratum/benchmark/BenchConfig.h b/src/base/net/stratum/benchmark/BenchConfig.h index f1310236..87e54197 100644 --- a/src/base/net/stratum/benchmark/BenchConfig.h +++ b/src/base/net/stratum/benchmark/BenchConfig.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 @@ -49,10 +49,11 @@ public: static constexpr const uint16_t kApiPort = 18805; # endif - BenchConfig(uint32_t size, const String &id, const rapidjson::Value &object); + BenchConfig(uint32_t size, const String &id, const rapidjson::Value &object, bool dmi); - static BenchConfig *create(const rapidjson::Value &object); + static BenchConfig *create(const rapidjson::Value &object, bool dmi); + inline bool isDMI() const { return m_dmi; } inline bool isSubmit() const { return m_submit; } inline const Algorithm &algorithm() const { return m_algorithm; } inline const String &id() const { return m_id; } @@ -67,6 +68,7 @@ private: static uint32_t getSize(const char *benchmark); Algorithm m_algorithm; + bool m_dmi; bool m_submit; String m_id; String m_seed; diff --git a/src/config.json b/src/config.json index 9821f184..dd65070f 100644 --- a/src/config.json +++ b/src/config.json @@ -83,6 +83,7 @@ ], "print-time": 60, "health-print-time": 60, + "dmi": true, "retries": 5, "retry-pause": 5, "syslog": false, diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 475c3eb2..51366670 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -1,12 +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-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 @@ -31,6 +25,12 @@ #include "net/Network.h" +#ifdef XMRIG_FEATURE_API +# include "base/api/Api.h" +# include "hw/api/HwApi.h" +#endif + + #include @@ -42,8 +42,6 @@ xmrig::Controller::Controller(Process *process) : xmrig::Controller::~Controller() { - delete m_network; - VirtualMemory::destroy(); } @@ -54,7 +52,12 @@ int xmrig::Controller::init() VirtualMemory::init(config()->cpu().memPoolSize(), config()->cpu().isHugePages()); - m_network = new Network(this); + m_network = std::make_shared(this); + +# ifdef XMRIG_FEATURE_API + m_hwApi = std::make_shared(); + api()->addListener(m_hwApi.get()); +# endif return 0; } @@ -62,7 +65,7 @@ int xmrig::Controller::init() #ifdef XMRIG_FEATURE_MO_BENCHMARK void xmrig::Controller::pre_start() { - m_miner = new Miner(this); + m_miner = std::make_shared(this); } #endif @@ -70,9 +73,9 @@ void xmrig::Controller::pre_start() void xmrig::Controller::start() { Base::start(); -#ifndef XMRIG_FEATURE_BENCHMARK - m_miner = new Miner(this); -#endif + + if (m_miner == nullptr) m_miner = std::make_shared(this); + network()->connect(); } @@ -81,29 +84,26 @@ void xmrig::Controller::stop() { Base::stop(); - delete m_network; - m_network = nullptr; + m_network.reset(); m_miner->stop(); - - delete m_miner; - m_miner = nullptr; + m_miner.reset(); } xmrig::Miner *xmrig::Controller::miner() const { - assert(m_miner != nullptr); + assert(m_miner); - return m_miner; + return m_miner.get(); } xmrig::Network *xmrig::Controller::network() const { - assert(m_network != nullptr); + assert(m_network); - return m_network; + return m_network.get(); } diff --git a/src/core/Controller.h b/src/core/Controller.h index 5c53af04..262f6f4d 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -1,12 +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-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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,12 +21,15 @@ #include "base/kernel/Base.h" -#include "base/tools/Object.h" + + +#include namespace xmrig { +class HwApi; class Job; class Miner; class Network; @@ -58,8 +55,12 @@ public: void execCommand(char command); private: - Miner *m_miner = nullptr; - Network *m_network = nullptr; + std::shared_ptr m_miner; + std::shared_ptr m_network; + +# ifdef XMRIG_FEATURE_API + std::shared_ptr m_hwApi; +# endif }; diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index d2978002..0f93864c 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 @@ -23,9 +23,9 @@ */ #include +#include #include #include -#include #include "core/config/Config.h" @@ -55,16 +55,19 @@ namespace xmrig { #ifdef XMRIG_FEATURE_OPENCL -static const char *kOcl = "opencl"; +const char *Config::kOcl = "opencl"; #endif #ifdef XMRIG_FEATURE_CUDA -static const char *kCuda = "cuda"; +const char *Config::kCuda = "cuda"; #endif - #if defined(XMRIG_FEATURE_NVML) || defined (XMRIG_FEATURE_ADL) -static const char *kHealthPrintTime = "health-print-time"; +const char *Config::kHealthPrintTime = "health-print-time"; +#endif + +#ifdef XMRIG_FEATURE_DMI +const char *Config::kDMI = "dmi"; #endif @@ -88,6 +91,10 @@ public: # if defined(XMRIG_FEATURE_NVML) || defined (XMRIG_FEATURE_ADL) uint32_t healthPrintTime = 60; # endif + +# ifdef XMRIG_FEATURE_DMI + bool dmi = true; +# endif }; } @@ -143,6 +150,14 @@ uint32_t xmrig::Config::healthPrintTime() const #endif +#ifdef XMRIG_FEATURE_DMI +bool xmrig::Config::isDMI() const +{ + return d_ptr->dmi; +} +#endif + + bool xmrig::Config::isShouldSave() const { if (!isAutoSave()) { @@ -201,6 +216,10 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName) m_benchmark.read(reader.getValue(kAlgoPerf)); # endif +# ifdef XMRIG_FEATURE_DMI + d_ptr->dmi = reader.getBool(kDMI, d_ptr->dmi); +# endif + return true; } @@ -246,6 +265,11 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const # if defined(XMRIG_FEATURE_NVML) || defined (XMRIG_FEATURE_ADL) doc.AddMember(StringRef(kHealthPrintTime), healthPrintTime(), allocator); # endif + +# ifdef XMRIG_FEATURE_DMI + doc.AddMember(StringRef(kDMI), isDMI(), allocator); +# endif + doc.AddMember(StringRef(kSyslog), isSyslog(), allocator); # ifdef XMRIG_FEATURE_TLS diff --git a/src/core/config/Config.h b/src/core/config/Config.h index d1735136..66c0bcdb 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 @@ -53,6 +53,22 @@ class Config : public BaseConfig public: XMRIG_DISABLE_COPY_MOVE(Config); +# ifdef XMRIG_FEATURE_OPENCL + static const char *kOcl; +# endif + +# ifdef XMRIG_FEATURE_CUDA + static const char *kCuda; +# endif + +# if defined(XMRIG_FEATURE_NVML) || defined (XMRIG_FEATURE_ADL) + static const char *kHealthPrintTime; +# endif + +# ifdef XMRIG_FEATURE_DMI + static const char *kDMI; +# endif + Config(); ~Config() override; @@ -73,7 +89,13 @@ public: # if defined(XMRIG_FEATURE_NVML) || defined (XMRIG_FEATURE_ADL) uint32_t healthPrintTime() const; # else - uint32_t healthPrintTime() const { return 0; } + uint32_t healthPrintTime() const { return 0; } +# endif + +# ifdef XMRIG_FEATURE_DMI + bool isDMI() const; +# else + static constexpr inline bool isDMI() { return false; } # endif bool isShouldSave() const; diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index b8a431fd..b32aede3 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 @@ -23,11 +23,11 @@ */ +#include "core/config/ConfigTransform.h" #include "base/kernel/interfaces/IConfig.h" -#include "backend/cpu/CpuConfig.h" #include "base/net/stratum/Pool.h" #include "base/net/stratum/Pools.h" -#include "core/config/ConfigTransform.h" +#include "core/config/Config.h" #include "crypto/cn/CnHash.h" @@ -51,14 +51,6 @@ static const char *kEnabled = "enabled"; static const char *kIntensity = "intensity"; static const char *kThreads = "threads"; -#ifdef XMRIG_FEATURE_OPENCL -static const char *kOcl = "opencl"; -#endif - -#ifdef XMRIG_FEATURE_CUDA -static const char *kCuda = "cuda"; -#endif - static inline uint64_t intensity(uint64_t av) { @@ -122,7 +114,7 @@ void xmrig::ConfigTransform::finalize(rapidjson::Document &doc) # ifdef XMRIG_FEATURE_OPENCL if (m_opencl) { - set(doc, kOcl, kEnabled, true); + set(doc, Config::kOcl, kEnabled, true); } # endif } @@ -208,47 +200,54 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const break; case IConfig::OclCacheKey: /* --opencl-no-cache */ - return set(doc, kOcl, "cache", false); + return set(doc, Config::kOcl, "cache", false); case IConfig::OclLoaderKey: /* --opencl-loader */ - return set(doc, kOcl, "loader", arg); + return set(doc, Config::kOcl, "loader", arg); case IConfig::OclDevicesKey: /* --opencl-devices */ m_opencl = true; - return set(doc, kOcl, "devices-hint", arg); + return set(doc, Config::kOcl, "devices-hint", arg); case IConfig::OclPlatformKey: /* --opencl-platform */ if (strlen(arg) < 3) { - return set(doc, kOcl, "platform", static_cast(strtol(arg, nullptr, 10))); + return set(doc, Config::kOcl, "platform", static_cast(strtol(arg, nullptr, 10))); } - return set(doc, kOcl, "platform", arg); + return set(doc, Config::kOcl, "platform", arg); # endif # ifdef XMRIG_FEATURE_CUDA case IConfig::CudaKey: /* --cuda */ - return set(doc, kCuda, kEnabled, true); + return set(doc, Config::kCuda, kEnabled, true); case IConfig::CudaLoaderKey: /* --cuda-loader */ - return set(doc, kCuda, "loader", arg); + return set(doc, Config::kCuda, "loader", arg); case IConfig::CudaDevicesKey: /* --cuda-devices */ - set(doc, kCuda, kEnabled, true); - return set(doc, kCuda, "devices-hint", arg); + set(doc, Config::kCuda, kEnabled, true); + return set(doc, Config::kCuda, "devices-hint", arg); case IConfig::CudaBFactorKey: /* --cuda-bfactor-hint */ - return set(doc, kCuda, "bfactor-hint", static_cast(strtol(arg, nullptr, 10))); + return set(doc, Config::kCuda, "bfactor-hint", static_cast(strtol(arg, nullptr, 10))); case IConfig::CudaBSleepKey: /* --cuda-bsleep-hint */ - return set(doc, kCuda, "bsleep-hint", static_cast(strtol(arg, nullptr, 10))); + return set(doc, Config::kCuda, "bsleep-hint", static_cast(strtol(arg, nullptr, 10))); # endif # ifdef XMRIG_FEATURE_NVML case IConfig::NvmlKey: /* --no-nvml */ - return set(doc, kCuda, "nvml", false); + return set(doc, Config::kCuda, "nvml", false); +# endif +# if defined(XMRIG_FEATURE_NVML) || defined (XMRIG_FEATURE_ADL) case IConfig::HealthPrintTimeKey: /* --health-print-time */ - return set(doc, "health-print-time", static_cast(strtol(arg, nullptr, 10))); + return set(doc, Config::kHealthPrintTime, static_cast(strtol(arg, nullptr, 10))); +# endif + +# ifdef XMRIG_FEATURE_DMI + case IConfig::DmiKey: /* --no-dmi */ + return set(doc, Config::kDMI, false); # endif # ifdef XMRIG_FEATURE_BENCHMARK diff --git a/src/core/config/ConfigTransform.h b/src/core/config/ConfigTransform.h index 0251777c..8fd2505c 100644 --- a/src/core/config/ConfigTransform.h +++ b/src/core/config/ConfigTransform.h @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 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 diff --git a/src/core/config/Config_default.h b/src/core/config/Config_default.h index 94cb88d6..afeecbce 100644 --- a/src/core/config/Config_default.h +++ b/src/core/config/Config_default.h @@ -1,12 +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-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 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 @@ -22,6 +16,7 @@ * along with this program. If not, see . */ + #ifndef XMRIG_CONFIG_DEFAULT_H #define XMRIG_CONFIG_DEFAULT_H @@ -29,6 +24,7 @@ namespace xmrig { +// This feature require CMake option: -DWITH_EMBEDDED_CONFIG=ON #ifdef XMRIG_FEATURE_EMBEDDED_CONFIG const static char *default_config = R"===( @@ -45,9 +41,9 @@ R"===( "restricted": true }, "autosave": true, - "version": 1, "background": false, "colors": true, + "title": true, "randomx": { "init": -1, "init-avx2": -1, @@ -80,6 +76,7 @@ R"===( "cache": true, "loader": null, "platform": "AMD", + "adl": true, "cn/0": false, "cn-lite/0": false }, @@ -90,7 +87,7 @@ R"===( "cn/0": false, "cn-lite/0": false }, - "donate-level": 5, + "donate-level": 1, "donate-over-proxy": 1, "log-file": null, "pools": [ @@ -107,15 +104,27 @@ R"===( "tls": false, "tls-fingerprint": null, "daemon": false, + "socks5": null, "self-select": null } ], "print-time": 60, "health-print-time": 60, + "dmi": true, "retries": 5, "retry-pause": 5, "syslog": false, + "tls": { + "enabled": false, + "protocols": null, + "cert": null, + "cert_key": null, + "ciphers": null, + "ciphersuites": null, + "dhparam": null + }, "user-agent": null, + "verbose": 0, "watch": true, "pause-on-battery": false } diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index ad8a8038..8bac99a5 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -159,7 +159,12 @@ static const option options[] = { # endif # ifdef XMRIG_FEATURE_NVML { "no-nvml", 0, nullptr, IConfig::NvmlKey }, +# endif +# if defined(XMRIG_FEATURE_NVML) || defined (XMRIG_FEATURE_ADL) { "health-print-time", 1, nullptr, IConfig::HealthPrintTimeKey }, +# endif +# ifdef XMRIG_FEATURE_DMI + { "no-dmi", 0, nullptr, IConfig::DmiKey }, # endif { nullptr, 0, nullptr, 0 } }; diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 54e629ec..261e571c 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -190,6 +190,10 @@ static inline const std::string &usage() u += " --hash=HASH compare benchmark result with specified hash\n"; # endif +# ifdef XMRIG_FEATURE_DMI + u += " --no-dmi disable DMI/SMBIOS reader\n"; +# endif + return u; } diff --git a/src/crypto/randomx/aes_hash.cpp b/src/crypto/randomx/aes_hash.cpp index 206300fd..2383dab4 100644 --- a/src/crypto/randomx/aes_hash.cpp +++ b/src/crypto/randomx/aes_hash.cpp @@ -371,7 +371,7 @@ hashAndFillAes1Rx4_impl* softAESImpl = &hashAndFillAes1Rx4<1,1>; void SelectSoftAESImpl(size_t threadsCount) { - constexpr int test_length_ms = 100; + constexpr uint64_t test_length_ms = 100; const std::array impl = { &hashAndFillAes1Rx4<1,1>, &hashAndFillAes1Rx4<2,1>, diff --git a/src/crypto/randomx/jit_compiler_x86.cpp b/src/crypto/randomx/jit_compiler_x86.cpp index 8c3145b2..aec051ed 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 @@ -417,17 +417,15 @@ namespace randomx { void JitCompilerX86::generateProgramPrologue(Program& prog, ProgramConfiguration& pcfg) { codePos = ADDR(randomx_program_prologue_first_load) - ADDR(randomx_program_prologue); - code[codePos + 2] = 0xc0 + pcfg.readReg0; - code[codePos + 5] = 0xc0 + pcfg.readReg1; - *(uint32_t*)(code + codePos + 10) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated; - *(uint32_t*)(code + codePos + 20) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated; + *(uint32_t*)(code + codePos + 4) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated; + *(uint32_t*)(code + codePos + 14) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated; if (hasAVX) { - uint32_t* p = (uint32_t*)(code + codePos + 67); + uint32_t* p = (uint32_t*)(code + codePos + 61); *p = (*p & 0xFF000000U) | 0x0077F8C5U; } # 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/randomx/jit_compiler_x86_static.S b/src/crypto/randomx/jit_compiler_x86_static.S index e2177147..2ead26e9 100644 --- a/src/crypto/randomx/jit_compiler_x86_static.S +++ b/src/crypto/randomx/jit_compiler_x86_static.S @@ -93,8 +93,6 @@ DECL(randomx_program_prologue): movapd xmm15, xmmword ptr [scaleMask+rip] DECL(randomx_program_prologue_first_load): - xor rax, r8 - xor rax, r8 mov rdx, rax and eax, RANDOMX_SCRATCHPAD_MASK ror rdx, 32 diff --git a/src/crypto/randomx/jit_compiler_x86_static.asm b/src/crypto/randomx/jit_compiler_x86_static.asm index 6e90cbf3..2c5d1bbe 100644 --- a/src/crypto/randomx/jit_compiler_x86_static.asm +++ b/src/crypto/randomx/jit_compiler_x86_static.asm @@ -81,8 +81,6 @@ randomx_program_prologue PROC randomx_program_prologue ENDP randomx_program_prologue_first_load PROC - xor rax, r8 - xor rax, r8 mov rdx, rax and eax, RANDOMX_SCRATCHPAD_MASK ror rdx, 32 diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index 40d3c612..a485b382 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,12 @@ #include "crypto/randomx/aes_hash.hpp" +#ifdef XMRIG_FEATURE_MSR +# include "crypto/rx/RxFix.h" +# include "crypto/rx/RxMsr.h" +#endif + + namespace xmrig { @@ -34,8 +40,6 @@ class RxPrivate; static bool osInitialized = false; -static bool msrInitialized = false; -static bool msrEnabled = false; static RxPrivate *d_ptr = nullptr; @@ -65,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; @@ -85,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; } @@ -98,13 +100,17 @@ 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) { - setupMainLoopExceptionFrame(); +# ifdef XMRIG_FIX_RYZEN + RxFix::setupMainLoopExceptionFrame(); +# endif + if (!cpu.isHwAES()) { SelectSoftAESImpl(cpu.threads().get(seed.algorithm()).count()); } @@ -131,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 42bd0c15..af804706 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,20 +52,11 @@ 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 static constexpr bool isMSR() { return false; } # endif - -private: - static bool msrInit(const RxConfig &config, const std::vector& threads); - static void msrDestroy(); - static void setupMainLoopExceptionFrame(); }; diff --git a/src/crypto/rx/RxConfig.h b/src/crypto/rx/RxConfig.h index fb3a656d..78d2f964 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/crypto/rx/RxFix.h b/src/crypto/rx/RxFix.h new file mode 100644 index 00000000..66d2e7d9 --- /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 00000000..1a3743c7 --- /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 00000000..75538be4 --- /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/RxMsr.cpp b/src/crypto/rx/RxMsr.cpp new file mode 100644 index 00000000..171579e9 --- /dev/null +++ b/src/crypto/rx/RxMsr.cpp @@ -0,0 +1,183 @@ +/* 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_cacheQoS = false; +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(); + m_cacheQoS = config.cacheQoS(); + + if (m_cacheQoS && !Cpu::info()->hasCatL3()) { + LOG_WARN("%s " YELLOW_BOLD("this CPU doesn't support cat_l3, cache QoS is unavailable"), Msr::tag()); + + m_cacheQoS = false; + } + + 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 { + 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(), 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 new file mode 100644 index 00000000..8e1bf954 --- /dev/null +++ b/src/crypto/rx/RxMsr.h @@ -0,0 +1,54 @@ +/* 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_cacheQoS; + 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 34a097bb..00000000 --- a/src/crypto/rx/Rx_linux.cpp +++ /dev/null @@ -1,313 +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 -#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; -} - - -#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 - - -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); - } -} - - -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 deleted file mode 100644 index 77e7c9b4..00000000 --- a/src/crypto/rx/Rx_win.cpp +++ /dev/null @@ -1,431 +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(" is 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; -} - - -#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 - - -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); - } -} - - -void xmrig::Rx::setupMainLoopExceptionFrame() -{ -# ifdef XMRIG_FIX_RYZEN - AddVectoredExceptionHandler(1, MainLoopHandler); -# endif -} diff --git a/src/donate.h b/src/donate.h index 9323dcab..1d29161c 100644 --- a/src/donate.h +++ b/src/donate.h @@ -34,7 +34,7 @@ * Example of how it works for the setting of 1%: * You miner will mine into your usual pool for random time (in range from 49.5 to 148.5 minutes), * then switch to the developer's pool for 1 minute, then switch again to your pool for 99 minutes - * and then switch agaiin to developer's pool for 1 minute, these rounds will continue until miner working. + * and then switch again to developer's pool for 1 minute, these rounds will continue until miner working. * * Randomised only first round, to prevent waves on the donation pool. * diff --git a/src/hw/api/HwApi.cpp b/src/hw/api/HwApi.cpp new file mode 100644 index 00000000..fed5de3f --- /dev/null +++ b/src/hw/api/HwApi.cpp @@ -0,0 +1,45 @@ +/* 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/api/HwApi.h" +#include "base/api/interfaces/IApiRequest.h" +#include "base/tools/String.h" + + +#ifdef XMRIG_FEATURE_DMI +# include "hw/dmi/DmiReader.h" +#endif + + +void xmrig::HwApi::onRequest(IApiRequest &request) +{ + if (request.method() == IApiRequest::METHOD_GET) { +# ifdef XMRIG_FEATURE_DMI + if (request.url() == "/2/dmi") { + if (!m_dmi) { + m_dmi = std::make_shared(); + m_dmi->read(); + } + + request.accept(); + m_dmi->toJSON(request.reply(), request.doc()); + } +# endif + } +} diff --git a/src/hw/api/HwApi.h b/src/hw/api/HwApi.h new file mode 100644 index 00000000..f434a0a5 --- /dev/null +++ b/src/hw/api/HwApi.h @@ -0,0 +1,53 @@ +/* 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_HWAPI_H +#define XMRIG_HWAPI_H + + +#include "base/api/interfaces/IApiListener.h" + + +#include + + +namespace xmrig { + + +struct DmiReader; + + +class HwApi : public IApiListener +{ +public: + HwApi() = default; + +protected: + void onRequest(IApiRequest &request) override; + +private: +# ifdef XMRIG_FEATURE_DMI + std::shared_ptr m_dmi; +# endif +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_HWAPI_H */ diff --git a/src/hw/api/api.cmake b/src/hw/api/api.cmake new file mode 100644 index 00000000..94b22470 --- /dev/null +++ b/src/hw/api/api.cmake @@ -0,0 +1,11 @@ +if (WITH_HTTP) + add_definitions(/DXMRIG_FEATURE_DMI) + + list(APPEND HEADERS + src/hw/api/HwApi.h + ) + + list(APPEND SOURCES + src/hw/api/HwApi.cpp + ) +endif() diff --git a/src/hw/dmi/DmiBoard.cpp b/src/hw/dmi/DmiBoard.cpp new file mode 100644 index 00000000..3cbe3dd9 --- /dev/null +++ b/src/hw/dmi/DmiBoard.cpp @@ -0,0 +1,50 @@ +/* XMRig + * Copyright (c) 2000-2002 Alan Cox + * Copyright (c) 2005-2020 Jean Delvare + * 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/dmi/DmiBoard.h" +#include "3rdparty/rapidjson/document.h" +#include "hw/dmi/DmiTools.h" + + +void xmrig::DmiBoard::decode(dmi_header *h) +{ + if (h->length < 0x08) { + return; + } + + m_vendor = dmi_string(h, 0x04); + m_product = dmi_string(h, 0x05); +} + + +#ifdef XMRIG_FEATURE_API +rapidjson::Value xmrig::DmiBoard::toJSON(rapidjson::Document &doc) const +{ + using namespace rapidjson; + + auto &allocator = doc.GetAllocator(); + Value out(kObjectType); + out.AddMember("vendor", m_vendor.toJSON(doc), allocator); + out.AddMember("product", m_product.toJSON(doc), allocator); + + return out; +} +#endif diff --git a/src/hw/dmi/DmiBoard.h b/src/hw/dmi/DmiBoard.h new file mode 100644 index 00000000..0c64da17 --- /dev/null +++ b/src/hw/dmi/DmiBoard.h @@ -0,0 +1,58 @@ +/* XMRig + * Copyright (c) 2000-2002 Alan Cox + * Copyright (c) 2005-2020 Jean Delvare + * 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_DMIBOARD_H +#define XMRIG_DMIBOARD_H + + +#include "base/tools/String.h" + + +namespace xmrig { + + +struct dmi_header; + + +class DmiBoard +{ +public: + DmiBoard() = default; + + inline const String &product() const { return m_product; } + inline const String &vendor() const { return m_vendor; } + inline bool isValid() const { return !m_product.isEmpty() && !m_vendor.isEmpty(); } + + void decode(dmi_header *h); + +# ifdef XMRIG_FEATURE_API + rapidjson::Value toJSON(rapidjson::Document &doc) const; +# endif + +private: + String m_product; + String m_vendor; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DMIBOARD_H */ diff --git a/src/hw/dmi/DmiMemory.cpp b/src/hw/dmi/DmiMemory.cpp new file mode 100644 index 00000000..05af0962 --- /dev/null +++ b/src/hw/dmi/DmiMemory.cpp @@ -0,0 +1,219 @@ +/* XMRig + * Copyright (c) 2000-2002 Alan Cox + * Copyright (c) 2005-2020 Jean Delvare + * 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/dmi/DmiMemory.h" +#include "3rdparty/rapidjson/document.h" +#include "hw/dmi/DmiTools.h" + + +#include +#include + + +namespace xmrig { + + +static inline uint16_t dmi_memory_device_width(uint16_t code) +{ + return (code == 0xFFFF || code == 0) ? 0 : code; +} + + +static const char *dmi_memory_device_form_factor(uint8_t code) +{ + static const std::array form_factor + { + "Other", + "Unknown", + "SIMM", + "SIP", + "Chip", + "DIP", + "ZIP", + "Proprietary Card", + "DIMM", + "TSOP", + "Row Of Chips", + "RIMM", + "SODIMM", + "SRIMM", + "FB-DIMM", + "Die" + }; + + if (code >= 0x01 && code <= form_factor.size()) { + return form_factor[code - 0x01]; + } + + return form_factor[1]; +} + + +static const char *dmi_memory_device_type(uint8_t code) +{ + static const std::array type + { + "Other", /* 0x01 */ + "Unknown", + "DRAM", + "EDRAM", + "VRAM", + "SRAM", + "RAM", + "ROM", + "Flash", + "EEPROM", + "FEPROM", + "EPROM", + "CDRAM", + "3DRAM", + "SDRAM", + "SGRAM", + "RDRAM", + "DDR", + "DDR2", + "DDR2 FB-DIMM", + "Reserved", + "Reserved", + "Reserved", + "DDR3", + "FBD2", + "DDR4", + "LPDDR", + "LPDDR2", + "LPDDR3", + "LPDDR4", + "Logical non-volatile device", + "HBM", + "HBM2", + "DDR5", + "LPDDR5" + }; + + if (code >= 0x01 && code <= type.size()) { + return type[code - 0x01]; + } + + return type[1]; +} + + +static uint64_t dmi_memory_device_speed(uint16_t code1, uint32_t code2) +{ + return (code1 == 0xFFFF) ? code2 : code1; +} + + +} // namespace xmrig + + + +xmrig::DmiMemory::DmiMemory(dmi_header *h) +{ + if (h->length < 0x15) { + return; + } + + m_totalWidth = dmi_memory_device_width(dmi_get(h, 0x08)); + m_width = dmi_memory_device_width(dmi_get(h, 0x0A)); + + auto size = dmi_get(h, 0x0C); + if (h->length >= 0x20 && size == 0x7FFF) { + m_size = (dmi_get(h, 0x1C) & 0x7FFFFFFFUL) * 1024ULL * 1024ULL; + } + else if (size) { + m_size = (1024ULL * (size & 0x7FFF) * ((size & 0x8000) ? 1 : 1024ULL)); + } + + m_formFactor = h->data[0x0E]; + m_slot = dmi_string(h, 0x10); + m_bank = dmi_string(h, 0x11); + m_type = h->data[0x12]; + + if (!m_size || h->length < 0x17) { + return; + } + + m_speed = dmi_memory_device_speed(dmi_get(h, 0x15), h->length >= 0x5C ? dmi_get(h, 0x54) : 0) * 1000000ULL; + + if (h->length < 0x1B) { + return; + } + + m_vendor = dmi_string(h, 0x17); + m_product = dmi_string(h, 0x1A); + + if (h->length < 0x1C) { + return; + } + + m_rank = h->data[0x1B] & 0x0F; + + if (h->length < 0x22) { + return; + } + + const uint64_t configuredSpeed = dmi_memory_device_speed(dmi_get(h, 0x20), h->length >= 0x5C ? dmi_get(h, 0x58) : 0) * 1000000ULL; + m_speed = configuredSpeed ? configuredSpeed : m_speed; + + if (h->length < 0x28) { + return; + } + + m_voltage = dmi_get(h, 0x26); +} + + +const char *xmrig::DmiMemory::formFactor() const +{ + return dmi_memory_device_form_factor(m_formFactor); +} + + +const char *xmrig::DmiMemory::type() const +{ + return dmi_memory_device_type(m_type); +} + + +#ifdef XMRIG_FEATURE_API +rapidjson::Value xmrig::DmiMemory::toJSON(rapidjson::Document &doc) const +{ + using namespace rapidjson; + + auto &allocator = doc.GetAllocator(); + Value out(kObjectType); + out.AddMember("slot", m_slot.toJSON(doc), allocator); + out.AddMember("type", StringRef(type()), allocator); + out.AddMember("form_factor", StringRef(formFactor()), allocator); + out.AddMember("size", m_size, allocator); + out.AddMember("speed", m_speed, allocator); + out.AddMember("rank", m_rank, allocator); + out.AddMember("voltage", m_voltage, allocator); + out.AddMember("width", m_width, allocator); + out.AddMember("total_width", m_totalWidth, allocator); + out.AddMember("vendor", m_vendor.toJSON(doc), allocator); + out.AddMember("product", m_product.toJSON(doc), allocator); + out.AddMember("bank", m_bank.toJSON(doc), allocator); + + return out; +} +#endif diff --git a/src/hw/dmi/DmiMemory.h b/src/hw/dmi/DmiMemory.h new file mode 100644 index 00000000..badee2cf --- /dev/null +++ b/src/hw/dmi/DmiMemory.h @@ -0,0 +1,78 @@ +/* XMRig + * Copyright (c) 2000-2002 Alan Cox + * Copyright (c) 2005-2020 Jean Delvare + * 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_DMIMEMORY_H +#define XMRIG_DMIMEMORY_H + + +#include "base/tools/String.h" + + +namespace xmrig { + + +struct dmi_header; + + +class DmiMemory +{ +public: + DmiMemory() = default; + DmiMemory(dmi_header *h); + + inline bool isValid() const { return !m_slot.isEmpty(); } + inline const String &bank() const { return m_bank; } + inline const String &product() const { return m_product; } + inline const String &slot() const { return m_slot; } + inline const String &vendor() const { return m_vendor; } + inline uint16_t totalWidth() const { return m_totalWidth; } + inline uint16_t voltage() const { return m_voltage; } + inline uint16_t width() const { return m_width; } + inline uint64_t size() const { return m_size; } + inline uint64_t speed() const { return m_speed; } + inline uint8_t rank() const { return m_rank; } + + const char *formFactor() const; + const char *type() const; + +# ifdef XMRIG_FEATURE_API + rapidjson::Value toJSON(rapidjson::Document &doc) const; +# endif + +private: + String m_bank; + String m_product; + String m_slot; + String m_vendor; + uint16_t m_totalWidth = 0; + uint16_t m_voltage = 0; + uint16_t m_width = 0; + uint64_t m_size = 0; + uint64_t m_speed = 0; + uint8_t m_formFactor = 0; + uint8_t m_rank = 0; + uint8_t m_type = 0; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DMIMEMORY_H */ diff --git a/src/hw/dmi/DmiReader.cpp b/src/hw/dmi/DmiReader.cpp new file mode 100644 index 00000000..18211759 --- /dev/null +++ b/src/hw/dmi/DmiReader.cpp @@ -0,0 +1,139 @@ +/* XMRig + * Copyright (c) 2000-2002 Alan Cox + * Copyright (c) 2005-2020 Jean Delvare + * 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/dmi/DmiReader.h" +#include "3rdparty/fmt/core.h" +#include "3rdparty/rapidjson/document.h" +#include "hw/dmi/DmiTools.h" + + +namespace xmrig { + + +static void dmi_get_header(dmi_header *h, uint8_t *data) +{ + h->type = data[0]; + h->length = data[1]; + h->handle = dmi_get(data + 2); + h->data = data; +} + + +} // namespace xmrig + + +#ifdef XMRIG_FEATURE_API +rapidjson::Value xmrig::DmiReader::toJSON(rapidjson::Document &doc) const +{ + rapidjson::Value obj; + toJSON(obj, doc); + + return obj; +} + + +void xmrig::DmiReader::toJSON(rapidjson::Value &out, rapidjson::Document &doc) const +{ + using namespace rapidjson; + + auto &allocator = doc.GetAllocator(); + out.SetObject(); + + Value memory(kArrayType); + memory.Reserve(m_memory.size(), allocator); + + for (const auto &value : m_memory) { + memory.PushBack(value.toJSON(doc), allocator); + } + + out.AddMember("smbios", Value(fmt::format("{}.{}.{}", m_version >> 16, m_version >> 8 & 0xff, m_version & 0xff).c_str(), allocator), allocator); + out.AddMember("system", m_system.toJSON(doc), allocator); + out.AddMember("board", m_board.toJSON(doc), allocator); + out.AddMember("memory", memory, allocator); +} +#endif + + +bool xmrig::DmiReader::decode(uint8_t *buf, const Cleanup &cleanup) +{ + const bool rc = decode(buf); + + cleanup(); + + return rc; +} + + +bool xmrig::DmiReader::decode(uint8_t *buf) +{ + if (!buf) { + return false; + } + + uint8_t *data = buf; + int i = 0; + + while (data + 4 <= buf + m_size) { + dmi_header h{}; + dmi_get_header(&h, data); + + if (h.length < 4 || h.type == 127) { + break; + } + i++; + + uint8_t *next = data + h.length; + while (static_cast(next - buf + 1) < m_size && (next[0] != 0 || next[1] != 0)) { + next++; + } + +# ifdef XMRIG_OS_APPLE + while ((unsigned long)(next - buf + 1) < m_size && (next[0] == 0 && next[1] == 0)) +# endif + next += 2; + + if (static_cast(next - buf) > m_size) { + data = next; + break; + } + + switch (h.type) { + case 1: + m_system.decode(&h); + break; + + case 2: + m_board.decode(&h); + break; + + case 17: + m_memory.emplace_back(&h); + break; + + default: + break; + } + + data = next; + } + + return true; +} diff --git a/src/hw/dmi/DmiReader.h b/src/hw/dmi/DmiReader.h new file mode 100644 index 00000000..a4f7eb8a --- /dev/null +++ b/src/hw/dmi/DmiReader.h @@ -0,0 +1,70 @@ +/* XMRig + * Copyright (c) 2000-2002 Alan Cox + * Copyright (c) 2005-2020 Jean Delvare + * 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_DMIREADER_H +#define XMRIG_DMIREADER_H + + +#include "hw/dmi/DmiBoard.h" +#include "hw/dmi/DmiMemory.h" + + +#include + + +namespace xmrig { + + +class DmiReader +{ +public: + DmiReader() = default; + + inline const DmiBoard &board() const { return m_board; } + inline const DmiBoard &system() const { return m_system; } + inline const std::vector &memory() const { return m_memory; } + inline uint32_t size() const { return m_size; } + inline uint32_t version() const { return m_version; } + + bool read(); + +# ifdef XMRIG_FEATURE_API + rapidjson::Value toJSON(rapidjson::Document &doc) const; + void toJSON(rapidjson::Value &out, rapidjson::Document &doc) const; +# endif + +private: + using Cleanup = std::function; + + bool decode(uint8_t *buf, const Cleanup &cleanup); + bool decode(uint8_t *buf); + + DmiBoard m_board; + DmiBoard m_system; + std::vector m_memory; + uint32_t m_size = 0; + uint32_t m_version = 0; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DMIREADER_H */ diff --git a/src/hw/dmi/DmiReader_mac.cpp b/src/hw/dmi/DmiReader_mac.cpp new file mode 100644 index 00000000..a23bfe47 --- /dev/null +++ b/src/hw/dmi/DmiReader_mac.cpp @@ -0,0 +1,108 @@ +/* XMRig + * Copyright (c) 2002-2006 Hugo Weber + * 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/dmi/DmiReader.h" +#include "hw/dmi/DmiTools.h" + + +#include + + +namespace xmrig { + + +static int checksum(const uint8_t *buf, size_t len) +{ + uint8_t sum = 0; + + for (size_t a = 0; a < len; a++) { + sum += buf[a]; + } + + return (sum == 0); +} + + +static uint8_t *dmi_table(uint32_t base, uint32_t &len, io_service_t service) +{ + CFMutableDictionaryRef properties = nullptr; + if (IORegistryEntryCreateCFProperties(service, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) { + return nullptr; + } + + CFDataRef data; + uint8_t *buf = nullptr; + + if (CFDictionaryGetValueIfPresent(properties, CFSTR("SMBIOS"), (const void **)&data)) { + assert(len == CFDataGetLength(data)); + + len = CFDataGetLength(data); + buf = reinterpret_cast(malloc(len)); + + CFDataGetBytes(data, CFRangeMake(0, len), buf); + } + + CFRelease(properties); + + return buf; +} + + +static uint8_t *smbios_decode(uint8_t *buf, uint32_t &size, uint32_t &version, io_service_t service) +{ + if (buf[0x05] > 0x20 || !checksum(buf, buf[0x05]) || memcmp(buf + 0x10, "_DMI_", 5) != 0 || !checksum(buf + 0x10, 0x0F)) { + return nullptr; + } + + version = ((buf[0x06] << 8) + buf[0x07]) << 8; + size = dmi_get(buf + 0x16); + + return dmi_table(dmi_get(buf + 0x18), size, service); +} + +} // namespace xmrig + + +bool xmrig::DmiReader::read() +{ + mach_port_t port; + IOMasterPort(MACH_PORT_NULL, &port); + + io_service_t service = IOServiceGetMatchingService(port, IOServiceMatching("AppleSMBIOS")); + if (service == MACH_PORT_NULL) { + return false; + } + + CFDataRef data = reinterpret_cast(IORegistryEntryCreateCFProperty(service, CFSTR("SMBIOS-EPS"), kCFAllocatorDefault, kNilOptions)); + if (!data) { + return false; + } + + uint8_t buf[0x20]{}; + CFDataGetBytes(data, CFRangeMake(0, sizeof(buf)), buf); + CFRelease(data); + + auto smb = smbios_decode(buf, m_size, m_version, service); + const bool rc = smb ? decode(smb) : false; + + IOObjectRelease(service); + + return rc; +} diff --git a/src/hw/dmi/DmiReader_unix.cpp b/src/hw/dmi/DmiReader_unix.cpp new file mode 100644 index 00000000..e01e2262 --- /dev/null +++ b/src/hw/dmi/DmiReader_unix.cpp @@ -0,0 +1,415 @@ +/* XMRig + * Copyright (c) 2000-2002 Alan Cox + * Copyright (c) 2005-2020 Jean Delvare + * 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/dmi/DmiReader.h" +#include "hw/dmi/DmiTools.h" + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __FreeBSD__ +# include +#endif + + +#define FLAG_NO_FILE_OFFSET (1 << 0) + + +namespace xmrig { + + +static const char *kMemDevice = "/dev/mem"; +static const char *kSysEntryFile = "/sys/firmware/dmi/tables/smbios_entry_point"; +static const char *kSysTableFile = "/sys/firmware/dmi/tables/DMI"; + + +static inline void safe_memcpy(void *dest, const void *src, size_t n) +{ +# ifdef XMRIG_ARM + for (size_t i = 0; i < n; i++) { + *((uint8_t *)dest + i) = *((const uint8_t *)src + i); + } +# else + memcpy(dest, src, n); +# endif +} + + + +static int myread(int fd, uint8_t *buf, size_t count, const char *prefix) +{ + ssize_t r = 1; + size_t r2 = 0; + + while (r2 != count && r != 0) { + r = read(fd, buf + r2, count - r2); + if (r == -1) { + if (errno != EINTR) { + return -1; + } + } + else { + r2 += r; + } + } + + if (r2 != count) { + return -1; + } + + return 0; +} + + +/* + * Reads all of file from given offset, up to max_len bytes. + * A buffer of at most max_len bytes is allocated by this function, and + * needs to be freed by the caller. + * This provides a similar usage model to mem_chunk() + * + * Returns a pointer to the allocated buffer, or NULL on error, and + * sets max_len to the length actually read. + */ +static uint8_t *read_file(off_t base, size_t *max_len, const char *filename) +{ + const int fd = open(filename, O_RDONLY); + uint8_t *p = nullptr; + + if (fd == -1) { + return nullptr; + } + + struct stat statbuf{}; + if (fstat(fd, &statbuf) == 0) { + if (base >= statbuf.st_size) { + goto out; + } + + if (*max_len > static_cast(statbuf.st_size) - base) { + *max_len = statbuf.st_size - base; + } + } + + if ((p = reinterpret_cast(malloc(*max_len))) == nullptr) { + goto out; + } + + if (lseek(fd, base, SEEK_SET) == -1) { + goto err_free; + } + + if (myread(fd, p, *max_len, filename) == 0) { + goto out; + } + +err_free: + free(p); + p = nullptr; + +out: + close(fd); + + return p; +} + + +/* + * Copy a physical memory chunk into a memory buffer. + * This function allocates memory. + */ +static uint8_t *mem_chunk(off_t base, size_t len, const char *devmem) +{ + const int fd = open(devmem, O_RDONLY); + uint8_t *p = nullptr; + uint8_t *mmp = nullptr; + struct stat statbuf{}; + +# ifdef _SC_PAGESIZE + const off_t mmoffset = base % sysconf(_SC_PAGESIZE); +# else + const off_t mmoffset = base % getpagesize(); +# endif + + if (fd == -1) { + return nullptr; + } + + if ((p = reinterpret_cast(malloc(len))) == nullptr) { + goto out; + } + + if (fstat(fd, &statbuf) == -1) { + goto err_free; + } + + if (S_ISREG(statbuf.st_mode) && base + (off_t)len > statbuf.st_size) { + goto err_free; + } + + mmp = reinterpret_cast(mmap(nullptr, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset)); + if (mmp == MAP_FAILED) { + goto try_read; + } + + safe_memcpy(p, mmp + mmoffset, len); + munmap(mmp, mmoffset + len); + + goto out; + +try_read: + if (lseek(fd, base, SEEK_SET) == -1) { + goto err_free; + } + + if (myread(fd, p, len, devmem) == 0) { + goto out; + } + +err_free: + free(p); + p = nullptr; + +out: + close(fd); + + return p; +} + + +static int checksum(const uint8_t *buf, size_t len) +{ + uint8_t sum = 0; + + for (size_t a = 0; a < len; a++) { + sum += buf[a]; + } + + return (sum == 0); +} + + +static uint8_t *dmi_table(off_t base, uint32_t &len, const char *devmem, uint32_t flags) +{ + if (flags & FLAG_NO_FILE_OFFSET) { + size_t size = len; + auto buf = read_file(0, &size, devmem); + len = size; + + return buf; + } + + return mem_chunk(base, len, devmem); +} + + +static uint8_t *smbios3_decode(uint8_t *buf, const char *devmem, uint32_t &size, uint32_t &version, uint32_t flags) +{ + if (buf[0x06] > 0x20 || !checksum(buf, buf[0x06])) { + return nullptr; + } + + version = (buf[0x07] << 16) + (buf[0x08] << 8) + buf[0x09]; + size = dmi_get(buf + 0x0C); + const u64 offset = dmi_get(buf + 0x10); + + return dmi_table(((off_t)offset.h << 32) | offset.l, size, devmem, flags); +} + + +static uint8_t *smbios_decode(uint8_t *buf, const char *devmem, uint32_t &size, uint32_t &version, uint32_t flags) +{ + if (buf[0x05] > 0x20 || !checksum(buf, buf[0x05]) || memcmp(buf + 0x10, "_DMI_", 5) != 0 || !checksum(buf + 0x10, 0x0F)) { + return nullptr; + } + + version = (buf[0x06] << 8) + buf[0x07]; + + switch (version) { + case 0x021F: + case 0x0221: + version = 0x0203; + break; + + case 0x0233: + version = 0x0206; + break; + } + + version = version << 8; + size = dmi_get(buf + 0x16); + + return dmi_table(dmi_get(buf + 0x18), size, devmem, flags); +} + + +static uint8_t *legacy_decode(uint8_t *buf, const char *devmem, uint32_t &size, uint32_t &version, uint32_t flags) +{ + if (!checksum(buf, 0x0F)) { + return nullptr; + } + + version = ((buf[0x0E] & 0xF0) << 12) + ((buf[0x0E] & 0x0F) << 8); + size = dmi_get(buf + 0x06); + + return dmi_table(dmi_get(buf + 0x08), size, devmem, flags); +} + + +#define EFI_NOT_FOUND (-1) +#define EFI_NO_SMBIOS (-2) +static off_t address_from_efi() +{ +# if defined(__linux__) + FILE *efi_systab; + const char *filename; + char linebuf[64]; + off_t address = 0; +# elif defined(__FreeBSD__) + char addrstr[KENV_MVALLEN + 1]; +# endif + +# if defined(__linux__) + if ((efi_systab = fopen(filename = "/sys/firmware/efi/systab", "r")) == nullptr && (efi_systab = fopen(filename = "/proc/efi/systab", "r")) == nullptr) { + return EFI_NOT_FOUND; + } + + address = EFI_NO_SMBIOS; + while ((fgets(linebuf, sizeof(linebuf) - 1, efi_systab)) != nullptr) { + char *addrp = strchr(linebuf, '='); + *(addrp++) = '\0'; + if (strcmp(linebuf, "SMBIOS3") == 0 || strcmp(linebuf, "SMBIOS") == 0) { + address = strtoull(addrp, nullptr, 0); + break; + } + } + + fclose(efi_systab); + + return address; +# elif defined(__FreeBSD__) + if (kenv(KENV_GET, "hint.smbios.0.mem", addrstr, sizeof(addrstr)) == -1) { + return EFI_NOT_FOUND; + } + + return strtoull(addrstr, nullptr, 0); +# endif + + return EFI_NOT_FOUND; +} + + +} // namespace xmrig + + +bool xmrig::DmiReader::read() +{ + size_t size = 0x20; + uint8_t *buf = read_file(0, &size, kSysEntryFile); + uint8_t *smb = nullptr; + + if (buf) { + smb = nullptr; + + if (size >= 24 && memcmp(buf, "_SM3_", 5) == 0) { + smb = smbios3_decode(buf, kSysTableFile, m_size, m_version, FLAG_NO_FILE_OFFSET); + } + else if (size >= 31 && memcmp(buf, "_SM_", 4) == 0) { + smb = smbios_decode(buf, kSysTableFile, m_size, m_version, FLAG_NO_FILE_OFFSET); + } + else if (size >= 15 && memcmp(buf, "_DMI_", 5) == 0) { + smb = legacy_decode(buf, kSysTableFile, m_size, m_version, FLAG_NO_FILE_OFFSET); + } + + if (smb) { + return decode(smb, [smb, buf]() { free(smb); free(buf); }); + } + + free(buf); + } + + const auto efi = address_from_efi(); + if (efi == EFI_NO_SMBIOS) { + return false; + } + + if (efi != EFI_NOT_FOUND) { + if ((buf = mem_chunk(efi, 0x20, kMemDevice)) == nullptr) { + return false; + } + + smb = nullptr; + + if (memcmp(buf, "_SM3_", 5) == 0) { + smb = smbios3_decode(buf, kMemDevice, m_size, m_version, 0); + } + else if (memcmp(buf, "_SM_", 4) == 0) { + smb = smbios_decode(buf, kSysTableFile, m_size, m_version, 0); + } + + if (smb) { + return decode(smb, [smb, buf]() { free(smb); free(buf); }); + } + + free(buf); + } + +# if defined(__x86_64__) || defined(_M_AMD64) + if ((buf = mem_chunk(0xF0000, 0x10000, kMemDevice)) == nullptr) { + return false; + } + + smb = nullptr; + + for (off_t fp = 0; fp <= 0xFFE0; fp += 16) { + if (memcmp(buf + fp, "_SM3_", 5) == 0) { + smb = smbios3_decode(buf + fp, kMemDevice, m_size, m_version, 0); + } + + if (smb) { + return decode(smb, [smb, buf]() { free(smb); free(buf); }); + } + } + + for (off_t fp = 0; fp <= 0xFFF0; fp += 16) { + if (memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) { + smb = smbios3_decode(buf + fp, kMemDevice, m_size, m_version, 0); + } + else if (!smb && memcmp(buf + fp, "_DMI_", 5) == 0) { + smb = legacy_decode(buf + fp, kMemDevice, m_size, m_version, 0); + } + + if (smb) { + return decode(smb, [smb, buf]() { free(smb); free(buf); }); + } + } + + free(buf); +# endif + + + return false; +} diff --git a/src/hw/dmi/DmiReader_win.cpp b/src/hw/dmi/DmiReader_win.cpp new file mode 100644 index 00000000..837bdb7b --- /dev/null +++ b/src/hw/dmi/DmiReader_win.cpp @@ -0,0 +1,68 @@ +/* XMRig + * Copyright (c) 2002-2006 Hugo Weber + * 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/dmi/DmiReader.h" +#include "hw/dmi/DmiTools.h" + + +#include + + +namespace xmrig { + + +/* + * Struct needed to get the SMBIOS table using GetSystemFirmwareTable API. + */ +struct RawSMBIOSData { + uint8_t Used20CallingMethod; + uint8_t SMBIOSMajorVersion; + uint8_t SMBIOSMinorVersion; + uint8_t DmiRevision; + uint32_t Length; + uint8_t SMBIOSTableData[]; +}; + + +} // namespace xmrig + + +bool xmrig::DmiReader::read() +{ + const uint32_t size = GetSystemFirmwareTable('RSMB', 0, nullptr, 0); + auto smb = reinterpret_cast(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size)); + + if (!smb) { + return false; + } + + if (GetSystemFirmwareTable('RSMB', 0, smb, size) != size) { + HeapFree(GetProcessHeap(), 0, smb); + + return false; + } + + m_version = (smb->SMBIOSMajorVersion << 16) + (smb->SMBIOSMinorVersion << 8) + smb->DmiRevision; + m_size = smb->Length; + + return decode(smb->SMBIOSTableData, [smb]() { + HeapFree(GetProcessHeap(), 0, smb); + }); +} diff --git a/src/hw/dmi/DmiTools.cpp b/src/hw/dmi/DmiTools.cpp new file mode 100644 index 00000000..e82c2f45 --- /dev/null +++ b/src/hw/dmi/DmiTools.cpp @@ -0,0 +1,75 @@ +/* XMRig + * Copyright (c) 2000-2002 Alan Cox + * Copyright (c) 2005-2020 Jean Delvare + * 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/dmi/DmiTools.h" + + +#include + + +namespace xmrig { + + +/* Replace non-ASCII characters with dots */ +static void ascii_filter(char *bp, size_t len) +{ + for (size_t i = 0; i < len; i++) { + if (bp[i] < 32 || bp[i] >= 127) { + bp[i] = '.'; + } + } +} + + +static char *_dmi_string(dmi_header *dm, uint8_t s, bool filter) +{ + char *bp = reinterpret_cast(dm->data); + + bp += dm->length; + while (s > 1 && *bp) { + bp += strlen(bp); + bp++; + s--; + } + + if (!*bp) { + return nullptr; + } + + if (filter) { + ascii_filter(bp, strlen(bp)); + } + + return bp; +} + + +const char *dmi_string(dmi_header *dm, size_t offset) +{ + if (offset < 4) { + return nullptr; + } + + return _dmi_string(dm, dm->data[offset], true); +} + + +} // namespace xmrig diff --git a/src/hw/dmi/DmiTools.h b/src/hw/dmi/DmiTools.h new file mode 100644 index 00000000..65a1dfd7 --- /dev/null +++ b/src/hw/dmi/DmiTools.h @@ -0,0 +1,60 @@ +/* XMRig + * Copyright (c) 2000-2002 Alan Cox + * Copyright (c) 2005-2020 Jean Delvare + * 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_DMITOOLS_H +#define XMRIG_DMITOOLS_H + + +#include +#include + + +namespace xmrig { + + +struct dmi_header +{ + uint8_t type; + uint8_t length; + uint16_t handle; + uint8_t *data; +}; + + +struct u64 { + uint32_t l; + uint32_t h; +}; + + +template +inline T dmi_get(const uint8_t *data) { return *reinterpret_cast(data); } + +template +inline T dmi_get(const dmi_header *h, size_t offset) { return *reinterpret_cast(h->data + offset); } + + +const char *dmi_string(dmi_header *dm, size_t offset); + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DMITOOLS_H */ diff --git a/src/hw/dmi/dmi.cmake b/src/hw/dmi/dmi.cmake new file mode 100644 index 00000000..b6f91616 --- /dev/null +++ b/src/hw/dmi/dmi.cmake @@ -0,0 +1,35 @@ +if (WITH_DMI AND (XMRIG_OS_WIN OR XMRIG_OS_LINUX OR XMRIG_OS_FREEBSD OR (XMRIG_OS_MACOS AND NOT XMRIG_ARM))) + set(WITH_DMI ON) +else() + set(WITH_DMI OFF) +endif() + +if (WITH_DMI) + add_definitions(/DXMRIG_FEATURE_DMI) + + list(APPEND HEADERS + src/hw/dmi/DmiBoard.h + src/hw/dmi/DmiMemory.h + src/hw/dmi/DmiReader.h + src/hw/dmi/DmiTools.h + ) + + list(APPEND SOURCES + src/hw/dmi/DmiBoard.cpp + src/hw/dmi/DmiMemory.cpp + src/hw/dmi/DmiReader.cpp + src/hw/dmi/DmiTools.cpp + ) + + if (XMRIG_OS_WIN) + list(APPEND SOURCES src/hw/dmi/DmiReader_win.cpp) + elseif(XMRIG_OS_LINUX OR XMRIG_OS_FREEBSD) + list(APPEND SOURCES src/hw/dmi/DmiReader_unix.cpp) + elseif(XMRIG_OS_MACOS) + list(APPEND SOURCES src/hw/dmi/DmiReader_mac.cpp) + find_library(CORESERVICES_LIBRARY CoreServices) + list(APPEND EXTRA_LIBS ${CORESERVICES_LIBRARY}) + endif() +else() + remove_definitions(/DXMRIG_FEATURE_DMI) +endif() diff --git a/src/hw/msr/Msr.cpp b/src/hw/msr/Msr.cpp new file mode 100644 index 00000000..1fed8776 --- /dev/null +++ b/src/hw/msr/Msr.cpp @@ -0,0 +1,88 @@ +/* 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 {}; +} + + +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; + 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 00000000..3bd88dd5 --- /dev/null +++ b/src/hw/msr/Msr.h @@ -0,0 +1,69 @@ +/* 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 +#include + + +namespace xmrig +{ + + +class MsrPrivate; + + +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; +}; + + +} /* 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 4c8e7f2a..eac88f0c 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 b14fda3b..00c0416a 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: @@ -57,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 new file mode 100644 index 00000000..0783ebc1 --- /dev/null +++ b/src/hw/msr/Msr_linux.cpp @@ -0,0 +1,122 @@ +/* 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 "backend/cpu/Cpu.h" +#include "base/io/log/Log.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace xmrig { + + +static int msr_open(int32_t cpu, int flags) +{ + const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? Cpu::info()->units().front() : cpu); + + return open(name.c_str(), flags); +} + + +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::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 int fd = msr_open(cpu, O_RDONLY); + + if (fd < 0) { + return false; + } + + const bool success = pread(fd, &value, sizeof value, reg) == sizeof value; + close(fd); + + return success; +} + + +bool xmrig::Msr::wrmsr(uint32_t reg, uint64_t value, int32_t cpu) +{ + const int fd = msr_open(cpu, 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 new file mode 100644 index 00000000..654f6778 --- /dev/null +++ b/src/hw/msr/Msr_win.cpp @@ -0,0 +1,255 @@ +/* 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 "backend/cpu/Cpu.h" +#include "base/io/log/Log.h" +#include "base/kernel/Platform.h" + + +#include +#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::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; +} diff --git a/src/version.h b/src/version.h index 793f42f1..8f232976 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 "6.7.2-mo3" +#define APP_VERSION "6.8.0-mo1" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2021 xmrig.com" #define APP_KIND "miner" #define APP_VER_MAJOR 6 -#define APP_VER_MINOR 7 -#define APP_VER_PATCH 2 +#define APP_VER_MINOR 8 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1920)