diff --git a/CHANGELOG.md b/CHANGELOG.md index b9f51507..b6dedbcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# v6.8.1 +- [#2064](https://github.com/xmrig/xmrig/pull/2064) Added documentation for config.json CPU options. +- [#2066](https://github.com/xmrig/xmrig/issues/2066) Fixed AMD GPUs health data readings on Linux. +- [#2067](https://github.com/xmrig/xmrig/pull/2067) Fixed compilation error when RandomX and Argon2 are disabled. +- [#2076](https://github.com/xmrig/xmrig/pull/2076) Added support for flexible huge page sizes on Linux. +- [#2077](https://github.com/xmrig/xmrig/pull/2077) Fixed `illegal instruction` crash on ARM. + # 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. diff --git a/doc/CPU.md b/doc/CPU.md index 385af6ad..508f1e2c 100644 --- a/doc/CPU.md +++ b/doc/CPU.md @@ -75,6 +75,35 @@ Each number represent one thread and means CPU affinity, this is default format ``` Internal format, but can be user defined. +## RandomX options + +#### `init` +Thread count to initialize RandomX dataset. Auto-detect (`-1`) or any number greater than 0 to use that many threads. + +#### `init-avx2` +Use AVX2 for dataset initialization. Faster on some CPUs. Auto-detect (`-1`), disabled (`0`), always enabled on CPUs that support AVX2 (`1`). + +#### `mode` +RandomX mining mode: `auto`, `fast` (2 GB memory), `light` (256 MB memory). + +#### `1gb-pages` +Use 1GB hugepages for RandomX dataset (Linux only). Enabled (`true`) or disabled (`false`). It gives 1-3% speedup. + +#### `rdmsr` +Restore MSR register values to their original values on exit. Used together with `wrmsr`. Enabled (`true`) or disabled (`false`). + +#### `wrmsr` +[MSR mod](https://xmrig.com/docs/miner/randomx-optimization-guide/msr). Enabled (`true`) or disabled (`false`). It gives up to 15% speedup depending on your system. + +#### `cache_qos` +[Cache QoS](https://xmrig.com/docs/miner/randomx-optimization-guide/qos). Enabled (`true`) or disabled (`false`). It's useful when you can't or don't want to mine on all CPU cores to make mining hashrate more stable. + +#### `numa` +NUMA support (better hashrate on multi-CPU servers and Ryzen Threadripper 1xxx/2xxx). Enabled (`true`) or disabled (`false`). + +#### `scratchpad_prefetch_mode` +Which instruction to use in RandomX loop to prefetch data from scratchpad. `1` is default and fastest in most cases. Can be off (`0`), `prefetcht0` instruction (`1`), `prefetchnta` instruction (`2`, a bit faster on Coffee Lake and a few other CPUs), `mov` instruction (`3`). + ## Shared options #### `enabled` @@ -83,23 +112,32 @@ Enable (`true`) or disable (`false`) CPU backend, by default `true`. #### `huge-pages` Enable (`true`) or disable (`false`) huge pages support, by default `true`. +#### `huge-pages-jit` +Enable (`true`) or disable (`false`) huge pages support for RandomX JIT code, by default `false`. It gives a very small boost on Ryzen CPUs, but hashrate is unstable between launches. Use with caution. + #### `hw-aes` Force enable (`true`) or disable (`false`) hardware AES support. Default value `null` means miner autodetect this feature. Usually don't need change this option, this option useful for some rare cases when miner can't detect hardware AES, but it available. If you force enable this option, but your hardware not support it, miner will crash. #### `priority` -Mining threads priority, value from `1` (lowest priority) to `5` (highest possible priority). Default value `null` means miner don't change threads priority at all. +Mining threads priority, value from `1` (lowest priority) to `5` (highest possible priority). Default value `null` means miner don't change threads priority at all. Setting priority higher than 2 can make your PC unresponsive. + +#### `memory-pool` (since v4.3.0) +Use continuous, persistent memory block for mining threads, useful for preserve huge pages allocation while algorithm swithing. Possible values `false` (feature disabled, by default) or `true` or specific count of 2 MB huge pages. It helps to avoid loosing huge pages for scratchpads when RandomX dataset is updated and mining threads restart after a 2-3 days of mining. + +#### `yield` (since v5.1.1) +Prefer system better system response/stability `true` (default value) or maximum hashrate `false`. #### `asm` Enable/configure or disable ASM optimizations. Possible values: `true`, `false`, `"intel"`, `"ryzen"`, `"bulldozer"`. #### `argon2-impl` (since v3.1.0) -Allow override automatically detected Argon2 implementation, this option added mostly for debug purposes, default value `null` means autodetect. Other possible values: `"x86_64"`, `"SSE2"`, `"SSSE3"`, `"XOP"`, `"AVX2"`, `"AVX-512F"`. Manual selection has no safe guards, if you CPU not support required instuctions, miner will crash. +Allow override automatically detected Argon2 implementation, this option added mostly for debug purposes, default value `null` means autodetect. This is used in RandomX dataset initialization and also in some other mining algorithms. Other possible values: `"x86_64"`, `"SSE2"`, `"SSSE3"`, `"XOP"`, `"AVX2"`, `"AVX-512F"`. Manual selection has no safe guards - if your CPU doesn't support required instuctions, miner will crash. + +#### `astrobwt-max-size` +AstroBWT algorithm: skip hashes with large stage 2 size, default: `550`, min: `400`, max: `1200`. Optimal value depends on your CPU/GPU + +#### `astrobwt-avx2` +AstroBWT algorithm: use AVX2 code. It's faster on some CPUs and slower on other #### `max-threads-hint` (since v4.2.0) Maximum CPU threads count (in percentage) hint for autoconfig. [CPU_MAX_USAGE.md](CPU_MAX_USAGE.md) - -#### `memory-pool` (since v4.3.0) -Use continuous, persistent memory block for mining threads, useful for preserve huge pages allocation while algorithm swithing. Possible values `false` (feature disabled, by default) or `true` or specific count of 2 MB huge pages. - -#### `yield` (since v5.1.1) -Prefer system better system response/stability `true` (default value) or maximum hashrate `false`. diff --git a/src/Summary.cpp b/src/Summary.cpp index eaee89bf..6b12e62f 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -146,7 +146,7 @@ static void print_memory(const Config *config) return; } - const bool vm = Cpu::info()->isVM(); + const bool printEmpty = reader.memory().size() <= 8; for (const auto &memory : reader.memory()) { if (!memory.isValid()) { @@ -155,14 +155,14 @@ static void print_memory(const Config *config) 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()); + "", memory.id().data(), memory.size() / oneGiB, memory.type(), memory.speed() / 1000000ULL, memory.product().data()); } - else if (!vm) { + else if (printEmpty) { Log::print(WHITE_BOLD(" %-13s") "%s: " BLACK_BOLD(""), "", memory.slot().data()); } } - const auto &board = vm ? reader.system() : reader.board(); + const auto &board = Cpu::info()->isVM() ? 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()); diff --git a/src/backend/common/misc/PciTopology.h b/src/backend/common/misc/PciTopology.h index ee531f50..af1844c9 100644 --- a/src/backend/common/misc/PciTopology.h +++ b/src/backend/common/misc/PciTopology.h @@ -1,13 +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 Lee Clagett - * 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 @@ -42,10 +35,15 @@ public: PciTopology() = default; PciTopology(uint32_t bus, uint32_t device, uint32_t function) : m_valid(true), m_bus(bus), m_device(device), m_function(function) {} - inline bool isValid() const { return m_valid; } - inline uint8_t bus() const { return m_bus; } - inline uint8_t device() const { return m_device; } - inline uint8_t function() const { return m_function; } + inline bool isEqual(const PciTopology &other) const { return m_valid == other.m_valid && toUint32() == other.toUint32(); } + inline bool isValid() const { return m_valid; } + inline uint8_t bus() const { return m_bus; } + inline uint8_t device() const { return m_device; } + inline uint8_t function() const { return m_function; } + + inline bool operator!=(const PciTopology &other) const { return !isEqual(other); } + inline bool operator<(const PciTopology &other) const { return toUint32() < other.toUint32(); } + inline bool operator==(const PciTopology &other) const { return isEqual(other); } String toString() const { @@ -60,6 +58,8 @@ public: } private: + inline uint32_t toUint32() const { return m_bus << 16 | m_device << 8 | m_function; } + bool m_valid = false; uint8_t m_bus = 0; uint8_t m_device = 0; diff --git a/src/backend/cpu/CpuConfig.cpp b/src/backend/cpu/CpuConfig.cpp index 9833a5da..3f743040 100644 --- a/src/backend/cpu/CpuConfig.cpp +++ b/src/backend/cpu/CpuConfig.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 (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 @@ -77,7 +71,7 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const Value obj(kObjectType); obj.AddMember(StringRef(kEnabled), m_enabled, allocator); - obj.AddMember(StringRef(kHugePages), m_hugePages, allocator); + obj.AddMember(StringRef(kHugePages), m_hugePageSize == 0 || m_hugePageSize == kDefaultHugePageSizeKb ? Value(isHugePages()) : Value(static_cast(m_hugePageSize)), allocator); obj.AddMember(StringRef(kHugePagesJit), m_hugePagesJit, allocator); obj.AddMember(StringRef(kHwAes), m_aes == AES_AUTO ? Value(kNullType) : Value(m_aes == AES_HW), allocator); obj.AddMember(StringRef(kPriority), priority() != -1 ? Value(priority()) : Value(kNullType), allocator); @@ -137,14 +131,14 @@ void xmrig::CpuConfig::read(const rapidjson::Value &value) { if (value.IsObject()) { m_enabled = Json::getBool(value, kEnabled, m_enabled); - m_hugePages = Json::getBool(value, kHugePages, m_hugePages); m_hugePagesJit = Json::getBool(value, kHugePagesJit, m_hugePagesJit); m_limit = Json::getUint(value, kMaxThreadsHint, m_limit); m_yield = Json::getBool(value, kYield, m_yield); setAesMode(Json::getValue(value, kHwAes)); - setPriority(Json::getInt(value, kPriority, -1)); + setHugePages(Json::getValue(value, kHugePages)); setMemoryPool(Json::getValue(value, kMemoryPool)); + setPriority(Json::getInt(value, kPriority, -1)); # ifdef XMRIG_FEATURE_ASM m_assembly = Json::getValue(value, kAsm); @@ -218,6 +212,19 @@ void xmrig::CpuConfig::setAesMode(const rapidjson::Value &value) } +void xmrig::CpuConfig::setHugePages(const rapidjson::Value &value) +{ + if (value.IsBool()) { + m_hugePageSize = value.GetBool() ? kDefaultHugePageSizeKb : 0U; + } + else if (value.IsUint()) { + const uint32_t size = value.GetUint(); + + m_hugePageSize = size < kOneGbPageSizeKb ? size : kDefaultHugePageSizeKb; + } +} + + void xmrig::CpuConfig::setMemoryPool(const rapidjson::Value &value) { if (value.IsBool()) { diff --git a/src/backend/cpu/CpuConfig.h b/src/backend/cpu/CpuConfig.h index 95defa67..536c221e 100644 --- a/src/backend/cpu/CpuConfig.h +++ b/src/backend/cpu/CpuConfig.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 (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 @@ -75,8 +69,9 @@ public: std::vector get(const Miner *miner, const Algorithm &algorithm) const; void read(const rapidjson::Value &value); + inline bool astrobwtAVX2() const { return m_astrobwtAVX2; } inline bool isEnabled() const { return m_enabled; } - inline bool isHugePages() const { return m_hugePages; } + inline bool isHugePages() const { return m_hugePageSize > 0; } inline bool isHugePagesJit() const { return m_hugePagesJit; } inline bool isShouldSave() const { return m_shouldSave; } inline bool isYield() const { return m_yield; } @@ -84,13 +79,17 @@ public: inline const String &argon2Impl() const { return m_argon2Impl; } inline const Threads &threads() const { return m_threads; } inline int astrobwtMaxSize() const { return m_astrobwtMaxSize; } - inline bool astrobwtAVX2() const { return m_astrobwtAVX2; } inline int priority() const { return m_priority; } + inline size_t hugePageSize() const { return m_hugePageSize * 1024U; } inline uint32_t limit() const { return m_limit; } private: + constexpr static size_t kDefaultHugePageSizeKb = 2048U; + constexpr static size_t kOneGbPageSizeKb = 1048576U; + void generate(); void setAesMode(const rapidjson::Value &value); + void setHugePages(const rapidjson::Value &value); void setMemoryPool(const rapidjson::Value &value); inline void setPriority(int priority) { m_priority = (priority >= -1 && priority <= 5) ? priority : -1; } @@ -99,13 +98,13 @@ private: Assembly m_assembly; bool m_astrobwtAVX2 = false; bool m_enabled = true; - bool m_hugePages = true; bool m_hugePagesJit = false; bool m_shouldSave = false; bool m_yield = true; int m_astrobwtMaxSize = 550; int m_memoryPool = 0; int m_priority = -1; + size_t m_hugePageSize = kDefaultHugePageSizeKb; String m_argon2Impl; Threads m_threads; uint32_t m_limit = 100; diff --git a/src/backend/cpu/platform/lscpu_arm.cpp b/src/backend/cpu/platform/lscpu_arm.cpp index 2aa4b12a..d632ac49 100644 --- a/src/backend/cpu/platform/lscpu_arm.cpp +++ b/src/backend/cpu/platform/lscpu_arm.cpp @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2018 Riku Voipio - * 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 @@ -87,16 +87,22 @@ static const id_part arm_part[] = { { 0xd03, "Cortex-A53" }, { 0xd04, "Cortex-A35" }, { 0xd05, "Cortex-A55" }, + { 0xd06, "Cortex-A65" }, { 0xd07, "Cortex-A57" }, { 0xd08, "Cortex-A72" }, { 0xd09, "Cortex-A73" }, { 0xd0a, "Cortex-A75" }, { 0xd0b, "Cortex-A76" }, { 0xd0c, "Neoverse-N1" }, + { 0xd0d, "Cortex-A77" }, + { 0xd0e, "Cortex-A76AE" }, { 0xd13, "Cortex-R52" }, { 0xd20, "Cortex-M23" }, { 0xd21, "Cortex-M33" }, + { 0xd41, "Cortex-A78" }, + { 0xd42, "Cortex-A78AE" }, { 0xd4a, "Neoverse-E1" }, + { 0xd4b, "Cortex-A78C" }, { -1, nullptr }, }; @@ -150,6 +156,7 @@ static const id_part samsung_part[] = { static const id_part nvidia_part[] = { { 0x000, "Denver" }, { 0x003, "Denver 2" }, + { 0x004, "Carmel" }, { -1, nullptr }, }; @@ -191,23 +198,36 @@ static const id_part intel_part[] = { { -1, nullptr }, }; +static const struct id_part fujitsu_part[] = { + { 0x001, "A64FX" }, + { -1, "unknown" }, +}; + static const id_part hisi_part[] = { { 0xd01, "Kunpeng-920" }, /* aka tsv110 */ { -1, nullptr }, }; +static const id_part apple_part[] = { + { 0x022, "M1" }, + { 0x023, "M1" }, + { -1, nullptr }, +}; + static const hw_impl hw_implementer[] = { { 0x41, arm_part, "ARM" }, { 0x42, brcm_part, "Broadcom" }, { 0x43, cavium_part, "Cavium" }, { 0x44, dec_part, "DEC" }, + { 0x46, fujitsu_part, "FUJITSU" }, { 0x48, hisi_part, "HiSilicon" }, { 0x4e, nvidia_part, "Nvidia" }, { 0x50, apm_part, "APM" }, { 0x51, qcom_part, "Qualcomm" }, { 0x53, samsung_part, "Samsung" }, { 0x56, marvell_part, "Marvell" }, + { 0x61, apple_part, "Apple" }, { 0x66, faraday_part, "Faraday" }, { 0x69, intel_part, "Intel" } }; diff --git a/src/backend/opencl/wrappers/AdlLib_linux.cpp b/src/backend/opencl/wrappers/AdlLib_linux.cpp index b297ec71..7d7adb31 100644 --- a/src/backend/opencl/wrappers/AdlLib_linux.cpp +++ b/src/backend/opencl/wrappers/AdlLib_linux.cpp @@ -1,8 +1,8 @@ /* XMRig - * Copyright 2008-2018 Advanced Micro Devices, Inc. - * Copyright 2018-2020 SChernykh - * Copyright 2020 Patrick Bollinger - * Copyright 2016-2020 XMRig , + * Copyright (c) 2008-2018 Advanced Micro Devices, Inc. + * Copyright (c) 2020 Patrick Bollinger + * 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 @@ -20,10 +20,13 @@ #include "backend/opencl/wrappers/AdlLib.h" +#include "3rdparty/fmt/core.h" #include "backend/opencl/wrappers/OclDevice.h" +#include #include +#include #include #include #include @@ -35,18 +38,27 @@ namespace xmrig { bool AdlLib::m_initialized = false; bool AdlLib::m_ready = false; static const std::string kPrefix = "/sys/bus/pci/drivers/amdgpu/"; +static std::map hwmon_cache; -static inline bool sysfs_is_file(const std::string &path) +static inline bool sysfs_is_file(const char *path) { struct stat sb; - return stat(path.c_str(), &sb) == 0 && ((sb.st_mode & S_IFMT) == S_IFREG); + return stat(path, &sb) == 0 && ((sb.st_mode & S_IFMT) == S_IFREG); } -static inline bool sysfs_is_amdgpu(const std::string &path) +static inline int dir_filter(const struct dirent *dirp) { + return strlen(dirp->d_name) > 5 ? 1 : 0; +} + + +static bool sysfs_is_amdgpu(const char *path, char *buf, const char *filename) +{ + strcpy(buf, filename); + if (!sysfs_is_file(path)) { return false; } @@ -63,8 +75,10 @@ static inline bool sysfs_is_amdgpu(const std::string &path) } -uint32_t sysfs_read(const std::string &path) +static uint32_t sysfs_read(const char *path, char *buf, const char *filename) { + strcpy(buf, filename); + std::ifstream file(path); if (!file.is_open()) { return 0; @@ -77,18 +91,44 @@ uint32_t sysfs_read(const std::string &path) } -static inline std::string sysfs_prefix(const PciTopology &topology) +static size_t sysfs_prefix(char path[PATH_MAX], const PciTopology &topology) { - const std::string path = kPrefix + "0000:" + topology.toString().data() + "/hwmon/hwmon"; + const auto it = hwmon_cache.find(topology); + if (it != hwmon_cache.end()) { + strcpy(path, it->second.data()); - for (uint32_t i = 1; i < 10; ++i) { - const std::string prefix = path + std::to_string(i) + "/"; - if (sysfs_is_amdgpu(prefix + "name") && (sysfs_read(prefix + "temp1_input") || sysfs_read(prefix + "power1_average"))) { - return prefix; - } + return it->second.size(); } - return {}; + char *base = fmt::format_to(path, "{}0000:{}/hwmon/", kPrefix, topology.toString()); + *base = '\0'; + char *end = nullptr; + + struct dirent **namelist; + int n = scandir(path, &namelist, dir_filter, nullptr); + if (n < 0) { + return {}; + } + + while (n--) { + if (!end) { + char *tmp = fmt::format_to(base, "{}/", namelist[n]->d_name); + end = (sysfs_is_amdgpu(path, tmp, "name") && (sysfs_read(path, tmp, "temp1_input") || sysfs_read(path, tmp, "power1_average"))) ? tmp : nullptr; + } + + free(namelist[n]); + } + + free(namelist); + + if (end) { + *end = '\0'; + hwmon_cache.insert({ topology, path }); + + return end - path; + } + + return 0; } @@ -124,20 +164,22 @@ AdlHealth xmrig::AdlLib::health(const OclDevice &device) return {}; } - const auto prefix = sysfs_prefix(device.topology()); - if (prefix.empty()) { + static char path[PATH_MAX]{}; + + char *buf = path + sysfs_prefix(path, device.topology()); + if (buf == path) { return {}; } AdlHealth health; - health.clock = sysfs_read(prefix + "freq1_input") / 1000000; - health.memClock = sysfs_read(prefix + "freq2_input") / 1000000; - health.power = sysfs_read(prefix + "power1_average") / 1000000; - health.rpm = sysfs_read(prefix + "fan1_input"); - health.temperature = sysfs_read(prefix + "temp2_input") / 1000; + health.clock = sysfs_read(path, buf, "freq1_input") / 1000000; + health.memClock = sysfs_read(path, buf, "freq2_input") / 1000000; + health.power = sysfs_read(path, buf, "power1_average") / 1000000; + health.rpm = sysfs_read(path, buf, "fan1_input"); + health.temperature = sysfs_read(path, buf, "temp2_input") / 1000; if (!health.temperature) { - health.temperature = sysfs_read(prefix + "temp1_input") / 1000; + health.temperature = sysfs_read(path, buf, "temp1_input") / 1000; } return health; diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 5baf0334..b739fa0f 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -85,6 +85,7 @@ public: BenchHashKey = 1047, BenchTokenKey = 1048, DmiKey = 1049, + HugePageSizeKey = 1050, // xmrig common CPUPriorityKey = 1021, diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 51366670..dcd2c702 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -50,7 +50,7 @@ int xmrig::Controller::init() { Base::init(); - VirtualMemory::init(config()->cpu().memPoolSize(), config()->cpu().isHugePages()); + VirtualMemory::init(config()->cpu().memPoolSize(), config()->cpu().hugePageSize()); m_network = std::make_shared(this); diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index b32aede3..7140837a 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -125,9 +125,10 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const BaseTransform::transform(doc, key, arg); switch (key) { - case IConfig::AVKey: /* --av */ - case IConfig::CPUPriorityKey: /* --cpu-priority */ - case IConfig::ThreadsKey: /* --threads */ + case IConfig::AVKey: /* --av */ + case IConfig::CPUPriorityKey: /* --cpu-priority */ + case IConfig::ThreadsKey: /* --threads */ + case IConfig::HugePageSizeKey: /* --hugepage-size */ return transformUint64(doc, key, static_cast(strtol(arg, nullptr, 10))); case IConfig::HugePagesKey: /* --no-huge-pages */ @@ -149,8 +150,10 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const case IConfig::YieldKey: /* --cpu-no-yield */ return set(doc, CpuConfig::kField, CpuConfig::kYield, false); +# ifdef XMRIG_ALGO_ARGON2 case IConfig::Argon2ImplKey: /* --argon2-impl */ return set(doc, CpuConfig::kField, CpuConfig::kArgon2Impl, arg); +# endif # ifdef XMRIG_FEATURE_ASM case IConfig::AssemblyKey: /* --asm */ @@ -304,6 +307,9 @@ void xmrig::ConfigTransform::transformUint64(rapidjson::Document &doc, int key, case IConfig::CPUPriorityKey: /* --cpu-priority */ return set(doc, CpuConfig::kField, CpuConfig::kPriority, arg); + case IConfig::HugePageSizeKey: /* --hugepage-size */ + return set(doc, CpuConfig::kField, CpuConfig::kHugePages, arg); + default: break; } diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index 8bac99a5..9d89da8f 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -75,6 +75,8 @@ static const option options[] = { # endif { "no-color", 0, nullptr, IConfig::ColorKey }, { "no-huge-pages", 0, nullptr, IConfig::HugePagesKey }, + { "no-hugepages", 0, nullptr, IConfig::HugePagesKey }, + { "hugepage-size", 1, nullptr, IConfig::HugePageSizeKey }, { "pass", 1, nullptr, IConfig::PasswordKey }, { "print-time", 1, nullptr, IConfig::PrintTimeKey }, { "retries", 1, nullptr, IConfig::RetriesKey }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 261e571c..a30ea133 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -83,6 +83,9 @@ static inline const std::string &usage() u += " --cpu-memory-pool=N number of 2 MB pages for persistent memory pool, -1 (auto), 0 (disable)\n"; u += " --cpu-no-yield prefer maximum hashrate rather than system response/stability\n"; u += " --no-huge-pages disable huge pages support\n"; +# ifdef XMRIG_OS_LINUX + u += " --hugepage-size=N custom hugepage size in kB\n"; +# endif u += " --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer\n"; # if defined(__x86_64__) || defined(_M_AMD64) @@ -155,7 +158,7 @@ static inline const std::string &usage() u += " -l, --log-file=FILE log all output to a file\n"; u += " --print-time=N print hashrate report every N seconds\n"; -# ifdef XMRIG_FEATURE_NVML +# if defined(XMRIG_FEATURE_NVML) || defined(XMRIG_FEATURE_ADL) u += " --health-print-time=N print health report every N seconds\n"; # endif u += " --no-color disable colored output\n"; diff --git a/src/crypto/common/HugePagesInfo.cpp b/src/crypto/common/HugePagesInfo.cpp index 3108c7de..0a134156 100644 --- a/src/crypto/common/HugePagesInfo.cpp +++ b/src/crypto/common/HugePagesInfo.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 (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,24 +21,16 @@ #include "crypto/common/VirtualMemory.h" -namespace xmrig { - -constexpr size_t twoMiB = 2U * 1024U * 1024U; -constexpr size_t oneGiB = 1024U * 1024U * 1024U; - -} // namespace xmrig - - xmrig::HugePagesInfo::HugePagesInfo(const VirtualMemory *memory) { if (memory->isOneGbPages()) { - size = VirtualMemory::align(memory->size(), oneGiB); - total = size / oneGiB; - allocated = size / oneGiB; + size = VirtualMemory::align(memory->size(), VirtualMemory::kOneGiB); + total = size / VirtualMemory::kOneGiB; + allocated = size / VirtualMemory::kOneGiB; } else { - size = memory->size(); - total = size / twoMiB; + size = VirtualMemory::alignToHugePageSize(memory->size()); + total = size / VirtualMemory::hugePageSize(); allocated = memory->isHugePages() ? total : 0; } } diff --git a/src/crypto/common/HugePagesInfo.h b/src/crypto/common/HugePagesInfo.h index 1dc93bb4..295817e3 100644 --- a/src/crypto/common/HugePagesInfo.h +++ b/src/crypto/common/HugePagesInfo.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 diff --git a/src/crypto/common/LinuxMemory.cpp b/src/crypto/common/LinuxMemory.cpp index 297992a2..8a00e1c3 100644 --- a/src/crypto/common/LinuxMemory.cpp +++ b/src/crypto/common/LinuxMemory.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 @@ -18,8 +18,6 @@ #include "crypto/common/LinuxMemory.h" #include "3rdparty/fmt/core.h" -#include "backend/cpu/Cpu.h" -#include "base/io/log/Log.h" #include "crypto/common/VirtualMemory.h" @@ -37,33 +35,32 @@ constexpr size_t twoMiB = 2U * 1024U * 1024U; constexpr size_t oneGiB = 1024U * 1024U * 1024U; -static inline std::string sysfs_path(uint32_t node, bool oneGbPages, bool nr) +static inline std::string sysfs_path(uint32_t node, size_t hugePageSize, bool nr) { - return fmt::format("/sys/devices/system/node/node{}/hugepages/hugepages-{}kB/{}_hugepages", node, oneGbPages ? "1048576" : "2048", nr ? "nr" : "free"); + return fmt::format("/sys/devices/system/node/node{}/hugepages/hugepages-{}kB/{}_hugepages", node, hugePageSize / 1024, nr ? "nr" : "free"); } -static inline bool write_nr_hugepages(uint32_t node, bool oneGbPages, uint64_t count) { return LinuxMemory::write(sysfs_path(node, oneGbPages, true).c_str(), count); } -static inline int64_t free_hugepages(uint32_t node, bool oneGbPages) { return LinuxMemory::read(sysfs_path(node, oneGbPages, false).c_str()); } -static inline int64_t nr_hugepages(uint32_t node, bool oneGbPages) { return LinuxMemory::read(sysfs_path(node, oneGbPages, true).c_str()); } +static inline bool write_nr_hugepages(uint32_t node, size_t hugePageSize, uint64_t count) { return LinuxMemory::write(sysfs_path(node, hugePageSize, true).c_str(), count); } +static inline int64_t free_hugepages(uint32_t node, size_t hugePageSize) { return LinuxMemory::read(sysfs_path(node, hugePageSize, false).c_str()); } +static inline int64_t nr_hugepages(uint32_t node, size_t hugePageSize) { return LinuxMemory::read(sysfs_path(node, hugePageSize, true).c_str()); } } // namespace xmrig -bool xmrig::LinuxMemory::reserve(size_t size, uint32_t node, bool oneGbPages) +bool xmrig::LinuxMemory::reserve(size_t size, uint32_t node, size_t hugePageSize) { std::lock_guard lock(mutex); - const size_t pageSize = oneGbPages ? oneGiB : twoMiB; - const size_t required = VirtualMemory::align(size, pageSize) / pageSize; + const size_t required = VirtualMemory::align(size, hugePageSize) / hugePageSize; - const auto available = free_hugepages(node, oneGbPages); + const auto available = free_hugepages(node, hugePageSize); if (available < 0 || static_cast(available) >= required) { return false; } - return write_nr_hugepages(node, oneGbPages, std::max(nr_hugepages(node, oneGbPages), 0) + (required - available)); + return write_nr_hugepages(node, hugePageSize, std::max(nr_hugepages(node, hugePageSize), 0) + (required - available)); } diff --git a/src/crypto/common/LinuxMemory.h b/src/crypto/common/LinuxMemory.h index 8f75f00e..0d71af24 100644 --- a/src/crypto/common/LinuxMemory.h +++ b/src/crypto/common/LinuxMemory.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 @@ -30,7 +30,7 @@ namespace xmrig { class LinuxMemory { public: - static bool reserve(size_t size, uint32_t node, bool oneGbPages = false); + static bool reserve(size_t size, uint32_t node, size_t hugePageSize); static bool write(const char *path, uint64_t value); static int64_t read(const char *path); diff --git a/src/crypto/common/VirtualMemory.cpp b/src/crypto/common/VirtualMemory.cpp index 7d8d980b..e425750d 100644 --- a/src/crypto/common/VirtualMemory.cpp +++ b/src/crypto/common/VirtualMemory.cpp @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2018-2020 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 @@ -36,16 +36,19 @@ namespace xmrig { -static IMemoryPool *pool = nullptr; + +size_t VirtualMemory::m_hugePageSize = VirtualMemory::kDefaultHugePageSize; +static IMemoryPool *pool = nullptr; static std::mutex mutex; + } // namespace xmrig xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool oneGbPages, bool usePool, uint32_t node, size_t alignSize) : - m_size(align(size)), - m_capacity(m_size), - m_node(node) + m_size(alignToHugePageSize(size)), + m_node(node), + m_capacity(m_size) { if (usePool) { std::lock_guard lock(mutex); @@ -114,18 +117,18 @@ void xmrig::VirtualMemory::destroy() } -void xmrig::VirtualMemory::init(size_t poolSize, bool hugePages) +void xmrig::VirtualMemory::init(size_t poolSize, size_t hugePageSize) { if (!pool) { - osInit(hugePages); + osInit(hugePageSize); } # ifdef XMRIG_FEATURE_HWLOC if (Cpu::info()->nodes() > 1) { - pool = new NUMAMemoryPool(align(poolSize, Cpu::info()->nodes()), hugePages); + pool = new NUMAMemoryPool(align(poolSize, Cpu::info()->nodes()), hugePageSize > 0); } else # endif { - pool = new MemoryPool(poolSize, hugePages); + pool = new MemoryPool(poolSize, hugePageSize > 0); } } diff --git a/src/crypto/common/VirtualMemory.h b/src/crypto/common/VirtualMemory.h index e0065e3e..3056cbae 100644 --- a/src/crypto/common/VirtualMemory.h +++ b/src/crypto/common/VirtualMemory.h @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2018-2020 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 @@ -39,6 +39,9 @@ class VirtualMemory public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(VirtualMemory) + constexpr static size_t kDefaultHugePageSize = 2U * 1024U * 1024U; + constexpr static size_t kOneGiB = 1024U * 1024U * 1024U; + VirtualMemory(size_t size, bool hugePages, bool oneGbPages, bool usePool, uint32_t node = 0, size_t alignSize = 64); ~VirtualMemory(); @@ -65,9 +68,11 @@ public: static void destroy(); static void flushInstructionCache(void *p, size_t size); static void freeLargePagesMemory(void *p, size_t size); - static void init(size_t poolSize, bool hugePages); + static void init(size_t poolSize, size_t hugePageSize); - static inline constexpr size_t align(size_t pos, size_t align = 2097152) { return ((pos - 1) / align + 1) * align; } + static inline constexpr size_t align(size_t pos, size_t align = kDefaultHugePageSize) { return ((pos - 1) / align + 1) * align; } + static inline size_t alignToHugePageSize(size_t pos) { return align(pos, hugePageSize()); } + static inline size_t hugePageSize() { return m_hugePageSize; } private: enum Flags { @@ -78,15 +83,17 @@ private: FLAG_MAX }; - static void osInit(bool hugePages); + static void osInit(size_t hugePageSize); bool allocateLargePagesMemory(); bool allocateOneGbPagesMemory(); void freeLargePagesMemory(); + static size_t m_hugePageSize; + const size_t m_size; - size_t m_capacity; const uint32_t m_node; + size_t m_capacity; std::bitset m_flags; uint8_t *m_scratchpad = nullptr; }; diff --git a/src/crypto/common/VirtualMemory_unix.cpp b/src/crypto/common/VirtualMemory_unix.cpp index 60d77cca..e3362bc1 100644 --- a/src/crypto/common/VirtualMemory_unix.cpp +++ b/src/crypto/common/VirtualMemory_unix.cpp @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2018-2020 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 @@ -18,13 +18,14 @@ */ -#include -#include - - +#include "crypto/common/VirtualMemory.h" #include "backend/cpu/Cpu.h" #include "crypto/common/portable/mm_malloc.h" -#include "crypto/common/VirtualMemory.h" + + +#include +#include +#include #ifdef XMRIG_OS_APPLE @@ -42,14 +43,21 @@ #endif -#if defined(XMRIG_OS_LINUX) -# if (defined(MAP_HUGE_1GB) || defined(MAP_HUGE_SHIFT)) -# define XMRIG_HAS_1GB_PAGES -# endif +#ifdef XMRIG_OS_LINUX # include "crypto/common/LinuxMemory.h" #endif +#ifndef MAP_HUGE_SHIFT +# define MAP_HUGE_SHIFT 26 +#endif + + +#ifndef MAP_HUGE_MASK +# define MAP_HUGE_MASK 0x3f +#endif + + #ifdef XMRIG_SECURE_JIT # define SECURE_PROT_EXEC 0 #else @@ -57,6 +65,19 @@ #endif +namespace xmrig { + + +#ifdef XMRIG_OS_LINUX +static inline int hugePagesFlag(size_t size) +{ + return (static_cast(log2(size)) & MAP_HUGE_MASK) << MAP_HUGE_SHIFT; +} +#endif + +} // namespace xmrig + + bool xmrig::VirtualMemory::isHugepagesAvailable() { # if defined(XMRIG_OS_MACOS) && defined(XMRIG_ARM) @@ -69,7 +90,7 @@ bool xmrig::VirtualMemory::isHugepagesAvailable() bool xmrig::VirtualMemory::isOneGbPagesAvailable() { -# ifdef XMRIG_HAS_1GB_PAGES +# ifdef XMRIG_OS_LINUX return Cpu::info()->hasOneGbPages(); # else return false; @@ -126,18 +147,10 @@ void *xmrig::VirtualMemory::allocateExecutableMemory(size_t size, bool hugePages # else -# if defined(MAP_HUGE_2MB) - constexpr int flag_2mb = MAP_HUGE_2MB; -# elif defined(MAP_HUGE_SHIFT) - constexpr int flag_2mb = (21 << MAP_HUGE_SHIFT); -# else - constexpr int flag_2mb = 0; -# endif - void *mem = nullptr; if (hugePages) { - mem = mmap(0, align(size), PROT_READ | PROT_WRITE | SECURE_PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | flag_2mb, -1, 0); + mem = mmap(0, align(size), PROT_READ | PROT_WRITE | SECURE_PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | hugePagesFlag(hugePageSize()), -1, 0); } if (!mem) { @@ -157,17 +170,7 @@ void *xmrig::VirtualMemory::allocateLargePagesMemory(size_t size) # elif defined(__FreeBSD__) void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0); # else - -# if defined(MAP_HUGE_2MB) - constexpr int flag_2mb = MAP_HUGE_2MB; -# elif defined(MAP_HUGE_SHIFT) - constexpr int flag_2mb = (21 << MAP_HUGE_SHIFT); -# else - constexpr int flag_2mb = 0; -# endif - - void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE | flag_2mb, 0, 0); - + void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE | hugePagesFlag(hugePageSize()), 0, 0); # endif return mem == MAP_FAILED ? nullptr : mem; @@ -176,17 +179,9 @@ void *xmrig::VirtualMemory::allocateLargePagesMemory(size_t size) void *xmrig::VirtualMemory::allocateOneGbPagesMemory(size_t size) { -# ifdef XMRIG_HAS_1GB_PAGES +# ifdef XMRIG_OS_LINUX if (isOneGbPagesAvailable()) { -# if defined(MAP_HUGE_1GB) - constexpr int flag_1gb = MAP_HUGE_1GB; -# elif defined(MAP_HUGE_SHIFT) - constexpr int flag_1gb = (30 << MAP_HUGE_SHIFT); -# else - constexpr int flag_1gb = 0; -# endif - - void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE | flag_1gb, 0, 0); + void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE | hugePagesFlag(kOneGiB), 0, 0); return mem == MAP_FAILED ? nullptr : mem; } @@ -212,15 +207,18 @@ void xmrig::VirtualMemory::freeLargePagesMemory(void *p, size_t size) } -void xmrig::VirtualMemory::osInit(bool) +void xmrig::VirtualMemory::osInit(size_t hugePageSize) { + if (hugePageSize) { + m_hugePageSize = hugePageSize; + } } bool xmrig::VirtualMemory::allocateLargePagesMemory() { -# if defined(XMRIG_OS_LINUX) - LinuxMemory::reserve(m_size, m_node); +# ifdef XMRIG_OS_LINUX + LinuxMemory::reserve(m_size, m_node, hugePageSize()); # endif m_scratchpad = static_cast(allocateLargePagesMemory(m_size)); @@ -242,8 +240,8 @@ bool xmrig::VirtualMemory::allocateLargePagesMemory() bool xmrig::VirtualMemory::allocateOneGbPagesMemory() { -# if defined(XMRIG_HAS_1GB_PAGES) - LinuxMemory::reserve(m_size, m_node, true); +# ifdef XMRIG_OS_LINUX + LinuxMemory::reserve(m_size, m_node, kOneGiB); # endif m_scratchpad = static_cast(allocateOneGbPagesMemory(m_size)); diff --git a/src/crypto/common/VirtualMemory_win.cpp b/src/crypto/common/VirtualMemory_win.cpp index fee5f585..acf8119f 100644 --- a/src/crypto/common/VirtualMemory_win.cpp +++ b/src/crypto/common/VirtualMemory_win.cpp @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2018-2020 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 @@ -24,9 +24,9 @@ #include +#include "crypto/common/VirtualMemory.h" #include "base/io/log/Log.h" #include "crypto/common/portable/mm_malloc.h" -#include "crypto/common/VirtualMemory.h" #ifdef XMRIG_SECURE_JIT @@ -233,9 +233,9 @@ void xmrig::VirtualMemory::freeLargePagesMemory(void *p, size_t) } -void xmrig::VirtualMemory::osInit(bool hugePages) +void xmrig::VirtualMemory::osInit(size_t hugePageSize) { - if (hugePages) { + if (hugePageSize) { hugepagesAvailable = TrySetLockPagesPrivilege(); } } diff --git a/src/crypto/randomx/jit_compiler_a64.cpp b/src/crypto/randomx/jit_compiler_a64.cpp index 4a6176e5..2e6492ad 100644 --- a/src/crypto/randomx/jit_compiler_a64.cpp +++ b/src/crypto/randomx/jit_compiler_a64.cpp @@ -171,7 +171,7 @@ void JitCompilerA64::generateProgram(Program& program, ProgramConfiguration& con emit32(ARMV8A::EOR | 10 | (IntRegMap[config.readReg0] << 5) | (IntRegMap[config.readReg1] << 16), code, codePos); # ifndef XMRIG_OS_APPLE - xmrig::VirtualMemory::flushInstructionCache(reinterpret_cast(code + MainLoopBegin), reinterpret_cast(code + codePos)); + xmrig::VirtualMemory::flushInstructionCache(reinterpret_cast(code + MainLoopBegin), codePos - MainLoopBegin); # endif } @@ -237,7 +237,7 @@ void JitCompilerA64::generateProgramLight(Program& program, ProgramConfiguration emit32(ARMV8A::ADD_IMM_HI | 2 | (2 << 5) | (imm_hi << 10), code, codePos); # ifndef XMRIG_OS_APPLE - xmrig::VirtualMemory::flushInstructionCache(reinterpret_cast(code + MainLoopBegin), reinterpret_cast(code + codePos)); + xmrig::VirtualMemory::flushInstructionCache(reinterpret_cast(code + MainLoopBegin), codePos - MainLoopBegin); # endif } @@ -364,7 +364,7 @@ void JitCompilerA64::generateSuperscalarHash(SuperscalarProgram(&programs)[N]) codePos += p2 - p1; # ifndef XMRIG_OS_APPLE - xmrig::VirtualMemory::flushInstructionCache(reinterpret_cast(code + CodeSize), reinterpret_cast(code + codePos)); + xmrig::VirtualMemory::flushInstructionCache(reinterpret_cast(code + CodeSize), codePos - MainLoopBegin); # endif } @@ -401,6 +401,10 @@ void JitCompilerA64::allocate(size_t size) code = static_cast(allocExecutableMemory(allocatedSize, hugePages)); memcpy(code, reinterpret_cast(randomx_program_aarch64), CodeSize); + +# ifndef XMRIG_OS_APPLE + xmrig::VirtualMemory::flushInstructionCache(reinterpret_cast(code), CodeSize); +# endif } diff --git a/src/crypto/rx/RxConfig.h b/src/crypto/rx/RxConfig.h index 78d2f964..ea1bf685 100644 --- a/src/crypto/rx/RxConfig.h +++ b/src/crypto/rx/RxConfig.h @@ -113,7 +113,6 @@ private: Mode readMode(const rapidjson::Value &value) const; - bool m_numa = true; bool m_oneGbPages = false; bool m_rdmsr = true; int m_threads = -1; @@ -123,6 +122,7 @@ private: ScratchpadPrefetchMode m_scratchpadPrefetchMode = ScratchpadPrefetchT0; # ifdef XMRIG_FEATURE_HWLOC + bool m_numa = true; std::vector m_nodeset; # endif diff --git a/src/hw/dmi/DmiMemory.cpp b/src/hw/dmi/DmiMemory.cpp index 05af0962..735af286 100644 --- a/src/hw/dmi/DmiMemory.cpp +++ b/src/hw/dmi/DmiMemory.cpp @@ -20,17 +20,22 @@ #include "hw/dmi/DmiMemory.h" +#include "3rdparty/fmt/format.h" #include "3rdparty/rapidjson/document.h" #include "hw/dmi/DmiTools.h" #include #include +#include namespace xmrig { +static const char *kIdFormat = "DIMM_{}{}"; + + static inline uint16_t dmi_memory_device_width(uint16_t code) { return (code == 0xFFFF || code == 0) ? 0 : code; @@ -143,9 +148,9 @@ xmrig::DmiMemory::DmiMemory(dmi_header *h) m_size = (1024ULL * (size & 0x7FFF) * ((size & 0x8000) ? 1 : 1024ULL)); } + setId(dmi_string(h, 0x10), dmi_string(h, 0x11)); + 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) { @@ -201,6 +206,7 @@ rapidjson::Value xmrig::DmiMemory::toJSON(rapidjson::Document &doc) const auto &allocator = doc.GetAllocator(); Value out(kObjectType); + out.AddMember("id", id().toJSON(doc), allocator); out.AddMember("slot", m_slot.toJSON(doc), allocator); out.AddMember("type", StringRef(type()), allocator); out.AddMember("form_factor", StringRef(formFactor()), allocator); @@ -217,3 +223,21 @@ rapidjson::Value xmrig::DmiMemory::toJSON(rapidjson::Document &doc) const return out; } #endif + + +void xmrig::DmiMemory::setId(const char *slot, const char *bank) +{ + m_slot = slot; + m_bank = bank; + + std::cmatch cm; + if (std::regex_match(slot, cm, std::regex("^Channel([A-Z])[-_]DIMM(\\d+)$", std::regex_constants::icase))) { + m_id = fmt::format(kIdFormat, cm.str(1), cm.str(2)).c_str(); + } + else if (std::regex_search(bank, cm, std::regex("CHANNEL ([A-Z])$"))) { + std::cmatch cm2; + if (std::regex_match(slot, cm2, std::regex("^DIMM (\\d+)$"))) { + m_id = fmt::format(kIdFormat, cm.str(1), cm2.str(1)).c_str(); + } + } +} diff --git a/src/hw/dmi/DmiMemory.h b/src/hw/dmi/DmiMemory.h index badee2cf..589b3b90 100644 --- a/src/hw/dmi/DmiMemory.h +++ b/src/hw/dmi/DmiMemory.h @@ -39,6 +39,7 @@ public: inline bool isValid() const { return !m_slot.isEmpty(); } inline const String &bank() const { return m_bank; } + inline const String &id() const { return m_id.isNull() ? m_slot : m_id; } inline const String &product() const { return m_product; } inline const String &slot() const { return m_slot; } inline const String &vendor() const { return m_vendor; } @@ -57,7 +58,10 @@ public: # endif private: + void setId(const char *slot, const char *bank); + String m_bank; + String m_id; String m_product; String m_slot; String m_vendor; diff --git a/src/version.h b/src/version.h index 8f232976..8dff136a 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig miner" -#define APP_VERSION "6.8.0-mo1" +#define APP_VERSION "6.8.1-mo1" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2021 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 6 #define APP_VER_MINOR 8 -#define APP_VER_PATCH 0 +#define APP_VER_PATCH 1 #ifdef _MSC_VER # if (_MSC_VER >= 1920)