From cc2de4f76872517d52940e4ba840db59aca3283f Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 15 Jan 2021 20:11:28 +0700 Subject: [PATCH 01/27] v6.7.3-dev --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index 82a96fba..0e91cd2e 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.7.2" +#define APP_VERSION "6.7.3-dev" #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 7 -#define APP_VER_PATCH 2 +#define APP_VER_PATCH 3 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From ea367da064b32a85b9e28887d3d0f90343fb6e0d Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 17 Jan 2021 17:48:35 +0700 Subject: [PATCH 02/27] #2043 Fix compile warning. --- src/crypto/randomx/aes_hash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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>, From 11e0d3de3aa501dcd44172b17f4b64ecced9607d Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 18 Jan 2021 11:23:29 +0700 Subject: [PATCH 03/27] Added DMI reader (Windows only). --- CMakeLists.txt | 3 + src/Summary.cpp | 30 ++++++ src/hw/dmi/DmiBoard.cpp | 35 +++++++ src/hw/dmi/DmiBoard.h | 54 ++++++++++ src/hw/dmi/DmiMemory.cpp | 192 ++++++++++++++++++++++++++++++++++ src/hw/dmi/DmiMemory.h | 74 +++++++++++++ src/hw/dmi/DmiReader.cpp | 87 +++++++++++++++ src/hw/dmi/DmiReader.h | 59 +++++++++++ src/hw/dmi/DmiReader_unix.cpp | 26 +++++ src/hw/dmi/DmiReader_win.cpp | 112 ++++++++++++++++++++ src/hw/dmi/DmiTools.cpp | 75 +++++++++++++ src/hw/dmi/DmiTools.h | 53 ++++++++++ src/hw/dmi/dmi.cmake | 25 +++++ 13 files changed, 825 insertions(+) create mode 100644 src/hw/dmi/DmiBoard.cpp create mode 100644 src/hw/dmi/DmiBoard.h create mode 100644 src/hw/dmi/DmiMemory.cpp create mode 100644 src/hw/dmi/DmiMemory.h create mode 100644 src/hw/dmi/DmiReader.cpp create mode 100644 src/hw/dmi/DmiReader.h create mode 100644 src/hw/dmi/DmiReader_unix.cpp create mode 100644 src/hw/dmi/DmiReader_win.cpp create mode 100644 src/hw/dmi/DmiTools.cpp create mode 100644 src/hw/dmi/DmiTools.h create mode 100644 src/hw/dmi/dmi.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 35fba8ea..c1a222fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,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 reader" OFF) option(BUILD_STATIC "Build static binary" OFF) option(ARM_TARGET "Force use specific ARM target 8 or 7" 0) @@ -197,6 +198,8 @@ if (WITH_EMBEDDED_CONFIG) add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG) endif() +include (src/hw/dmi/dmi.cmake) + include_directories(src) include_directories(src/3rdparty) include_directories(${UV_INCLUDE_DIR}) diff --git a/src/Summary.cpp b/src/Summary.cpp index ebaeb356..345ed48e 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -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 @@ -130,6 +135,31 @@ static void print_memory() totalMem / oneGiB, percent ); + +# ifdef XMRIG_FEATURE_DMI + DmiReader reader; + if (!reader.read()) { + return; + } + + for (const auto &memory : reader.memory()) { + if (!memory.isValid()) { + continue; + } + + if (!memory.size()) { + Log::print(WHITE_BOLD(" %-13s") WHITE_BOLD("%s: ") BLACK_BOLD(""), "", memory.slot().data()); + continue; + } + + Log::print(WHITE_BOLD(" %-13s") WHITE_BOLD("%s: ") CYAN_BOLD("%" PRIu64 " GB ") WHITE_BOLD("%s @ %" PRIu64 " MHz ") BLACK_BOLD("%s"), + "", memory.slot().data(), memory.size() / oneGiB, memory.type(), memory.speed() / 1000000ULL, memory.product().data()); + } + + if (reader.board().isValid()) { + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") " - " WHITE_BOLD("%s"), "MOTHERBOARD", reader.board().vendor().data(), reader.board().product().data()); + } +# endif } diff --git a/src/hw/dmi/DmiBoard.cpp b/src/hw/dmi/DmiBoard.cpp new file mode 100644 index 00000000..381865f4 --- /dev/null +++ b/src/hw/dmi/DmiBoard.cpp @@ -0,0 +1,35 @@ +/* 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 "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); +} diff --git a/src/hw/dmi/DmiBoard.h b/src/hw/dmi/DmiBoard.h new file mode 100644 index 00000000..dd28a607 --- /dev/null +++ b/src/hw/dmi/DmiBoard.h @@ -0,0 +1,54 @@ +/* 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); + +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..0006d006 --- /dev/null +++ b/src/hw/dmi/DmiMemory.cpp @@ -0,0 +1,192 @@ +/* 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 "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; + } + + m_speed = std::max(m_speed, dmi_memory_device_speed(dmi_get(h, 0x20), h->length >= 0x5C ? dmi_get(h, 0x58) : 0) * 1000000ULL); + + 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); +} diff --git a/src/hw/dmi/DmiMemory.h b/src/hw/dmi/DmiMemory.h new file mode 100644 index 00000000..b9a0468b --- /dev/null +++ b/src/hw/dmi/DmiMemory.h @@ -0,0 +1,74 @@ +/* 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; + +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..66083845 --- /dev/null +++ b/src/hw/dmi/DmiReader.cpp @@ -0,0 +1,87 @@ +/* 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" + + +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 + + +bool xmrig::DmiReader::decode(uint8_t *buf) +{ + if (!buf || !m_count) { + return false; + } + + uint8_t *data = buf; + int i = 0; + + while ((i < m_count || !m_count) && 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++; + } + next += 2; + + if (static_cast(next - buf) > m_size) { + data = next; + break; + } + + switch (h.type) { + 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..69ba483b --- /dev/null +++ b/src/hw/dmi/DmiReader.h @@ -0,0 +1,59 @@ +/* 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" + + +namespace xmrig { + + +class DmiReader +{ +public: + DmiReader() = default; + + inline const DmiBoard &board() const { return m_board; } + inline const std::vector &memory() const { return m_memory; } + inline uint16_t count() const { return m_count; } + inline uint32_t size() const { return m_size; } + inline uint32_t version() const { return m_version; } + + bool read(); + +private: + bool decode(uint8_t *buf); + + DmiBoard m_board; + uint16_t m_count = 0; + uint32_t m_size = 0; + uint32_t m_version = 0; + std::vector m_memory; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DMIREADER_H */ diff --git a/src/hw/dmi/DmiReader_unix.cpp b/src/hw/dmi/DmiReader_unix.cpp new file mode 100644 index 00000000..4919935f --- /dev/null +++ b/src/hw/dmi/DmiReader_unix.cpp @@ -0,0 +1,26 @@ +/* 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/dmi/DmiReader.h" + + +bool xmrig::DmiReader::read() +{ + return false; +} diff --git a/src/hw/dmi/DmiReader_win.cpp b/src/hw/dmi/DmiReader_win.cpp new file mode 100644 index 00000000..6b8e2ac4 --- /dev/null +++ b/src/hw/dmi/DmiReader_win.cpp @@ -0,0 +1,112 @@ +/* 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[]; +}; + + +/* + * Counts the number of SMBIOS structures present in + * the SMBIOS table. + * + * buf - Pointer that receives the SMBIOS Table address. + * This will be the address of the BYTE array from + * the RawSMBIOSData struct. + * + * len - The length of the SMBIOS Table pointed by buff. + * + * return - The number of SMBIOS strutctures. + * + * Remarks: + * The SMBIOS Table Entry Point has this information, + * however the GetSystemFirmwareTable API doesn't + * return all fields from the Entry Point, and + * DMIDECODE uses this value as a parameter for + * dmi_table function. This is the reason why + * this function was make. + * + * Hugo Weber address@hidden + */ +uint16_t count_smbios_structures(const uint8_t *buf, uint32_t len) +{ + uint16_t count = 0; + uint32_t offset = 0; + + while (offset < len) { + offset += reinterpret_cast(buf + offset)->length; + count++; + + while ((*reinterpret_cast(buf + offset) != 0) && (offset < len)) { + offset++; + } + + offset += 2; + } + + return count; +} + + +} // 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; + m_count = count_smbios_structures(smb->SMBIOSTableData, m_size); + + const bool rc = decode(smb->SMBIOSTableData); + HeapFree(GetProcessHeap(), 0, smb); + + return rc; +} 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..e929e6fe --- /dev/null +++ b/src/hw/dmi/DmiTools.h @@ -0,0 +1,53 @@ +/* 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 + + +namespace xmrig { + + +struct dmi_header +{ + uint8_t type; + uint8_t length; + uint16_t handle; + uint8_t *data; +}; + + +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..ff4882ce --- /dev/null +++ b/src/hw/dmi/dmi.cmake @@ -0,0 +1,25 @@ +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) + list(APPEND SOURCES src/hw/dmi/DmiReader_unix.cpp) + endif() +else() + remove_definitions(/DXMRIG_FEATURE_DMI) +endif() From 05e6f661690f067b2ed0f507ea8717b73449e7ed Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 18 Jan 2021 16:53:42 +0700 Subject: [PATCH 04/27] Added basic Linux support. --- CMakeLists.txt | 2 +- src/hw/dmi/DmiMemory.cpp | 2 +- src/hw/dmi/DmiReader.cpp | 4 +- src/hw/dmi/DmiReader.h | 2 - src/hw/dmi/DmiReader_unix.cpp | 168 +++++++++++++++++++++++++++++++++- src/hw/dmi/DmiReader_win.cpp | 43 --------- src/hw/dmi/DmiTools.h | 7 ++ 7 files changed, 177 insertions(+), 51 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1a222fc..69f40fcd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,7 +170,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) diff --git a/src/hw/dmi/DmiMemory.cpp b/src/hw/dmi/DmiMemory.cpp index 0006d006..f02a64ec 100644 --- a/src/hw/dmi/DmiMemory.cpp +++ b/src/hw/dmi/DmiMemory.cpp @@ -170,7 +170,7 @@ xmrig::DmiMemory::DmiMemory(dmi_header *h) return; } - m_speed = std::max(m_speed, dmi_memory_device_speed(dmi_get(h, 0x20), h->length >= 0x5C ? dmi_get(h, 0x58) : 0) * 1000000ULL); + m_speed = std::max(m_speed, dmi_memory_device_speed(dmi_get(h, 0x20), h->length >= 0x5C ? dmi_get(h, 0x58) : 0) * 1000000ULL); if (h->length < 0x28) { return; diff --git a/src/hw/dmi/DmiReader.cpp b/src/hw/dmi/DmiReader.cpp index 66083845..66f1dd5f 100644 --- a/src/hw/dmi/DmiReader.cpp +++ b/src/hw/dmi/DmiReader.cpp @@ -40,14 +40,14 @@ static void dmi_get_header(dmi_header *h, uint8_t *data) bool xmrig::DmiReader::decode(uint8_t *buf) { - if (!buf || !m_count) { + if (!buf) { return false; } uint8_t *data = buf; int i = 0; - while ((i < m_count || !m_count) && data + 4 <= buf + m_size) { + while (data + 4 <= buf + m_size) { dmi_header h{}; dmi_get_header(&h, data); diff --git a/src/hw/dmi/DmiReader.h b/src/hw/dmi/DmiReader.h index 69ba483b..243b5164 100644 --- a/src/hw/dmi/DmiReader.h +++ b/src/hw/dmi/DmiReader.h @@ -36,7 +36,6 @@ public: inline const DmiBoard &board() const { return m_board; } inline const std::vector &memory() const { return m_memory; } - inline uint16_t count() const { return m_count; } inline uint32_t size() const { return m_size; } inline uint32_t version() const { return m_version; } @@ -46,7 +45,6 @@ private: bool decode(uint8_t *buf); DmiBoard m_board; - uint16_t m_count = 0; uint32_t m_size = 0; uint32_t m_version = 0; std::vector m_memory; diff --git a/src/hw/dmi/DmiReader_unix.cpp b/src/hw/dmi/DmiReader_unix.cpp index 4919935f..e9b25abc 100644 --- a/src/hw/dmi/DmiReader_unix.cpp +++ b/src/hw/dmi/DmiReader_unix.cpp @@ -1,6 +1,8 @@ /* XMRig - * Copyright (c) 2018-2021 SChernykh - * Copyright (c) 2016-2021 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 @@ -18,9 +20,171 @@ #include "hw/dmi/DmiReader.h" +#include "hw/dmi/DmiTools.h" + + +#include +#include +#include +#include +#include + + +#define FLAG_NO_FILE_OFFSET (1 << 0) + + +namespace xmrig { + + +static const char *kSysEntryFile = "/sys/firmware/dmi/tables/smbios_entry_point"; +static const char *kSysTableFile = "/sys/firmware/dmi/tables/DMI"; + + + +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; +} + + +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) +{ + uint8_t *buf = nullptr; + + if (flags & FLAG_NO_FILE_OFFSET) { + size_t size = len; + buf = read_file(0, &size, devmem); + len = size; + } + else { + // FIXME + } + + return buf; +} + + +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);; +} + + +} // namespace xmrig bool xmrig::DmiReader::read() { + size_t size = 0x20; + uint8_t *buf = read_file(0, &size, kSysEntryFile); + + if (buf) { + uint8_t *smb = nullptr; + + if (size >= 24 && memcmp(buf, "_SM3_", 5) == 0) { + smb = smbios3_decode(buf, kSysTableFile, m_size, m_version, FLAG_NO_FILE_OFFSET); + } + + if (smb) { + decode(smb); + + free(smb); + free(buf); + + return true; + } + } + return false; } diff --git a/src/hw/dmi/DmiReader_win.cpp b/src/hw/dmi/DmiReader_win.cpp index 6b8e2ac4..b79f952a 100644 --- a/src/hw/dmi/DmiReader_win.cpp +++ b/src/hw/dmi/DmiReader_win.cpp @@ -41,48 +41,6 @@ struct RawSMBIOSData { }; -/* - * Counts the number of SMBIOS structures present in - * the SMBIOS table. - * - * buf - Pointer that receives the SMBIOS Table address. - * This will be the address of the BYTE array from - * the RawSMBIOSData struct. - * - * len - The length of the SMBIOS Table pointed by buff. - * - * return - The number of SMBIOS strutctures. - * - * Remarks: - * The SMBIOS Table Entry Point has this information, - * however the GetSystemFirmwareTable API doesn't - * return all fields from the Entry Point, and - * DMIDECODE uses this value as a parameter for - * dmi_table function. This is the reason why - * this function was make. - * - * Hugo Weber address@hidden - */ -uint16_t count_smbios_structures(const uint8_t *buf, uint32_t len) -{ - uint16_t count = 0; - uint32_t offset = 0; - - while (offset < len) { - offset += reinterpret_cast(buf + offset)->length; - count++; - - while ((*reinterpret_cast(buf + offset) != 0) && (offset < len)) { - offset++; - } - - offset += 2; - } - - return count; -} - - } // namespace xmrig @@ -103,7 +61,6 @@ bool xmrig::DmiReader::read() m_version = (smb->SMBIOSMajorVersion << 16) + (smb->SMBIOSMinorVersion << 8) + smb->DmiRevision; m_size = smb->Length; - m_count = count_smbios_structures(smb->SMBIOSTableData, m_size); const bool rc = decode(smb->SMBIOSTableData); HeapFree(GetProcessHeap(), 0, smb); diff --git a/src/hw/dmi/DmiTools.h b/src/hw/dmi/DmiTools.h index e929e6fe..65a1dfd7 100644 --- a/src/hw/dmi/DmiTools.h +++ b/src/hw/dmi/DmiTools.h @@ -22,6 +22,7 @@ #define XMRIG_DMITOOLS_H +#include #include @@ -37,6 +38,12 @@ struct dmi_header }; +struct u64 { + uint32_t l; + uint32_t h; +}; + + template inline T dmi_get(const uint8_t *data) { return *reinterpret_cast(data); } From 3b8d081c8c63c717dc366f17fad861b75cea45c7 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 18 Jan 2021 22:56:57 +0700 Subject: [PATCH 05/27] Add support for older DMI formats on Linux. --- src/Summary.cpp | 6 ++-- src/hw/dmi/DmiReader.cpp | 10 ++++++ src/hw/dmi/DmiReader.h | 6 ++++ src/hw/dmi/DmiReader_unix.cpp | 57 ++++++++++++++++++++++++++++++----- src/hw/dmi/DmiReader_win.cpp | 7 ++--- 5 files changed, 72 insertions(+), 14 deletions(-) diff --git a/src/Summary.cpp b/src/Summary.cpp index 345ed48e..b925232f 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -129,7 +129,7 @@ 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, @@ -148,11 +148,11 @@ static void print_memory() } if (!memory.size()) { - Log::print(WHITE_BOLD(" %-13s") WHITE_BOLD("%s: ") BLACK_BOLD(""), "", memory.slot().data()); + Log::print(WHITE_BOLD(" %-13s") "%s: " BLACK_BOLD(""), "", memory.slot().data()); continue; } - Log::print(WHITE_BOLD(" %-13s") WHITE_BOLD("%s: ") CYAN_BOLD("%" PRIu64 " GB ") WHITE_BOLD("%s @ %" PRIu64 " MHz ") BLACK_BOLD("%s"), + 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()); } diff --git a/src/hw/dmi/DmiReader.cpp b/src/hw/dmi/DmiReader.cpp index 66f1dd5f..8993531a 100644 --- a/src/hw/dmi/DmiReader.cpp +++ b/src/hw/dmi/DmiReader.cpp @@ -38,6 +38,16 @@ static void dmi_get_header(dmi_header *h, uint8_t *data) } // namespace xmrig +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) { diff --git a/src/hw/dmi/DmiReader.h b/src/hw/dmi/DmiReader.h index 243b5164..f140f867 100644 --- a/src/hw/dmi/DmiReader.h +++ b/src/hw/dmi/DmiReader.h @@ -26,6 +26,9 @@ #include "hw/dmi/DmiMemory.h" +#include + + namespace xmrig { @@ -42,6 +45,9 @@ public: bool read(); private: + using Cleanup = std::function; + + bool decode(uint8_t *buf, const Cleanup &cleanup); bool decode(uint8_t *buf); DmiBoard m_board; diff --git a/src/hw/dmi/DmiReader_unix.cpp b/src/hw/dmi/DmiReader_unix.cpp index e9b25abc..db516012 100644 --- a/src/hw/dmi/DmiReader_unix.cpp +++ b/src/hw/dmi/DmiReader_unix.cpp @@ -157,7 +157,46 @@ static uint8_t *smbios3_decode(uint8_t *buf, const char *devmem, uint32_t &size, 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);; + 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); } @@ -175,14 +214,18 @@ bool xmrig::DmiReader::read() 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) { - decode(smb); - - free(smb); - free(buf); - - return true; + return decode(smb, [smb, buf]() { + free(smb); + free(buf); + }); } } diff --git a/src/hw/dmi/DmiReader_win.cpp b/src/hw/dmi/DmiReader_win.cpp index b79f952a..837bdb7b 100644 --- a/src/hw/dmi/DmiReader_win.cpp +++ b/src/hw/dmi/DmiReader_win.cpp @@ -62,8 +62,7 @@ bool xmrig::DmiReader::read() m_version = (smb->SMBIOSMajorVersion << 16) + (smb->SMBIOSMinorVersion << 8) + smb->DmiRevision; m_size = smb->Length; - const bool rc = decode(smb->SMBIOSTableData); - HeapFree(GetProcessHeap(), 0, smb); - - return rc; + return decode(smb->SMBIOSTableData, [smb]() { + HeapFree(GetProcessHeap(), 0, smb); + }); } From 3df47052ed499a24d9045efed07a9c5f8713c387 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 19 Jan 2021 01:23:09 +0700 Subject: [PATCH 06/27] Added legacy DMI readers for Linux. --- src/hw/dmi/DmiReader_unix.cpp | 211 +++++++++++++++++++++++++++++++--- 1 file changed, 197 insertions(+), 14 deletions(-) diff --git a/src/hw/dmi/DmiReader_unix.cpp b/src/hw/dmi/DmiReader_unix.cpp index db516012..d73e3943 100644 --- a/src/hw/dmi/DmiReader_unix.cpp +++ b/src/hw/dmi/DmiReader_unix.cpp @@ -25,19 +25,38 @@ #include #include +#include #include #include #include +#ifdef __FreeBSD__ +# include +#endif + + #define FLAG_NO_FILE_OFFSET (1 << 0) namespace xmrig { -static const char *kSysEntryFile = "/sys/firmware/dmi/tables/smbios_entry_point"; -static const char *kSysTableFile = "/sys/firmware/dmi/tables/DMI"; +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 +} @@ -118,6 +137,69 @@ out: } +/* + * 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; @@ -132,18 +214,15 @@ static int checksum(const uint8_t *buf, size_t len) static uint8_t *dmi_table(off_t base, uint32_t &len, const char *devmem, uint32_t flags) { - uint8_t *buf = nullptr; - if (flags & FLAG_NO_FILE_OFFSET) { size_t size = len; - buf = read_file(0, &size, devmem); + auto buf = read_file(0, &size, devmem); len = size; - } - else { - // FIXME + + return buf; } - return buf; + return mem_chunk(base, len, devmem); } @@ -200,6 +279,50 @@ static uint8_t *legacy_decode(uint8_t *buf, const char *devmem, uint32_t &size, } +#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]; +# elif defined(__FreeBSD__) + char addrstr[KENV_MVALLEN + 1]; +# endif + + off_t address = 0; + +# 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 @@ -207,9 +330,10 @@ bool xmrig::DmiReader::read() { size_t size = 0x20; uint8_t *buf = read_file(0, &size, kSysEntryFile); + uint8_t *smb = nullptr; if (buf) { - uint8_t *smb = nullptr; + smb = nullptr; if (size >= 24 && memcmp(buf, "_SM3_", 5) == 0) { smb = smbios3_decode(buf, kSysTableFile, m_size, m_version, FLAG_NO_FILE_OFFSET); @@ -222,12 +346,71 @@ bool xmrig::DmiReader::read() } if (smb) { - return decode(smb, [smb, buf]() { - free(smb); - free(buf); - }); + 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; } From 9dffcdaddd02752c8a39827521227dcd57f4bc1f Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 19 Jan 2021 01:45:17 +0700 Subject: [PATCH 07/27] Enable FreeBSD support. --- src/hw/dmi/DmiReader_unix.cpp | 3 +-- src/hw/dmi/dmi.cmake | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hw/dmi/DmiReader_unix.cpp b/src/hw/dmi/DmiReader_unix.cpp index d73e3943..ff57b7a6 100644 --- a/src/hw/dmi/DmiReader_unix.cpp +++ b/src/hw/dmi/DmiReader_unix.cpp @@ -287,12 +287,11 @@ static off_t address_from_efi() FILE *efi_systab; const char *filename; char linebuf[64]; + off_t address = 0; # elif defined(__FreeBSD__) char addrstr[KENV_MVALLEN + 1]; # endif - off_t address = 0; - # 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; diff --git a/src/hw/dmi/dmi.cmake b/src/hw/dmi/dmi.cmake index ff4882ce..e10ec3ed 100644 --- a/src/hw/dmi/dmi.cmake +++ b/src/hw/dmi/dmi.cmake @@ -17,7 +17,7 @@ if (WITH_DMI) if (XMRIG_OS_WIN) list(APPEND SOURCES src/hw/dmi/DmiReader_win.cpp) - elseif(XMRIG_OS_LINUX) + elseif(XMRIG_OS_LINUX OR XMRIG_OS_FREEBSD) list(APPEND SOURCES src/hw/dmi/DmiReader_unix.cpp) endif() else() From 24c290963aea6034d7ece6fafdc4480943dd8d7f Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 19 Jan 2021 14:16:03 +0700 Subject: [PATCH 08/27] Added DMI reader for macOS. --- src/Summary.cpp | 12 ++-- src/hw/dmi/DmiReader.cpp | 4 ++ src/hw/dmi/DmiReader_mac.cpp | 108 +++++++++++++++++++++++++++++++++++ src/hw/dmi/dmi.cmake | 4 ++ 4 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 src/hw/dmi/DmiReader_mac.cpp diff --git a/src/Summary.cpp b/src/Summary.cpp index b925232f..8118f99d 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -147,13 +147,13 @@ static void print_memory() continue; } - if (!memory.size()) { - Log::print(WHITE_BOLD(" %-13s") "%s: " BLACK_BOLD(""), "", memory.slot().data()); - 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 (!Cpu::info()->isVM()) { + Log::print(WHITE_BOLD(" %-13s") "%s: " BLACK_BOLD(""), "", memory.slot().data()); } - - 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()); } if (reader.board().isValid()) { diff --git a/src/hw/dmi/DmiReader.cpp b/src/hw/dmi/DmiReader.cpp index 8993531a..5c6a9607 100644 --- a/src/hw/dmi/DmiReader.cpp +++ b/src/hw/dmi/DmiReader.cpp @@ -70,6 +70,10 @@ bool xmrig::DmiReader::decode(uint8_t *buf) 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) { 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/dmi.cmake b/src/hw/dmi/dmi.cmake index e10ec3ed..aee0ff9a 100644 --- a/src/hw/dmi/dmi.cmake +++ b/src/hw/dmi/dmi.cmake @@ -19,6 +19,10 @@ if (WITH_DMI) 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) From dea5be0a57029074bde06db1faabbcd82be64bb8 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 20 Jan 2021 00:43:01 +0700 Subject: [PATCH 09/27] Added basic system reader. --- src/Summary.cpp | 8 ++++++-- src/hw/dmi/DmiBoard.cpp | 1 - src/hw/dmi/DmiReader.cpp | 4 ++++ src/hw/dmi/DmiReader.h | 4 +++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Summary.cpp b/src/Summary.cpp index 8118f99d..0cbbbbca 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -142,6 +142,8 @@ static void print_memory() return; } + const bool vm = Cpu::info()->isVM(); + for (const auto &memory : reader.memory()) { if (!memory.isValid()) { continue; @@ -151,12 +153,14 @@ static void print_memory() 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 (!Cpu::info()->isVM()) { + else if (!vm) { Log::print(WHITE_BOLD(" %-13s") "%s: " BLACK_BOLD(""), "", memory.slot().data()); } } - if (reader.board().isValid()) { + 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", reader.board().vendor().data(), reader.board().product().data()); } # endif diff --git a/src/hw/dmi/DmiBoard.cpp b/src/hw/dmi/DmiBoard.cpp index 381865f4..5ebfd9aa 100644 --- a/src/hw/dmi/DmiBoard.cpp +++ b/src/hw/dmi/DmiBoard.cpp @@ -23,7 +23,6 @@ #include "hw/dmi/DmiTools.h" - void xmrig::DmiBoard::decode(dmi_header *h) { if (h->length < 0x08) { diff --git a/src/hw/dmi/DmiReader.cpp b/src/hw/dmi/DmiReader.cpp index 5c6a9607..9854ff1b 100644 --- a/src/hw/dmi/DmiReader.cpp +++ b/src/hw/dmi/DmiReader.cpp @@ -82,6 +82,10 @@ bool xmrig::DmiReader::decode(uint8_t *buf) } switch (h.type) { + case 1: + m_system.decode(&h); + break; + case 2: m_board.decode(&h); break; diff --git a/src/hw/dmi/DmiReader.h b/src/hw/dmi/DmiReader.h index f140f867..ccf2311a 100644 --- a/src/hw/dmi/DmiReader.h +++ b/src/hw/dmi/DmiReader.h @@ -38,6 +38,7 @@ 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; } @@ -51,9 +52,10 @@ private: 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; - std::vector m_memory; }; From efc5e5d81128389cad59ea0d9a6258dd717c8c9c Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 20 Jan 2021 00:45:36 +0700 Subject: [PATCH 10/27] Fix summary. --- src/Summary.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Summary.cpp b/src/Summary.cpp index 0cbbbbca..e0c4d58e 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -161,7 +161,7 @@ static void print_memory() 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", reader.board().vendor().data(), reader.board().product().data()); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") " - " WHITE_BOLD("%s"), "MOTHERBOARD", board.vendor().data(), board.product().data()); } # endif } From 9a0200790042d22664a39f54c0199f27318c69a5 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 20 Jan 2021 16:02:48 +0700 Subject: [PATCH 11/27] Added config option "dmi" and command line option "--no-dmi". --- CMakeLists.txt | 2 +- src/Summary.cpp | 32 ++++++++++------- src/Summary.h | 4 +-- src/base/kernel/interfaces/IConfig.h | 5 +-- src/core/config/Config.cpp | 38 +++++++++++++++++---- src/core/config/Config.h | 28 +++++++++++++-- src/core/config/ConfigTransform.cpp | 51 ++++++++++++++-------------- src/core/config/ConfigTransform.h | 4 +-- src/core/config/Config_platform.h | 5 +++ src/core/config/usage.h | 4 +++ src/hw/dmi/dmi.cmake | 4 +++ 11 files changed, 121 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69f40fcd..fe411cb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,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 reader" OFF) +option(WITH_DMI "Enable DMI/SMBIOS reader" OFF) option(BUILD_STATIC "Build static binary" OFF) option(ARM_TARGET "Force use specific ARM target 8 or 7" 0) diff --git a/src/Summary.cpp b/src/Summary.cpp index e0c4d58e..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 @@ -76,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")); @@ -92,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(); @@ -121,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()); @@ -137,6 +137,10 @@ static void print_memory() ); # ifdef XMRIG_FEATURE_DMI + if (!config->isDMI()) { + return; + } + DmiReader reader; if (!reader.read()) { return; @@ -167,7 +171,7 @@ static void print_memory() } -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", @@ -209,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/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 8b5ae278..792c43a1 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/core/config/Config.cpp b/src/core/config/Config.cpp index 792b3873..f8b7bb85 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()) { @@ -191,6 +206,10 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName) d_ptr->healthPrintTime = reader.getUint(kHealthPrintTime, d_ptr->healthPrintTime); # endif +# ifdef XMRIG_FEATURE_DMI + d_ptr->dmi = reader.getBool(kDMI, d_ptr->dmi); +# endif + return true; } @@ -236,6 +255,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 501b8c59..d8433beb 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 @@ -50,6 +50,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; @@ -70,7 +86,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_platform.h b/src/core/config/Config_platform.h index f698836c..b6fcd1c1 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -155,7 +155,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/hw/dmi/dmi.cmake b/src/hw/dmi/dmi.cmake index aee0ff9a..5140692a 100644 --- a/src/hw/dmi/dmi.cmake +++ b/src/hw/dmi/dmi.cmake @@ -1,3 +1,7 @@ +if (WITH_DMI) + set(WITH_DMI XMRIG_OS_WIN OR XMRIG_OS_LINUX OR XMRIG_OS_FREEBSD OR (XMRIG_OS_MACOS AND NOT XMRIG_ARM)) +endif() + if (WITH_DMI) add_definitions(/DXMRIG_FEATURE_DMI) From b99dc440afb77d6d680a59588602e17f51d282e0 Mon Sep 17 00:00:00 2001 From: alvv-z <77728785+alvv-z@users.noreply.github.com> Date: Wed, 20 Jan 2021 12:36:47 +0100 Subject: [PATCH 12/27] Spelling Check agaiin -> again --- src/donate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. * From 8471f7fad3db29e0765d733335647c63fedc5822 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 20 Jan 2021 22:54:02 +0700 Subject: [PATCH 13/27] Added "GET /2/dmi" API endpoint. --- CMakeLists.txt | 3 +- src/base/api/Api.cpp | 10 +--- src/base/api/Api.h | 11 +---- src/base/api/interfaces/IApiListener.h | 14 +++--- src/base/api/interfaces/IApiRequest.h | 16 +++---- src/base/kernel/interfaces/IBaseListener.h | 18 ++++---- src/core/Controller.cpp | 42 ++++++++--------- src/core/Controller.h | 23 +++++----- src/hw/api/HwApi.cpp | 47 +++++++++++++++++++ src/hw/api/HwApi.h | 53 ++++++++++++++++++++++ src/hw/api/api.cmake | 11 +++++ src/hw/dmi/DmiBoard.cpp | 16 +++++++ src/hw/dmi/DmiBoard.h | 4 ++ src/hw/dmi/DmiMemory.cpp | 26 +++++++++++ src/hw/dmi/DmiMemory.h | 4 ++ src/hw/dmi/DmiReader.cpp | 34 ++++++++++++++ src/hw/dmi/DmiReader.h | 5 ++ 17 files changed, 263 insertions(+), 74 deletions(-) create mode 100644 src/hw/api/HwApi.cpp create mode 100644 src/hw/api/HwApi.h create mode 100644 src/hw/api/api.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index fe411cb1..79486e03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,7 +198,8 @@ if (WITH_EMBEDDED_CONFIG) add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG) endif() -include (src/hw/dmi/dmi.cmake) +include(src/hw/api/api.cmake) +include(src/hw/dmi/dmi.cmake) include_directories(src) include_directories(src/3rdparty) 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/core/Controller.cpp b/src/core/Controller.cpp index 8f230e00..40c3aeac 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; } @@ -64,7 +67,7 @@ void xmrig::Controller::start() { Base::start(); - m_miner = new Miner(this); + m_miner = std::make_shared(this); network()->connect(); } @@ -74,29 +77,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 94708473..13704f15 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; @@ -55,8 +52,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/hw/api/HwApi.cpp b/src/hw/api/HwApi.cpp new file mode 100644 index 00000000..5aedbf33 --- /dev/null +++ b/src/hw/api/HwApi.cpp @@ -0,0 +1,47 @@ +/* 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" + +#include "base/io/log/Log.h" // FIXME + + +#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 index 5ebfd9aa..3cbe3dd9 100644 --- a/src/hw/dmi/DmiBoard.cpp +++ b/src/hw/dmi/DmiBoard.cpp @@ -20,6 +20,7 @@ #include "hw/dmi/DmiBoard.h" +#include "3rdparty/rapidjson/document.h" #include "hw/dmi/DmiTools.h" @@ -32,3 +33,18 @@ void xmrig::DmiBoard::decode(dmi_header *h) 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 index dd28a607..0c64da17 100644 --- a/src/hw/dmi/DmiBoard.h +++ b/src/hw/dmi/DmiBoard.h @@ -42,6 +42,10 @@ public: void decode(dmi_header *h); +# ifdef XMRIG_FEATURE_API + rapidjson::Value toJSON(rapidjson::Document &doc) const; +# endif + private: String m_product; String m_vendor; diff --git a/src/hw/dmi/DmiMemory.cpp b/src/hw/dmi/DmiMemory.cpp index f02a64ec..5b36e2ba 100644 --- a/src/hw/dmi/DmiMemory.cpp +++ b/src/hw/dmi/DmiMemory.cpp @@ -20,6 +20,7 @@ #include "hw/dmi/DmiMemory.h" +#include "3rdparty/rapidjson/document.h" #include "hw/dmi/DmiTools.h" @@ -190,3 +191,28 @@ 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 index b9a0468b..badee2cf 100644 --- a/src/hw/dmi/DmiMemory.h +++ b/src/hw/dmi/DmiMemory.h @@ -52,6 +52,10 @@ public: 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; diff --git a/src/hw/dmi/DmiReader.cpp b/src/hw/dmi/DmiReader.cpp index 9854ff1b..18211759 100644 --- a/src/hw/dmi/DmiReader.cpp +++ b/src/hw/dmi/DmiReader.cpp @@ -20,6 +20,8 @@ #include "hw/dmi/DmiReader.h" +#include "3rdparty/fmt/core.h" +#include "3rdparty/rapidjson/document.h" #include "hw/dmi/DmiTools.h" @@ -38,6 +40,38 @@ static void dmi_get_header(dmi_header *h, uint8_t *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); diff --git a/src/hw/dmi/DmiReader.h b/src/hw/dmi/DmiReader.h index ccf2311a..a4f7eb8a 100644 --- a/src/hw/dmi/DmiReader.h +++ b/src/hw/dmi/DmiReader.h @@ -45,6 +45,11 @@ public: 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; From ef8cc28f3f250eb3adcd380a3da253a83102ab8d Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 21 Jan 2021 23:22:01 +0700 Subject: [PATCH 14/27] Added DMI data to online benchmark. --- src/base/net/stratum/Pools.cpp | 6 +++--- src/base/net/stratum/Pools.h | 4 ++-- src/base/net/stratum/benchmark/BenchClient.cpp | 17 +++++++++++++++-- src/base/net/stratum/benchmark/BenchClient.h | 4 ++-- src/base/net/stratum/benchmark/BenchConfig.cpp | 11 ++++++----- src/base/net/stratum/benchmark/BenchConfig.h | 10 ++++++---- src/hw/api/HwApi.cpp | 2 -- 7 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index a9c245fa..d2ab3012 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/hw/api/HwApi.cpp b/src/hw/api/HwApi.cpp index 5aedbf33..fed5de3f 100644 --- a/src/hw/api/HwApi.cpp +++ b/src/hw/api/HwApi.cpp @@ -21,8 +21,6 @@ #include "base/api/interfaces/IApiRequest.h" #include "base/tools/String.h" -#include "base/io/log/Log.h" // FIXME - #ifdef XMRIG_FEATURE_DMI # include "hw/dmi/DmiReader.h" From c8588903e37f356b9d55ba5d304b3534d0ab1c04 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 22 Jan 2021 00:12:34 +0700 Subject: [PATCH 15/27] Enable DMI reader by default. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 79486e03..6a927ab7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,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" 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) From 3b7d30a91d513fad9812ddfebb20f7866ba8479b Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 22 Jan 2021 00:27:38 +0700 Subject: [PATCH 16/27] v6.8.0-dev --- src/version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/version.h b/src/version.h index 0e91cd2e..81fa0366 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.3-dev" +#define APP_VERSION "6.8.0-dev" #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 3 +#define APP_VER_MINOR 8 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From 6bab6248858edede0ba12e07fe423af8985494d7 Mon Sep 17 00:00:00 2001 From: GoDzM4TT3O Date: Fri, 22 Jan 2021 14:18:28 +0100 Subject: [PATCH 17/27] Add missing "cstdio" library Compilation fails if the above library is missing. This fixes a compilation error. --- src/hw/dmi/DmiReader_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hw/dmi/DmiReader_unix.cpp b/src/hw/dmi/DmiReader_unix.cpp index ff57b7a6..e01e2262 100644 --- a/src/hw/dmi/DmiReader_unix.cpp +++ b/src/hw/dmi/DmiReader_unix.cpp @@ -29,7 +29,7 @@ #include #include #include - +#include #ifdef __FreeBSD__ # include From c48e2e6af8ec16350f95b3871967cd8a9bfdce7e Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 22 Jan 2021 23:50:25 +0700 Subject: [PATCH 18/27] Added new class Msr. --- cmake/randomx.cmake | 15 +- src/crypto/rx/RxConfig.h | 2 +- src/hw/msr/Msr.cpp | 70 +++++++++ src/hw/msr/Msr.h | 61 ++++++++ src/{crypto/rx => hw}/msr/MsrItem.cpp | 14 +- src/{crypto/rx => hw}/msr/MsrItem.h | 15 +- src/hw/msr/Msr_linux.cpp | 86 +++++++++++ src/hw/msr/Msr_win.cpp | 204 ++++++++++++++++++++++++++ 8 files changed, 438 insertions(+), 29 deletions(-) create mode 100644 src/hw/msr/Msr.cpp create mode 100644 src/hw/msr/Msr.h rename src/{crypto/rx => hw}/msr/MsrItem.cpp (69%) rename src/{crypto/rx => hw}/msr/MsrItem.h (70%) create mode 100644 src/hw/msr/Msr_linux.cpp create mode 100644 src/hw/msr/Msr_win.cpp diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index 5d44e05f..56c8cc18 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -100,13 +100,20 @@ if (WITH_RANDOMX) message("-- WITH_MSR=ON") if (XMRIG_OS_WIN) - list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_win.cpp) + list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_win.cpp src/hw/msr/Msr_win.cpp) elseif (XMRIG_OS_LINUX) - list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_linux.cpp) + list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_linux.cpp src/hw/msr/Msr_linux.cpp) endif() - list(APPEND HEADERS_CRYPTO src/crypto/rx/msr/MsrItem.h) - list(APPEND SOURCES_CRYPTO src/crypto/rx/msr/MsrItem.cpp) + list(APPEND HEADERS_CRYPTO + src/hw/msr/Msr.h + src/hw/msr/MsrItem.h + ) + + list(APPEND SOURCES_CRYPTO + src/hw/msr/Msr.cpp + src/hw/msr/MsrItem.cpp + ) else() remove_definitions(/DXMRIG_FEATURE_MSR) remove_definitions(/DXMRIG_FIX_RYZEN) diff --git a/src/crypto/rx/RxConfig.h b/src/crypto/rx/RxConfig.h index 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/hw/msr/Msr.cpp b/src/hw/msr/Msr.cpp new file mode 100644 index 00000000..68c60e6e --- /dev/null +++ b/src/hw/msr/Msr.cpp @@ -0,0 +1,70 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "hw/msr/Msr.h" +#include "base/io/log/Log.h" + + +namespace xmrig { + + +static const char *kTag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr "); +static std::weak_ptr instance; + + +} // namespace xmrig + + + +const char *xmrig::Msr::tag() +{ + return kTag; +} + + + +std::shared_ptr xmrig::Msr::get() +{ + auto msr = instance.lock(); + if (!msr) { + msr = std::make_shared(); + instance = msr; + } + + if (msr->isAvailable()) { + return msr; + } + + return {}; +} + + +xmrig::MsrItem xmrig::Msr::read(uint32_t reg, int32_t cpu, bool verbose) const +{ + uint64_t value = 0; + if (rdmsr(reg, cpu, value)) { + return { reg, value }; + } + + if (verbose) { + LOG_WARN("%s " YELLOW_BOLD("cannot read MSR 0x%08" PRIx32), tag(), reg); + } + + return {}; +} diff --git a/src/hw/msr/Msr.h b/src/hw/msr/Msr.h new file mode 100644 index 00000000..5f325a25 --- /dev/null +++ b/src/hw/msr/Msr.h @@ -0,0 +1,61 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_MSR_H +#define XMRIG_MSR_H + + +#include "base/tools/Object.h" +#include "hw/msr/MsrItem.h" + + +#include + + +namespace xmrig +{ + + +class MsrPrivate; + + +class Msr +{ +public: + XMRIG_DISABLE_COPY_MOVE(Msr) + + Msr(); + ~Msr(); + + static const char *tag(); + static std::shared_ptr get(); + + bool isAvailable() const; + MsrItem read(uint32_t reg, int32_t cpu = -1, bool verbose = true) const; + +private: + bool rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const; + + MsrPrivate *d_ptr = nullptr; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_MSR_H */ diff --git a/src/crypto/rx/msr/MsrItem.cpp b/src/hw/msr/MsrItem.cpp similarity index 69% rename from src/crypto/rx/msr/MsrItem.cpp rename to src/hw/msr/MsrItem.cpp index 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..ad3c9d39 100644 --- a/src/crypto/rx/msr/MsrItem.h +++ b/src/hw/msr/MsrItem.h @@ -1,14 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2019 XMR-Stak , - * Copyright 2018 Lee Clagett - * Copyright 2018-2019 tevador - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,9 +31,6 @@ namespace xmrig { -class RxDataset; - - class MsrItem { public: diff --git a/src/hw/msr/Msr_linux.cpp b/src/hw/msr/Msr_linux.cpp new file mode 100644 index 00000000..02a29c72 --- /dev/null +++ b/src/hw/msr/Msr_linux.cpp @@ -0,0 +1,86 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "hw/msr/Msr.h" +#include "3rdparty/fmt/core.h" +#include "base/io/log/Log.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace xmrig { + + +class MsrPrivate +{ +public: + bool available = true; +}; + + +} // namespace xmrig + + +xmrig::Msr::Msr() : d_ptr(new MsrPrivate()) +{ + if (system("/sbin/modprobe msr allow_writes=on > /dev/null 2>&1") != 0) { + LOG_WARN("%s " YELLOW_BOLD("msr kernel module is not available"), Msr::tag()); + + d_ptr->available = false; + } +} + + +xmrig::Msr::~Msr() +{ + delete d_ptr; +} + + +bool xmrig::Msr::isAvailable() const +{ + return d_ptr->available; +} + + +bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const +{ + const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? 0 : cpu); + const int fd = open(name.c_str(), O_RDONLY); + + if (fd < 0) { + return false; + } + + const bool success = pread(fd, &value, sizeof value, reg) == sizeof value; + close(fd); + + return success; +} diff --git a/src/hw/msr/Msr_win.cpp b/src/hw/msr/Msr_win.cpp new file mode 100644 index 00000000..d055785c --- /dev/null +++ b/src/hw/msr/Msr_win.cpp @@ -0,0 +1,204 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "hw/msr/Msr.h" +#include "base/io/log/Log.h" + + +#include +#include +#include + + +#define SERVICE_NAME L"WinRing0_1_2_0" +#define IOCTL_READ_MSR CTL_CODE(40000, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +namespace xmrig { + + +static const wchar_t *kServiceName = SERVICE_NAME; + + +class MsrPrivate +{ +public: + bool uninstall() + { + if (driver != INVALID_HANDLE_VALUE) { + CloseHandle(driver); + } + + if (!service) { + return true; + } + + bool result = true; + + if (!reuse) { + SERVICE_STATUS serviceStatus; + + if (!ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus)) { + result = false; + } + + if (!DeleteService(service)) { + LOG_ERR("%s " RED("failed to remove WinRing0 driver, error %u"), Msr::tag(), GetLastError()); + result = false; + } + } + + CloseServiceHandle(service); + service = nullptr; + + return result; + } + + + bool reuse = false; + HANDLE driver = INVALID_HANDLE_VALUE; + SC_HANDLE manager = nullptr; + SC_HANDLE service = nullptr; +}; + + +} // namespace xmrig + + +xmrig::Msr::Msr() : d_ptr(new MsrPrivate()) +{ + DWORD err = 0; + + d_ptr->manager = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); + if (!d_ptr->manager) { + if ((err = GetLastError()) == ERROR_ACCESS_DENIED) { + LOG_WARN("%s " YELLOW_BOLD("to access MSR registers Administrator privileges required."), tag()); + } + else { + LOG_ERR("%s " RED("failed to open service control manager, error %u"), tag(), err); + } + + return; + } + + std::vector dir; + + do { + dir.resize(dir.empty() ? MAX_PATH : dir.size() * 2); + GetModuleFileNameW(nullptr, dir.data(), dir.size()); + err = GetLastError(); + } while (err == ERROR_INSUFFICIENT_BUFFER); + + if (err != ERROR_SUCCESS) { + LOG_ERR("%s " RED("failed to get path to driver, error %u"), tag(), err); + return; + } + + for (auto it = dir.end() - 1; it != dir.begin(); --it) { + if ((*it == L'\\') || (*it == L'/')) { + ++it; + *it = L'\0'; + break; + } + } + + const std::wstring path = std::wstring(dir.data()) + L"WinRing0x64.sys"; + + d_ptr->service = OpenServiceW(d_ptr->manager, kServiceName, SERVICE_ALL_ACCESS); + if (d_ptr->service) { + LOG_WARN("%s " YELLOW("service ") YELLOW_BOLD("WinRing0_1_2_0") YELLOW(" already exists"), tag()); + + SERVICE_STATUS status; + const auto rc = QueryServiceStatus(d_ptr->service, &status); + + if (rc) { + DWORD dwBytesNeeded = 0; + + QueryServiceConfigA(d_ptr->service, nullptr, 0, &dwBytesNeeded); + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + std::vector buffer(dwBytesNeeded); + auto config = reinterpret_cast(buffer.data()); + + if (QueryServiceConfigA(d_ptr->service, config, buffer.size(), &dwBytesNeeded)) { + LOG_INFO("%s " YELLOW("service path: ") YELLOW_BOLD("\"%s\""), tag(), config->lpBinaryPathName); + } + } + } + + if (rc && status.dwCurrentState == SERVICE_RUNNING) { + d_ptr->reuse = true; + } + else if (!d_ptr->uninstall()) { + return; + } + } + + if (!d_ptr->reuse) { + d_ptr->service = CreateServiceW(d_ptr->manager, kServiceName, kServiceName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr); + if (!d_ptr->service) { + LOG_ERR("%s " RED("failed to install WinRing0 driver, error %u"), tag(), GetLastError()); + + return; + } + + if (!StartService(d_ptr->service, 0, nullptr)) { + err = GetLastError(); + if (err != ERROR_SERVICE_ALREADY_RUNNING) { + if (err == ERROR_FILE_NOT_FOUND) { + LOG_ERR("%s " RED("failed to start WinRing0 driver: ") RED_BOLD("\"WinRing0x64.sys not found\""), tag()); + } + else { + LOG_ERR("%s " RED("failed to start WinRing0 driver, error %u"), tag(), err); + } + + d_ptr->uninstall(); + + return; + } + } + } + + d_ptr->driver = CreateFileW(L"\\\\.\\" SERVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (d_ptr->driver == INVALID_HANDLE_VALUE) { + LOG_ERR("%s " RED("failed to connect to WinRing0 driver, error %u"), tag(), GetLastError());; + } +} + + +xmrig::Msr::~Msr() +{ + d_ptr->uninstall(); + + delete d_ptr; +} + + +bool xmrig::Msr::isAvailable() const +{ + return d_ptr->driver != INVALID_HANDLE_VALUE; +} + + +bool xmrig::Msr::rdmsr(uint32_t reg, int32_t, uint64_t &value) const +{ + DWORD size = 0; + + return DeviceIoControl(d_ptr->driver, IOCTL_READ_MSR, ®, sizeof(reg), &value, sizeof(value), &size, nullptr) != 0; +} From b9d813c40303425387b92158d2b1213b745e0aef Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 23 Jan 2021 00:27:56 +0700 Subject: [PATCH 19/27] Move Ryzen related fixes to RxFix class. --- cmake/randomx.cmake | 13 ++++- src/crypto/randomx/jit_compiler_x86.cpp | 8 +-- src/crypto/rx/Rx.cpp | 14 ++++- src/crypto/rx/Rx.h | 9 +-- src/crypto/rx/RxFix.h | 42 ++++++++++++++ src/crypto/rx/RxFix_linux.cpp | 71 ++++++++++++++++++++++++ src/crypto/rx/RxFix_win.cpp | 74 +++++++++++++++++++++++++ src/crypto/rx/Rx_linux.cpp | 41 -------------- src/crypto/rx/Rx_win.cpp | 45 --------------- 9 files changed, 215 insertions(+), 102 deletions(-) create mode 100644 src/crypto/rx/RxFix.h create mode 100644 src/crypto/rx/RxFix_linux.cpp create mode 100644 src/crypto/rx/RxFix_win.cpp diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index 56c8cc18..83c8e5b3 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -100,12 +100,21 @@ if (WITH_RANDOMX) message("-- WITH_MSR=ON") if (XMRIG_OS_WIN) - list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_win.cpp src/hw/msr/Msr_win.cpp) + list(APPEND SOURCES_CRYPTO + src/crypto/rx/Rx_win.cpp + src/hw/msr/Msr_win.cpp + src/crypto/rx/RxFix_win.cpp + ) elseif (XMRIG_OS_LINUX) - list(APPEND SOURCES_CRYPTO src/crypto/rx/Rx_linux.cpp src/hw/msr/Msr_linux.cpp) + list(APPEND SOURCES_CRYPTO + src/crypto/rx/Rx_linux.cpp + src/hw/msr/Msr_linux.cpp + src/crypto/rx/RxFix_linux.cpp + ) endif() list(APPEND HEADERS_CRYPTO + src/crypto/rx/RxFix.h src/hw/msr/Msr.h src/hw/msr/MsrItem.h ) diff --git a/src/crypto/randomx/jit_compiler_x86.cpp b/src/crypto/randomx/jit_compiler_x86.cpp index 8c3145b2..17227c34 100644 --- a/src/crypto/randomx/jit_compiler_x86.cpp +++ b/src/crypto/randomx/jit_compiler_x86.cpp @@ -1,7 +1,7 @@ /* Copyright (c) 2018-2020, tevador -Copyright (c) 2019-2020, SChernykh -Copyright (c) 2019-2020, XMRig , +Copyright (c) 2019-2021, SChernykh +Copyright (c) 2019-2021, XMRig , All rights reserved. @@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "crypto/rx/Profiler.h" #ifdef XMRIG_FIX_RYZEN -# include "crypto/rx/Rx.h" +# include "crypto/rx/RxFix.h" #endif #ifdef _MSC_VER @@ -427,7 +427,7 @@ namespace randomx { } # ifdef XMRIG_FIX_RYZEN - xmrig::Rx::setMainLoopBounds(mainLoopBounds); + xmrig::RxFix::setMainLoopBounds(mainLoopBounds); # endif memcpy(code + prologueSize - 48, &pcfg.eMask, sizeof(pcfg.eMask)); diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index 40d3c612..99ca6b0a 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2018-2019 tevador - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,11 @@ #include "crypto/randomx/aes_hash.hpp" +#ifdef XMRIG_FIX_RYZEN +# include "crypto/rx/RxFix.h" +#endif + + namespace xmrig { @@ -104,7 +109,10 @@ bool xmrig::Rx::init(const T &seed, const RxConfig &config, const CpuConfig &cpu } if (!osInitialized) { - setupMainLoopExceptionFrame(); +# ifdef XMRIG_FIX_RYZEN + RxFix::setupMainLoopExceptionFrame(); +# endif + if (!cpu.isHwAES()) { SelectSoftAESImpl(cpu.threads().get(seed.algorithm()).count()); } diff --git a/src/crypto/rx/Rx.h b/src/crypto/rx/Rx.h index 42bd0c15..a93f7449 100644 --- a/src/crypto/rx/Rx.h +++ b/src/crypto/rx/Rx.h @@ -1,7 +1,7 @@ /* XMRig * Copyright (c) 2018-2019 tevador - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,10 +52,6 @@ public: template static bool init(const T &seed, const RxConfig &config, const CpuConfig &cpu); template static bool isReady(const T &seed); -# ifdef XMRIG_FIX_RYZEN - static void setMainLoopBounds(const std::pair& bounds); -# endif - # ifdef XMRIG_FEATURE_MSR static bool isMSR(); # else @@ -65,7 +61,6 @@ public: private: static bool msrInit(const RxConfig &config, const std::vector& threads); static void msrDestroy(); - static void setupMainLoopExceptionFrame(); }; diff --git a/src/crypto/rx/RxFix.h b/src/crypto/rx/RxFix.h new file mode 100644 index 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/Rx_linux.cpp b/src/crypto/rx/Rx_linux.cpp index 6228825b..e7398002 100644 --- a/src/crypto/rx/Rx_linux.cpp +++ b/src/crypto/rx/Rx_linux.cpp @@ -37,8 +37,6 @@ #include #include #include -#include -#include namespace xmrig { @@ -235,33 +233,6 @@ static bool wrmsr(const MsrItems& preset, const std::vector& threads, } -#ifdef XMRIG_FIX_RYZEN -static thread_local std::pair mainLoopBounds = { nullptr, nullptr }; - -static void MainLoopHandler(int sig, siginfo_t *info, void *ucontext) -{ - ucontext_t *ucp = (ucontext_t*) ucontext; - - LOG_VERBOSE(YELLOW_BOLD("%s at %p"), (sig == SIGSEGV) ? "SIGSEGV" : "SIGILL", ucp->uc_mcontext.gregs[REG_RIP]); - - void* p = reinterpret_cast(ucp->uc_mcontext.gregs[REG_RIP]); - const std::pair& loopBounds = mainLoopBounds; - - if ((loopBounds.first <= p) && (p < loopBounds.second)) { - ucp->uc_mcontext.gregs[REG_RIP] = reinterpret_cast(loopBounds.second); - } - else { - abort(); - } -} - -void Rx::setMainLoopBounds(const std::pair& bounds) -{ - mainLoopBounds = bounds; -} -#endif - - } // namespace xmrig @@ -299,15 +270,3 @@ void xmrig::Rx::msrDestroy() LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts); } } - - -void xmrig::Rx::setupMainLoopExceptionFrame() -{ -# ifdef XMRIG_FIX_RYZEN - struct sigaction act = {}; - act.sa_sigaction = MainLoopHandler; - act.sa_flags = SA_RESTART | SA_SIGINFO; - sigaction(SIGSEGV, &act, nullptr); - sigaction(SIGILL, &act, nullptr); -# endif -} diff --git a/src/crypto/rx/Rx_win.cpp b/src/crypto/rx/Rx_win.cpp index d131822f..36e13819 100644 --- a/src/crypto/rx/Rx_win.cpp +++ b/src/crypto/rx/Rx_win.cpp @@ -348,43 +348,6 @@ static bool wrmsr(const MsrItems &preset, const std::vector& threads, } -#ifdef XMRIG_FIX_RYZEN -static thread_local std::pair mainLoopBounds = { nullptr, nullptr }; - -static LONG WINAPI MainLoopHandler(_EXCEPTION_POINTERS *ExceptionInfo) -{ - if (ExceptionInfo->ExceptionRecord->ExceptionCode == 0xC0000005) { - const char* accessType; - switch (ExceptionInfo->ExceptionRecord->ExceptionInformation[0]) { - case 0: accessType = "read"; break; - case 1: accessType = "write"; break; - case 8: accessType = "DEP violation"; break; - default: accessType = "unknown"; break; - } - LOG_VERBOSE(YELLOW_BOLD("[THREAD %u] Access violation at 0x%p: %s at address 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionAddress, accessType, ExceptionInfo->ExceptionRecord->ExceptionInformation[1]); - } - else { - LOG_VERBOSE(YELLOW_BOLD("[THREAD %u] Exception 0x%08X at 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); - } - - void* p = reinterpret_cast(ExceptionInfo->ContextRecord->Rip); - const std::pair& loopBounds = mainLoopBounds; - - if ((loopBounds.first <= p) && (p < loopBounds.second)) { - ExceptionInfo->ContextRecord->Rip = reinterpret_cast(loopBounds.second); - return EXCEPTION_CONTINUE_EXECUTION; - } - - return EXCEPTION_CONTINUE_SEARCH; -} - -void Rx::setMainLoopBounds(const std::pair& bounds) -{ - mainLoopBounds = bounds; -} -#endif - - } // namespace xmrig @@ -421,11 +384,3 @@ void xmrig::Rx::msrDestroy() LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts); } } - - -void xmrig::Rx::setupMainLoopExceptionFrame() -{ -# ifdef XMRIG_FIX_RYZEN - AddVectoredExceptionHandler(1, MainLoopHandler); -# endif -} From 9dae559b73726b53469bd67a1b8b341c2927565f Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 23 Jan 2021 23:23:39 +0700 Subject: [PATCH 20/27] Added RxMsr class. --- cmake/randomx.cmake | 8 +- src/backend/cpu/interfaces/ICpuInfo.h | 11 +- src/backend/cpu/platform/BasicCpuInfo.cpp | 9 +- src/backend/cpu/platform/BasicCpuInfo.h | 61 ++-- src/backend/cpu/platform/HwlocCpuInfo.cpp | 24 +- src/backend/cpu/platform/HwlocCpuInfo.h | 6 +- src/crypto/rx/Rx.cpp | 45 +-- src/crypto/rx/Rx.h | 4 - src/crypto/rx/RxMsr.cpp | 184 +++++++++++ src/crypto/rx/RxMsr.h | 53 +++ src/crypto/rx/Rx_linux.cpp | 272 --------------- src/crypto/rx/Rx_win.cpp | 386 ---------------------- src/hw/msr/Msr.cpp | 18 + src/hw/msr/Msr.h | 8 + src/hw/msr/MsrItem.h | 5 + src/hw/msr/Msr_linux.cpp | 34 +- src/hw/msr/Msr_win.cpp | 53 ++- 17 files changed, 435 insertions(+), 746 deletions(-) create mode 100644 src/crypto/rx/RxMsr.cpp create mode 100644 src/crypto/rx/RxMsr.h delete mode 100644 src/crypto/rx/Rx_linux.cpp delete mode 100644 src/crypto/rx/Rx_win.cpp diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index 83c8e5b3..976f1186 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -101,25 +101,25 @@ if (WITH_RANDOMX) if (XMRIG_OS_WIN) list(APPEND SOURCES_CRYPTO - src/crypto/rx/Rx_win.cpp - src/hw/msr/Msr_win.cpp src/crypto/rx/RxFix_win.cpp + src/hw/msr/Msr_win.cpp ) elseif (XMRIG_OS_LINUX) list(APPEND SOURCES_CRYPTO - src/crypto/rx/Rx_linux.cpp - src/hw/msr/Msr_linux.cpp src/crypto/rx/RxFix_linux.cpp + src/hw/msr/Msr_linux.cpp ) endif() list(APPEND HEADERS_CRYPTO src/crypto/rx/RxFix.h + src/crypto/rx/RxMsr.h src/hw/msr/Msr.h src/hw/msr/MsrItem.h ) list(APPEND SOURCES_CRYPTO + src/crypto/rx/RxMsr.cpp src/hw/msr/Msr.cpp src/hw/msr/MsrItem.cpp ) diff --git a/src/backend/cpu/interfaces/ICpuInfo.h b/src/backend/cpu/interfaces/ICpuInfo.h index 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 2a4dc829..bcf77e92 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/HwlocCpuInfo.cpp b/src/backend/cpu/platform/HwlocCpuInfo.cpp index 6a684124..8b1c4536 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.cpp +++ b/src/backend/cpu/platform/HwlocCpuInfo.cpp @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -170,7 +170,8 @@ xmrig::HwlocCpuInfo::HwlocCpuInfo() findCache(root, 2, 3, [this](hwloc_obj_t found) { this->m_cache[found->attr->cache.depth] += found->attr->cache.size; }); - m_threads = countByType(m_topology, HWLOC_OBJ_PU); + setThreads(countByType(m_topology, HWLOC_OBJ_PU)); + m_cores = countByType(m_topology, HWLOC_OBJ_CORE); m_nodes = std::max(hwloc_bitmap_weight(hwloc_topology_get_complete_nodeset(m_topology)), 1); m_packages = countByType(m_topology, HWLOC_OBJ_PACKAGE); @@ -395,3 +396,20 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith } # endif } + + +void xmrig::HwlocCpuInfo::setThreads(size_t threads) +{ + m_threads = threads; + + if (m_units.size() != m_threads) { + m_units.resize(m_threads); + } + + hwloc_obj_t pu = nullptr; + size_t i = 0; + + while ((pu = hwloc_get_next_obj_by_type(m_topology, HWLOC_OBJ_PU, pu)) != nullptr) { + m_units[i++] = static_cast(pu->os_index); + } +} diff --git a/src/backend/cpu/platform/HwlocCpuInfo.h b/src/backend/cpu/platform/HwlocCpuInfo.h index 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/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index 99ca6b0a..a485b382 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -27,8 +27,9 @@ #include "crypto/randomx/aes_hash.hpp" -#ifdef XMRIG_FIX_RYZEN +#ifdef XMRIG_FEATURE_MSR # include "crypto/rx/RxFix.h" +# include "crypto/rx/RxMsr.h" #endif @@ -39,8 +40,6 @@ class RxPrivate; static bool osInitialized = false; -static bool msrInitialized = false; -static bool msrEnabled = false; static RxPrivate *d_ptr = nullptr; @@ -70,9 +69,9 @@ xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId) void xmrig::Rx::destroy() { - if (osInitialized) { - msrDestroy(); - } +# ifdef XMRIG_FEATURE_MSR + RxMsr::destroy(); +# endif delete d_ptr; @@ -90,11 +89,9 @@ template bool xmrig::Rx::init(const T &seed, const RxConfig &config, const CpuConfig &cpu) { if (seed.algorithm().family() != Algorithm::RANDOM_X) { - if (msrInitialized) { - msrDestroy(); - msrInitialized = false; - msrEnabled = false; - } +# ifdef XMRIG_FEATURE_MSR + RxMsr::destroy(); +# endif return true; } @@ -103,10 +100,11 @@ bool xmrig::Rx::init(const T &seed, const RxConfig &config, const CpuConfig &cpu randomx_set_huge_pages_jit(cpu.isHugePagesJit()); randomx_set_optimized_dataset_init(config.initDatasetAVX2()); - if (!msrInitialized) { - msrEnabled = msrInit(config, cpu.threads().get(seed.algorithm()).data()); - msrInitialized = true; +# ifdef XMRIG_FEATURE_MSR + if (!RxMsr::isInitialized()) { + RxMsr::init(config, cpu.threads().get(seed.algorithm()).data()); } +# endif if (!osInitialized) { # ifdef XMRIG_FIX_RYZEN @@ -139,24 +137,7 @@ bool xmrig::Rx::isReady(const T &seed) #ifdef XMRIG_FEATURE_MSR bool xmrig::Rx::isMSR() { - return msrEnabled; -} -#else -bool xmrig::Rx::msrInit(const RxConfig &, const std::vector &) -{ - return false; -} - - -void xmrig::Rx::msrDestroy() -{ -} -#endif - - -#ifndef XMRIG_FIX_RYZEN -void xmrig::Rx::setupMainLoopExceptionFrame() -{ + return RxMsr::isEnabled(); } #endif diff --git a/src/crypto/rx/Rx.h b/src/crypto/rx/Rx.h index a93f7449..af804706 100644 --- a/src/crypto/rx/Rx.h +++ b/src/crypto/rx/Rx.h @@ -57,10 +57,6 @@ public: # else static constexpr bool isMSR() { return false; } # endif - -private: - static bool msrInit(const RxConfig &config, const std::vector& threads); - static void msrDestroy(); }; diff --git a/src/crypto/rx/RxMsr.cpp b/src/crypto/rx/RxMsr.cpp new file mode 100644 index 00000000..6083e9b3 --- /dev/null +++ b/src/crypto/rx/RxMsr.cpp @@ -0,0 +1,184 @@ +/* XMRig + * Copyright (c) 2018-2019 tevador + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "crypto/rx/RxMsr.h" +#include "backend/cpu/Cpu.h" +#include "backend/cpu/CpuThread.h" +#include "base/io/log/Log.h" +#include "base/tools/Chrono.h" +#include "crypto/rx/RxConfig.h" +#include "hw/msr/Msr.h" + + +#include +#include + + +namespace xmrig { + + +bool RxMsr::m_enabled = false; +bool RxMsr::m_initialized = false; + + +static MsrItems items; + + +#ifdef XMRIG_OS_WIN +static constexpr inline int32_t get_cpu(int32_t) { return -1; } +#else +static constexpr inline int32_t get_cpu(int32_t cpu) { return cpu; } +#endif + + +static bool wrmsr(const MsrItems &preset, const std::vector &threads, bool cache_qos, bool save) +{ + auto msr = Msr::get(); + if (!msr) { + return false; + } + + if (save) { + items.reserve(preset.size()); + + for (const auto &i : preset) { + auto item = msr->read(i.reg()); + if (!item.isValid()) { + items.clear(); + + return false; + } + + LOG_VERBOSE("%s " CYAN_BOLD("0x%08" PRIx32) CYAN(":0x%016" PRIx64) CYAN_BOLD(" -> 0x%016" PRIx64), Msr::tag(), i.reg(), item.value(), MsrItem::maskedValue(item.value(), i.value(), i.mask())); + + items.emplace_back(item); + } + } + + // Which CPU cores will have access to the full L3 cache + std::set cacheEnabled; + bool cacheQoSDisabled = threads.empty(); + + if (cache_qos) { + const auto &units = Cpu::info()->units(); + + for (const auto &t : threads) { + const auto affinity = static_cast(t.affinity()); + + // If some thread has no affinity or wrong affinity, disable cache QoS + if (affinity < 0 || std::find(units.begin(), units.end(), affinity) == units.end()) { + cacheQoSDisabled = true; + + LOG_WARN("%s " YELLOW_BOLD("cache QoS can only be enabled when all mining threads have affinity set"), Msr::tag()); + break; + } + + cacheEnabled.insert(affinity); + } + } + + return msr->write([&msr, &preset, cache_qos, &cacheEnabled, cacheQoSDisabled](int32_t cpu) { + for (const auto &item : preset) { + if (!msr->write(item, get_cpu(cpu))) { + return false; + } + } + + if (!cache_qos) { + return true; + } + + // Assign Class Of Service 0 to current CPU core (default, full L3 cache available) + if (cacheQoSDisabled || cacheEnabled.count(cpu)) { + return msr->write(0xC8F, 0, get_cpu(cpu)); + } + + // Disable L3 cache for Class Of Service 1 + if (!msr->write(0xC91, 0, get_cpu(cpu))) { + // Some CPUs don't let set it to all zeros + if (!msr->write(0xC91, 1, get_cpu(cpu))) { + return false; + } + } + + // Assign Class Of Service 1 to current CPU core + return msr->write(0xC8F, 1ULL << 32, get_cpu(cpu)); + }); +} + + +} // namespace xmrig + + +bool xmrig::RxMsr::init(const RxConfig &config, const std::vector &threads) +{ + if (isInitialized()) { + return isEnabled(); + } + + m_initialized = true; + m_enabled = false; + + const auto &preset = config.msrPreset(); + if (preset.empty()) { + return false; + } + + const uint64_t ts = Chrono::steadyMSecs(); + bool cache_qos = config.cacheQoS(); + + if (cache_qos && !Cpu::info()->hasCatL3()) { + if (!threads.empty()) { + LOG_WARN("%s " YELLOW_BOLD("this CPU doesn't support cat_l3, cache QoS is unavailable"), Msr::tag()); + } + + cache_qos = false; + } + + if ((m_enabled = wrmsr(preset, threads, cache_qos, config.rdmsr()))) { + LOG_NOTICE("%s " GREEN_BOLD("register values for \"%s\" preset have been set successfully") BLACK_BOLD(" (%" PRIu64 " ms)"), Msr::tag(), config.msrPresetName(), Chrono::steadyMSecs() - ts); + } + else { + LOG_ERR("%s " RED_BOLD("FAILED TO APPLY MSR MOD, HASHRATE WILL BE LOW"), Msr::tag()); + } + + return isEnabled(); +} + + +void xmrig::RxMsr::destroy() +{ + if (!isInitialized()) { + return; + } + + m_initialized = false; + m_enabled = false; + + if (items.empty()) { + return; + } + + const uint64_t ts = Chrono::steadyMSecs(); + + if (!wrmsr(items, std::vector(), true, false)) { + LOG_ERR("%s " RED_BOLD("failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)")), Msr::tag(), Chrono::steadyMSecs() - ts); + } +} diff --git a/src/crypto/rx/RxMsr.h b/src/crypto/rx/RxMsr.h new file mode 100644 index 00000000..870e298c --- /dev/null +++ b/src/crypto/rx/RxMsr.h @@ -0,0 +1,53 @@ +/* XMRig + * Copyright (c) 2018-2019 tevador + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_RXMSR_H +#define XMRIG_RXMSR_H + + +#include + + +namespace xmrig +{ + + +class CpuThread; +class RxConfig; + + +class RxMsr +{ +public: + static inline bool isEnabled() { return m_enabled; } + static inline bool isInitialized() { return m_initialized; } + + static bool init(const RxConfig &config, const std::vector &threads); + static void destroy(); + +private: + static bool m_enabled; + static bool m_initialized; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_RXMSR_H */ diff --git a/src/crypto/rx/Rx_linux.cpp b/src/crypto/rx/Rx_linux.cpp deleted file mode 100644 index e7398002..00000000 --- a/src/crypto/rx/Rx_linux.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* XMRig - * Copyright (c) 2018-2019 tevador - * Copyright (c) 2000 Transmeta Corporation - * Copyright (c) 2004-2008 H. Peter Anvin - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "crypto/rx/Rx.h" -#include "backend/cpu/Cpu.h" -#include "backend/cpu/CpuThread.h" -#include "base/io/log/Log.h" -#include "base/tools/Chrono.h" -#include "crypto/rx/RxConfig.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace xmrig { - - -static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " "; -static MsrItems savedState; - - -static inline int dir_filter(const struct dirent *dirp) -{ - return isdigit(dirp->d_name[0]) ? 1 : 0; -} - - -bool rdmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t &value) -{ - char msr_file_name[64]{}; - - sprintf(msr_file_name, "/dev/cpu/%u/msr", cpu); - int fd = open(msr_file_name, O_RDONLY); - if (fd < 0) { - return false; - } - - const bool success = pread(fd, &value, sizeof value, reg) == sizeof value; - - close(fd); - - return success; -} - - -static MsrItem rdmsr(uint32_t reg) -{ - uint64_t value = 0; - if (!rdmsr_on_cpu(reg, 0, value)) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot read MSR 0x%08" PRIx32, tag, reg); - - return {}; - } - - return { reg, value }; -} - - -static uint64_t get_masked_value(uint64_t old_value, uint64_t new_value, uint64_t mask) -{ - return (new_value & mask) | (old_value & ~mask); -} - - -static bool wrmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t value, uint64_t mask) -{ - // If a bit in mask is set to 1, use new value, otherwise use old value - if (mask != MsrItem::kNoMask) { - uint64_t old_value; - if (rdmsr_on_cpu(reg, cpu, old_value)) { - value = get_masked_value(old_value, value, mask); - } - } - - char msr_file_name[64]{}; - - sprintf(msr_file_name, "/dev/cpu/%u/msr", cpu); - int fd = open(msr_file_name, O_WRONLY); - if (fd < 0) { - return false; - } - - const bool success = pwrite(fd, &value, sizeof value, reg) == sizeof value; - - close(fd); - - return success; -} - - -template -static bool wrmsr_on_all_cpus(uint32_t reg, uint64_t value, uint64_t mask, T&& callback) -{ - struct dirent **namelist; - int dir_entries = scandir("/dev/cpu", &namelist, dir_filter, 0); - int errors = 0; - - while (dir_entries--) { - if (!callback(reg, strtoul(namelist[dir_entries]->d_name, nullptr, 10), value, mask)) { - ++errors; - } - - free(namelist[dir_entries]); - } - - free(namelist); - - if (errors) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, tag, reg, value); - } - - return errors == 0; -} - - -static bool wrmsr_modprobe() -{ - if (system("/sbin/modprobe msr allow_writes=on > /dev/null 2>&1") != 0) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "msr kernel module is not available", tag); - - return false; - } - - return true; -} - - -static bool wrmsr(const MsrItems& preset, const std::vector& threads, bool cache_qos, bool save) -{ - if (!wrmsr_modprobe()) { - return false; - } - - if (save) { - for (const auto &i : preset) { - auto item = rdmsr(i.reg()); - LOG_VERBOSE(CLEAR "%s" CYAN_BOLD("0x%08" PRIx32) CYAN(":0x%016" PRIx64) CYAN_BOLD(" -> 0x%016" PRIx64), tag, i.reg(), item.value(), get_masked_value(item.value(), i.value(), i.mask())); - - if (item.isValid()) { - savedState.emplace_back(item); - } - } - } - - for (const auto &i : preset) { - if (!wrmsr_on_all_cpus(i.reg(), i.value(), i.mask(), [](uint32_t reg, uint32_t cpu, uint64_t value, uint64_t mask) { return wrmsr_on_cpu(reg, cpu, value, mask); })) { - return false; - } - } - - const uint32_t n = Cpu::info()->threads(); - - // Which CPU cores will have access to the full L3 cache - std::vector cacheEnabled(n, false); - bool cacheQoSDisabled = threads.empty(); - - for (const CpuThread& t : threads) { - // If some thread has no affinity or wrong affinity, disable cache QoS - if ((t.affinity() < 0) || (t.affinity() >= n)) { - cacheQoSDisabled = true; - if (cache_qos) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "Cache QoS can only be enabled when all mining threads have affinity set", tag); - } - break; - } - - cacheEnabled[t.affinity()] = true; - } - - if (cache_qos && !Cpu::info()->hasCatL3()) { - if (!threads.empty()) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "This CPU doesn't support cat_l3, cache QoS is unavailable", tag); - } - cache_qos = false; - } - - bool result = true; - - if (cache_qos) { - result = wrmsr_on_all_cpus(0xC8F, 0, MsrItem::kNoMask, [&cacheEnabled, cacheQoSDisabled](uint32_t, uint32_t cpu, uint64_t, uint64_t) { - if (cacheQoSDisabled || (cpu >= cacheEnabled.size()) || cacheEnabled[cpu]) { - // Assign Class Of Service 0 to current CPU core (default, full L3 cache available) - if (!wrmsr_on_cpu(0xC8F, cpu, 0, MsrItem::kNoMask)) { - return false; - } - } - else { - // Disable L3 cache for Class Of Service 1 - if (!wrmsr_on_cpu(0xC91, cpu, 0, MsrItem::kNoMask)) { - // Some CPUs don't let set it to all zeros - if (!wrmsr_on_cpu(0xC91, cpu, 1, MsrItem::kNoMask)) { - return false; - } - } - - // Assign Class Of Service 1 to current CPU core - if (!wrmsr_on_cpu(0xC8F, cpu, 1ULL << 32, MsrItem::kNoMask)) { - return false; - } - } - return true; - }); - } - - return result; -} - - -} // namespace xmrig - - -bool xmrig::Rx::msrInit(const RxConfig &config, const std::vector &threads) -{ - const auto &preset = config.msrPreset(); - if (preset.empty()) { - return false; - } - - const uint64_t ts = Chrono::steadyMSecs(); - - if (wrmsr(preset, threads, config.cacheQoS(), config.rdmsr())) { - LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for \"%s\" preset have been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, config.msrPresetName(), Chrono::steadyMSecs() - ts); - - return true; - } - - - LOG_ERR(CLEAR "%s" RED_BOLD_S "FAILED TO APPLY MSR MOD, HASHRATE WILL BE LOW", tag); - - return false; -} - - -void xmrig::Rx::msrDestroy() -{ - if (savedState.empty()) { - return; - } - - const uint64_t ts = Chrono::steadyMSecs(); - - if (!wrmsr(savedState, std::vector(), true, false)) { - LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts); - } -} diff --git a/src/crypto/rx/Rx_win.cpp b/src/crypto/rx/Rx_win.cpp deleted file mode 100644 index 36e13819..00000000 --- a/src/crypto/rx/Rx_win.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* XMRig - * Copyright (c) 2018-2019 tevador - * Copyright (c) 2000 Transmeta Corporation - * Copyright (c) 2004-2008 H. Peter Anvin - * Copyright (c) 2007-2009 hiyohiyo , - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "crypto/rx/Rx.h" -#include "backend/cpu/Cpu.h" -#include "backend/cpu/CpuThread.h" -#include "base/io/log/Log.h" -#include "base/kernel/Platform.h" -#include "base/tools/Chrono.h" -#include "crypto/rx/RxConfig.h" - - -#include -#include -#include -#include - - -#define SERVICE_NAME L"WinRing0_1_2_0" - - -namespace xmrig { - - -static bool reuseDriver = false; -static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " "; -static MsrItems savedState; - - -static SC_HANDLE hManager; -static SC_HANDLE hService; - - -static bool wrmsr_uninstall_driver() -{ - if (!hService) { - return true; - } - - bool result = true; - - if (!reuseDriver) { - SERVICE_STATUS serviceStatus; - - if (!ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus)) { - result = false; - } - - if (!DeleteService(hService)) { - LOG_ERR(CLEAR "%s" RED_S "failed to remove WinRing0 driver, error %u", tag, GetLastError()); - result = false; - } - } - - CloseServiceHandle(hService); - hService = nullptr; - - return result; -} - - -static HANDLE wrmsr_install_driver() -{ - DWORD err = 0; - - hManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); - if (!hManager) { - err = GetLastError(); - - if (err == ERROR_ACCESS_DENIED) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "to write MSR registers Administrator privileges required.", tag); - } - else { - LOG_ERR(CLEAR "%s" RED_S "failed to open service control manager, error %u", tag, err); - } - - return nullptr; - } - - std::vector dir; - dir.resize(MAX_PATH); - do { - dir.resize(dir.size() * 2); - GetModuleFileNameW(nullptr, dir.data(), dir.size()); - err = GetLastError(); - } while (err == ERROR_INSUFFICIENT_BUFFER); - - if (err != ERROR_SUCCESS) { - LOG_ERR(CLEAR "%s" RED_S "failed to get path to driver, error %u", tag, err); - return nullptr; - } - - for (auto it = dir.end() - 1; it != dir.begin(); --it) { - if ((*it == L'\\') || (*it == L'/')) { - ++it; - *it = L'\0'; - break; - } - } - - std::wstring driverPath = dir.data(); - driverPath += L"WinRing0x64.sys"; - - hService = OpenServiceW(hManager, SERVICE_NAME, SERVICE_ALL_ACCESS); - if (hService) { - LOG_WARN(CLEAR "%s" YELLOW("service ") YELLOW_BOLD("WinRing0_1_2_0") YELLOW(" already exists"), tag); - - SERVICE_STATUS status; - const auto rc = QueryServiceStatus(hService, &status); - - if (rc) { - DWORD dwBytesNeeded; - - QueryServiceConfigA(hService, nullptr, 0, &dwBytesNeeded); - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - std::vector buffer(dwBytesNeeded); - auto config = reinterpret_cast(buffer.data()); - - if (QueryServiceConfigA(hService, config, buffer.size(), &dwBytesNeeded)) { - LOG_INFO(CLEAR "%s" YELLOW("service path: ") YELLOW_BOLD("\"%s\""), tag, config->lpBinaryPathName); - } - } - } - - if (rc && status.dwCurrentState == SERVICE_RUNNING) { - reuseDriver = true; - } - else if (!wrmsr_uninstall_driver()) { - return nullptr; - } - } - - if (!reuseDriver) { - hService = CreateServiceW(hManager, SERVICE_NAME, SERVICE_NAME, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, driverPath.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr); - if (!hService) { - LOG_ERR(CLEAR "%s" RED_S "failed to install WinRing0 driver, error %u", tag, GetLastError()); - - return nullptr; - } - - if (!StartService(hService, 0, nullptr)) { - err = GetLastError(); - if (err != ERROR_SERVICE_ALREADY_RUNNING) { - if (err == ERROR_FILE_NOT_FOUND) { - LOG_ERR(CLEAR "%s" RED("failed to start WinRing0 driver: ") RED_BOLD("\"WinRing0x64.sys not found\""), tag); - } - else { - LOG_ERR(CLEAR "%s" RED_S "failed to start WinRing0 driver, error %u", tag, err); - } - - wrmsr_uninstall_driver(); - - return nullptr; - } - } - } - - HANDLE hDriver = CreateFileW(L"\\\\.\\" SERVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (!hDriver) { - LOG_ERR(CLEAR "%s" RED_S "failed to connect to WinRing0 driver, error %u", tag, GetLastError()); - - return nullptr; - } - - return hDriver; -} - - -#define IOCTL_READ_MSR CTL_CODE(40000, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS) - - -static bool rdmsr(HANDLE driver, uint32_t reg, uint64_t &value) -{ - DWORD size = 0; - - return DeviceIoControl(driver, IOCTL_READ_MSR, ®, sizeof(reg), &value, sizeof(value), &size, nullptr) != 0; -} - - -static MsrItem rdmsr(HANDLE driver, uint32_t reg) -{ - uint64_t value = 0; - if (!rdmsr(driver, reg, value)) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot read MSR 0x%08" PRIx32, tag, reg); - - return {}; - } - - return { reg, value }; -} - - -static uint64_t get_masked_value(uint64_t old_value, uint64_t new_value, uint64_t mask) -{ - return (new_value & mask) | (old_value & ~mask); -} - - -static bool wrmsr(HANDLE driver, uint32_t reg, uint64_t value, uint64_t mask) -{ - struct { - uint32_t reg = 0; - uint32_t value[2]{}; - } input; - - static_assert(sizeof(input) == 12, "Invalid struct size for WinRing0 driver"); - - // If a bit in mask is set to 1, use new value, otherwise use old value - if (mask != MsrItem::kNoMask) { - uint64_t old_value; - if (rdmsr(driver, reg, old_value)) { - value = get_masked_value(old_value, value, mask); - } - } - - input.reg = reg; - *(reinterpret_cast(input.value)) = value; - - DWORD output; - DWORD k; - - if (!DeviceIoControl(driver, IOCTL_WRITE_MSR, &input, sizeof(input), &output, sizeof(output), &k, nullptr)) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, tag, reg, value); - - return false; - } - - return true; -} - - -static bool wrmsr(const MsrItems &preset, const std::vector& threads, bool cache_qos, bool save) -{ - bool success = true; - - HANDLE driver = wrmsr_install_driver(); - if (!driver) { - wrmsr_uninstall_driver(); - - if (hManager) { - CloseServiceHandle(hManager); - } - - return false; - } - - if (save) { - for (const auto &i : preset) { - auto item = rdmsr(driver, i.reg()); - LOG_VERBOSE(CLEAR "%s" CYAN_BOLD("0x%08" PRIx32) CYAN(":0x%016" PRIx64) CYAN_BOLD(" -> 0x%016" PRIx64), tag, i.reg(), item.value(), get_masked_value(item.value(), i.value(), i.mask())); - - if (item.isValid()) { - savedState.emplace_back(item); - } - } - } - - const uint32_t n = Cpu::info()->threads(); - - // Which CPU cores will have access to the full L3 cache - std::vector cacheEnabled(n, false); - bool cacheQoSDisabled = threads.empty(); - - for (const CpuThread& t : threads) { - // If some thread has no affinity or wrong affinity, disable cache QoS - if ((t.affinity() < 0) || (t.affinity() >= n)) { - cacheQoSDisabled = true; - if (cache_qos) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "Cache QoS can only be enabled when all mining threads have affinity set", tag); - } - break; - } - - cacheEnabled[t.affinity()] = true; - } - - if (cache_qos && !Cpu::info()->hasCatL3()) { - if (!threads.empty()) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "This CPU doesn't support cat_l3, cache QoS is unavailable", tag); - } - cache_qos = false; - } - - std::thread wrmsr_thread([n, driver, &preset, &cacheEnabled, cache_qos, cacheQoSDisabled, &success]() { - for (uint32_t i = 0; i < n; ++i) { - if (!Platform::setThreadAffinity(i)) { - continue; - } - - for (const auto &i : preset) { - success &= wrmsr(driver, i.reg(), i.value(), i.mask()); - } - - if (cache_qos) { - if (cacheQoSDisabled || cacheEnabled[i]) { - // Assign Class Of Service 0 to current CPU core (default, full L3 cache available) - success &= wrmsr(driver, 0xC8F, 0, MsrItem::kNoMask); - } - else { - // Disable L3 cache for Class Of Service 1 - if (!wrmsr(driver, 0xC91, 0, MsrItem::kNoMask)) { - // Some CPUs don't let set it to all zeros - if (!wrmsr(driver, 0xC91, 1, MsrItem::kNoMask)) { - success = false; - } - } - - // Assign Class Of Service 1 to current CPU core - success &= wrmsr(driver, 0xC8F, 1ULL << 32, MsrItem::kNoMask); - } - } - - if (!success) { - break; - } - } - }); - - wrmsr_thread.join(); - - CloseHandle(driver); - - wrmsr_uninstall_driver(); - CloseServiceHandle(hManager); - - return success; -} - - -} // namespace xmrig - - -bool xmrig::Rx::msrInit(const RxConfig &config, const std::vector& threads) -{ - const auto &preset = config.msrPreset(); - if (preset.empty()) { - return false; - } - - const uint64_t ts = Chrono::steadyMSecs(); - - if (wrmsr(preset, threads, config.cacheQoS(), config.rdmsr())) { - LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for \"%s\" preset has been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, config.msrPresetName(), Chrono::steadyMSecs() - ts); - - return true; - } - - LOG_ERR(CLEAR "%s" RED_BOLD_S "FAILED TO APPLY MSR MOD, HASHRATE WILL BE LOW", tag); - - return false; -} - - -void xmrig::Rx::msrDestroy() -{ - if (savedState.empty()) { - return; - } - - const uint64_t ts = Chrono::steadyMSecs(); - - if (!wrmsr(savedState, std::vector(), true, false)) { - LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts); - } -} diff --git a/src/hw/msr/Msr.cpp b/src/hw/msr/Msr.cpp index 68c60e6e..1fed8776 100644 --- a/src/hw/msr/Msr.cpp +++ b/src/hw/msr/Msr.cpp @@ -55,6 +55,24 @@ std::shared_ptr xmrig::Msr::get() } +bool xmrig::Msr::write(uint32_t reg, uint64_t value, int32_t cpu, uint64_t mask, bool verbose) +{ + if (mask != MsrItem::kNoMask) { + uint64_t old_value; + if (rdmsr(reg, cpu, old_value)) { + value = MsrItem::maskedValue(old_value, value, mask); + } + } + + const bool result = wrmsr(reg, value, cpu); + if (!result && verbose) { + LOG_WARN("%s " YELLOW_BOLD("cannot set MSR 0x%08" PRIx32 " to 0x%016" PRIx64), tag(), reg, value); + } + + return result; +} + + xmrig::MsrItem xmrig::Msr::read(uint32_t reg, int32_t cpu, bool verbose) const { uint64_t value = 0; diff --git a/src/hw/msr/Msr.h b/src/hw/msr/Msr.h index 5f325a25..3bd88dd5 100644 --- a/src/hw/msr/Msr.h +++ b/src/hw/msr/Msr.h @@ -24,6 +24,7 @@ #include "hw/msr/MsrItem.h" +#include #include @@ -39,17 +40,24 @@ class Msr public: XMRIG_DISABLE_COPY_MOVE(Msr) + using Callback = std::function; + Msr(); ~Msr(); static const char *tag(); static std::shared_ptr get(); + inline bool write(const MsrItem &item, int32_t cpu = -1, bool verbose = true) { return write(item.reg(), item.value(), cpu, item.mask(), verbose); } + bool isAvailable() const; + bool write(uint32_t reg, uint64_t value, int32_t cpu = -1, uint64_t mask = MsrItem::kNoMask, bool verbose = true); + bool write(Callback &&callback); MsrItem read(uint32_t reg, int32_t cpu = -1, bool verbose = true) const; private: bool rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const; + bool wrmsr(uint32_t reg, uint64_t value, int32_t cpu); MsrPrivate *d_ptr = nullptr; }; diff --git a/src/hw/msr/MsrItem.h b/src/hw/msr/MsrItem.h index ad3c9d39..00c0416a 100644 --- a/src/hw/msr/MsrItem.h +++ b/src/hw/msr/MsrItem.h @@ -46,6 +46,11 @@ public: inline uint64_t value() const { return m_value; } inline uint64_t mask() const { return m_mask; } + static inline uint64_t maskedValue(uint64_t old_value, uint64_t new_value, uint64_t mask) + { + return (new_value & mask) | (old_value & ~mask); + } + rapidjson::Value toJSON(rapidjson::Document &doc) const; String toString() const; diff --git a/src/hw/msr/Msr_linux.cpp b/src/hw/msr/Msr_linux.cpp index 02a29c72..9053c32f 100644 --- a/src/hw/msr/Msr_linux.cpp +++ b/src/hw/msr/Msr_linux.cpp @@ -19,6 +19,7 @@ #include "hw/msr/Msr.h" #include "3rdparty/fmt/core.h" +#include "backend/cpu/Cpu.h" #include "base/io/log/Log.h" @@ -31,8 +32,6 @@ #include #include #include -#include -#include namespace xmrig { @@ -70,6 +69,20 @@ bool xmrig::Msr::isAvailable() const } +bool xmrig::Msr::write(Callback &&callback) +{ + const auto &units = Cpu::info()->units(); + + for (int32_t pu : units) { + if (!callback(pu)) { + return false; + } + } + + return true; +} + + bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const { const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? 0 : cpu); @@ -84,3 +97,20 @@ bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const return success; } + + +bool xmrig::Msr::wrmsr(uint32_t reg, uint64_t value, int32_t cpu) +{ + const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? 0 : cpu); + int fd = open(name.c_str(), O_WRONLY); + + if (fd < 0) { + return false; + } + + const bool success = pwrite(fd, &value, sizeof value, reg) == sizeof value; + + close(fd); + + return success; +} diff --git a/src/hw/msr/Msr_win.cpp b/src/hw/msr/Msr_win.cpp index d055785c..654f6778 100644 --- a/src/hw/msr/Msr_win.cpp +++ b/src/hw/msr/Msr_win.cpp @@ -18,10 +18,13 @@ #include "hw/msr/Msr.h" +#include "backend/cpu/Cpu.h" #include "base/io/log/Log.h" +#include "base/kernel/Platform.h" #include +#include #include #include @@ -196,9 +199,57 @@ bool xmrig::Msr::isAvailable() const } -bool xmrig::Msr::rdmsr(uint32_t reg, int32_t, uint64_t &value) const +bool xmrig::Msr::write(Callback &&callback) { + const auto &units = Cpu::info()->units(); + bool success = false; + + std::thread thread([&callback, &units, &success]() { + for (int32_t pu : units) { + if (!Platform::setThreadAffinity(pu)) { + continue; + } + + if (!callback(pu)) { + return; + } + } + + success = true; + }); + + thread.join(); + + return success; +} + + +bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const +{ + assert(cpu < 0); + DWORD size = 0; return DeviceIoControl(d_ptr->driver, IOCTL_READ_MSR, ®, sizeof(reg), &value, sizeof(value), &size, nullptr) != 0; } + + +bool xmrig::Msr::wrmsr(uint32_t reg, uint64_t value, int32_t cpu) +{ + assert(cpu < 0); + + struct { + uint32_t reg = 0; + uint32_t value[2]{}; + } input; + + static_assert(sizeof(input) == 12, "Invalid struct size for WinRing0 driver"); + + input.reg = reg; + *(reinterpret_cast(input.value)) = value; + + DWORD output; + DWORD k; + + return DeviceIoControl(d_ptr->driver, IOCTL_WRITE_MSR, &input, sizeof(input), &output, sizeof(output), &k, nullptr) != 0; +} From 672f6df6c1d02951dc0e95cd19f03bec4646e8da Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 24 Jan 2021 02:23:27 +0700 Subject: [PATCH 21/27] Fixed Cache QoS restore on exit where it not supported. --- src/crypto/rx/RxMsr.cpp | 15 +++++++-------- src/crypto/rx/RxMsr.h | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/crypto/rx/RxMsr.cpp b/src/crypto/rx/RxMsr.cpp index 6083e9b3..171579e9 100644 --- a/src/crypto/rx/RxMsr.cpp +++ b/src/crypto/rx/RxMsr.cpp @@ -34,6 +34,7 @@ namespace xmrig { +bool RxMsr::m_cacheQoS = false; bool RxMsr::m_enabled = false; bool RxMsr::m_initialized = false; @@ -142,17 +143,15 @@ bool xmrig::RxMsr::init(const RxConfig &config, const std::vector &th } const uint64_t ts = Chrono::steadyMSecs(); - bool cache_qos = config.cacheQoS(); + m_cacheQoS = config.cacheQoS(); - if (cache_qos && !Cpu::info()->hasCatL3()) { - if (!threads.empty()) { - LOG_WARN("%s " YELLOW_BOLD("this CPU doesn't support cat_l3, cache QoS is unavailable"), Msr::tag()); - } + if (m_cacheQoS && !Cpu::info()->hasCatL3()) { + LOG_WARN("%s " YELLOW_BOLD("this CPU doesn't support cat_l3, cache QoS is unavailable"), Msr::tag()); - cache_qos = false; + m_cacheQoS = false; } - if ((m_enabled = wrmsr(preset, threads, cache_qos, config.rdmsr()))) { + if ((m_enabled = wrmsr(preset, threads, m_cacheQoS, config.rdmsr()))) { LOG_NOTICE("%s " GREEN_BOLD("register values for \"%s\" preset have been set successfully") BLACK_BOLD(" (%" PRIu64 " ms)"), Msr::tag(), config.msrPresetName(), Chrono::steadyMSecs() - ts); } else { @@ -178,7 +177,7 @@ void xmrig::RxMsr::destroy() const uint64_t ts = Chrono::steadyMSecs(); - if (!wrmsr(items, std::vector(), true, false)) { + if (!wrmsr(items, std::vector(), m_cacheQoS, false)) { LOG_ERR("%s " RED_BOLD("failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)")), Msr::tag(), Chrono::steadyMSecs() - ts); } } diff --git a/src/crypto/rx/RxMsr.h b/src/crypto/rx/RxMsr.h index 870e298c..8e1bf954 100644 --- a/src/crypto/rx/RxMsr.h +++ b/src/crypto/rx/RxMsr.h @@ -42,6 +42,7 @@ public: static void destroy(); private: + static bool m_cacheQoS; static bool m_enabled; static bool m_initialized; }; From 78922a077213b95c437e296fc4c72f597a6124b5 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Sat, 23 Jan 2021 22:28:50 +0100 Subject: [PATCH 22/27] RandomX JIT x86: remove unnecessary instructions Adopted from https://github.com/tevador/RandomX/pull/201 --- src/crypto/randomx/jit_compiler_x86.cpp | 8 +++----- src/crypto/randomx/jit_compiler_x86_static.S | 2 -- src/crypto/randomx/jit_compiler_x86_static.asm | 2 -- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/crypto/randomx/jit_compiler_x86.cpp b/src/crypto/randomx/jit_compiler_x86.cpp index 8c3145b2..5685b080 100644 --- a/src/crypto/randomx/jit_compiler_x86.cpp +++ b/src/crypto/randomx/jit_compiler_x86.cpp @@ -417,12 +417,10 @@ 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; } 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 From 0fa5db8fa38357efbc82c86fbb44b0369385fb2a Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 24 Jan 2021 15:02:22 +0700 Subject: [PATCH 23/27] Code cleanup. --- src/backend/cpu/platform/HwlocCpuInfo.cpp | 4 ++++ src/hw/msr/Msr_linux.cpp | 14 ++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/backend/cpu/platform/HwlocCpuInfo.cpp b/src/backend/cpu/platform/HwlocCpuInfo.cpp index 8b1c4536..6ef74229 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.cpp +++ b/src/backend/cpu/platform/HwlocCpuInfo.cpp @@ -400,6 +400,10 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith void xmrig::HwlocCpuInfo::setThreads(size_t threads) { + if (!threads) { + return; + } + m_threads = threads; if (m_units.size() != m_threads) { diff --git a/src/hw/msr/Msr_linux.cpp b/src/hw/msr/Msr_linux.cpp index 9053c32f..0783ebc1 100644 --- a/src/hw/msr/Msr_linux.cpp +++ b/src/hw/msr/Msr_linux.cpp @@ -37,6 +37,14 @@ 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: @@ -85,8 +93,7 @@ bool xmrig::Msr::write(Callback &&callback) bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const { - const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? 0 : cpu); - const int fd = open(name.c_str(), O_RDONLY); + const int fd = msr_open(cpu, O_RDONLY); if (fd < 0) { return false; @@ -101,8 +108,7 @@ bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const bool xmrig::Msr::wrmsr(uint32_t reg, uint64_t value, int32_t cpu) { - const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? 0 : cpu); - int fd = open(name.c_str(), O_WRONLY); + const int fd = msr_open(cpu, O_WRONLY); if (fd < 0) { return false; From 1424b2975f7495f09e816b038aef676ac93381e6 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 24 Jan 2021 15:56:02 +0700 Subject: [PATCH 24/27] Fixed DMI memory speed. --- src/hw/dmi/DmiMemory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hw/dmi/DmiMemory.cpp b/src/hw/dmi/DmiMemory.cpp index 5b36e2ba..05af0962 100644 --- a/src/hw/dmi/DmiMemory.cpp +++ b/src/hw/dmi/DmiMemory.cpp @@ -171,7 +171,8 @@ xmrig::DmiMemory::DmiMemory(dmi_header *h) return; } - m_speed = std::max(m_speed, dmi_memory_device_speed(dmi_get(h, 0x20), h->length >= 0x5C ? dmi_get(h, 0x58) : 0) * 1000000ULL); + 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; From b9081e992bea3bb223ac3dedf4f13083ced814d2 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 25 Jan 2021 22:00:42 +0700 Subject: [PATCH 25/27] Code cleanup --- src/backend/cpu/platform/BasicCpuInfo_arm.cpp | 9 +++++++-- src/backend/cpu/platform/HwlocCpuInfo.cpp | 8 ++------ src/hw/dmi/dmi.cmake | 6 ++++-- 3 files changed, 13 insertions(+), 10 deletions(-) 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 6ef74229..b1dd7ca9 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.cpp +++ b/src/backend/cpu/platform/HwlocCpuInfo.cpp @@ -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); @@ -278,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()) { diff --git a/src/hw/dmi/dmi.cmake b/src/hw/dmi/dmi.cmake index 5140692a..b6f91616 100644 --- a/src/hw/dmi/dmi.cmake +++ b/src/hw/dmi/dmi.cmake @@ -1,5 +1,7 @@ -if (WITH_DMI) - set(WITH_DMI XMRIG_OS_WIN OR XMRIG_OS_LINUX OR XMRIG_OS_FREEBSD OR (XMRIG_OS_MACOS AND NOT XMRIG_ARM)) +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) From 2d45cc64c19de440ea039b80a7d998117e6175b2 Mon Sep 17 00:00:00 2001 From: xmrig Date: Tue, 26 Jan 2021 15:08:05 +0700 Subject: [PATCH 26/27] Update CHANGELOG.md --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) 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. From 8eb9b4d37a4a9e1082d2e31dc8af170a098c44d3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 26 Jan 2021 15:15:08 +0700 Subject: [PATCH 27/27] Update default config example. --- src/config.json | 1 + src/core/config/Config_default.h | 29 +++++++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/config.json b/src/config.json index aad27326..bfb01696 100644 --- a/src/config.json +++ b/src/config.json @@ -80,6 +80,7 @@ ], "print-time": 60, "health-print-time": 60, + "dmi": true, "retries": 5, "retry-pause": 5, "syslog": false, 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 }