From 171762d1aa321d6856f5cbdc1e09b413b32eda5d Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 15 Sep 2019 18:04:18 +0700 Subject: [PATCH 01/49] v3.1.2 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index a0c461cf..1bbb14ac 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 CPU miner" -#define APP_VERSION "3.1.2-dev" +#define APP_VERSION "3.1.2" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" From 1cd1f13feea3febab76883768ef351df2e201794 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 16 Sep 2019 00:29:46 +0700 Subject: [PATCH 02/49] v3.1.3-dev --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index 1bbb14ac..3529e72c 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 CPU miner" -#define APP_VERSION "3.1.2" +#define APP_VERSION "3.1.3-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 3 #define APP_VER_MINOR 1 -#define APP_VER_PATCH 2 +#define APP_VER_PATCH 3 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From f6752310b49386b0bd639b2f5ea5484b1ec22b80 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 20 Sep 2019 14:54:18 +0700 Subject: [PATCH 03/49] Backport fixes from v4. --- CHANGELOG.md | 4 ++++ src/base/io/json/Json_win.cpp | 3 ++- src/core/Miner.cpp | 11 +++++------ src/crypto/common/Nonce.cpp | 1 - 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30e53359..0a3cda0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v3.1.3 +- [#1180](https://github.com/xmrig/xmrig/issues/1180) Fixed possible duplicated shares after algorithm switching. +- Fixed wrong config file permissions after write (only gcc builds on recent Windows 10 affected). + # v3.1.2 - Many RandomX optimizations and fixes. - [#1132](https://github.com/xmrig/xmrig/issues/1132) Fixed build on CentOS 7. diff --git a/src/base/io/json/Json_win.cpp b/src/base/io/json/Json_win.cpp index 73aff2c5..cb6f02f6 100644 --- a/src/base/io/json/Json_win.cpp +++ b/src/base/io/json/Json_win.cpp @@ -28,6 +28,7 @@ #ifdef __GNUC__ # include +# include # include #endif @@ -102,7 +103,7 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc) return false; } # elif defined(__GNUC__) - const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_CREAT | _O_TRUNC); + const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_CREAT | _O_TRUNC, _S_IWRITE); if (fd == -1) { return false; } diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index 26a5d7e7..b1b0bf9c 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -112,16 +112,15 @@ public: { active = true; + if (reset) { + Nonce::reset(job.index()); + } + for (IBackend *backend : backends) { backend->setJob(job); } - if (reset) { - Nonce::reset(job.index()); - } - else { - Nonce::touch(); - } + Nonce::touch(); if (enabled) { Nonce::pause(false);; diff --git a/src/crypto/common/Nonce.cpp b/src/crypto/common/Nonce.cpp index 151819e0..e79cb310 100644 --- a/src/crypto/common/Nonce.cpp +++ b/src/crypto/common/Nonce.cpp @@ -78,7 +78,6 @@ void xmrig::Nonce::reset(uint8_t index) std::lock_guard lock(mutex); m_nonces[index] = 0; - touch(); } From 05b2c66aafae9156611b61bbe2a607a2ac11aeec Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 20 Sep 2019 15:02:20 +0700 Subject: [PATCH 04/49] v3.1.3 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 3529e72c..151e925b 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 CPU miner" -#define APP_VERSION "3.1.3-dev" +#define APP_VERSION "3.1.3" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" From 7a1ff6bfed6a4118e77ddb0b13b7bde4951abc2e Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 20 Sep 2019 16:45:17 +0700 Subject: [PATCH 05/49] v3.1.4-dev --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index 151e925b..81e2bcce 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 CPU miner" -#define APP_VERSION "3.1.3" +#define APP_VERSION "3.1.4-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 3 #define APP_VER_MINOR 1 -#define APP_VER_PATCH 3 +#define APP_VER_PATCH 4 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From 6e45ab599eb974225c7f84670c0991d3b8eb43bf Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 20 Sep 2019 16:46:56 +0700 Subject: [PATCH 06/49] v4.0.2-evo --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index 613c4e00..f4cb9118 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 "4.0.1-beta" +#define APP_VERSION "4.0.2-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 4 #define APP_VER_MINOR 0 -#define APP_VER_PATCH 1 +#define APP_VER_PATCH 2 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From e57798360fe344d72b1bddfa2637472c16b63057 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 21 Sep 2019 03:22:19 +0700 Subject: [PATCH 07/49] #1183 Disable stdin handler if not available. --- src/base/io/Console.cpp | 16 +++++++- src/base/io/Console.h | 12 ++++-- src/base/io/log/backends/ConsoleLog.cpp | 22 ++++++++--- src/base/io/log/backends/ConsoleLog.h | 12 ++++-- src/base/tools/Object.h | 52 +++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 src/base/tools/Object.h diff --git a/src/base/io/Console.cpp b/src/base/io/Console.cpp index 0e5cd269..bba73035 100644 --- a/src/base/io/Console.cpp +++ b/src/base/io/Console.cpp @@ -31,8 +31,11 @@ xmrig::Console::Console(IConsoleListener *listener) : m_listener(listener) { - m_tty = new uv_tty_t; + if (!isSupported()) { + return; + } + m_tty = new uv_tty_t; m_tty->data = this; uv_tty_init(uv_default_loop(), m_tty, 0, 1); @@ -53,6 +56,10 @@ xmrig::Console::~Console() void xmrig::Console::stop() { + if (!m_tty) { + return; + } + uv_tty_reset_mode(); Handle::close(m_tty); @@ -60,6 +67,13 @@ void xmrig::Console::stop() } +bool xmrig::Console::isSupported() const +{ + const uv_handle_type type = uv_guess_handle(0); + return type == UV_TTY || type == UV_NAMED_PIPE; +} + + void xmrig::Console::onAllocBuffer(uv_handle_t *handle, size_t, uv_buf_t *buf) { auto console = static_cast(handle->data); diff --git a/src/base/io/Console.h b/src/base/io/Console.h index c0a36ec4..0a075348 100644 --- a/src/base/io/Console.h +++ b/src/base/io/Console.h @@ -26,9 +26,11 @@ #define XMRIG_CONSOLE_H -#include +#include "base/tools/Object.h" +#include + namespace xmrig { @@ -39,18 +41,22 @@ class IConsoleListener; class Console { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Console) + Console(IConsoleListener *listener); ~Console(); void stop(); private: + bool isSupported() const; + static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); - char m_buf[1]; + char m_buf[1] = { 0 }; IConsoleListener *m_listener; - uv_tty_t *m_tty; + uv_tty_t *m_tty = nullptr; }; diff --git a/src/base/io/log/backends/ConsoleLog.cpp b/src/base/io/log/backends/ConsoleLog.cpp index a5b6c1a7..34a7d66b 100644 --- a/src/base/io/log/backends/ConsoleLog.cpp +++ b/src/base/io/log/backends/ConsoleLog.cpp @@ -24,7 +24,7 @@ */ -#include +#include #include "base/tools/Handle.h" @@ -32,9 +32,13 @@ #include "base/io/log/Log.h" -xmrig::ConsoleLog::ConsoleLog() : - m_stream(nullptr) +xmrig::ConsoleLog::ConsoleLog() { + if (!isSupported()) { + Log::colors = false; + return; + } + m_tty = new uv_tty_t; if (uv_tty_init(uv_default_loop(), m_tty, 1, 0) < 0) { @@ -66,7 +70,7 @@ xmrig::ConsoleLog::~ConsoleLog() void xmrig::ConsoleLog::print(int, const char *line, size_t, size_t size, bool colors) { - if (Log::colors != colors) { + if (!m_tty || Log::colors != colors) { return; } @@ -86,12 +90,18 @@ void xmrig::ConsoleLog::print(int, const char *line, size_t, size_t size, bool c } +bool xmrig::ConsoleLog::isSupported() const +{ + const uv_handle_type type = uv_guess_handle(1); + return type == UV_TTY || type == UV_NAMED_PIPE; +} + + bool xmrig::ConsoleLog::isWritable() const { if (!m_stream || uv_is_writable(m_stream) != 1) { return false; } - const uv_handle_type type = uv_guess_handle(1); - return type == UV_TTY || type == UV_NAMED_PIPE; + return isSupported(); } diff --git a/src/base/io/log/backends/ConsoleLog.h b/src/base/io/log/backends/ConsoleLog.h index 90e4fa14..6277cc7b 100644 --- a/src/base/io/log/backends/ConsoleLog.h +++ b/src/base/io/log/backends/ConsoleLog.h @@ -27,11 +27,12 @@ #define XMRIG_CONSOLELOG_H -typedef struct uv_stream_s uv_stream_t; -typedef struct uv_tty_s uv_tty_t; +using uv_stream_t = struct uv_stream_s; +using uv_tty_t = struct uv_tty_s; #include "base/kernel/interfaces/ILogBackend.h" +#include "base/tools/Object.h" namespace xmrig { @@ -40,6 +41,8 @@ namespace xmrig { class ConsoleLog : public ILogBackend { public: + XMRIG_DISABLE_COPY_MOVE(ConsoleLog) + ConsoleLog(); ~ConsoleLog() override; @@ -47,10 +50,11 @@ protected: void print(int level, const char *line, size_t offset, size_t size, bool colors) override; private: + bool isSupported() const; bool isWritable() const; - uv_stream_t *m_stream; - uv_tty_t *m_tty; + uv_stream_t *m_stream = nullptr; + uv_tty_t *m_tty = nullptr; }; diff --git a/src/base/tools/Object.h b/src/base/tools/Object.h new file mode 100644 index 00000000..7e460e44 --- /dev/null +++ b/src/base/tools/Object.h @@ -0,0 +1,52 @@ +/* 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 , + * + * 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_OBJECT_H +#define XMRIG_OBJECT_H + + +#include + + +namespace xmrig { + + +#define XMRIG_DISABLE_COPY_MOVE(X) \ + X(const X &other) = delete; \ + X(X &&other) = delete; \ + X &operator=(const X &other) = delete; \ + X &operator=(X &&other) = delete; + + +#define XMRIG_DISABLE_COPY_MOVE_DEFAULT(X) \ + X() = delete; \ + X(const X &other) = delete; \ + X(X &&other) = delete; \ + X &operator=(const X &other) = delete; \ + X &operator=(X &&other) = delete; + + +} /* namespace xmrig */ + +#endif /* XMRIG_OBJECT_H */ From 38f4f4f695480e912d8402e1ae5858be3d40d451 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Sat, 21 Sep 2019 10:10:52 +0200 Subject: [PATCH 08/49] Added JIT compiler for RandomX on ARMv8 --- cmake/randomx.cmake | 7 + src/crypto/randomx/common.hpp | 2 +- src/crypto/randomx/instructions_portable.cpp | 12 +- src/crypto/randomx/intrin_portable.h | 146 ++- src/crypto/randomx/jit_compiler_a64.cpp | 1020 +++++++++++++++++ src/crypto/randomx/jit_compiler_a64.hpp | 94 +- src/crypto/randomx/jit_compiler_a64_static.S | 576 ++++++++++ .../randomx/jit_compiler_a64_static.hpp | 51 + src/crypto/randomx/randomx.cpp | 56 +- src/crypto/randomx/randomx.h | 8 + src/crypto/randomx/vm_compiled.cpp | 3 + src/crypto/rx/RxVm.cpp | 2 - 12 files changed, 1918 insertions(+), 59 deletions(-) create mode 100644 src/crypto/randomx/jit_compiler_a64.cpp create mode 100644 src/crypto/randomx/jit_compiler_a64_static.S create mode 100644 src/crypto/randomx/jit_compiler_a64_static.hpp diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index d0d892b9..27b6e5e6 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -51,6 +51,13 @@ if (WITH_RANDOMX) ) # cheat because cmake and ccache hate each other set_property(SOURCE src/crypto/randomx/jit_compiler_x86_static.S PROPERTY LANGUAGE C) + elseif (XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND SOURCES_CRYPTO + src/crypto/randomx/jit_compiler_a64_static.S + src/crypto/randomx/jit_compiler_a64.cpp + ) + # cheat because cmake and ccache hate each other + set_property(SOURCE src/crypto/randomx/jit_compiler_a64_static.S PROPERTY LANGUAGE C) endif() if (CMAKE_CXX_COMPILER_ID MATCHES Clang) diff --git a/src/crypto/randomx/common.hpp b/src/crypto/randomx/common.hpp index da36f2c5..48f31bac 100644 --- a/src/crypto/randomx/common.hpp +++ b/src/crypto/randomx/common.hpp @@ -108,7 +108,7 @@ namespace randomx { class JitCompilerX86; using JitCompiler = JitCompilerX86; #elif defined(__aarch64__) - #define RANDOMX_HAVE_COMPILER 0 + #define RANDOMX_HAVE_COMPILER 1 class JitCompilerA64; using JitCompiler = JitCompilerA64; #else diff --git a/src/crypto/randomx/instructions_portable.cpp b/src/crypto/randomx/instructions_portable.cpp index b28203a9..d08ee587 100644 --- a/src/crypto/randomx/instructions_portable.cpp +++ b/src/crypto/randomx/instructions_portable.cpp @@ -82,6 +82,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define HAVE_SETROUNDMODE_IMPL #endif +#ifndef HAVE_SETROUNDMODE_IMPL + static void setRoundMode_(uint32_t mode) { + fesetround(mode); + } +#endif + #ifndef HAVE_ROTR64 uint64_t rotr64(uint64_t a, unsigned int b) { return (a >> b) | (a << (-b & 63)); @@ -127,12 +133,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef RANDOMX_DEFAULT_FENV -# ifndef HAVE_SETROUNDMODE_IMPL - static void setRoundMode_(uint32_t mode) { - fesetround(mode); - } -# endif - void rx_reset_float_state() { setRoundMode_(FE_TONEAREST); rx_set_double_precision(); //set precision to 53 bits if needed by the platform diff --git a/src/crypto/randomx/intrin_portable.h b/src/crypto/randomx/intrin_portable.h index e4916096..346c433a 100644 --- a/src/crypto/randomx/intrin_portable.h +++ b/src/crypto/randomx/intrin_portable.h @@ -376,11 +376,138 @@ FORCE_INLINE rx_vec_f128 rx_cvt_packed_int_vec_f128(const void* addr) { #define RANDOMX_DEFAULT_FENV -void rx_reset_float_state(); +#elif defined(__aarch64__) -void rx_set_rounding_mode(uint32_t mode); +#include +#include +#include -#else //end altivec +typedef uint8x16_t rx_vec_i128; +typedef float64x2_t rx_vec_f128; + +inline void* rx_aligned_alloc(size_t size, size_t align) { + void* p; + if (posix_memalign(&p, align, size) == 0) + return p; + + return 0; +}; + +#define rx_aligned_free(a) free(a) + +inline void rx_prefetch_nta(void* ptr) { + asm volatile ("prfm pldl1strm, [%0]\n" : : "r" (ptr)); +} + +FORCE_INLINE rx_vec_f128 rx_load_vec_f128(const double* pd) { + return vld1q_f64((const float64_t*)pd); +} + +FORCE_INLINE void rx_store_vec_f128(double* mem_addr, rx_vec_f128 val) { + vst1q_f64((float64_t*)mem_addr, val); +} + +FORCE_INLINE rx_vec_f128 rx_swap_vec_f128(rx_vec_f128 a) { + float64x2_t temp; + temp = vcopyq_laneq_f64(temp, 1, a, 1); + a = vcopyq_laneq_f64(a, 1, a, 0); + return vcopyq_laneq_f64(a, 0, temp, 1); +} + +FORCE_INLINE rx_vec_f128 rx_set_vec_f128(uint64_t x1, uint64_t x0) { + uint64x2_t temp0 = vdupq_n_u64(x0); + uint64x2_t temp1 = vdupq_n_u64(x1); + return vreinterpretq_f64_u64(vcopyq_laneq_u64(temp0, 1, temp1, 0)); +} + +FORCE_INLINE rx_vec_f128 rx_set1_vec_f128(uint64_t x) { + return vreinterpretq_f64_u64(vdupq_n_u64(x)); +} + +#define rx_add_vec_f128 vaddq_f64 +#define rx_sub_vec_f128 vsubq_f64 +#define rx_mul_vec_f128 vmulq_f64 +#define rx_div_vec_f128 vdivq_f64 +#define rx_sqrt_vec_f128 vsqrtq_f64 + +FORCE_INLINE rx_vec_f128 rx_xor_vec_f128(rx_vec_f128 a, rx_vec_f128 b) { + return vreinterpretq_f64_u8(veorq_u8(vreinterpretq_u8_f64(a), vreinterpretq_u8_f64(b))); +} + +FORCE_INLINE rx_vec_f128 rx_and_vec_f128(rx_vec_f128 a, rx_vec_f128 b) { + return vreinterpretq_f64_u8(vandq_u8(vreinterpretq_u8_f64(a), vreinterpretq_u8_f64(b))); +} + +FORCE_INLINE rx_vec_f128 rx_or_vec_f128(rx_vec_f128 a, rx_vec_f128 b) { + return vreinterpretq_f64_u8(vorrq_u8(vreinterpretq_u8_f64(a), vreinterpretq_u8_f64(b))); +} + +#ifdef __ARM_FEATURE_CRYPTO + + +FORCE_INLINE rx_vec_i128 rx_aesenc_vec_i128(rx_vec_i128 a, rx_vec_i128 key) { + const uint8x16_t zero = { 0 }; + return vaesmcq_u8(vaeseq_u8(a, zero)) ^ key; +} + +FORCE_INLINE rx_vec_i128 rx_aesdec_vec_i128(rx_vec_i128 a, rx_vec_i128 key) { + const uint8x16_t zero = { 0 }; + return vaesimcq_u8(vaesdq_u8(a, zero)) ^ key; +} + +#define HAVE_AES + +#endif + +#define rx_xor_vec_i128 veorq_u8 + +FORCE_INLINE int rx_vec_i128_x(rx_vec_i128 a) { + return vgetq_lane_s32(vreinterpretq_s32_u8(a), 0); +} + +FORCE_INLINE int rx_vec_i128_y(rx_vec_i128 a) { + return vgetq_lane_s32(vreinterpretq_s32_u8(a), 1); +} + +FORCE_INLINE int rx_vec_i128_z(rx_vec_i128 a) { + return vgetq_lane_s32(vreinterpretq_s32_u8(a), 2); +} + +FORCE_INLINE int rx_vec_i128_w(rx_vec_i128 a) { + return vgetq_lane_s32(vreinterpretq_s32_u8(a), 3); +} + +FORCE_INLINE rx_vec_i128 rx_set_int_vec_i128(int _I3, int _I2, int _I1, int _I0) { + int32_t data[4]; + data[0] = _I0; + data[1] = _I1; + data[2] = _I2; + data[3] = _I3; + return vreinterpretq_u8_s32(vld1q_s32(data)); +}; + +#define rx_xor_vec_i128 veorq_u8 + +FORCE_INLINE rx_vec_i128 rx_load_vec_i128(const rx_vec_i128* mem_addr) { + return vld1q_u8((const uint8_t*)mem_addr); +} + +FORCE_INLINE void rx_store_vec_i128(rx_vec_i128* mem_addr, rx_vec_i128 val) { + vst1q_u8((uint8_t*)mem_addr, val); +} + +FORCE_INLINE rx_vec_f128 rx_cvt_packed_int_vec_f128(const void* addr) { + double lo = unsigned32ToSigned2sCompl(load32((uint8_t*)addr + 0)); + double hi = unsigned32ToSigned2sCompl(load32((uint8_t*)addr + 4)); + rx_vec_f128 x; + x = vsetq_lane_f64(lo, x, 0); + x = vsetq_lane_f64(hi, x, 1); + return x; +} + +#define RANDOMX_DEFAULT_FENV + +#else //portable fallback #include #include @@ -487,7 +614,6 @@ FORCE_INLINE rx_vec_f128 rx_set1_vec_f128(uint64_t x) { return v; } - FORCE_INLINE rx_vec_f128 rx_xor_vec_f128(rx_vec_f128 a, rx_vec_f128 b) { rx_vec_f128 x; x.i.u64[0] = a.i.u64[0] ^ b.i.u64[0]; @@ -578,10 +704,6 @@ FORCE_INLINE rx_vec_f128 rx_cvt_packed_int_vec_f128(const void* addr) { #define RANDOMX_DEFAULT_FENV -void rx_reset_float_state(); - -void rx_set_rounding_mode(uint32_t mode); - #endif #ifndef HAVE_AES @@ -598,6 +720,14 @@ FORCE_INLINE rx_vec_i128 rx_aesdec_vec_i128(rx_vec_i128 v, rx_vec_i128 rkey) { } #endif +#ifdef RANDOMX_DEFAULT_FENV + +void rx_reset_float_state(); + +void rx_set_rounding_mode(uint32_t mode); + +#endif + double loadDoublePortable(const void* addr); uint64_t mulh(uint64_t, uint64_t); int64_t smulh(int64_t, int64_t); diff --git a/src/crypto/randomx/jit_compiler_a64.cpp b/src/crypto/randomx/jit_compiler_a64.cpp new file mode 100644 index 00000000..08f84f1c --- /dev/null +++ b/src/crypto/randomx/jit_compiler_a64.cpp @@ -0,0 +1,1020 @@ +/* +Copyright (c) 2018-2019, tevador +Copyright (c) 2019, SChernykh + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "crypto/randomx/jit_compiler_a64.hpp" +#include "crypto/randomx/superscalar.hpp" +#include "crypto/randomx/program.hpp" +#include "crypto/randomx/reciprocal.h" +#include "crypto/randomx/virtual_memory.hpp" + +namespace ARMV8A { + +constexpr uint32_t B = 0x14000000; +constexpr uint32_t EOR = 0xCA000000; +constexpr uint32_t EOR32 = 0x4A000000; +constexpr uint32_t ADD = 0x8B000000; +constexpr uint32_t SUB = 0xCB000000; +constexpr uint32_t MUL = 0x9B007C00; +constexpr uint32_t UMULH = 0x9BC07C00; +constexpr uint32_t SMULH = 0x9B407C00; +constexpr uint32_t MOVZ = 0xD2800000; +constexpr uint32_t MOVN = 0x92800000; +constexpr uint32_t MOVK = 0xF2800000; +constexpr uint32_t ADD_IMM_LO = 0x91000000; +constexpr uint32_t ADD_IMM_HI = 0x91400000; +constexpr uint32_t LDR_LITERAL = 0x58000000; +constexpr uint32_t ROR = 0x9AC02C00; +constexpr uint32_t ROR_IMM = 0x93C00000; +constexpr uint32_t MOV_REG = 0xAA0003E0; +constexpr uint32_t MOV_VREG_EL = 0x6E080400; +constexpr uint32_t FADD = 0x4E60D400; +constexpr uint32_t FSUB = 0x4EE0D400; +constexpr uint32_t FEOR = 0x6E201C00; +constexpr uint32_t FMUL = 0x6E60DC00; +constexpr uint32_t FDIV = 0x6E60FC00; +constexpr uint32_t FSQRT = 0x6EE1F800; + +} + +namespace randomx { + +static const size_t CodeSize = ((uint8_t*)randomx_init_dataset_aarch64_end) - ((uint8_t*)randomx_program_aarch64); +static const size_t MainLoopBegin = ((uint8_t*)randomx_program_aarch64_main_loop) - ((uint8_t*)randomx_program_aarch64); +static const size_t PrologueSize = ((uint8_t*)randomx_program_aarch64_vm_instructions) - ((uint8_t*)randomx_program_aarch64); +static const size_t ImulRcpLiteralsEnd = ((uint8_t*)randomx_program_aarch64_imul_rcp_literals_end) - ((uint8_t*)randomx_program_aarch64); + +static size_t CalcDatasetItemSize() +{ + return + // Prologue + ((uint8_t*)randomx_calc_dataset_item_aarch64_prefetch - (uint8_t*)randomx_calc_dataset_item_aarch64) + + // Main loop + RandomX_CurrentConfig.CacheAccesses * ( + // Main loop prologue + ((uint8_t*)randomx_calc_dataset_item_aarch64_mix - ((uint8_t*)randomx_calc_dataset_item_aarch64_prefetch)) + 4 + + // Inner main loop (instructions) + ((RandomX_CurrentConfig.SuperscalarLatency * 3) + 2) * 16 + + // Main loop epilogue + ((uint8_t*)randomx_calc_dataset_item_aarch64_store_result - (uint8_t*)randomx_calc_dataset_item_aarch64_mix) + 4 + ) + + // Epilogue + ((uint8_t*)randomx_calc_dataset_item_aarch64_end - (uint8_t*)randomx_calc_dataset_item_aarch64_store_result); +} + +constexpr uint32_t IntRegMap[8] = { 4, 5, 6, 7, 12, 13, 14, 15 }; + +JitCompilerA64::JitCompilerA64() + : code((uint8_t*) allocExecutableMemory(CodeSize + CalcDatasetItemSize())) + , literalPos(ImulRcpLiteralsEnd) + , num32bitLiterals(0) +{ + memset(reg_changed_offset, 0, sizeof(reg_changed_offset)); + memcpy(code, (void*) randomx_program_aarch64, CodeSize); +} + +JitCompilerA64::~JitCompilerA64() +{ + freePagedMemory(code, CodeSize + CalcDatasetItemSize()); +} + +void JitCompilerA64::generateProgram(Program& program, ProgramConfiguration& config) +{ + uint32_t codePos = MainLoopBegin + 4; + + // and w16, w10, ScratchpadL3Mask64 + emit32(0x121A0000 | 16 | (10 << 5) | ((RandomX_CurrentConfig.Log2_ScratchpadL3 - 7) << 10), code, codePos); + + // and w17, w18, ScratchpadL3Mask64 + emit32(0x121A0000 | 17 | (18 << 5) | ((RandomX_CurrentConfig.Log2_ScratchpadL3 - 7) << 10), code, codePos); + + codePos = PrologueSize; + literalPos = ImulRcpLiteralsEnd; + num32bitLiterals = 0; + + for (uint32_t i = 0; i < RegistersCount; ++i) + reg_changed_offset[i] = codePos; + + for (uint32_t i = 0; i < program.getSize(); ++i) + { + Instruction& instr = program(i); + instr.src %= RegistersCount; + instr.dst %= RegistersCount; + (this->*engine[instr.opcode])(instr, codePos); + } + + // Update spMix2 + // eor w18, config.readReg2, config.readReg3 + emit32(ARMV8A::EOR32 | 18 | (IntRegMap[config.readReg2] << 5) | (IntRegMap[config.readReg3] << 16), code, codePos); + + // Jump back to the main loop + const uint32_t offset = (((uint8_t*)randomx_program_aarch64_vm_instructions_end) - ((uint8_t*)randomx_program_aarch64)) - codePos; + emit32(ARMV8A::B | (offset / 4), code, codePos); + + // and w18, w18, CacheLineAlignMask + codePos = (((uint8_t*)randomx_program_aarch64_cacheline_align_mask1) - ((uint8_t*)randomx_program_aarch64)); + emit32(0x121A0000 | 18 | (18 << 5) | ((RandomX_CurrentConfig.Log2_DatasetBaseSize - 7) << 10), code, codePos); + + // and w10, w10, CacheLineAlignMask + codePos = (((uint8_t*)randomx_program_aarch64_cacheline_align_mask2) - ((uint8_t*)randomx_program_aarch64)); + emit32(0x121A0000 | 10 | (10 << 5) | ((RandomX_CurrentConfig.Log2_DatasetBaseSize - 7) << 10), code, codePos); + + // Update spMix1 + // eor x10, config.readReg0, config.readReg1 + codePos = ((uint8_t*)randomx_program_aarch64_update_spMix1) - ((uint8_t*)randomx_program_aarch64); + emit32(ARMV8A::EOR | 10 | (IntRegMap[config.readReg0] << 5) | (IntRegMap[config.readReg1] << 16), code, codePos); + +#ifdef __GNUC__ + __builtin___clear_cache(reinterpret_cast(code + MainLoopBegin), reinterpret_cast(code + codePos)); +#endif +} + +void JitCompilerA64::generateProgramLight(Program& program, ProgramConfiguration& config, uint32_t datasetOffset) +{ + uint32_t codePos = MainLoopBegin + 4; + + // and w16, w10, ScratchpadL3Mask64 + emit32(0x121A0000 | 16 | (10 << 5) | ((RandomX_CurrentConfig.Log2_ScratchpadL3 - 7) << 10), code, codePos); + + // and w17, w18, ScratchpadL3Mask64 + emit32(0x121A0000 | 17 | (18 << 5) | ((RandomX_CurrentConfig.Log2_ScratchpadL3 - 7) << 10), code, codePos); + + codePos = PrologueSize; + literalPos = ImulRcpLiteralsEnd; + num32bitLiterals = 0; + + for (uint32_t i = 0; i < RegistersCount; ++i) + reg_changed_offset[i] = codePos; + + for (uint32_t i = 0; i < program.getSize(); ++i) + { + Instruction& instr = program(i); + instr.src %= RegistersCount; + instr.dst %= RegistersCount; + (this->*engine[instr.opcode])(instr, codePos); + } + + // Update spMix2 + // eor w18, config.readReg2, config.readReg3 + emit32(ARMV8A::EOR32 | 18 | (IntRegMap[config.readReg2] << 5) | (IntRegMap[config.readReg3] << 16), code, codePos); + + // Jump back to the main loop + const uint32_t offset = (((uint8_t*)randomx_program_aarch64_vm_instructions_end_light) - ((uint8_t*)randomx_program_aarch64)) - codePos; + emit32(ARMV8A::B | (offset / 4), code, codePos); + + // and w2, w9, CacheLineAlignMask + codePos = (((uint8_t*)randomx_program_aarch64_light_cacheline_align_mask) - ((uint8_t*)randomx_program_aarch64)); + emit32(0x121A0000 | 2 | (9 << 5) | ((RandomX_CurrentConfig.Log2_DatasetBaseSize - 7) << 10), code, codePos); + + // Update spMix1 + // eor x10, config.readReg0, config.readReg1 + codePos = ((uint8_t*)randomx_program_aarch64_update_spMix1) - ((uint8_t*)randomx_program_aarch64); + emit32(ARMV8A::EOR | 10 | (IntRegMap[config.readReg0] << 5) | (IntRegMap[config.readReg1] << 16), code, codePos); + + // Apply dataset offset + codePos = ((uint8_t*)randomx_program_aarch64_light_dataset_offset) - ((uint8_t*)randomx_program_aarch64); + + datasetOffset /= CacheLineSize; + const uint32_t imm_lo = datasetOffset & ((1 << 12) - 1); + const uint32_t imm_hi = datasetOffset >> 12; + + emit32(ARMV8A::ADD_IMM_LO | 2 | (2 << 5) | (imm_lo << 10), code, codePos); + emit32(ARMV8A::ADD_IMM_HI | 2 | (2 << 5) | (imm_hi << 10), code, codePos); + +#ifdef __GNUC__ + __builtin___clear_cache(reinterpret_cast(code + MainLoopBegin), reinterpret_cast(code + codePos)); +#endif +} + +template +void JitCompilerA64::generateSuperscalarHash(SuperscalarProgram(&programs)[N], std::vector &reciprocalCache) +{ + uint32_t codePos = CodeSize; + + uint8_t* p1 = (uint8_t*)randomx_calc_dataset_item_aarch64; + uint8_t* p2 = (uint8_t*)randomx_calc_dataset_item_aarch64_prefetch; + memcpy(code + codePos, p1, p2 - p1); + codePos += p2 - p1; + + num32bitLiterals = 64; + constexpr uint32_t tmp_reg = 12; + + for (size_t i = 0; i < RandomX_CurrentConfig.CacheAccesses; ++i) + { + // and x11, x10, CacheSize / CacheLineSize - 1 + emit32(0x92400000 | 11 | (10 << 5) | ((RandomX_CurrentConfig.Log2_CacheSize - 1) << 10), code, codePos); + + p1 = ((uint8_t*)randomx_calc_dataset_item_aarch64_prefetch) + 4; + p2 = (uint8_t*)randomx_calc_dataset_item_aarch64_mix; + memcpy(code + codePos, p1, p2 - p1); + codePos += p2 - p1; + + SuperscalarProgram& prog = programs[i]; + const size_t progSize = prog.getSize(); + + uint32_t jmp_pos = codePos; + codePos += 4; + + // Fill in literal pool + for (size_t j = 0; j < progSize; ++j) + { + const Instruction& instr = prog(j); + if (static_cast(instr.opcode) == randomx::SuperscalarInstructionType::IMUL_RCP) + emit64(reciprocalCache[instr.getImm32()], code, codePos); + } + + // Jump over literal pool + uint32_t literal_pos = jmp_pos; + emit32(ARMV8A::B | ((codePos - jmp_pos) / 4), code, literal_pos); + + for (size_t j = 0; j < progSize; ++j) + { + const Instruction& instr = prog(j); + const uint32_t src = instr.src; + const uint32_t dst = instr.dst; + + switch (static_cast(instr.opcode)) + { + case randomx::SuperscalarInstructionType::ISUB_R: + emit32(ARMV8A::SUB | dst | (dst << 5) | (src << 16), code, codePos); + break; + case randomx::SuperscalarInstructionType::IXOR_R: + emit32(ARMV8A::EOR | dst | (dst << 5) | (src << 16), code, codePos); + break; + case randomx::SuperscalarInstructionType::IADD_RS: + emit32(ARMV8A::ADD | dst | (dst << 5) | (instr.getModShift() << 10) | (src << 16), code, codePos); + break; + case randomx::SuperscalarInstructionType::IMUL_R: + emit32(ARMV8A::MUL | dst | (dst << 5) | (src << 16), code, codePos); + break; + case randomx::SuperscalarInstructionType::IROR_C: + emit32(ARMV8A::ROR_IMM | dst | (dst << 5) | ((instr.getImm32() & 63) << 10) | (dst << 16), code, codePos); + break; + case randomx::SuperscalarInstructionType::IADD_C7: + case randomx::SuperscalarInstructionType::IADD_C8: + case randomx::SuperscalarInstructionType::IADD_C9: + emitAddImmediate(dst, dst, instr.getImm32(), code, codePos); + break; + case randomx::SuperscalarInstructionType::IXOR_C7: + case randomx::SuperscalarInstructionType::IXOR_C8: + case randomx::SuperscalarInstructionType::IXOR_C9: + emitMovImmediate(tmp_reg, instr.getImm32(), code, codePos); + emit32(ARMV8A::EOR | dst | (dst << 5) | (tmp_reg << 16), code, codePos); + break; + case randomx::SuperscalarInstructionType::IMULH_R: + emit32(ARMV8A::UMULH | dst | (dst << 5) | (src << 16), code, codePos); + break; + case randomx::SuperscalarInstructionType::ISMULH_R: + emit32(ARMV8A::SMULH | dst | (dst << 5) | (src << 16), code, codePos); + break; + case randomx::SuperscalarInstructionType::IMUL_RCP: + { + int32_t offset = (literal_pos - codePos) / 4; + offset &= (1 << 19) - 1; + literal_pos += 8; + + // ldr tmp_reg, reciprocal + emit32(ARMV8A::LDR_LITERAL | tmp_reg | (offset << 5), code, codePos); + + // mul dst, dst, tmp_reg + emit32(ARMV8A::MUL | dst | (dst << 5) | (tmp_reg << 16), code, codePos); + } + break; + default: + break; + } + } + + p1 = (uint8_t*)randomx_calc_dataset_item_aarch64_mix; + p2 = (uint8_t*)randomx_calc_dataset_item_aarch64_store_result; + memcpy(code + codePos, p1, p2 - p1); + codePos += p2 - p1; + + // Update registerValue + emit32(ARMV8A::MOV_REG | 10 | (prog.getAddressRegister() << 16), code, codePos); + } + + p1 = (uint8_t*)randomx_calc_dataset_item_aarch64_store_result; + p2 = (uint8_t*)randomx_calc_dataset_item_aarch64_end; + memcpy(code + codePos, p1, p2 - p1); + codePos += p2 - p1; + +#ifdef __GNUC__ + __builtin___clear_cache(reinterpret_cast(code + CodeSize), reinterpret_cast(code + codePos)); +#endif +} + +template void JitCompilerA64::generateSuperscalarHash(SuperscalarProgram(&programs)[RANDOMX_CACHE_MAX_ACCESSES], std::vector &reciprocalCache); + +DatasetInitFunc* JitCompilerA64::getDatasetInitFunc() +{ + return (DatasetInitFunc*)(code + (((uint8_t*)randomx_init_dataset_aarch64) - ((uint8_t*)randomx_program_aarch64))); +} + +size_t JitCompilerA64::getCodeSize() +{ + return CodeSize; +} + +void JitCompilerA64::emitMovImmediate(uint32_t dst, uint32_t imm, uint8_t* code, uint32_t& codePos) +{ + uint32_t k = codePos; + + if (imm < (1 << 16)) + { + // movz tmp_reg, imm32 (16 low bits) + emit32(ARMV8A::MOVZ | dst | (imm << 5), code, k); + } + else + { + if (num32bitLiterals < 64) + { + if (static_cast(imm) < 0) + { + // smov dst, vN.s[M] + emit32(0x4E042C00 | dst | ((num32bitLiterals / 4) << 5) | ((num32bitLiterals % 4) << 19), code, k); + } + else + { + // umov dst, vN.s[M] + emit32(0x0E043C00 | dst | ((num32bitLiterals / 4) << 5) | ((num32bitLiterals % 4) << 19), code, k); + } + + ((uint32_t*)(code + ImulRcpLiteralsEnd))[num32bitLiterals] = imm; + ++num32bitLiterals; + } + else + { + if (static_cast(imm) < 0) + { + // movn tmp_reg, ~imm32 (16 high bits) + emit32(ARMV8A::MOVN | dst | (1 << 21) | ((~imm >> 16) << 5), code, k); + } + else + { + // movz tmp_reg, imm32 (16 high bits) + emit32(ARMV8A::MOVZ | dst | (1 << 21) | ((imm >> 16) << 5), code, k); + } + + // movk tmp_reg, imm32 (16 low bits) + emit32(ARMV8A::MOVK | dst | ((imm & 0xFFFF) << 5), code, k); + } + } + + codePos = k; +} + +void JitCompilerA64::emitAddImmediate(uint32_t dst, uint32_t src, uint32_t imm, uint8_t* code, uint32_t& codePos) +{ + uint32_t k = codePos; + + if (imm < (1 << 24)) + { + const uint32_t imm_lo = imm & ((1 << 12) - 1); + const uint32_t imm_hi = imm >> 12; + + if (imm_lo && imm_hi) + { + emit32(ARMV8A::ADD_IMM_LO | dst | (src << 5) | (imm_lo << 10), code, k); + emit32(ARMV8A::ADD_IMM_HI | dst | (dst << 5) | (imm_hi << 10), code, k); + } + else if (imm_lo) + { + emit32(ARMV8A::ADD_IMM_LO | dst | (src << 5) | (imm_lo << 10), code, k); + } + else + { + emit32(ARMV8A::ADD_IMM_HI | dst | (src << 5) | (imm_hi << 10), code, k); + } + } + else + { + constexpr uint32_t tmp_reg = 18; + emitMovImmediate(tmp_reg, imm, code, k); + + // add dst, src, tmp_reg + emit32(ARMV8A::ADD | dst | (src << 5) | (tmp_reg << 16), code, k); + } + + codePos = k; +} + +template +void JitCompilerA64::emitMemLoad(uint32_t dst, uint32_t src, Instruction& instr, uint8_t* code, uint32_t& codePos) +{ + uint32_t k = codePos; + + uint32_t imm = instr.getImm32(); + + if (src != dst) + { + imm &= instr.getModMem() ? (RandomX_CurrentConfig.ScratchpadL1_Size - 1) : (RandomX_CurrentConfig.ScratchpadL2_Size - 1); + emitAddImmediate(tmp_reg, src, imm, code, k); + + constexpr uint32_t t = 0x927d0000 | tmp_reg | (tmp_reg << 5); + const uint32_t andInstrL1 = t | ((RandomX_CurrentConfig.Log2_ScratchpadL1 - 4) << 10); + const uint32_t andInstrL2 = t | ((RandomX_CurrentConfig.Log2_ScratchpadL2 - 4) << 10); + + emit32(instr.getModMem() ? andInstrL1 : andInstrL2, code, k); + + // ldr tmp_reg, [x2, tmp_reg] + emit32(0xf8606840 | tmp_reg | (tmp_reg << 16), code, k); + } + else + { + imm = (imm & ScratchpadL3Mask) >> 3; + emitMovImmediate(tmp_reg, imm, code, k); + + // ldr tmp_reg, [x2, tmp_reg, lsl 3] + emit32(0xf8607840 | tmp_reg | (tmp_reg << 16), code, k); + } + + codePos = k; +} + +template +void JitCompilerA64::emitMemLoadFP(uint32_t src, Instruction& instr, uint8_t* code, uint32_t& codePos) +{ + uint32_t k = codePos; + + uint32_t imm = instr.getImm32(); + constexpr uint32_t tmp_reg = 18; + + imm &= instr.getModMem() ? (RandomX_CurrentConfig.ScratchpadL1_Size - 1) : (RandomX_CurrentConfig.ScratchpadL2_Size - 1); + emitAddImmediate(tmp_reg, src, imm, code, k); + + constexpr uint32_t t = 0x927d0000 | tmp_reg | (tmp_reg << 5); + const uint32_t andInstrL1 = t | ((RandomX_CurrentConfig.Log2_ScratchpadL1 - 4) << 10); + const uint32_t andInstrL2 = t | ((RandomX_CurrentConfig.Log2_ScratchpadL2 - 4) << 10); + + emit32(instr.getModMem() ? andInstrL1 : andInstrL2, code, k); + + // add tmp_reg, x2, tmp_reg + emit32(ARMV8A::ADD | tmp_reg | (2 << 5) | (tmp_reg << 16), code, k); + + // ldpsw tmp_reg, tmp_reg + 1, [tmp_reg] + emit32(0x69400000 | tmp_reg | (tmp_reg << 5) | ((tmp_reg + 1) << 10), code, k); + + // ins tmp_reg_fp.d[0], tmp_reg + emit32(0x4E081C00 | tmp_reg_fp | (tmp_reg << 5), code, k); + + // ins tmp_reg_fp.d[1], tmp_reg + 1 + emit32(0x4E181C00 | tmp_reg_fp | ((tmp_reg + 1) << 5), code, k); + + // scvtf tmp_reg_fp.2d, tmp_reg_fp.2d + emit32(0x4E61D800 | tmp_reg_fp | (tmp_reg_fp << 5), code, k); + + codePos = k; +} + +void JitCompilerA64::h_IADD_RS(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + const uint32_t shift = instr.getModShift(); + + // add dst, src << shift + emit32(ARMV8A::ADD | dst | (dst << 5) | (shift << 10) | (src << 16), code, k); + + if (instr.dst == RegisterNeedsDisplacement) + emitAddImmediate(dst, dst, instr.getImm32(), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_IADD_M(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + constexpr uint32_t tmp_reg = 18; + emitMemLoad(dst, src, instr, code, k); + + // add dst, dst, tmp_reg + emit32(ARMV8A::ADD | dst | (dst << 5) | (tmp_reg << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_ISUB_R(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + if (src != dst) + { + // sub dst, dst, src + emit32(ARMV8A::SUB | dst | (dst << 5) | (src << 16), code, k); + } + else + { + emitAddImmediate(dst, dst, -instr.getImm32(), code, k); + } + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_ISUB_M(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + constexpr uint32_t tmp_reg = 18; + emitMemLoad(dst, src, instr, code, k); + + // sub dst, dst, tmp_reg + emit32(ARMV8A::SUB | dst | (dst << 5) | (tmp_reg << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_IMUL_R(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + if (src == dst) + { + src = 18; + emitMovImmediate(src, instr.getImm32(), code, k); + } + + // mul dst, dst, src + emit32(ARMV8A::MUL | dst | (dst << 5) | (src << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_IMUL_M(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + constexpr uint32_t tmp_reg = 18; + emitMemLoad(dst, src, instr, code, k); + + // sub dst, dst, tmp_reg + emit32(ARMV8A::MUL | dst | (dst << 5) | (tmp_reg << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_IMULH_R(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + // umulh dst, dst, src + emit32(ARMV8A::UMULH | dst | (dst << 5) | (src << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_IMULH_M(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + constexpr uint32_t tmp_reg = 18; + emitMemLoad(dst, src, instr, code, k); + + // umulh dst, dst, tmp_reg + emit32(ARMV8A::UMULH | dst | (dst << 5) | (tmp_reg << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_ISMULH_R(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + // smulh dst, dst, src + emit32(ARMV8A::SMULH | dst | (dst << 5) | (src << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_ISMULH_M(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + constexpr uint32_t tmp_reg = 18; + emitMemLoad(dst, src, instr, code, k); + + // smulh dst, dst, tmp_reg + emit32(ARMV8A::SMULH | dst | (dst << 5) | (tmp_reg << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_IMUL_RCP(Instruction& instr, uint32_t& codePos) +{ + const uint64_t divisor = instr.getImm32(); + if (isZeroOrPowerOf2(divisor)) + return; + + uint32_t k = codePos; + + constexpr uint32_t tmp_reg = 18; + const uint32_t dst = IntRegMap[instr.dst]; + + constexpr uint64_t N = 1ULL << 63; + const uint64_t q = N / divisor; + const uint64_t r = N % divisor; +#ifdef __GNUC__ + const uint64_t shift = 64 - __builtin_clzll(divisor); +#else + uint64_t shift = 32; + for (uint64_t k = 1U << 31; (k & divisor) == 0; k >>= 1) + --shift; +#endif + + const uint32_t literal_id = (ImulRcpLiteralsEnd - literalPos) / sizeof(uint64_t); + + literalPos -= sizeof(uint64_t); + *(uint64_t*)(code + literalPos) = (q << shift) + ((r << shift) / divisor); + + if (literal_id < 13) + { + static constexpr uint32_t literal_regs[13] = { 30 << 16, 29 << 16, 28 << 16, 27 << 16, 26 << 16, 25 << 16, 24 << 16, 23 << 16, 22 << 16, 21 << 16, 20 << 16, 11 << 16, 0 }; + + // mul dst, dst, literal_reg + emit32(ARMV8A::MUL | dst | (dst << 5) | literal_regs[literal_id], code, k); + } + else + { + // ldr tmp_reg, reciprocal + const uint32_t offset = (literalPos - k) / 4; + emit32(ARMV8A::LDR_LITERAL | tmp_reg | (offset << 5), code, k); + + // mul dst, dst, tmp_reg + emit32(ARMV8A::MUL | dst | (dst << 5) | (tmp_reg << 16), code, k); + } + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_INEG_R(Instruction& instr, uint32_t& codePos) +{ + const uint32_t dst = IntRegMap[instr.dst]; + + // sub dst, xzr, dst + emit32(ARMV8A::SUB | dst | (31 << 5) | (dst << 16), code, codePos); + + reg_changed_offset[instr.dst] = codePos; +} + +void JitCompilerA64::h_IXOR_R(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + if (src == dst) + { + src = 18; + emitMovImmediate(src, instr.getImm32(), code, k); + } + + // eor dst, dst, src + emit32(ARMV8A::EOR | dst | (dst << 5) | (src << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_IXOR_M(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + constexpr uint32_t tmp_reg = 18; + emitMemLoad(dst, src, instr, code, k); + + // eor dst, dst, tmp_reg + emit32(ARMV8A::EOR | dst | (dst << 5) | (tmp_reg << 16), code, k); + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_IROR_R(Instruction& instr, uint32_t& codePos) +{ + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + if (src != dst) + { + // ror dst, dst, src + emit32(ARMV8A::ROR | dst | (dst << 5) | (src << 16), code, codePos); + } + else + { + // ror dst, dst, imm + emit32(ARMV8A::ROR_IMM | dst | (dst << 5) | ((instr.getImm32() & 63) << 10) | (dst << 16), code, codePos); + } + + reg_changed_offset[instr.dst] = codePos; +} + +void JitCompilerA64::h_IROL_R(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + if (src != dst) + { + constexpr uint32_t tmp_reg = 18; + + // sub tmp_reg, xzr, src + emit32(ARMV8A::SUB | tmp_reg | (31 << 5) | (src << 16), code, k); + + // ror dst, dst, tmp_reg + emit32(ARMV8A::ROR | dst | (dst << 5) | (tmp_reg << 16), code, k); + } + else + { + // ror dst, dst, imm + emit32(ARMV8A::ROR_IMM | dst | (dst << 5) | ((-instr.getImm32() & 63) << 10) | (dst << 16), code, k); + } + + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_ISWAP_R(Instruction& instr, uint32_t& codePos) +{ + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + + if (src == dst) + return; + + uint32_t k = codePos; + + constexpr uint32_t tmp_reg = 18; + emit32(ARMV8A::MOV_REG | tmp_reg | (dst << 16), code, k); + emit32(ARMV8A::MOV_REG | dst | (src << 16), code, k); + emit32(ARMV8A::MOV_REG | src | (tmp_reg << 16), code, k); + + reg_changed_offset[instr.src] = k; + reg_changed_offset[instr.dst] = k; + codePos = k; +} + +void JitCompilerA64::h_FSWAP_R(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t dst = instr.dst + 16; + + constexpr uint32_t tmp_reg_fp = 28; + constexpr uint32_t src_index1 = 1 << 14; + constexpr uint32_t dst_index1 = 1 << 20; + + emit32(ARMV8A::MOV_VREG_EL | tmp_reg_fp | (dst << 5) | src_index1, code, k); + emit32(ARMV8A::MOV_VREG_EL | dst | (dst << 5) | dst_index1, code, k); + emit32(ARMV8A::MOV_VREG_EL | dst | (tmp_reg_fp << 5), code, k); + + codePos = k; +} + +void JitCompilerA64::h_FADD_R(Instruction& instr, uint32_t& codePos) +{ + const uint32_t src = (instr.src % 4) + 24; + const uint32_t dst = (instr.dst % 4) + 16; + + emit32(ARMV8A::FADD | dst | (dst << 5) | (src << 16), code, codePos); +} + +void JitCompilerA64::h_FADD_M(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = (instr.dst % 4) + 16; + + constexpr uint32_t tmp_reg_fp = 28; + emitMemLoadFP(src, instr, code, k); + + emit32(ARMV8A::FADD | dst | (dst << 5) | (tmp_reg_fp << 16), code, k); + + codePos = k; +} + +void JitCompilerA64::h_FSUB_R(Instruction& instr, uint32_t& codePos) +{ + const uint32_t src = (instr.src % 4) + 24; + const uint32_t dst = (instr.dst % 4) + 16; + + emit32(ARMV8A::FSUB | dst | (dst << 5) | (src << 16), code, codePos); +} + +void JitCompilerA64::h_FSUB_M(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = (instr.dst % 4) + 16; + + constexpr uint32_t tmp_reg_fp = 28; + emitMemLoadFP(src, instr, code, k); + + emit32(ARMV8A::FSUB | dst | (dst << 5) | (tmp_reg_fp << 16), code, k); + + codePos = k; +} + +void JitCompilerA64::h_FSCAL_R(Instruction& instr, uint32_t& codePos) +{ + const uint32_t dst = (instr.dst % 4) + 16; + + emit32(ARMV8A::FEOR | dst | (dst << 5) | (31 << 16), code, codePos); +} + +void JitCompilerA64::h_FMUL_R(Instruction& instr, uint32_t& codePos) +{ + const uint32_t src = (instr.src % 4) + 24; + const uint32_t dst = (instr.dst % 4) + 20; + + emit32(ARMV8A::FMUL | dst | (dst << 5) | (src << 16), code, codePos); +} + +void JitCompilerA64::h_FDIV_M(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = (instr.dst % 4) + 20; + + constexpr uint32_t tmp_reg_fp = 28; + emitMemLoadFP(src, instr, code, k); + + // and tmp_reg_fp, tmp_reg_fp, and_mask_reg + emit32(0x4E201C00 | tmp_reg_fp | (tmp_reg_fp << 5) | (29 << 16), code, k); + + // orr tmp_reg_fp, tmp_reg_fp, or_mask_reg + emit32(0x4EA01C00 | tmp_reg_fp | (tmp_reg_fp << 5) | (30 << 16), code, k); + + emit32(ARMV8A::FDIV | dst | (dst << 5) | (tmp_reg_fp << 16), code, k); + + codePos = k; +} + +void JitCompilerA64::h_FSQRT_R(Instruction& instr, uint32_t& codePos) +{ + const uint32_t dst = (instr.dst % 4) + 20; + + emit32(ARMV8A::FSQRT | dst | (dst << 5), code, codePos); +} + +void JitCompilerA64::h_CBRANCH(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t dst = IntRegMap[instr.dst]; + const uint32_t modCond = instr.getModCond(); + const uint32_t shift = modCond + RandomX_CurrentConfig.JumpOffset; + const uint32_t imm = (instr.getImm32() | (1U << shift)) & ~(1U << (shift - 1)); + + emitAddImmediate(dst, dst, imm, code, k); + + // tst dst, mask + emit32((0xF2781C1F - (modCond << 16)) | (dst << 5), code, k); + + int32_t offset = reg_changed_offset[instr.dst]; + offset = ((offset - k) >> 2) & ((1 << 19) - 1); + + // beq target + emit32(0x54000000 | (offset << 5), code, k); + + for (uint32_t i = 0; i < RegistersCount; ++i) + reg_changed_offset[i] = k; + + codePos = k; +} + +void JitCompilerA64::h_CFROUND(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + + constexpr uint32_t tmp_reg = 18; + constexpr uint32_t fpcr_tmp_reg = 8; + + // ror tmp_reg, src, imm + emit32(ARMV8A::ROR_IMM | tmp_reg | (src << 5) | ((instr.getImm32() & 63) << 10) | (src << 16), code, k); + + // bfi fpcr_tmp_reg, tmp_reg, 40, 2 + emit32(0xB3580400 | fpcr_tmp_reg | (tmp_reg << 5), code, k); + + // rbit tmp_reg, fpcr_tmp_reg + emit32(0xDAC00000 | tmp_reg | (fpcr_tmp_reg << 5), code, k); + + // msr fpcr, tmp_reg + emit32(0xD51B4400 | tmp_reg, code, k); + + codePos = k; +} + +void JitCompilerA64::h_ISTORE(Instruction& instr, uint32_t& codePos) +{ + uint32_t k = codePos; + + const uint32_t src = IntRegMap[instr.src]; + const uint32_t dst = IntRegMap[instr.dst]; + constexpr uint32_t tmp_reg = 18; + + uint32_t imm = instr.getImm32(); + + if (instr.getModCond() < StoreL3Condition) + imm &= instr.getModMem() ? (RandomX_CurrentConfig.ScratchpadL1_Size - 1) : (RandomX_CurrentConfig.ScratchpadL2_Size - 1); + else + imm &= RandomX_CurrentConfig.ScratchpadL3_Size - 1; + + emitAddImmediate(tmp_reg, dst, imm, code, k); + + constexpr uint32_t t = 0x927d0000 | tmp_reg | (tmp_reg << 5); + const uint32_t andInstrL1 = t | ((RandomX_CurrentConfig.Log2_ScratchpadL1 - 4) << 10); + const uint32_t andInstrL2 = t | ((RandomX_CurrentConfig.Log2_ScratchpadL2 - 4) << 10); + const uint32_t andInstrL3 = t | ((RandomX_CurrentConfig.Log2_ScratchpadL3 - 4) << 10); + + emit32((instr.getModCond() < StoreL3Condition) ? (instr.getModMem() ? andInstrL1 : andInstrL2) : andInstrL3, code, k); + + // str src, [x2, tmp_reg] + emit32(0xF8206840 | src | (tmp_reg << 16), code, k); + + codePos = k; +} + +void JitCompilerA64::h_NOP(Instruction& instr, uint32_t& codePos) +{ +} + +InstructionGeneratorA64 JitCompilerA64::engine[256] = {}; + +} diff --git a/src/crypto/randomx/jit_compiler_a64.hpp b/src/crypto/randomx/jit_compiler_a64.hpp index 4b0bed66..e524feb8 100644 --- a/src/crypto/randomx/jit_compiler_a64.hpp +++ b/src/crypto/randomx/jit_compiler_a64.hpp @@ -1,5 +1,6 @@ /* Copyright (c) 2018-2019, tevador +Copyright (c) 2019, SChernykh All rights reserved. @@ -32,42 +33,91 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "crypto/randomx/common.hpp" +#include "crypto/randomx/jit_compiler_a64_static.hpp" namespace randomx { class Program; class ProgramConfiguration; class SuperscalarProgram; + class Instruction; + + typedef void(JitCompilerA64::*InstructionGeneratorA64)(Instruction&, uint32_t&); class JitCompilerA64 { public: - JitCompilerA64() { - throw std::runtime_error("ARM64 JIT compiler is not implemented yet."); - } - void generateProgram(Program&, ProgramConfiguration&) { + JitCompilerA64(); + ~JitCompilerA64(); + + void generateProgram(Program&, ProgramConfiguration&); + void generateProgramLight(Program&, ProgramConfiguration&, uint32_t); - } - void generateProgramLight(Program&, ProgramConfiguration&, uint32_t) { - - } template - void generateSuperscalarHash(SuperscalarProgram(&programs)[N], std::vector &) { + void generateSuperscalarHash(SuperscalarProgram(&programs)[N], std::vector &); - } - void generateDatasetInitCode() { + void generateDatasetInitCode() {} + ProgramFunc* getProgramFunc() { return reinterpret_cast(code); } + DatasetInitFunc* getDatasetInitFunc(); + uint8_t* getCode() { return code; } + size_t getCodeSize(); + + static InstructionGeneratorA64 engine[256]; + uint32_t reg_changed_offset[8]; + uint8_t* code; + uint32_t literalPos; + uint32_t num32bitLiterals; + + static void emit32(uint32_t val, uint8_t* code, uint32_t& codePos) + { + *(uint32_t*)(code + codePos) = val; + codePos += sizeof(val); } - ProgramFunc* getProgramFunc() { - return nullptr; - } - DatasetInitFunc* getDatasetInitFunc() { - return nullptr; - } - uint8_t* getCode() { - return nullptr; - } - size_t getCodeSize() { - return 0; + + static void emit64(uint64_t val, uint8_t* code, uint32_t& codePos) + { + *(uint64_t*)(code + codePos) = val; + codePos += sizeof(val); } + + void emitMovImmediate(uint32_t dst, uint32_t imm, uint8_t* code, uint32_t& codePos); + void emitAddImmediate(uint32_t dst, uint32_t src, uint32_t imm, uint8_t* code, uint32_t& codePos); + + template + void emitMemLoad(uint32_t dst, uint32_t src, Instruction& instr, uint8_t* code, uint32_t& codePos); + + template + void emitMemLoadFP(uint32_t src, Instruction& instr, uint8_t* code, uint32_t& codePos); + + void h_IADD_RS(Instruction&, uint32_t&); + void h_IADD_M(Instruction&, uint32_t&); + void h_ISUB_R(Instruction&, uint32_t&); + void h_ISUB_M(Instruction&, uint32_t&); + void h_IMUL_R(Instruction&, uint32_t&); + void h_IMUL_M(Instruction&, uint32_t&); + void h_IMULH_R(Instruction&, uint32_t&); + void h_IMULH_M(Instruction&, uint32_t&); + void h_ISMULH_R(Instruction&, uint32_t&); + void h_ISMULH_M(Instruction&, uint32_t&); + void h_IMUL_RCP(Instruction&, uint32_t&); + void h_INEG_R(Instruction&, uint32_t&); + void h_IXOR_R(Instruction&, uint32_t&); + void h_IXOR_M(Instruction&, uint32_t&); + void h_IROR_R(Instruction&, uint32_t&); + void h_IROL_R(Instruction&, uint32_t&); + void h_ISWAP_R(Instruction&, uint32_t&); + void h_FSWAP_R(Instruction&, uint32_t&); + void h_FADD_R(Instruction&, uint32_t&); + void h_FADD_M(Instruction&, uint32_t&); + void h_FSUB_R(Instruction&, uint32_t&); + void h_FSUB_M(Instruction&, uint32_t&); + void h_FSCAL_R(Instruction&, uint32_t&); + void h_FMUL_R(Instruction&, uint32_t&); + void h_FDIV_M(Instruction&, uint32_t&); + void h_FSQRT_R(Instruction&, uint32_t&); + void h_CBRANCH(Instruction&, uint32_t&); + void h_CFROUND(Instruction&, uint32_t&); + void h_ISTORE(Instruction&, uint32_t&); + void h_NOP(Instruction&, uint32_t&); }; } diff --git a/src/crypto/randomx/jit_compiler_a64_static.S b/src/crypto/randomx/jit_compiler_a64_static.S new file mode 100644 index 00000000..a813e821 --- /dev/null +++ b/src/crypto/randomx/jit_compiler_a64_static.S @@ -0,0 +1,576 @@ +# Copyright (c) 2018-2019, tevador +# Copyright (c) 2019, SChernykh +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + .arch armv8-a + .text + .global randomx_program_aarch64 + .global randomx_program_aarch64_main_loop + .global randomx_program_aarch64_vm_instructions + .global randomx_program_aarch64_imul_rcp_literals_end + .global randomx_program_aarch64_vm_instructions_end + .global randomx_program_aarch64_cacheline_align_mask1 + .global randomx_program_aarch64_cacheline_align_mask2 + .global randomx_program_aarch64_update_spMix1 + .global randomx_program_aarch64_vm_instructions_end_light + .global randomx_program_aarch64_light_cacheline_align_mask + .global randomx_program_aarch64_light_dataset_offset + .global randomx_init_dataset_aarch64 + .global randomx_init_dataset_aarch64_end + .global randomx_calc_dataset_item_aarch64 + .global randomx_calc_dataset_item_aarch64_prefetch + .global randomx_calc_dataset_item_aarch64_mix + .global randomx_calc_dataset_item_aarch64_store_result + .global randomx_calc_dataset_item_aarch64_end + +# Register allocation + +# x0 -> pointer to reg buffer and then literal for IMUL_RCP +# x1 -> pointer to mem buffer and then to dataset +# x2 -> pointer to scratchpad +# x3 -> loop counter +# x4 -> "r0" +# x5 -> "r1" +# x6 -> "r2" +# x7 -> "r3" +# x8 -> fpcr (reversed bits) +# x9 -> mx, ma +# x10 -> spMix1 +# x11 -> literal for IMUL_RCP +# x12 -> "r4" +# x13 -> "r5" +# x14 -> "r6" +# x15 -> "r7" +# x16 -> spAddr0 +# x17 -> spAddr1 +# x18 -> temporary +# x19 -> temporary +# x20 -> literal for IMUL_RCP +# x21 -> literal for IMUL_RCP +# x22 -> literal for IMUL_RCP +# x23 -> literal for IMUL_RCP +# x24 -> literal for IMUL_RCP +# x25 -> literal for IMUL_RCP +# x26 -> literal for IMUL_RCP +# x27 -> literal for IMUL_RCP +# x28 -> literal for IMUL_RCP +# x29 -> literal for IMUL_RCP +# x30 -> literal for IMUL_RCP + +# v0-v15 -> store 32-bit literals +# v16 -> "f0" +# v17 -> "f1" +# v18 -> "f2" +# v19 -> "f3" +# v20 -> "e0" +# v21 -> "e1" +# v22 -> "e2" +# v23 -> "e3" +# v24 -> "a0" +# v25 -> "a1" +# v26 -> "a2" +# v27 -> "a3" +# v28 -> temporary +# v29 -> E 'and' mask = 0x00ffffffffffffff00ffffffffffffff +# v30 -> E 'or' mask = 0x3*00000000******3*00000000****** +# v31 -> scale mask = 0x81f000000000000081f0000000000000 + +randomx_program_aarch64: + # Save callee-saved registers + sub sp, sp, 192 + stp x16, x17, [sp] + stp x18, x19, [sp, 16] + stp x20, x21, [sp, 32] + stp x22, x23, [sp, 48] + stp x24, x25, [sp, 64] + stp x26, x27, [sp, 80] + stp x28, x29, [sp, 96] + stp x8, x30, [sp, 112] + stp d8, d9, [sp, 128] + stp d10, d11, [sp, 144] + stp d12, d13, [sp, 160] + stp d14, d15, [sp, 176] + + # Zero integer registers + mov x4, xzr + mov x5, xzr + mov x6, xzr + mov x7, xzr + mov x12, xzr + mov x13, xzr + mov x14, xzr + mov x15, xzr + + # Load ma, mx and dataset pointer + ldp x9, x1, [x1] + + # Load initial spMix value + mov x10, x9 + + # Load group A registers + ldp q24, q25, [x0, 192] + ldp q26, q27, [x0, 224] + + # Load E 'and' mask + mov x16, 0x00FFFFFFFFFFFFFF + ins v29.d[0], x16 + ins v29.d[1], x16 + + # Load E 'or' mask (stored in reg.f[0]) + ldr q30, [x0, 64] + + # Load scale mask + mov x16, 0x80f0000000000000 + ins v31.d[0], x16 + ins v31.d[1], x16 + + # Read fpcr + mrs x8, fpcr + rbit x8, x8 + + # Save x0 + str x0, [sp, -16]! + + # Read literals + ldr x0, literal_x0 + ldr x11, literal_x11 + ldr x20, literal_x20 + ldr x21, literal_x21 + ldr x22, literal_x22 + ldr x23, literal_x23 + ldr x24, literal_x24 + ldr x25, literal_x25 + ldr x26, literal_x26 + ldr x27, literal_x27 + ldr x28, literal_x28 + ldr x29, literal_x29 + ldr x30, literal_x30 + + ldr q0, literal_v0 + ldr q1, literal_v1 + ldr q2, literal_v2 + ldr q3, literal_v3 + ldr q4, literal_v4 + ldr q5, literal_v5 + ldr q6, literal_v6 + ldr q7, literal_v7 + ldr q8, literal_v8 + ldr q9, literal_v9 + ldr q10, literal_v10 + ldr q11, literal_v11 + ldr q12, literal_v12 + ldr q13, literal_v13 + ldr q14, literal_v14 + ldr q15, literal_v15 + +randomx_program_aarch64_main_loop: + # spAddr0 = spMix1 & ScratchpadL3Mask64; + # spAddr1 = (spMix1 >> 32) & ScratchpadL3Mask64; + lsr x18, x10, 32 + + # Actual mask will be inserted by JIT compiler + and w16, w10, 1 + and w17, w18, 1 + + # x16 = scratchpad + spAddr0 + # x17 = scratchpad + spAddr1 + add x16, x16, x2 + add x17, x17, x2 + + # xor integer registers with scratchpad data (spAddr0) + ldp x18, x19, [x16] + eor x4, x4, x18 + eor x5, x5, x19 + ldp x18, x19, [x16, 16] + eor x6, x6, x18 + eor x7, x7, x19 + ldp x18, x19, [x16, 32] + eor x12, x12, x18 + eor x13, x13, x19 + ldp x18, x19, [x16, 48] + eor x14, x14, x18 + eor x15, x15, x19 + + # Load group F registers (spAddr1) + ldpsw x18, x19, [x17] + ins v16.d[0], x18 + ins v16.d[1], x19 + ldpsw x18, x19, [x17, 8] + ins v17.d[0], x18 + ins v17.d[1], x19 + ldpsw x18, x19, [x17, 16] + ins v18.d[0], x18 + ins v18.d[1], x19 + ldpsw x18, x19, [x17, 24] + ins v19.d[0], x18 + ins v19.d[1], x19 + scvtf v16.2d, v16.2d + scvtf v17.2d, v17.2d + scvtf v18.2d, v18.2d + scvtf v19.2d, v19.2d + + # Load group E registers (spAddr1) + ldpsw x18, x19, [x17, 32] + ins v20.d[0], x18 + ins v20.d[1], x19 + ldpsw x18, x19, [x17, 40] + ins v21.d[0], x18 + ins v21.d[1], x19 + ldpsw x18, x19, [x17, 48] + ins v22.d[0], x18 + ins v22.d[1], x19 + ldpsw x18, x19, [x17, 56] + ins v23.d[0], x18 + ins v23.d[1], x19 + scvtf v20.2d, v20.2d + scvtf v21.2d, v21.2d + scvtf v22.2d, v22.2d + scvtf v23.2d, v23.2d + and v20.16b, v20.16b, v29.16b + and v21.16b, v21.16b, v29.16b + and v22.16b, v22.16b, v29.16b + and v23.16b, v23.16b, v29.16b + orr v20.16b, v20.16b, v30.16b + orr v21.16b, v21.16b, v30.16b + orr v22.16b, v22.16b, v30.16b + orr v23.16b, v23.16b, v30.16b + + # Execute VM instructions +randomx_program_aarch64_vm_instructions: + + # 16 KB buffer for generated instructions + .fill 4096,4,0 + +literal_x0: .fill 1,8,0 +literal_x11: .fill 1,8,0 +literal_x20: .fill 1,8,0 +literal_x21: .fill 1,8,0 +literal_x22: .fill 1,8,0 +literal_x23: .fill 1,8,0 +literal_x24: .fill 1,8,0 +literal_x25: .fill 1,8,0 +literal_x26: .fill 1,8,0 +literal_x27: .fill 1,8,0 +literal_x28: .fill 1,8,0 +literal_x29: .fill 1,8,0 +literal_x30: .fill 1,8,0 +randomx_program_aarch64_imul_rcp_literals_end: + +literal_v0: .fill 2,8,0 +literal_v1: .fill 2,8,0 +literal_v2: .fill 2,8,0 +literal_v3: .fill 2,8,0 +literal_v4: .fill 2,8,0 +literal_v5: .fill 2,8,0 +literal_v6: .fill 2,8,0 +literal_v7: .fill 2,8,0 +literal_v8: .fill 2,8,0 +literal_v9: .fill 2,8,0 +literal_v10: .fill 2,8,0 +literal_v11: .fill 2,8,0 +literal_v12: .fill 2,8,0 +literal_v13: .fill 2,8,0 +literal_v14: .fill 2,8,0 +literal_v15: .fill 2,8,0 + +randomx_program_aarch64_vm_instructions_end: + + # mx ^= r[readReg2] ^ r[readReg3]; + eor x9, x9, x18 + + # Calculate dataset pointer for dataset prefetch + mov w18, w9 +randomx_program_aarch64_cacheline_align_mask1: + # Actual mask will be inserted by JIT compiler + and x18, x18, 1 + add x18, x18, x1 + + # Prefetch dataset data + prfm pldl2strm, [x18] + + # mx <-> ma + ror x9, x9, 32 + + # Calculate dataset pointer for dataset read + mov w10, w9 +randomx_program_aarch64_cacheline_align_mask2: + # Actual mask will be inserted by JIT compiler + and x10, x10, 1 + add x10, x10, x1 + +randomx_program_aarch64_xor_with_dataset_line: + # xor integer registers with dataset data + ldp x18, x19, [x10] + eor x4, x4, x18 + eor x5, x5, x19 + ldp x18, x19, [x10, 16] + eor x6, x6, x18 + eor x7, x7, x19 + ldp x18, x19, [x10, 32] + eor x12, x12, x18 + eor x13, x13, x19 + ldp x18, x19, [x10, 48] + eor x14, x14, x18 + eor x15, x15, x19 + +randomx_program_aarch64_update_spMix1: + # JIT compiler will replace it with "eor x10, config.readReg0, config.readReg1" + eor x10, x0, x0 + + # Store integer registers to scratchpad (spAddr1) + stp x4, x5, [x17, 0] + stp x6, x7, [x17, 16] + stp x12, x13, [x17, 32] + stp x14, x15, [x17, 48] + + # xor group F and group E registers + eor v16.16b, v16.16b, v20.16b + eor v17.16b, v17.16b, v21.16b + eor v18.16b, v18.16b, v22.16b + eor v19.16b, v19.16b, v23.16b + + # Store FP registers to scratchpad (spAddr0) + stp q16, q17, [x16, 0] + stp q18, q19, [x16, 32] + + subs x3, x3, 1 + bne randomx_program_aarch64_main_loop + + # Restore x0 + ldr x0, [sp], 16 + + # Store integer registers + stp x4, x5, [x0, 0] + stp x6, x7, [x0, 16] + stp x12, x13, [x0, 32] + stp x14, x15, [x0, 48] + + # Store FP registers + stp q16, q17, [x0, 64] + stp q18, q19, [x0, 96] + stp q20, q21, [x0, 128] + stp q22, q23, [x0, 160] + + # Restore callee-saved registers + ldp x16, x17, [sp] + ldp x18, x19, [sp, 16] + ldp x20, x21, [sp, 32] + ldp x22, x23, [sp, 48] + ldp x24, x25, [sp, 64] + ldp x26, x27, [sp, 80] + ldp x28, x29, [sp, 96] + ldp x8, x30, [sp, 112] + ldp d8, d9, [sp, 128] + ldp d10, d11, [sp, 144] + ldp d12, d13, [sp, 160] + ldp d14, d15, [sp, 176] + add sp, sp, 192 + + ret + +randomx_program_aarch64_vm_instructions_end_light: + sub sp, sp, 96 + stp x0, x1, [sp, 64] + stp x2, x30, [sp, 80] + + # mx ^= r[readReg2] ^ r[readReg3]; + eor x9, x9, x18 + + # mx <-> ma + ror x9, x9, 32 + + # x0 -> pointer to cache memory + mov x0, x1 + + # x1 -> pointer to output + mov x1, sp + +randomx_program_aarch64_light_cacheline_align_mask: + # Actual mask will be inserted by JIT compiler + and w2, w9, 1 + + # x2 -> item number + lsr x2, x2, 6 + +randomx_program_aarch64_light_dataset_offset: + # Apply dataset offset (filled in by JIT compiler) + add x2, x2, 0 + add x2, x2, 0 + + bl randomx_calc_dataset_item_aarch64 + + mov x10, sp + ldp x0, x1, [sp, 64] + ldp x2, x30, [sp, 80] + add sp, sp, 96 + + b randomx_program_aarch64_xor_with_dataset_line + + + +# Input parameters +# +# x0 -> pointer to cache +# x1 -> pointer to dataset memory at startItem +# x2 -> start item +# x3 -> end item + +randomx_init_dataset_aarch64: + # Save x30 (return address) + str x30, [sp, -16]! + + # Load pointer to cache memory + ldr x0, [x0] + +randomx_init_dataset_aarch64_main_loop: + bl randomx_calc_dataset_item_aarch64 + add x1, x1, 64 + add x2, x2, 1 + cmp x2, x3 + bne randomx_init_dataset_aarch64_main_loop + + # Restore x30 (return address) + ldr x30, [sp], 16 + + ret + +randomx_init_dataset_aarch64_end: + +# Input parameters +# +# x0 -> pointer to cache memory +# x1 -> pointer to output +# x2 -> item number +# +# Register allocation +# +# x0-x7 -> output value (calculated dataset item) +# x8 -> pointer to cache memory +# x9 -> pointer to output +# x10 -> registerValue +# x11 -> mixBlock +# x12 -> temporary +# x13 -> temporary + +randomx_calc_dataset_item_aarch64: + sub sp, sp, 112 + stp x0, x1, [sp] + stp x2, x3, [sp, 16] + stp x4, x5, [sp, 32] + stp x6, x7, [sp, 48] + stp x8, x9, [sp, 64] + stp x10, x11, [sp, 80] + stp x12, x13, [sp, 96] + + mov x8, x0 + mov x9, x1 + mov x10, x2 + + # rl[0] = (itemNumber + 1) * superscalarMul0; + ldr x12, superscalarMul0 + madd x0, x2, x12, x12 + + # rl[1] = rl[0] ^ superscalarAdd1; + ldr x12, superscalarAdd1 + eor x1, x0, x12 + + # rl[2] = rl[0] ^ superscalarAdd2; + ldr x12, superscalarAdd2 + eor x2, x0, x12 + + # rl[3] = rl[0] ^ superscalarAdd3; + ldr x12, superscalarAdd3 + eor x3, x0, x12 + + # rl[4] = rl[0] ^ superscalarAdd4; + ldr x12, superscalarAdd4 + eor x4, x0, x12 + + # rl[5] = rl[0] ^ superscalarAdd5; + ldr x12, superscalarAdd5 + eor x5, x0, x12 + + # rl[6] = rl[0] ^ superscalarAdd6; + ldr x12, superscalarAdd6 + eor x6, x0, x12 + + # rl[7] = rl[0] ^ superscalarAdd7; + ldr x12, superscalarAdd7 + eor x7, x0, x12 + + b randomx_calc_dataset_item_aarch64_prefetch + +superscalarMul0: .quad 6364136223846793005 +superscalarAdd1: .quad 9298411001130361340 +superscalarAdd2: .quad 12065312585734608966 +superscalarAdd3: .quad 9306329213124626780 +superscalarAdd4: .quad 5281919268842080866 +superscalarAdd5: .quad 10536153434571861004 +superscalarAdd6: .quad 3398623926847679864 +superscalarAdd7: .quad 9549104520008361294 + +# Prefetch -> SuperScalar hash -> Mix will be repeated N times + +randomx_calc_dataset_item_aarch64_prefetch: + # Actual mask will be inserted by JIT compiler + and x11, x10, 1 + add x11, x8, x11, lsl 6 + prfm pldl2strm, [x11] + + # Generated SuperScalar hash program goes here + +randomx_calc_dataset_item_aarch64_mix: + ldp x12, x13, [x11] + eor x0, x0, x12 + eor x1, x1, x13 + ldp x12, x13, [x11, 16] + eor x2, x2, x12 + eor x3, x3, x13 + ldp x12, x13, [x11, 32] + eor x4, x4, x12 + eor x5, x5, x13 + ldp x12, x13, [x11, 48] + eor x6, x6, x12 + eor x7, x7, x13 + +randomx_calc_dataset_item_aarch64_store_result: + stp x0, x1, [x9] + stp x2, x3, [x9, 16] + stp x4, x5, [x9, 32] + stp x6, x7, [x9, 48] + + ldp x0, x1, [sp] + ldp x2, x3, [sp, 16] + ldp x4, x5, [sp, 32] + ldp x6, x7, [sp, 48] + ldp x8, x9, [sp, 64] + ldp x10, x11, [sp, 80] + ldp x12, x13, [sp, 96] + add sp, sp, 112 + + ret + +randomx_calc_dataset_item_aarch64_end: diff --git a/src/crypto/randomx/jit_compiler_a64_static.hpp b/src/crypto/randomx/jit_compiler_a64_static.hpp new file mode 100644 index 00000000..a9b922e2 --- /dev/null +++ b/src/crypto/randomx/jit_compiler_a64_static.hpp @@ -0,0 +1,51 @@ +/* +Copyright (c) 2018-2019, tevador +Copyright (c) 2019, SChernykh + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +extern "C" { + void randomx_program_aarch64(void* reg, void* mem, void* scratchpad, uint64_t iterations); + void randomx_program_aarch64_main_loop(); + void randomx_program_aarch64_vm_instructions(); + void randomx_program_aarch64_imul_rcp_literals_end(); + void randomx_program_aarch64_vm_instructions_end(); + void randomx_program_aarch64_cacheline_align_mask1(); + void randomx_program_aarch64_cacheline_align_mask2(); + void randomx_program_aarch64_update_spMix1(); + void randomx_program_aarch64_vm_instructions_end_light(); + void randomx_program_aarch64_light_cacheline_align_mask(); + void randomx_program_aarch64_light_dataset_offset(); + void randomx_init_dataset_aarch64(); + void randomx_init_dataset_aarch64_end(); + void randomx_calc_dataset_item_aarch64(); + void randomx_calc_dataset_item_aarch64_prefetch(); + void randomx_calc_dataset_item_aarch64_mix(); + void randomx_calc_dataset_item_aarch64_store_result(); + void randomx_calc_dataset_item_aarch64_end(); +} diff --git a/src/crypto/randomx/randomx.cpp b/src/crypto/randomx/randomx.cpp index 51680704..cab1be9f 100644 --- a/src/crypto/randomx/randomx.cpp +++ b/src/crypto/randomx/randomx.cpp @@ -26,6 +26,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "crypto/randomx/common.hpp" #include "crypto/randomx/randomx.h" #include "crypto/randomx/dataset.hpp" #include "crypto/randomx/vm_interpreted.hpp" @@ -33,7 +34,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "crypto/randomx/vm_compiled.hpp" #include "crypto/randomx/vm_compiled_light.hpp" #include "crypto/randomx/blake2/blake2.h" + +#if defined(_M_X64) || defined(__x86_64__) #include "crypto/randomx/jit_compiler_x86_static.hpp" +#elif defined(XMRIG_ARM) +#include "crypto/randomx/jit_compiler_a64_static.hpp" +#endif + #include RandomX_ConfigurationWownero::RandomX_ConfigurationWownero() @@ -156,19 +163,10 @@ RandomX_ConfigurationBase::RandomX_ConfigurationBase() #endif } +static uint32_t Log2(size_t value) { return (value > 1) ? (Log2(value / 2) + 1) : 0; } + void RandomX_ConfigurationBase::Apply() { -#if defined(_M_X64) || defined(__x86_64__) - *(uint32_t*)(codeShhPrefetchTweaked + 3) = ArgonMemory * 16 - 1; - const uint32_t DatasetBaseMask = DatasetBaseSize - RANDOMX_DATASET_ITEM_SIZE; - *(uint32_t*)(codeReadDatasetTweaked + 7) = DatasetBaseMask; - *(uint32_t*)(codeReadDatasetTweaked + 23) = DatasetBaseMask; - *(uint32_t*)(codeReadDatasetLightSshInitTweaked + 59) = DatasetBaseMask; -#endif - - CacheLineAlignMask_Calculated = (DatasetBaseSize - 1) & ~(RANDOMX_DATASET_ITEM_SIZE - 1); - DatasetExtraItems_Calculated = DatasetExtraSize / RANDOMX_DATASET_ITEM_SIZE; - ScratchpadL1Mask_Calculated = (ScratchpadL1_Size / sizeof(uint64_t) - 1) * 8; ScratchpadL1Mask16_Calculated = (ScratchpadL1_Size / sizeof(uint64_t) / 2 - 1) * 16; ScratchpadL2Mask_Calculated = (ScratchpadL2_Size / sizeof(uint64_t) - 1) * 8; @@ -176,22 +174,40 @@ void RandomX_ConfigurationBase::Apply() ScratchpadL3Mask_Calculated = (((ScratchpadL3_Size / sizeof(uint64_t)) - 1) * 8); ScratchpadL3Mask64_Calculated = ((ScratchpadL3_Size / sizeof(uint64_t)) / 8 - 1) * 64; -#if defined(_M_X64) || defined(__x86_64__) - *(uint32_t*)(codePrefetchScratchpadTweaked + 4) = ScratchpadL3Mask64_Calculated; - *(uint32_t*)(codePrefetchScratchpadTweaked + 18) = ScratchpadL3Mask64_Calculated; -#endif + CacheLineAlignMask_Calculated = (DatasetBaseSize - 1) & ~(RANDOMX_DATASET_ITEM_SIZE - 1); + DatasetExtraItems_Calculated = DatasetExtraSize / RANDOMX_DATASET_ITEM_SIZE; ConditionMask_Calculated = (1 << JumpBits) - 1; - constexpr int CEIL_NULL = 0; - int k = 0; - #if defined(_M_X64) || defined(__x86_64__) + *(uint32_t*)(codeShhPrefetchTweaked + 3) = ArgonMemory * 16 - 1; + const uint32_t DatasetBaseMask = DatasetBaseSize - RANDOMX_DATASET_ITEM_SIZE; + *(uint32_t*)(codeReadDatasetTweaked + 7) = DatasetBaseMask; + *(uint32_t*)(codeReadDatasetTweaked + 23) = DatasetBaseMask; + *(uint32_t*)(codeReadDatasetLightSshInitTweaked + 59) = DatasetBaseMask; + + *(uint32_t*)(codePrefetchScratchpadTweaked + 4) = ScratchpadL3Mask64_Calculated; + *(uint32_t*)(codePrefetchScratchpadTweaked + 18) = ScratchpadL3Mask64_Calculated; + #define JIT_HANDLE(x, prev) randomx::JitCompilerX86::engine[k] = &randomx::JitCompilerX86::h_##x + +#elif defined(XMRIG_ARM) + + Log2_ScratchpadL1 = Log2(ScratchpadL1_Size); + Log2_ScratchpadL2 = Log2(ScratchpadL2_Size); + Log2_ScratchpadL3 = Log2(ScratchpadL3_Size); + Log2_DatasetBaseSize = Log2(DatasetBaseSize); + Log2_CacheSize = Log2((ArgonMemory * randomx::ArgonBlockSize) / randomx::CacheLineSize); + +#define JIT_HANDLE(x, prev) randomx::JitCompilerA64::engine[k] = &randomx::JitCompilerA64::h_##x + #else #define JIT_HANDLE(x, prev) #endif + constexpr int CEIL_NULL = 0; + int k = 0; + #define INST_HANDLE(x, prev) \ CEIL_##x = CEIL_##prev + RANDOMX_FREQ_##x; \ for (; k < CEIL_##x; ++k) { JIT_HANDLE(x, prev); } @@ -435,12 +451,12 @@ extern "C" { assert(inputSize == 0 || input != nullptr); assert(output != nullptr); alignas(16) uint64_t tempHash[8]; - rx_blake2b(tempHash, sizeof(tempHash), input, inputSize, nullptr, 0); + rx_blake2b(tempHash, sizeof(tempHash), input, inputSize, nullptr, 0); machine->initScratchpad(&tempHash); machine->resetRoundingMode(); for (uint32_t chain = 0; chain < RandomX_CurrentConfig.ProgramCount - 1; ++chain) { machine->run(&tempHash); - rx_blake2b(tempHash, sizeof(tempHash), machine->getRegisterFile(), sizeof(randomx::RegisterFile), nullptr, 0); + rx_blake2b(tempHash, sizeof(tempHash), machine->getRegisterFile(), sizeof(randomx::RegisterFile), nullptr, 0); } machine->run(&tempHash); machine->getFinalResult(output, RANDOMX_HASH_SIZE); diff --git a/src/crypto/randomx/randomx.h b/src/crypto/randomx/randomx.h index 05b7bdc8..c69fb313 100644 --- a/src/crypto/randomx/randomx.h +++ b/src/crypto/randomx/randomx.h @@ -133,6 +133,14 @@ struct RandomX_ConfigurationBase uint32_t ConditionMask_Calculated; +#ifdef XMRIG_ARM + uint32_t Log2_ScratchpadL1; + uint32_t Log2_ScratchpadL2; + uint32_t Log2_ScratchpadL3; + uint32_t Log2_DatasetBaseSize; + uint32_t Log2_CacheSize; +#endif + int CEIL_IADD_RS; int CEIL_IADD_M; int CEIL_ISUB_R; diff --git a/src/crypto/randomx/vm_compiled.cpp b/src/crypto/randomx/vm_compiled.cpp index f3b9758c..d2ee59e8 100644 --- a/src/crypto/randomx/vm_compiled.cpp +++ b/src/crypto/randomx/vm_compiled.cpp @@ -50,6 +50,9 @@ namespace randomx { template void CompiledVm::execute() { +#ifdef XMRIG_ARM + memcpy(reg.f, config.eMask, sizeof(config.eMask)); +#endif compiler.getProgramFunc()(reg, mem, scratchpad, RandomX_CurrentConfig.ProgramIterations); } diff --git a/src/crypto/rx/RxVm.cpp b/src/crypto/rx/RxVm.cpp index 275f9558..6426443a 100644 --- a/src/crypto/rx/RxVm.cpp +++ b/src/crypto/rx/RxVm.cpp @@ -33,11 +33,9 @@ xmrig::RxVm::RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes) { -# ifndef XMRIG_ARM if (!softAes) { m_flags |= RANDOMX_FLAG_HARD_AES; } -# endif if (dataset->get()) { m_flags |= RANDOMX_FLAG_FULL_MEM; From e002dbf57ec5f54d68923f949b29852d41eae93c Mon Sep 17 00:00:00 2001 From: SChernykh Date: Sat, 21 Sep 2019 10:48:14 +0200 Subject: [PATCH 09/49] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07654d04..850ddef8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,7 +143,7 @@ else() endif() endif() -if (CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Android") EXECUTE_PROCESS(COMMAND uname -o COMMAND tr -d '\n' OUTPUT_VARIABLE OPERATING_SYSTEM) if (OPERATING_SYSTEM MATCHES "Android") set(EXTRA_LIBS ${EXTRA_LIBS} log) From cf6bd0e7726b989da7740b9661e32057f75fde91 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 21 Sep 2019 19:05:52 +0700 Subject: [PATCH 10/49] #1183 Fixed crash in background mode. --- src/App.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/App.cpp b/src/App.cpp index de45a499..008df0a7 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -150,7 +150,11 @@ void xmrig::App::onSignal(int signum) void xmrig::App::close() { m_signals->stop(); - m_console->stop(); + + if (m_console) { + m_console->stop(); + } + m_controller->stop(); Log::destroy(); From 2e49930b94628ef4658564f8f98b8c775f37fe4c Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 21 Sep 2019 19:26:27 +0700 Subject: [PATCH 11/49] Optimized initialization. --- src/App.cpp | 33 ++++++++------- src/App.h | 11 +++-- src/App_unix.cpp | 23 ++++++---- src/App_win.cpp | 9 ++-- src/base/kernel/Base.cpp | 84 +++++++++++++++++++------------------ src/base/kernel/Base.h | 4 ++ src/base/kernel/Process.cpp | 7 +--- src/base/kernel/Process.h | 1 - src/core/Controller.cpp | 14 +------ src/core/Controller.h | 4 +- 10 files changed, 98 insertions(+), 92 deletions(-) diff --git a/src/App.cpp b/src/App.cpp index 008df0a7..5f59e1b5 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -24,7 +24,7 @@ */ -#include +#include #include @@ -42,18 +42,9 @@ #include "version.h" -xmrig::App::App(Process *process) : - m_console(nullptr), - m_signals(nullptr) +xmrig::App::App(Process *process) { m_controller = new Controller(process); - if (m_controller->init() != 0) { - return; - } - - if (!m_controller->config()->isBackground()) { - m_console = new Console(this); - } } @@ -68,12 +59,26 @@ xmrig::App::~App() int xmrig::App::exec() { if (!m_controller->isReady()) { + LOG_EMERG("no valid configuration found."); + return 2; } m_signals = new Signals(this); - background(); + int rc = 0; + if (background(rc)) { + return rc; + } + + rc = m_controller->init(); + if (rc != 0) { + return rc; + } + + if (!m_controller->isBackground()) { + m_console = new Console(this); + } VirtualMemory::init(m_controller->config()->cpu().isHugePages()); @@ -87,10 +92,10 @@ int xmrig::App::exec() m_controller->start(); - const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + rc = uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_loop_close(uv_default_loop()); - return r; + return rc; } diff --git a/src/App.h b/src/App.h index aa534aad..b46dcefa 100644 --- a/src/App.h +++ b/src/App.h @@ -29,6 +29,7 @@ #include "base/kernel/interfaces/IConsoleListener.h" #include "base/kernel/interfaces/ISignalListener.h" +#include "base/tools/Object.h" namespace xmrig { @@ -44,6 +45,8 @@ class Signals; class App : public IConsoleListener, public ISignalListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(App) + App(Process *process); ~App() override; @@ -54,12 +57,12 @@ protected: void onSignal(int signum) override; private: - void background(); + bool background(int &rc); void close(); - Console *m_console; - Controller *m_controller; - Signals *m_signals; + Console *m_console = nullptr; + Controller *m_controller = nullptr; + Signals *m_signals = nullptr; }; diff --git a/src/App_unix.cpp b/src/App_unix.cpp index 5149513c..ae2905db 100644 --- a/src/App_unix.cpp +++ b/src/App_unix.cpp @@ -23,33 +23,36 @@ */ -#include -#include -#include +#include +#include +#include #include #include "App.h" #include "base/io/log/Log.h" -#include "core/config/Config.h" #include "core/Controller.h" -void xmrig::App::background() +bool xmrig::App::background(int &rc) { signal(SIGPIPE, SIG_IGN); - if (!m_controller->config()->isBackground()) { - return; + if (!m_controller->isBackground()) { + return false; } int i = fork(); if (i < 0) { - exit(1); + rc = 1; + + return true; } if (i > 0) { - exit(0); + rc = 0; + + return true; } i = setsid(); @@ -62,4 +65,6 @@ void xmrig::App::background() if (i < 0) { LOG_ERR("chdir() failed (errno = %d)", errno); } + + return false; } diff --git a/src/App_win.cpp b/src/App_win.cpp index a41ed505..e803080c 100644 --- a/src/App_win.cpp +++ b/src/App_win.cpp @@ -29,13 +29,12 @@ #include "App.h" #include "core/Controller.h" -#include "core/config/Config.h" -void xmrig::App::background() +bool xmrig::App::background(int &) { - if (!m_controller->config()->isBackground()) { - return; + if (!m_controller->isBackground()) { + return false; } HWND hcon = GetConsoleWindow(); @@ -46,4 +45,6 @@ void xmrig::App::background() CloseHandle(h); FreeConsole(); } + + return false; } diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp index 3740655d..90c7cb57 100644 --- a/src/base/kernel/Base.cpp +++ b/src/base/kernel/Base.cpp @@ -23,7 +23,7 @@ */ -#include +#include #include @@ -64,15 +64,16 @@ static const char *kConfigPathV2 = "/2/config"; #endif -class xmrig::BasePrivate +namespace xmrig { + + +class BasePrivate { public: - inline BasePrivate(Process *process) : - api(nullptr), - config(nullptr), - process(process), - watcher(nullptr) - {} + XMRIG_DISABLE_COPY_MOVE_DEFAULT(BasePrivate) + + + inline BasePrivate(Process *process) : config(load(process)) {} inline ~BasePrivate() @@ -94,13 +95,33 @@ public: } - inline Config *load() + inline void replace(Config *newConfig) + { + Config *previousConfig = config; + config = newConfig; + + for (IBaseListener *listener : listeners) { + listener->onConfigChanged(config, previousConfig); + } + + delete previousConfig; + } + + + Api *api = nullptr; + Config *config = nullptr; + std::vector listeners; + Watcher *watcher = nullptr; + + +private: + inline Config *load(Process *process) { JsonChain chain; ConfigTransform transform; std::unique_ptr config; - transform.load(chain, process, transform); + ConfigTransform::load(chain, process, transform); if (read(chain, config)) { return config.release(); @@ -122,29 +143,12 @@ public: return nullptr; } - - - inline void replace(Config *newConfig) - { - Config *previousConfig = config; - config = newConfig; - - for (IBaseListener *listener : listeners) { - listener->onConfigChanged(config, previousConfig); - } - - delete previousConfig; - } - - - Api *api; - Config *config; - Process *process; - std::vector listeners; - Watcher *watcher; }; +} // namespace xmrig + + xmrig::Base::Base(Process *process) : d_ptr(new BasePrivate(process)) { @@ -165,14 +169,6 @@ bool xmrig::Base::isReady() const int xmrig::Base::init() { - d_ptr->config = d_ptr->load(); - - if (!d_ptr->config) { - LOG_EMERG("No valid configuration found. Exiting."); - - return 1; - } - # ifdef XMRIG_FEATURE_API d_ptr->api = new Api(this); d_ptr->api->addListener(this); @@ -184,7 +180,7 @@ int xmrig::Base::init() Platform::setProcessPriority(config()->cpu().priority()); # endif - if (config()->isBackground()) { + if (isBackground()) { Log::background = true; } else { @@ -240,6 +236,12 @@ xmrig::Api *xmrig::Base::api() const } +bool xmrig::Base::isBackground() const +{ + return d_ptr->config && d_ptr->config->isBackground(); +} + + bool xmrig::Base::reload(const rapidjson::Value &json) { JsonReader reader(json); @@ -247,7 +249,7 @@ bool xmrig::Base::reload(const rapidjson::Value &json) return false; } - Config *config = new Config(); + auto config = new Config(); if (!config->read(reader, d_ptr->config->fileName())) { delete config; @@ -289,7 +291,7 @@ void xmrig::Base::onFileChanged(const String &fileName) JsonChain chain; chain.addFile(fileName); - Config *config = new Config(); + auto config = new Config(); if (!config->read(chain, chain.fileName())) { LOG_ERR("reloading failed"); diff --git a/src/base/kernel/Base.h b/src/base/kernel/Base.h index 8eb68866..ef850edd 100644 --- a/src/base/kernel/Base.h +++ b/src/base/kernel/Base.h @@ -29,6 +29,7 @@ #include "base/api/interfaces/IApiListener.h" #include "base/kernel/interfaces/IConfigListener.h" #include "base/kernel/interfaces/IWatcherListener.h" +#include "base/tools/Object.h" #include "rapidjson/fwd.h" @@ -45,6 +46,8 @@ class Process; class Base : public IWatcherListener, public IApiListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Base) + Base(Process *process); ~Base() override; @@ -54,6 +57,7 @@ public: virtual void stop(); Api *api() const; + bool isBackground() const; bool reload(const rapidjson::Value &json); Config *config() const; void addListener(IBaseListener *listener); diff --git a/src/base/kernel/Process.cpp b/src/base/kernel/Process.cpp index 9193d378..fae0d679 100644 --- a/src/base/kernel/Process.cpp +++ b/src/base/kernel/Process.cpp @@ -23,8 +23,8 @@ */ +#include #include -#include #include "base/kernel/Process.h" @@ -55,11 +55,6 @@ xmrig::Process::Process(int argc, char **argv) : } -xmrig::Process::~Process() -{ -} - - xmrig::String xmrig::Process::location(Location location, const char *fileName) const { constexpr const size_t max = 520; diff --git a/src/base/kernel/Process.h b/src/base/kernel/Process.h index 9b29eb57..22959044 100644 --- a/src/base/kernel/Process.h +++ b/src/base/kernel/Process.h @@ -47,7 +47,6 @@ public: # endif Process(int argc, char **argv); - ~Process(); String location(Location location, const char *fileName = nullptr) const; diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 54c9ee34..848396a7 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -23,7 +23,7 @@ */ -#include +#include #include "backend/cpu/Cpu.h" @@ -44,20 +44,10 @@ xmrig::Controller::~Controller() } -bool xmrig::Controller::isReady() const -{ - return Base::isReady() && m_network; -} - - int xmrig::Controller::init() { Cpu::init(); - - const int rc = Base::init(); - if (rc != 0) { - return rc; - } + Base::init(); m_network = new Network(this); return 0; diff --git a/src/core/Controller.h b/src/core/Controller.h index da7ba368..b2b8c9cb 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -27,6 +27,7 @@ #include "base/kernel/Base.h" +#include "base/tools/Object.h" namespace xmrig { @@ -40,10 +41,11 @@ class Network; class Controller : public Base { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Controller) + Controller(Process *process); ~Controller() override; - bool isReady() const override; int init() override; void start() override; void stop() override; From cbdf1e6c095ed6d5a14f62d2b3ae967e4a7b076b Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 22 Sep 2019 00:59:53 +0700 Subject: [PATCH 12/49] Revert instructions_portable.cpp to avoid warning on gcc compilers. --- src/crypto/randomx/instructions_portable.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/crypto/randomx/instructions_portable.cpp b/src/crypto/randomx/instructions_portable.cpp index d08ee587..b28203a9 100644 --- a/src/crypto/randomx/instructions_portable.cpp +++ b/src/crypto/randomx/instructions_portable.cpp @@ -82,12 +82,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define HAVE_SETROUNDMODE_IMPL #endif -#ifndef HAVE_SETROUNDMODE_IMPL - static void setRoundMode_(uint32_t mode) { - fesetround(mode); - } -#endif - #ifndef HAVE_ROTR64 uint64_t rotr64(uint64_t a, unsigned int b) { return (a >> b) | (a << (-b & 63)); @@ -133,6 +127,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef RANDOMX_DEFAULT_FENV +# ifndef HAVE_SETROUNDMODE_IMPL + static void setRoundMode_(uint32_t mode) { + fesetround(mode); + } +# endif + void rx_reset_float_state() { setRoundMode_(FE_TONEAREST); rx_set_double_precision(); //set precision to 53 bits if needed by the platform From 54d73b7ac5eac52901506250f9a118363f77d091 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 22 Sep 2019 02:10:14 +0700 Subject: [PATCH 13/49] Extended OpenCL threads information. --- src/backend/common/misc/PciTopology.h | 22 ++++++++++++++++------ src/backend/opencl/OclBackend.cpp | 8 +++++--- src/backend/opencl/wrappers/OclDevice.cpp | 21 +++++++++++++++++---- src/backend/opencl/wrappers/OclDevice.h | 10 ++++++---- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/backend/common/misc/PciTopology.h b/src/backend/common/misc/PciTopology.h index dcfacb20..4f362bc4 100644 --- a/src/backend/common/misc/PciTopology.h +++ b/src/backend/common/misc/PciTopology.h @@ -27,7 +27,7 @@ #define XMRIG_PCITOPOLOGY_H -#include +#include #include "base/tools/String.h" @@ -40,19 +40,29 @@ class PciTopology { public: PciTopology() = default; - PciTopology(uint32_t bus, uint32_t device, uint32_t function) : bus(bus), device(device), function(function) {} + PciTopology(uint32_t bus, uint32_t device, uint32_t function) : m_bus(bus), m_device(device), m_function(function) {} - uint32_t bus = 0; - uint32_t device = 0; - uint32_t function = 0; + inline bool isValid() const { return m_bus >= 0; } + inline uint32_t bus() const { return isValid() ? m_bus : 0; } + inline uint32_t device() const { return m_device; } + inline uint32_t function() const { return m_function; } String toString() const { + if (!isValid()) { + return "n/a"; + } + char *buf = new char[8](); - snprintf(buf, 8, "%02x:%02x.%01x", bus, device, function); + snprintf(buf, 8, "%02x:%02x.%01x", bus(), device(), function()); return buf; } + +private: + int32_t m_bus = -1; + uint32_t m_device = 0; + uint32_t m_function = 0; }; diff --git a/src/backend/opencl/OclBackend.cpp b/src/backend/opencl/OclBackend.cpp index 65c3ded9..4820ce08 100644 --- a/src/backend/opencl/OclBackend.cpp +++ b/src/backend/opencl/OclBackend.cpp @@ -150,7 +150,7 @@ public: for (const OclDevice &device : devices) { Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") " %s " WHITE_BOLD("%uMHz") " cu:" WHITE_BOLD("%u") " mem:" CYAN("%zu/%zu") " MB", "OPENCL GPU", device.index(), - device.hasTopology() ? device.topology().toString().data() : "n/a", + device.topology().toString().data(), device.printableName().data(), device.clock(), device.computeUnits(), @@ -177,7 +177,7 @@ public: CYAN_BOLD("%3u") " |" CYAN_BOLD("%3s") " |" CYAN_BOLD("%3u") " |" CYAN("%5zu") " | %s", i, data.thread.index(), - data.device.hasTopology() ? data.device.topology().toString().data() : "n/a", + data.device.topology().toString().data(), data.thread.intensity(), data.thread.worksize(), data.thread.stridedIndex(), @@ -285,7 +285,7 @@ void xmrig::OclBackend::printHashrate(bool details) Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval), num + 8, sizeof num / 3), Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3), data.device.index(), - data.device.hasTopology() ? data.device.topology().toString().data() : "n/a", + data.device.topology().toString().data(), data.device.printableName().data() ); @@ -401,6 +401,8 @@ rapidjson::Value xmrig::OclBackend::toJSON(rapidjson::Document &doc) const thread.AddMember("affinity", data.affinity, allocator); thread.AddMember("hashrate", hashrate()->toJSON(i, doc), allocator); + data.device.toJSON(thread, doc); + i++; threads.PushBack(thread, allocator); } diff --git a/src/backend/opencl/wrappers/OclDevice.cpp b/src/backend/opencl/wrappers/OclDevice.cpp index f6338717..f9495403 100644 --- a/src/backend/opencl/wrappers/OclDevice.cpp +++ b/src/backend/opencl/wrappers/OclDevice.cpp @@ -142,16 +142,14 @@ xmrig::OclDevice::OclDevice(uint32_t index, cl_device_id id, cl_platform_id plat topology_amd topology; if (OclLib::getDeviceInfo(id, 0x4037 /* CL_DEVICE_TOPOLOGY_AMD */, sizeof(topology), &topology, nullptr) == CL_SUCCESS && topology.raw.type == 1) { - m_topology = true; - m_pciTopology = PciTopology(static_cast(topology.pcie.bus), static_cast(topology.pcie.device), static_cast(topology.pcie.function)); + m_topology = PciTopology(static_cast(topology.pcie.bus), static_cast(topology.pcie.device), static_cast(topology.pcie.function)); } } else if (m_vendorId == OCL_VENDOR_NVIDIA) { cl_uint bus = 0; if (OclLib::getDeviceInfo(id, 0x4008 /* CL_DEVICE_PCI_BUS_ID_NV */, sizeof (bus), &bus, nullptr) == CL_SUCCESS) { - m_topology = true; cl_uint slot = OclLib::getUint(id, 0x4009 /* CL_DEVICE_PCI_SLOT_ID_NV */); - m_pciTopology = PciTopology(bus, (slot >> 3) & 0xff, slot & 7); + m_topology = PciTopology(bus, (slot >> 3) & 0xff, slot & 7); } } } @@ -205,3 +203,18 @@ void xmrig::OclDevice::generate(const Algorithm &algorithm, OclThreads &threads) } } } + + +#ifdef XMRIG_FEATURE_API +void xmrig::OclDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc) const +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + + out.AddMember("board", board().toJSON(doc), allocator); + out.AddMember("name", name().toJSON(doc), allocator); + out.AddMember("bus-id", topology().toString().toJSON(doc), allocator); + out.AddMember("cu", computeUnits(), allocator); + out.AddMember("global-mem", globalMemSize(), allocator); +} +#endif diff --git a/src/backend/opencl/wrappers/OclDevice.h b/src/backend/opencl/wrappers/OclDevice.h index 517fa2bd..3be58ed2 100644 --- a/src/backend/opencl/wrappers/OclDevice.h +++ b/src/backend/opencl/wrappers/OclDevice.h @@ -69,10 +69,9 @@ public: uint32_t clock() const; void generate(const Algorithm &algorithm, OclThreads &threads) const; - inline bool hasTopology() const { return m_topology; } inline bool isValid() const { return m_id != nullptr && m_platform != nullptr; } inline cl_device_id id() const { return m_id; } - inline const PciTopology &topology() const { return m_pciTopology; } + inline const PciTopology &topology() const { return m_topology; } inline const String &board() const { return m_board.isNull() ? m_name : m_board; } inline const String &name() const { return m_name; } inline const String &vendor() const { return m_vendor; } @@ -81,8 +80,11 @@ public: inline uint32_t computeUnits() const { return m_computeUnits; } inline uint32_t index() const { return m_index; } +# ifdef XMRIG_FEATURE_API + void toJSON(rapidjson::Value &out, rapidjson::Document &doc) const; +# endif + private: - bool m_topology = false; cl_device_id m_id = nullptr; cl_platform_id m_platform = nullptr; const String m_board; @@ -91,7 +93,7 @@ private: const uint32_t m_computeUnits = 1; const uint32_t m_index = 0; OclVendor m_vendorId = OCL_VENDOR_UNKNOWN; - PciTopology m_pciTopology; + PciTopology m_topology; Type m_type = Unknown; }; From c7e4815d790d7b840747d0bfa1996959c52dd6e7 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 23 Sep 2019 01:27:05 +0700 Subject: [PATCH 14/49] Use more JS friendly names. --- src/backend/opencl/wrappers/OclDevice.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/opencl/wrappers/OclDevice.cpp b/src/backend/opencl/wrappers/OclDevice.cpp index f9495403..b10713d4 100644 --- a/src/backend/opencl/wrappers/OclDevice.cpp +++ b/src/backend/opencl/wrappers/OclDevice.cpp @@ -213,8 +213,8 @@ void xmrig::OclDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc) c out.AddMember("board", board().toJSON(doc), allocator); out.AddMember("name", name().toJSON(doc), allocator); - out.AddMember("bus-id", topology().toString().toJSON(doc), allocator); + out.AddMember("bus_id", topology().toString().toJSON(doc), allocator); out.AddMember("cu", computeUnits(), allocator); - out.AddMember("global-mem", globalMemSize(), allocator); + out.AddMember("global_mem", globalMemSize(), allocator); } #endif From 637301d340591bcf174c04fe3f7045170963558f Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 23 Sep 2019 03:47:40 +0700 Subject: [PATCH 15/49] Improved/restructured --help output. --- src/backend/cpu/Cpu.cpp | 28 ++-- src/backend/cpu/Cpu.h | 1 - src/base/kernel/Entry.cpp | 4 +- src/base/kernel/config/BaseTransform.cpp | 15 +- src/base/kernel/config/BaseTransform.h | 2 - src/base/kernel/interfaces/IConfig.h | 1 + src/core/Controller.cpp | 1 - src/core/config/ConfigTransform.cpp | 9 +- src/core/config/ConfigTransform.h | 3 - src/core/config/Config_platform.h | 12 +- src/core/config/usage.h | 176 +++++++++++------------ 11 files changed, 119 insertions(+), 133 deletions(-) diff --git a/src/backend/cpu/Cpu.cpp b/src/backend/cpu/Cpu.cpp index 4d9effce..5d095e68 100644 --- a/src/backend/cpu/Cpu.cpp +++ b/src/backend/cpu/Cpu.cpp @@ -23,7 +23,7 @@ */ -#include +#include #include "backend/cpu/Cpu.h" @@ -44,7 +44,15 @@ static xmrig::ICpuInfo *cpuInfo = nullptr; xmrig::ICpuInfo *xmrig::Cpu::info() { - assert(cpuInfo != nullptr); + if (cpuInfo == nullptr) { +# if defined(XMRIG_FEATURE_HWLOC) + cpuInfo = new HwlocCpuInfo(); +# elif defined(XMRIG_FEATURE_LIBCPUID) + cpuInfo = new AdvancedCpuInfo(); +# else + cpuInfo = new BasicCpuInfo(); +# endif + } return cpuInfo; } @@ -62,7 +70,7 @@ rapidjson::Value xmrig::Cpu::toJSON(rapidjson::Document &doc) cpu.AddMember("brand", StringRef(i->brand()), allocator); cpu.AddMember("aes", i->hasAES(), allocator); cpu.AddMember("avx2", i->hasAVX2(), allocator); - cpu.AddMember("x64", i->isX64(), allocator); + cpu.AddMember("x64", ICpuInfo::isX64(), allocator); cpu.AddMember("l2", static_cast(i->L2()), allocator); cpu.AddMember("l3", static_cast(i->L3()), allocator); cpu.AddMember("cores", static_cast(i->cores()), allocator); @@ -81,20 +89,6 @@ rapidjson::Value xmrig::Cpu::toJSON(rapidjson::Document &doc) } -void xmrig::Cpu::init() -{ - assert(cpuInfo == nullptr); - -# if defined(XMRIG_FEATURE_HWLOC) - cpuInfo = new HwlocCpuInfo(); -# elif defined(XMRIG_FEATURE_LIBCPUID) - cpuInfo = new AdvancedCpuInfo(); -# else - cpuInfo = new BasicCpuInfo(); -# endif -} - - void xmrig::Cpu::release() { assert(cpuInfo != nullptr); diff --git a/src/backend/cpu/Cpu.h b/src/backend/cpu/Cpu.h index bece97d3..a8dd1f3a 100644 --- a/src/backend/cpu/Cpu.h +++ b/src/backend/cpu/Cpu.h @@ -37,7 +37,6 @@ class Cpu public: static ICpuInfo *info(); static rapidjson::Value toJSON(rapidjson::Document &doc); - static void init(); static void release(); inline static Assembly::Id assembly(Assembly::Id hint) { return hint == Assembly::AUTO ? Cpu::info()->assembly() : hint; } diff --git a/src/base/kernel/Entry.cpp b/src/base/kernel/Entry.cpp index 605f8e20..1d1b7eb8 100644 --- a/src/base/kernel/Entry.cpp +++ b/src/base/kernel/Entry.cpp @@ -23,7 +23,7 @@ */ -#include +#include #include @@ -161,7 +161,7 @@ int xmrig::Entry::exec(const Process &process, Id id) { switch (id) { case Usage: - printf(usage); + printf("%s\n", usage().c_str()); return 0; case Version: diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 12e7d848..a10960a4 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -23,7 +23,7 @@ */ -#include +#include #ifdef _MSC_VER @@ -50,12 +50,7 @@ static const char *kApi = "api"; static const char *kHttp = "http"; static const char *kPools = "pools"; -} - - -xmrig::BaseTransform::BaseTransform() -{ -} +} // namespace xmrig void xmrig::BaseTransform::load(JsonChain &chain, Process *process, IConfigTransform &transform) @@ -68,7 +63,7 @@ void xmrig::BaseTransform::load(JsonChain &chain, Process *process, IConfigTrans Document doc(kObjectType); - while (1) { + while (true) { key = getopt_long(argc, argv, short_options, options, nullptr); if (key < 0) { break; @@ -226,8 +221,10 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b case IConfig::TlsKey: /* --tls */ return add(doc, kPools, "tls", enable); +# ifdef XMRIG_FEATURE_HTTP case IConfig::DaemonKey: /* --daemon */ return add(doc, kPools, "daemon", enable); +# endif # ifndef XMRIG_PROXY_PROJECT case IConfig::NicehashKey: /* --nicehash */ @@ -273,8 +270,10 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui case IConfig::PrintTimeKey: /* --print-time */ return set(doc, "print-time", arg); +# ifdef XMRIG_FEATURE_HTTP case IConfig::DaemonPollKey: /* --daemon-poll-interval */ return add(doc, kPools, "daemon-poll-interval", arg); +# endif default: break; diff --git a/src/base/kernel/config/BaseTransform.h b/src/base/kernel/config/BaseTransform.h index 02b28c12..5fa0c8c5 100644 --- a/src/base/kernel/config/BaseTransform.h +++ b/src/base/kernel/config/BaseTransform.h @@ -44,8 +44,6 @@ class Process; class BaseTransform : public IConfigTransform { public: - BaseTransform(); - static void load(JsonChain &chain, Process *process, IConfigTransform &transform); protected: diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 86b8067c..0569a3d1 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -78,6 +78,7 @@ public: PrintTimeKey = 1007, // xmrig cpu + CPUKey = 1024, AVKey = 'v', CPUAffinityKey = 1020, DryRunKey = 5000, diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 848396a7..80381e32 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -46,7 +46,6 @@ xmrig::Controller::~Controller() int xmrig::Controller::init() { - Cpu::init(); Base::init(); m_network = new Network(this); diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index ce0d324c..f11fe930 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -80,12 +80,7 @@ static inline bool isHwAes(uint64_t av) } -} - - -xmrig::ConfigTransform::ConfigTransform() : BaseTransform() -{ -} +} // namespace xmrig void xmrig::ConfigTransform::finalize(rapidjson::Document &doc) @@ -131,7 +126,7 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const return transformUint64(doc, key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); } -# ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM case IConfig::AssemblyKey: /* --asm */ return set(doc, kCpu, "asm", arg); # endif diff --git a/src/core/config/ConfigTransform.h b/src/core/config/ConfigTransform.h index 440a7169..7ec3cdec 100644 --- a/src/core/config/ConfigTransform.h +++ b/src/core/config/ConfigTransform.h @@ -34,9 +34,6 @@ namespace xmrig { class ConfigTransform : public BaseTransform { -public: - ConfigTransform(); - protected: void finalize(rapidjson::Document &doc) override; void transform(rapidjson::Document &doc, int key, const char *arg) override; diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index b7415f4d..a10f3c16 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -45,6 +45,7 @@ static const char short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S"; static const option options[] = { { "algo", 1, nullptr, IConfig::AlgorithmKey }, +# ifdef XMRIG_FEATURE_HTTP { "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, { "api-id", 1, nullptr, IConfig::ApiIdKey }, { "http-enabled", 0, nullptr, IConfig::HttpEnabledKey }, @@ -52,6 +53,9 @@ static const option options[] = { { "http-access-token", 1, nullptr, IConfig::HttpAccessTokenKey }, { "http-port", 1, nullptr, IConfig::HttpPort }, { "http-no-restricted", 0, nullptr, IConfig::HttpRestrictedKey }, + { "daemon", 0, nullptr, IConfig::DaemonKey }, + { "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey }, +# endif { "av", 1, nullptr, IConfig::AVKey }, { "background", 0, nullptr, IConfig::BackgroundKey }, { "config", 1, nullptr, IConfig::ConfigKey }, @@ -76,13 +80,17 @@ static const option options[] = { { "user-agent", 1, nullptr, IConfig::UserAgentKey }, { "userpass", 1, nullptr, IConfig::UserpassKey }, { "rig-id", 1, nullptr, IConfig::RigIdKey }, +# ifdef XMRIG_FEATURE_TLS { "tls", 0, nullptr, IConfig::TlsKey }, { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, +# endif +# ifdef XMRIG_FEATURE_ASM { "asm", 1, nullptr, IConfig::AssemblyKey }, - { "daemon", 0, nullptr, IConfig::DaemonKey }, - { "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey }, +# endif +# ifdef XMRIG_ALGO_RANDOMX { "randomx-init", 1, nullptr, IConfig::RandomXInitKey }, { "randomx-no-numa", 0, nullptr, IConfig::RandomXNumaKey }, +# endif { nullptr, 0, nullptr, 0 } }; diff --git a/src/core/config/usage.h b/src/core/config/usage.h index b41ec6db..34998bce 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -29,99 +29,95 @@ #include "version.h" +#include + + namespace xmrig { -static char const usage[] = "\ -Usage: " APP_ID " [OPTIONS]\n\ -Options:\n\ - -a, --algo=ALGO specify the algorithm to use\n\ - cn/r, cn/2, cn/1, cn/0, cn/double, cn/half, cn/fast,\n\ - cn/rwz, cn/zls, cn/xao, cn/rto" -#ifdef XMRIG_ALGO_CN_GPU -", cn/gpu,\n" -#else -",\n" -#endif -#ifdef XMRIG_ALGO_CN_LITE -"\ - cn-lite/1,\n" -#endif -#ifdef XMRIG_ALGO_CN_HEAVY -"\ - cn-heavy/xhv, cn-heavy/tube, cn-heavy/0,\n" -#endif -#ifdef XMRIG_ALGO_CN_PICO -"\ - cn-pico,\n" -#endif -#ifdef XMRIG_ALGO_RANDOMX -"\ - rx/wow, rx/loki\n" -#endif -"\ - -o, --url=URL URL of mining server\n\ - -O, --userpass=U:P username:password pair for mining server\n\ - -u, --user=USERNAME username for mining server\n\ - -p, --pass=PASSWORD password for mining server\n\ - --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\ - -t, --threads=N number of miner threads\n\ - -v, --av=N algorithm variation, 0 auto select\n\ - -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\ - --nicehash enable nicehash.com support\n" -#ifdef XMRIG_FEATURE_TLS -"\ - --tls enable SSL/TLS support (needs pool support)\n\ - --tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n" -#endif -#ifdef XMRIG_FEATURE_HTTP -"\ - --daemon use daemon RPC instead of pool for solo mining\n\ - --daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)\n" -#endif -"\ - -r, --retries=N number of times to retry before switch to backup server (default: 5)\n\ - -R, --retry-pause=N time to pause between retries (default: 5)\n\ - --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\ - --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\ - --no-huge-pages disable huge pages support\n\ - --no-color disable colored output\n\ - --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ - --user-agent set custom user-agent string for pool\n\ - -B, --background run the miner in the background\n\ - -c, --config=FILE load a JSON-format configuration file\n\ - -l, --log-file=FILE log all output to a file\n" -# ifdef HAVE_SYSLOG_H -"\ - -S, --syslog use system log for output messages\n" -# endif -"\ - --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer.\n\ - --print-time=N print hashrate report every N seconds\n" -#ifdef XMRIG_FEATURE_HTTP -"\ - --api-worker-id=ID custom worker-id for API\n\ - --api-id=ID custom instance ID for API\n\ - --http-enabled enable HTTP API\n\ - --http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n\ - --http-port=N bind port for HTTP API\n\ - --http-access-token=T access token for HTTP API\n\ - --http-no-restricted enable full remote access to HTTP API (only if access token set)\n" -#endif -#ifdef XMRIG_ALGO_RANDOMX -"\ - --randomx-init=N threads count to initialize RandomX dataset\n\ - --randomx-no-numa disable NUMA support for RandomX\n" -#endif -#ifdef XMRIG_FEATURE_HWLOC -"\ - --export-topology export hwloc topology to a XML file and exit\n" -#endif -"\ - --dry-run test configuration and exit\n\ - -h, --help display this help and exit\n\ - -V, --version output version information and exit\n\ -"; +static inline const std::string &usage() +{ + static std::string u; + + if (!u.empty()) { + return u; + } + + u += "Usage: " APP_ID " [OPTIONS]\n\nNetwork:\n"; + u += " -o, --url=URL URL of mining server\n"; + u += " -a, --algo=ALGO mining algorithm https://xmrig.com/docs/algorithms\n"; + u += " -u, --user=USERNAME username for mining server\n"; + u += " -p, --pass=PASSWORD password for mining server\n"; + u += " -O, --userpass=U:P username:password pair for mining server\n"; + u += " -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n"; + u += " --nicehash enable nicehash.com support\n"; + u += " --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n"; + +# ifdef XMRIG_FEATURE_TLS + u += " --tls enable SSL/TLS support (needs pool support)\n"; + u += " --tls-fingerprint=HEX pool TLS certificate fingerprint for strict certificate pinning\n"; +# endif + +# ifdef XMRIG_FEATURE_HTTP + u += " --daemon use daemon RPC instead of pool for solo mining\n"; + u += " --daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)\n"; +# endif + + u += " -r, --retries=N number of times to retry before switch to backup server (default: 5)\n"; + u += " -R, --retry-pause=N time to pause between retries (default: 5)\n"; + u += " --user-agent set custom user-agent string for pool\n"; + u += " --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n"; + u += " --donate-over-proxy=N control donate over xmrig-proxy feature\n"; + + u += "\nCPU backend:\n"; + + u += " -t, --threads=N number of CPU threads\n"; + u += " -v, --av=N algorithm variation, 0 auto select\n"; + u += " --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n"; + u += " --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n"; + u += " --no-huge-pages disable huge pages support\n"; + u += " --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer\n"; + +# ifdef XMRIG_ALGO_RANDOMX + u += " --randomx-init=N threads count to initialize RandomX dataset\n"; + u += " --randomx-no-numa disable NUMA support for RandomX\n"; +# endif + +# ifdef XMRIG_FEATURE_HTTP + u += "\nAPI:\n"; + u += " --api-worker-id=ID custom worker-id for API\n"; + u += " --api-id=ID custom instance ID for API\n"; + u += " --http-enabled enable HTTP API\n"; + u += " --http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n"; + u += " --http-port=N bind port for HTTP API\n"; + u += " --http-access-token=T access token for HTTP API\n"; + u += " --http-no-restricted enable full remote access to HTTP API (only if access token set)\n"; +# endif + + u += "\nLogging:\n"; + +# ifdef HAVE_SYSLOG_H + u += " -S, --syslog use system log for output messages\n"; +# endif + + u += " -l, --log-file=FILE log all output to a file\n"; + u += " --print-time=N print hashrate report every N seconds\n"; + u += " --no-color disable colored output\n"; + + u += "\nMisc:\n"; + + u += " -c, --config=FILE load a JSON-format configuration file\n"; + u += " -B, --background run the miner in the background\n"; + u += " -V, --version output version information and exit\n"; + u += " -h, --help display this help and exit\n"; + u += " --dry-run test configuration and exit\n"; + +# ifdef XMRIG_FEATURE_HWLOC + u += " --export-topology export hwloc topology to a XML file and exit\n"; +# endif + + return u; +} } /* namespace xmrig */ From 290493e4858216954a041d75e778e3ea0b62bdd5 Mon Sep 17 00:00:00 2001 From: xmrig Date: Mon, 23 Sep 2019 03:57:33 +0700 Subject: [PATCH 16/49] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dce82107..784de18a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v4.0.2-beta +- [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd. +- [#1185](https://github.com/xmrig/xmrig/pull/1185) Added JIT compiler for RandomX on ARMv8. + # v4.0.1-beta - [#1177](https://github.com/xmrig/xmrig/issues/1177) Fixed compatibility with old AMD drivers. - [#1180](https://github.com/xmrig/xmrig/issues/1180) Fixed possible duplicated shares after algorithm switching. From 0f05936e63b5dcc4a04a59e7e7ff2e2706bd9245 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 23 Sep 2019 04:53:33 +0700 Subject: [PATCH 17/49] Removed option --http-enabled. --- CHANGELOG.md | 1 + src/base/kernel/config/BaseTransform.cpp | 11 ++++++++++- src/base/kernel/config/BaseTransform.h | 2 ++ src/core/config/usage.h | 1 - 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 784de18a..47fb5015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # v4.0.2-beta - [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd. - [#1185](https://github.com/xmrig/xmrig/pull/1185) Added JIT compiler for RandomX on ARMv8. +- Command line option `--http-enabled` removed, HTTP API enabled automatically if any other `--http-*` option provided. # v4.0.1-beta - [#1177](https://github.com/xmrig/xmrig/issues/1177) Fixed compatibility with old AMD drivers. diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index a10960a4..bd43036c 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -102,6 +102,10 @@ void xmrig::BaseTransform::finalize(rapidjson::Document &doc) } } } + + if (m_http) { + set(doc, kHttp, "enabled", true); + } } @@ -164,9 +168,11 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch return set(doc, "log-file", arg); case IConfig::HttpAccessTokenKey: /* --http-access-token */ + m_http = true; return set(doc, kHttp, "access-token", arg); case IConfig::HttpHostKey: /* --http-host */ + m_http = true; return set(doc, kHttp, "host", arg); case IConfig::ApiWorkerIdKey: /* --api-worker-id */ @@ -235,10 +241,12 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b return set(doc, "colors", enable); case IConfig::HttpRestrictedKey: /* --http-no-restricted */ + m_http = true; return set(doc, kHttp, "restricted", enable); case IConfig::HttpEnabledKey: /* --http-enabled */ - return set(doc, kHttp, "enabled", enable); + m_http = true; + break; case IConfig::DryRunKey: /* --dry-run */ return set(doc, "dry-run", enable); @@ -265,6 +273,7 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui return set(doc, "donate-over-proxy", arg); case IConfig::HttpPort: /* --http-port */ + m_http = true; return set(doc, kHttp, "port", arg); case IConfig::PrintTimeKey: /* --print-time */ diff --git a/src/base/kernel/config/BaseTransform.h b/src/base/kernel/config/BaseTransform.h index 5fa0c8c5..f926861d 100644 --- a/src/base/kernel/config/BaseTransform.h +++ b/src/base/kernel/config/BaseTransform.h @@ -102,6 +102,8 @@ protected: private: void transformBoolean(rapidjson::Document &doc, int key, bool enable); void transformUint64(rapidjson::Document &doc, int key, uint64_t arg); + + bool m_http = false; }; diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 34998bce..615921b3 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -87,7 +87,6 @@ static inline const std::string &usage() u += "\nAPI:\n"; u += " --api-worker-id=ID custom worker-id for API\n"; u += " --api-id=ID custom instance ID for API\n"; - u += " --http-enabled enable HTTP API\n"; u += " --http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n"; u += " --http-port=N bind port for HTTP API\n"; u += " --http-access-token=T access token for HTTP API\n"; From bdb72684b0ba0c63f12f146ae4b784f15cc3ccc8 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 23 Sep 2019 05:08:59 +0700 Subject: [PATCH 18/49] Added command line option --no-cpu --- CHANGELOG.md | 3 ++- src/core/config/ConfigTransform.cpp | 4 ++++ src/core/config/Config_platform.h | 1 + src/core/config/usage.h | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47fb5015..a83f24d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # v4.0.2-beta - [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd. - [#1185](https://github.com/xmrig/xmrig/pull/1185) Added JIT compiler for RandomX on ARMv8. -- Command line option `--http-enabled` removed, HTTP API enabled automatically if any other `--http-*` option provided. +- Added command line option `--no-cpu` to disable CPU backend. +- Removed command line option `--http-enabled`, HTTP API enabled automatically if any other `--http-*` option provided. # v4.0.1-beta - [#1177](https://github.com/xmrig/xmrig/issues/1177) Fixed compatibility with old AMD drivers. diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index f11fe930..4dc009ad 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -118,6 +118,7 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const return transformUint64(doc, key, static_cast(strtol(arg, nullptr, 10))); case IConfig::HugePagesKey: /* --no-huge-pages */ + case IConfig::CPUKey: /* --no-cpu */ return transformBoolean(doc, key, false); case IConfig::CPUAffinityKey: /* --cpu-affinity */ @@ -151,6 +152,9 @@ void xmrig::ConfigTransform::transformBoolean(rapidjson::Document &doc, int key, case IConfig::HugePagesKey: /* --no-huge-pages */ return set(doc, kCpu, "huge-pages", enable); + case IConfig::CPUKey: /* --no-cpu */ + return set(doc, kCpu, "enabled", enable); + default: break; } diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index a10f3c16..d4a0a5b8 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -80,6 +80,7 @@ static const option options[] = { { "user-agent", 1, nullptr, IConfig::UserAgentKey }, { "userpass", 1, nullptr, IConfig::UserpassKey }, { "rig-id", 1, nullptr, IConfig::RigIdKey }, + { "no-cpu", 0, nullptr, IConfig::CPUKey }, # ifdef XMRIG_FEATURE_TLS { "tls", 0, nullptr, IConfig::TlsKey }, { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 615921b3..f64842ae 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -71,6 +71,7 @@ static inline const std::string &usage() u += "\nCPU backend:\n"; + u += " --no-cpu disable CPU backend\n"; u += " -t, --threads=N number of CPU threads\n"; u += " -v, --av=N algorithm variation, 0 auto select\n"; u += " --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n"; From d9dc6a396f415df815e5046d3692910ef74e1722 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 23 Sep 2019 05:33:48 +0700 Subject: [PATCH 19/49] Add support for initialize OpenCL in runtime. --- src/backend/opencl/OclBackend.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/backend/opencl/OclBackend.cpp b/src/backend/opencl/OclBackend.cpp index 4820ce08..9b226811 100644 --- a/src/backend/opencl/OclBackend.cpp +++ b/src/backend/opencl/OclBackend.cpp @@ -135,6 +135,10 @@ public: return printDisabled(RED_S " (failed to load OpenCL runtime)"); } + if (platform.isValid()) { + return; + } + platform = cl.platform(); if (!platform.isValid()) { return printDisabled(RED_S " (selected OpenCL platform NOT found)"); @@ -302,12 +306,15 @@ void xmrig::OclBackend::printHashrate(bool details) void xmrig::OclBackend::setJob(const Job &job) { + const OclConfig &cl = d_ptr->controller->config()->cl(); + if (cl.isEnabled()) { + d_ptr->init(cl); + } + if (!isEnabled()) { return stop(); } - const OclConfig &cl = d_ptr->controller->config()->cl(); - std::vector threads = cl.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->platform, d_ptr->devices, tag); if (!d_ptr->threads.empty() && d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) { return; From 3e42fa28df431208c7b5def2990c267b634c7e97 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 23 Sep 2019 05:51:46 +0700 Subject: [PATCH 20/49] OpenCL backend disabled by default. --- CHANGELOG.md | 1 + src/backend/opencl/OclConfig.cpp | 18 ++++++++++++------ src/backend/opencl/OclConfig.h | 2 +- src/config.json | 2 +- src/core/config/Config_default.h | 2 +- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a83f24d7..24749dd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # v4.0.2-beta +- **OpenCL backend disabled by default.**. - [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd. - [#1185](https://github.com/xmrig/xmrig/pull/1185) Added JIT compiler for RandomX on ARMv8. - Added command line option `--no-cpu` to disable CPU backend. diff --git a/src/backend/opencl/OclConfig.cpp b/src/backend/opencl/OclConfig.cpp index cdb38ccb..cec10b35 100644 --- a/src/backend/opencl/OclConfig.cpp +++ b/src/backend/opencl/OclConfig.cpp @@ -215,16 +215,18 @@ void xmrig::OclConfig::read(const rapidjson::Value &value) setPlatform(Json::getValue(value, kPlatform)); - if (isEnabled()) { - m_threads.read(value); + m_threads.read(value); - generate(); - } + generate(); } - else if (value.IsBool() && value.IsFalse()) { - m_enabled = false; + else if (value.IsBool()) { + m_enabled = value.GetBool(); + + generate(); } else { + m_shouldSave = true; + generate(); } } @@ -232,6 +234,10 @@ void xmrig::OclConfig::read(const rapidjson::Value &value) void xmrig::OclConfig::generate() { + if (!isEnabled()) { + return; + } + if (!OclLib::init(loader())) { return; } diff --git a/src/backend/opencl/OclConfig.h b/src/backend/opencl/OclConfig.h index 22d1378e..72546342 100644 --- a/src/backend/opencl/OclConfig.h +++ b/src/backend/opencl/OclConfig.h @@ -56,7 +56,7 @@ private: void setPlatform(const rapidjson::Value &platform); bool m_cache = true; - bool m_enabled = true; + bool m_enabled = false; bool m_shouldSave = false; String m_loader; String m_platformVendor; diff --git a/src/config.json b/src/config.json index 2f88ecab..3023d22a 100644 --- a/src/config.json +++ b/src/config.json @@ -29,7 +29,7 @@ "cn-lite/0": false }, "opencl": { - "enabled": true, + "enabled": false, "cache": true, "loader": null, "platform": "AMD", diff --git a/src/core/config/Config_default.h b/src/core/config/Config_default.h index 8011bf16..b6816649 100644 --- a/src/core/config/Config_default.h +++ b/src/core/config/Config_default.h @@ -63,7 +63,7 @@ R"===( "cn-lite/0": false }, "opencl": { - "enabled": true, + "enabled": false, "cache": true, "loader": null, "platform": "AMD", From 5f948d0d96d63696663e7fff286a5bbc314a36cd Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 24 Sep 2019 00:03:50 +0700 Subject: [PATCH 21/49] Fixed potential truncation. --- src/backend/common/misc/PciTopology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/common/misc/PciTopology.h b/src/backend/common/misc/PciTopology.h index 4f362bc4..ce33ebdb 100644 --- a/src/backend/common/misc/PciTopology.h +++ b/src/backend/common/misc/PciTopology.h @@ -54,7 +54,7 @@ public: } char *buf = new char[8](); - snprintf(buf, 8, "%02x:%02x.%01x", bus(), device(), function()); + snprintf(buf, 8, "%02hhx:%02hhx.%01hhx", bus(), device(), function()); return buf; } From 2604705bab38a0faa404f776af8111dfde7716c8 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 24 Sep 2019 03:14:35 +0700 Subject: [PATCH 22/49] Added command line option --opencl. --- .../AMD_Opteron_6344_x2_N4_win7_2_0_4_bug.xml | 262 ++++++++++++ .../AMD_Opteron_6348_x4_N8_linux_2_0_4.xml | 399 ++++++++++++++++++ src/base/kernel/interfaces/IConfig.h | 1 + src/core/config/ConfigTransform.cpp | 21 +- src/core/config/ConfigTransform.h | 1 + src/core/config/Config_platform.h | 3 + src/core/config/usage.h | 7 +- 7 files changed, 691 insertions(+), 3 deletions(-) create mode 100644 doc/topology/AMD_Opteron_6344_x2_N4_win7_2_0_4_bug.xml create mode 100644 doc/topology/AMD_Opteron_6348_x4_N8_linux_2_0_4.xml diff --git a/doc/topology/AMD_Opteron_6344_x2_N4_win7_2_0_4_bug.xml b/doc/topology/AMD_Opteron_6344_x2_N4_win7_2_0_4_bug.xml new file mode 100644 index 00000000..f3a25ff5 --- /dev/null +++ b/doc/topology/AMD_Opteron_6344_x2_N4_win7_2_0_4_bug.xml @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/topology/AMD_Opteron_6348_x4_N8_linux_2_0_4.xml b/doc/topology/AMD_Opteron_6348_x4_N8_linux_2_0_4.xml new file mode 100644 index 00000000..909dbcb9 --- /dev/null +++ b/doc/topology/AMD_Opteron_6348_x4_N8_linux_2_0_4.xml @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 2 5 6 + 10 22 16 22 22 10 22 16 16 22 + 10 22 22 16 22 10 + + + diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 0569a3d1..7823d325 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -100,6 +100,7 @@ public: OclMemChunkKey = 1408, OclUnrollKey = 1409, OclCompModeKey = 1410, + OclKey = 1411, // xmrig-proxy AccessLogFileKey = 'A', diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index 4dc009ad..fdf70b37 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -35,11 +35,16 @@ namespace xmrig static const char *kAffinity = "affinity"; static const char *kAsterisk = "*"; static const char *kCpu = "cpu"; +static const char *kEnabled = "enabled"; static const char *kIntensity = "intensity"; static const char *kThreads = "threads"; #ifdef XMRIG_ALGO_RANDOMX -static const char *kRandomX = "randomx"; +static const char *kRandomX = "randomx"; +#endif + +#ifdef XMRIG_FEATURE_OPENCL +static const char *kOcl = "opencl"; #endif @@ -104,6 +109,12 @@ void xmrig::ConfigTransform::finalize(rapidjson::Document &doc) doc[kCpu].AddMember(StringRef(kAsterisk), profile, doc.GetAllocator()); } + +# ifdef XMRIG_FEATURE_OPENCL + if (m_opencl) { + set(doc, kOcl, kEnabled, true); + } +# endif } @@ -140,6 +151,12 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const return set(doc, kRandomX, "numa", false); # endif +# ifdef XMRIG_FEATURE_OPENCL + case IConfig::OclKey: /* --opencl */ + m_opencl = true; + break; +# endif + default: break; } @@ -153,7 +170,7 @@ void xmrig::ConfigTransform::transformBoolean(rapidjson::Document &doc, int key, return set(doc, kCpu, "huge-pages", enable); case IConfig::CPUKey: /* --no-cpu */ - return set(doc, kCpu, "enabled", enable); + return set(doc, kCpu, kEnabled, enable); default: break; diff --git a/src/core/config/ConfigTransform.h b/src/core/config/ConfigTransform.h index 7ec3cdec..66c497ab 100644 --- a/src/core/config/ConfigTransform.h +++ b/src/core/config/ConfigTransform.h @@ -42,6 +42,7 @@ private: void transformBoolean(rapidjson::Document &doc, int key, bool enable); void transformUint64(rapidjson::Document &doc, int key, uint64_t arg); + bool m_opencl = false; int64_t m_affinity = -1; uint64_t m_intensity = 1; uint64_t m_threads = 0; diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index d4a0a5b8..fcad8bc5 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -91,6 +91,9 @@ static const option options[] = { # ifdef XMRIG_ALGO_RANDOMX { "randomx-init", 1, nullptr, IConfig::RandomXInitKey }, { "randomx-no-numa", 0, nullptr, IConfig::RandomXNumaKey }, +# endif +# ifdef XMRIG_FEATURE_OPENCL + { "opencl", 0, nullptr, IConfig::OclKey }, # endif { nullptr, 0, nullptr, 0 } }; diff --git a/src/core/config/usage.h b/src/core/config/usage.h index f64842ae..60225d0b 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -71,7 +71,7 @@ static inline const std::string &usage() u += "\nCPU backend:\n"; - u += " --no-cpu disable CPU backend\n"; + u += " --no-cpu disable CPU mining backend\n"; u += " -t, --threads=N number of CPU threads\n"; u += " -v, --av=N algorithm variation, 0 auto select\n"; u += " --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n"; @@ -94,6 +94,11 @@ static inline const std::string &usage() u += " --http-no-restricted enable full remote access to HTTP API (only if access token set)\n"; # endif +# ifdef XMRIG_FEATURE_OPENCL + u += "\nOpenCL backend:\n"; + u += " --opencl enable OpenCL mining backend\n"; +# endif + u += "\nLogging:\n"; # ifdef HAVE_SYSLOG_H From c6096c3c340b39171a6fcfebd19fd21e2b8da7c1 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Mon, 23 Sep 2019 23:12:40 +0200 Subject: [PATCH 23/49] Workaround for a bug in binutils-2.32-1 on ARM ldr/madd instruction sequence makes compiled binary crash, so separate them. --- src/crypto/randomx/jit_compiler_a64_static.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/crypto/randomx/jit_compiler_a64_static.S b/src/crypto/randomx/jit_compiler_a64_static.S index a813e821..be37602b 100644 --- a/src/crypto/randomx/jit_compiler_a64_static.S +++ b/src/crypto/randomx/jit_compiler_a64_static.S @@ -485,12 +485,13 @@ randomx_calc_dataset_item_aarch64: stp x10, x11, [sp, 80] stp x12, x13, [sp, 96] + ldr x12, superscalarMul0 + mov x8, x0 mov x9, x1 mov x10, x2 # rl[0] = (itemNumber + 1) * superscalarMul0; - ldr x12, superscalarMul0 madd x0, x2, x12, x12 # rl[1] = rl[0] ^ superscalarAdd1; From 1bba25e08065e335f0e59e799152927807594916 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Tue, 24 Sep 2019 08:53:00 +0200 Subject: [PATCH 24/49] Set scratchpad pointer to null by default To avoid freeing random blocks of memory in some cases. --- src/crypto/randomx/virtual_machine.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/randomx/virtual_machine.hpp b/src/crypto/randomx/virtual_machine.hpp index 2dc89bb5..c85af009 100644 --- a/src/crypto/randomx/virtual_machine.hpp +++ b/src/crypto/randomx/virtual_machine.hpp @@ -64,7 +64,7 @@ protected: alignas(64) randomx::RegisterFile reg; alignas(16) randomx::ProgramConfiguration config; randomx::MemoryRegisters mem; - uint8_t* scratchpad; + uint8_t* scratchpad = nullptr; union { randomx_cache* cachePtr = nullptr; randomx_dataset* datasetPtr; From 6267ecc3dce8f1a230265c2c5d774eb3f9953e8e Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 24 Sep 2019 18:39:43 +0700 Subject: [PATCH 25/49] Implemented --opencl-no-cache, --opencl-loader, --opencl-platform command line options. --- src/core/config/ConfigTransform.cpp | 13 +++++++++++++ src/core/config/Config_platform.h | 8 ++++++++ src/core/config/usage.h | 9 +++++++++ 3 files changed, 30 insertions(+) diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index fdf70b37..58f6aa64 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -155,6 +155,19 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const case IConfig::OclKey: /* --opencl */ m_opencl = true; break; + + case IConfig::OclCacheKey: /* --opencl-no-cache */ + return set(doc, kOcl, "cache", false); + + case IConfig::OclLoaderKey: /* --opencl-loader */ + return set(doc, kOcl, "loader", arg); + + case IConfig::OclPlatformKey: /* --opencl-platform */ + if (strlen(arg) < 3) { + return set(doc, kOcl, "platform", static_cast(strtol(arg, nullptr, 10))); + } + + return set(doc, kOcl, "platform", arg); # endif default: diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index fcad8bc5..79c3b159 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -94,6 +94,14 @@ static const option options[] = { # endif # ifdef XMRIG_FEATURE_OPENCL { "opencl", 0, nullptr, IConfig::OclKey }, + { "opencl-devices", 1, nullptr, IConfig::OclDevicesKey }, + { "opencl-launch", 1, nullptr, IConfig::OclLaunchKey }, + { "opencl-strided-index", 1, nullptr, IConfig::OclSridedIndexKey }, + { "opencl-mem-chunk", 1, nullptr, IConfig::OclMemChunkKey }, + { "opencl-affinity", 1, nullptr, IConfig::OclAffinityKey }, + { "opencl-platform", 1, nullptr, IConfig::OclPlatformKey }, + { "opencl-loader", 1, nullptr, IConfig::OclLoaderKey }, + { "opencl-no-cache", 0, nullptr, IConfig::OclCacheKey }, # endif { nullptr, 0, nullptr, 0 } }; diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 60225d0b..f1d5fda5 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -97,6 +97,15 @@ static inline const std::string &usage() # ifdef XMRIG_FEATURE_OPENCL u += "\nOpenCL backend:\n"; u += " --opencl enable OpenCL mining backend\n"; + u += " --opencl-devices=N list of OpenCL devices to use\n"; + u += " --opencl-launch=IxW list of launch config, intensity and worksize\n"; + u += " --opencl-strided-index=N list of strided_index option values for each thread\n"; + u += " --opencl-mem-chunk=N list of mem_chunk option values for each thread\n"; + u += " --opencl-affinity=N list of affinity GPU threads to a CPU\n"; + u += " --opencl-platform=N OpenCL platform index or name\n"; + u += " --opencl-loader=N path to OpenCL-ICD-Loader (OpenCL.dll or libOpenCL.so)\n"; + u += " --opencl-no-cache disable OpenCL cache\n"; + u += " --print-platforms print available OpenCL platforms and exit\n"; # endif u += "\nLogging:\n"; From d6f05557710472ca4afdb9ec2536d5ba6274a392 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 24 Sep 2019 23:01:03 +0700 Subject: [PATCH 26/49] Added command line option --opencl-devices (hint mode) --- src/backend/opencl/OclConfig.cpp | 40 +++++++++++++++++++++++++++-- src/backend/opencl/OclConfig.h | 2 ++ src/backend/opencl/OclThread.cpp | 4 +++ src/base/io/json/Json.cpp | 21 +++++++++++++++ src/core/config/ConfigTransform.cpp | 4 +++ 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/backend/opencl/OclConfig.cpp b/src/backend/opencl/OclConfig.cpp index cec10b35..7424dba7 100644 --- a/src/backend/opencl/OclConfig.cpp +++ b/src/backend/opencl/OclConfig.cpp @@ -30,12 +30,16 @@ #include "rapidjson/document.h" +#include + + namespace xmrig { static const char *kAMD = "AMD"; static const char *kCache = "cache"; static const char *kCn = "cn"; static const char *kCn2 = "cn/2"; +static const char *kDevicesHint = "devices-hint"; static const char *kEnabled = "enabled"; static const char *kINTEL = "INTEL"; static const char *kLoader = "loader"; @@ -90,6 +94,22 @@ static size_t generate(const char *key, Threads &threads, const Algo } +static inline std::vector filterDevices(const std::vector &devices, const std::vector &hints) +{ + std::vector out; + out.reserve(std::min(devices.size(), hints.size())); + + for (const auto &device : devices) { + auto it = std::find(hints.begin(), hints.end(), device.index()); + if (it != hints.end()) { + out.emplace_back(device); + } + } + + return out; +} + + } @@ -214,6 +234,7 @@ void xmrig::OclConfig::read(const rapidjson::Value &value) m_loader = Json::getString(value, kLoader); setPlatform(Json::getValue(value, kPlatform)); + setDevicesHint(Json::getString(value, kDevicesHint)); m_threads.read(value); @@ -234,7 +255,7 @@ void xmrig::OclConfig::read(const rapidjson::Value &value) void xmrig::OclConfig::generate() { - if (!isEnabled()) { + if (!isEnabled() || m_threads.has("*")) { return; } @@ -242,7 +263,7 @@ void xmrig::OclConfig::generate() return; } - const auto devices = platform().devices(); + const auto devices = m_devicesHint.empty() ? platform().devices() : filterDevices(platform().devices(), m_devicesHint); if (devices.empty()) { return; } @@ -287,6 +308,21 @@ void xmrig::OclConfig::generate() } +void xmrig::OclConfig::setDevicesHint(const char *devicesHint) +{ + if (devicesHint == nullptr) { + return; + } + + const auto indexes = String(devicesHint).split(','); + m_devicesHint.reserve(indexes.size()); + + for (const auto &index : indexes) { + m_devicesHint.push_back(strtoul(index, nullptr, 10)); + } +} + + void xmrig::OclConfig::setPlatform(const rapidjson::Value &platform) { if (platform.IsString()) { diff --git a/src/backend/opencl/OclConfig.h b/src/backend/opencl/OclConfig.h index 72546342..9dd5ad1d 100644 --- a/src/backend/opencl/OclConfig.h +++ b/src/backend/opencl/OclConfig.h @@ -53,11 +53,13 @@ public: private: void generate(); + void setDevicesHint(const char *devicesHint); void setPlatform(const rapidjson::Value &platform); bool m_cache = true; bool m_enabled = false; bool m_shouldSave = false; + std::vector m_devicesHint; String m_loader; String m_platformVendor; Threads m_threads; diff --git a/src/backend/opencl/OclThread.cpp b/src/backend/opencl/OclThread.cpp index 02ef5f3b..8ca4574f 100644 --- a/src/backend/opencl/OclThread.cpp +++ b/src/backend/opencl/OclThread.cpp @@ -52,6 +52,10 @@ static const char* kDatasetHost = "dataset_host"; xmrig::OclThread::OclThread(const rapidjson::Value &value) { + if (!value.IsObject()) { + return; + } + m_index = Json::getUint(value, kIndex); m_worksize = std::max(std::min(Json::getUint(value, kWorksize), 128u), 1u); m_unrollFactor = std::max(std::min(Json::getUint(value, kUnroll, m_unrollFactor), 128u), 1u); diff --git a/src/base/io/json/Json.cpp b/src/base/io/json/Json.cpp index 07986c4a..03d4c65a 100644 --- a/src/base/io/json/Json.cpp +++ b/src/base/io/json/Json.cpp @@ -27,6 +27,9 @@ #include "rapidjson/document.h" +#include + + namespace xmrig { static const rapidjson::Value kNullValue; @@ -36,6 +39,8 @@ static const rapidjson::Value kNullValue; bool xmrig::Json::getBool(const rapidjson::Value &obj, const char *key, bool defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsBool()) { return i->value.GetBool(); @@ -47,6 +52,8 @@ bool xmrig::Json::getBool(const rapidjson::Value &obj, const char *key, bool def const char *xmrig::Json::getString(const rapidjson::Value &obj, const char *key, const char *defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsString()) { return i->value.GetString(); @@ -58,6 +65,8 @@ const char *xmrig::Json::getString(const rapidjson::Value &obj, const char *key, const rapidjson::Value &xmrig::Json::getArray(const rapidjson::Value &obj, const char *key) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsArray()) { return i->value; @@ -69,6 +78,8 @@ const rapidjson::Value &xmrig::Json::getArray(const rapidjson::Value &obj, const const rapidjson::Value &xmrig::Json::getObject(const rapidjson::Value &obj, const char *key) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsObject()) { return i->value; @@ -80,6 +91,8 @@ const rapidjson::Value &xmrig::Json::getObject(const rapidjson::Value &obj, cons const rapidjson::Value &xmrig::Json::getValue(const rapidjson::Value &obj, const char *key) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd()) { return i->value; @@ -91,6 +104,8 @@ const rapidjson::Value &xmrig::Json::getValue(const rapidjson::Value &obj, const int xmrig::Json::getInt(const rapidjson::Value &obj, const char *key, int defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsInt()) { return i->value.GetInt(); @@ -102,6 +117,8 @@ int xmrig::Json::getInt(const rapidjson::Value &obj, const char *key, int defaul int64_t xmrig::Json::getInt64(const rapidjson::Value &obj, const char *key, int64_t defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsInt64()) { return i->value.GetInt64(); @@ -113,6 +130,8 @@ int64_t xmrig::Json::getInt64(const rapidjson::Value &obj, const char *key, int6 uint64_t xmrig::Json::getUint64(const rapidjson::Value &obj, const char *key, uint64_t defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsUint64()) { return i->value.GetUint64(); @@ -124,6 +143,8 @@ uint64_t xmrig::Json::getUint64(const rapidjson::Value &obj, const char *key, ui unsigned xmrig::Json::getUint(const rapidjson::Value &obj, const char *key, unsigned defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsUint()) { return i->value.GetUint(); diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index 58f6aa64..e7bd383f 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -162,6 +162,10 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const case IConfig::OclLoaderKey: /* --opencl-loader */ return set(doc, kOcl, "loader", arg); + case IConfig::OclDevicesKey: /* --opencl-devices */ + m_opencl = true; + return set(doc, kOcl, "devices-hint", arg); + case IConfig::OclPlatformKey: /* --opencl-platform */ if (strlen(arg) < 3) { return set(doc, kOcl, "platform", static_cast(strtol(arg, nullptr, 10))); From 838f078fa51b7618b627d94751f1727456570400 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 26 Sep 2019 01:53:16 +0700 Subject: [PATCH 27/49] Advanced opencl options postponed. --- CHANGELOG.md | 1 + src/core/config/Config_platform.h | 4 ---- src/core/config/usage.h | 4 ---- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24749dd9..fb8d9dba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd. - [#1185](https://github.com/xmrig/xmrig/pull/1185) Added JIT compiler for RandomX on ARMv8. - Added command line option `--no-cpu` to disable CPU backend. +- Added OpenCL specific command line options: `--opencl`, `--opencl-devices`, `--opencl-platform`, `--opencl-loader` and `--opencl-no-cache`. - Removed command line option `--http-enabled`, HTTP API enabled automatically if any other `--http-*` option provided. # v4.0.1-beta diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index 79c3b159..e58a9fb7 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -95,10 +95,6 @@ static const option options[] = { # ifdef XMRIG_FEATURE_OPENCL { "opencl", 0, nullptr, IConfig::OclKey }, { "opencl-devices", 1, nullptr, IConfig::OclDevicesKey }, - { "opencl-launch", 1, nullptr, IConfig::OclLaunchKey }, - { "opencl-strided-index", 1, nullptr, IConfig::OclSridedIndexKey }, - { "opencl-mem-chunk", 1, nullptr, IConfig::OclMemChunkKey }, - { "opencl-affinity", 1, nullptr, IConfig::OclAffinityKey }, { "opencl-platform", 1, nullptr, IConfig::OclPlatformKey }, { "opencl-loader", 1, nullptr, IConfig::OclLoaderKey }, { "opencl-no-cache", 0, nullptr, IConfig::OclCacheKey }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index f1d5fda5..fc9695a3 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -98,10 +98,6 @@ static inline const std::string &usage() u += "\nOpenCL backend:\n"; u += " --opencl enable OpenCL mining backend\n"; u += " --opencl-devices=N list of OpenCL devices to use\n"; - u += " --opencl-launch=IxW list of launch config, intensity and worksize\n"; - u += " --opencl-strided-index=N list of strided_index option values for each thread\n"; - u += " --opencl-mem-chunk=N list of mem_chunk option values for each thread\n"; - u += " --opencl-affinity=N list of affinity GPU threads to a CPU\n"; u += " --opencl-platform=N OpenCL platform index or name\n"; u += " --opencl-loader=N path to OpenCL-ICD-Loader (OpenCL.dll or libOpenCL.so)\n"; u += " --opencl-no-cache disable OpenCL cache\n"; From 0f367ab117db6fa8da103426580a2d42a311abf3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 26 Sep 2019 17:29:24 +0700 Subject: [PATCH 28/49] Added "restricted" field to "GET /1/summary" request. --- src/base/api/Api.cpp | 7 ++++--- src/base/api/Api.h | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/base/api/Api.cpp b/src/base/api/Api.cpp index b52e6976..22f00b77 100644 --- a/src/base/api/Api.cpp +++ b/src/base/api/Api.cpp @@ -117,9 +117,10 @@ void xmrig::Api::exec(IApiRequest &request) auto &allocator = request.doc().GetAllocator(); request.accept(); - request.reply().AddMember("id", StringRef(m_id), allocator); - request.reply().AddMember("worker_id", StringRef(m_workerId), allocator); - request.reply().AddMember("uptime", (Chrono::currentMSecsSinceEpoch() - m_timestamp) / 1000, allocator); + request.reply().AddMember("id", StringRef(m_id), allocator); + request.reply().AddMember("worker_id", StringRef(m_workerId), allocator); + request.reply().AddMember("uptime", (Chrono::currentMSecsSinceEpoch() - m_timestamp) / 1000, allocator); + request.reply().AddMember("restricted", request.isRestricted(), allocator); Value features(kArrayType); # ifdef XMRIG_FEATURE_API diff --git a/src/base/api/Api.h b/src/base/api/Api.h index 334609c9..0c1a728d 100644 --- a/src/base/api/Api.h +++ b/src/base/api/Api.h @@ -27,10 +27,11 @@ #include -#include +#include #include "base/kernel/interfaces/IBaseListener.h" +#include "base/tools/Object.h" namespace xmrig { @@ -47,6 +48,8 @@ class String; class Api : public IBaseListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Api) + Api(Base *base); ~Api() override; From 88a9f8d892a552f2230b231cdbc5d2e147ec0ede Mon Sep 17 00:00:00 2001 From: xmrig Date: Thu, 26 Sep 2019 23:40:01 +0700 Subject: [PATCH 29/49] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb8d9dba..ce58c88e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ -# v4.0.2-beta +# v4.1.0-beta - **OpenCL backend disabled by default.**. - [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd. - [#1185](https://github.com/xmrig/xmrig/pull/1185) Added JIT compiler for RandomX on ARMv8. +- Improved API endpoint `GET /2/backends` and added support for this endpoint to [workers.xmrig.info](http://workers.xmrig.info). - Added command line option `--no-cpu` to disable CPU backend. - Added OpenCL specific command line options: `--opencl`, `--opencl-devices`, `--opencl-platform`, `--opencl-loader` and `--opencl-no-cache`. - Removed command line option `--http-enabled`, HTTP API enabled automatically if any other `--http-*` option provided. From 56e070b3d140144b1de1d329a56dbcff62514062 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 26 Sep 2019 23:41:11 +0700 Subject: [PATCH 30/49] v4.1.0-evo --- src/version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/version.h b/src/version.h index f4cb9118..53f3139e 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 "4.0.2-evo" +#define APP_VERSION "4.1.0-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "miner" #define APP_VER_MAJOR 4 -#define APP_VER_MINOR 0 -#define APP_VER_PATCH 2 +#define APP_VER_MINOR 1 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From 18bf9d3d95f490c4fb2e8cfd1956501f6dbfbb75 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 27 Sep 2019 01:03:37 +0700 Subject: [PATCH 31/49] Reduced PciTopology class size. --- src/backend/common/misc/PciTopology.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/backend/common/misc/PciTopology.h b/src/backend/common/misc/PciTopology.h index ce33ebdb..ee531f50 100644 --- a/src/backend/common/misc/PciTopology.h +++ b/src/backend/common/misc/PciTopology.h @@ -40,12 +40,12 @@ class PciTopology { public: PciTopology() = default; - PciTopology(uint32_t bus, uint32_t device, uint32_t function) : m_bus(bus), m_device(device), m_function(function) {} + PciTopology(uint32_t bus, uint32_t device, uint32_t function) : m_valid(true), m_bus(bus), m_device(device), m_function(function) {} - inline bool isValid() const { return m_bus >= 0; } - inline uint32_t bus() const { return isValid() ? m_bus : 0; } - inline uint32_t device() const { return m_device; } - inline uint32_t function() const { return m_function; } + inline bool isValid() const { return m_valid; } + inline uint8_t bus() const { return m_bus; } + inline uint8_t device() const { return m_device; } + inline uint8_t function() const { return m_function; } String toString() const { @@ -60,9 +60,10 @@ public: } private: - int32_t m_bus = -1; - uint32_t m_device = 0; - uint32_t m_function = 0; + bool m_valid = false; + uint8_t m_bus = 0; + uint8_t m_device = 0; + uint8_t m_function = 0; }; From 41ec1b4cb23b17bab6c10822a303f8c6fef57a59 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 27 Sep 2019 01:55:05 +0700 Subject: [PATCH 32/49] Fixed build with gcc 4.8. --- src/backend/opencl/runners/tools/OclCnR.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/opencl/runners/tools/OclCnR.cpp b/src/backend/opencl/runners/tools/OclCnR.cpp index ed415194..929938cc 100644 --- a/src/backend/opencl/runners/tools/OclCnR.cpp +++ b/src/backend/opencl/runners/tools/OclCnR.cpp @@ -237,7 +237,7 @@ private: for (size_t i = 0; i < OclCnR::kHeightChunkSize; ++i) { V4_Instruction code[256]; const int code_size = v4_random_math_init(code, offset + i); - const std::string kernel = std::regex_replace(cryptonight_r_cl, std::regex("XMRIG_INCLUDE_RANDOM_MATH"), getCode(code, code_size)); + const std::string kernel = std::regex_replace(std::string(cryptonight_r_cl), std::regex("XMRIG_INCLUDE_RANDOM_MATH"), getCode(code, code_size)); source += std::regex_replace(kernel, std::regex("KERNEL_NAME"), "cn1_" + std::to_string(offset + i)); } From ffccaa8817dae844b673f72701e295f1426dacb1 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 27 Sep 2019 02:14:32 +0700 Subject: [PATCH 33/49] v4.1.0-beta --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 53f3139e..5bf8e78c 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 "4.1.0-evo" +#define APP_VERSION "4.1.0-beta" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" From 82aaa89ab6956811eeb017d6862d600b46247830 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 27 Sep 2019 02:56:22 +0700 Subject: [PATCH 34/49] v4.2.0-evo --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index 5bf8e78c..eb4ac706 100644 --- a/src/version.h +++ b/src/version.h @@ -28,14 +28,14 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig miner" -#define APP_VERSION "4.1.0-beta" +#define APP_VERSION "4.2.0-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "miner" #define APP_VER_MAJOR 4 -#define APP_VER_MINOR 1 +#define APP_VER_MINOR 2 #define APP_VER_PATCH 0 #ifdef _MSC_VER From e1d1a5226cce0c9c177c01b94ebbf14fde98542f Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 27 Sep 2019 05:41:45 +0700 Subject: [PATCH 35/49] Added coin option. --- CMakeLists.txt | 2 + src/base/kernel/config/BaseTransform.cpp | 19 +++++ src/base/kernel/config/BaseTransform.h | 2 + src/base/kernel/interfaces/IConfig.h | 1 + src/base/net/stratum/Client.cpp | 12 ++- src/base/net/stratum/Job.h | 1 + src/base/net/stratum/Pool.cpp | 4 + src/base/net/stratum/Pool.h | 4 +- src/base/net/stratum/Pools.cpp | 5 +- src/config.json | 1 + src/core/config/Config_default.h | 1 + src/core/config/Config_platform.h | 1 + src/core/config/usage.h | 1 + src/crypto/common/Coin.cpp | 103 +++++++++++++++++++++++ src/crypto/common/Coin.h | 75 +++++++++++++++++ 15 files changed, 227 insertions(+), 5 deletions(-) create mode 100644 src/crypto/common/Coin.cpp create mode 100644 src/crypto/common/Coin.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b3a4b5dc..c75efb41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ set(HEADERS_CRYPTO src/crypto/cn/skein_port.h src/crypto/cn/soft_aes.h src/crypto/common/Algorithm.h + src/crypto/common/Coin.h src/crypto/common/keccak.h src/crypto/common/Nonce.h src/crypto/common/portable/mm_malloc.h @@ -105,6 +106,7 @@ set(SOURCES_CRYPTO src/crypto/cn/CnCtx.cpp src/crypto/cn/CnHash.cpp src/crypto/common/Algorithm.cpp + src/crypto/common/Coin.cpp src/crypto/common/keccak.cpp src/crypto/common/Nonce.cpp src/crypto/common/VirtualMemory.cpp diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 12e7d848..7090b6b7 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -47,6 +47,7 @@ namespace xmrig static const char *kAlgo = "algo"; static const char *kApi = "api"; +static const char *kCoin = "coin"; static const char *kHttp = "http"; static const char *kPools = "pools"; @@ -107,6 +108,15 @@ void xmrig::BaseTransform::finalize(rapidjson::Document &doc) } } } + + if (m_coin.isValid() && doc.HasMember(kPools)) { + auto &pools = doc[kPools]; + for (Value &pool : pools.GetArray()) { + if (!pool.HasMember(kCoin)) { + pool.AddMember(StringRef(kCoin), m_coin.toJSON(), allocator); + } + } + } } @@ -122,6 +132,15 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch } break; + case IConfig::CoinKey: /* --coin */ + if (!doc.HasMember(kPools)) { + m_coin = arg; + } + else { + return add(doc, kPools, kCoin, arg); + } + break; + case IConfig::UserpassKey: /* --userpass */ { const char *p = strrchr(arg, ':'); diff --git a/src/base/kernel/config/BaseTransform.h b/src/base/kernel/config/BaseTransform.h index 02b28c12..ab83a63f 100644 --- a/src/base/kernel/config/BaseTransform.h +++ b/src/base/kernel/config/BaseTransform.h @@ -27,6 +27,7 @@ #include "base/kernel/interfaces/IConfigTransform.h" +#include "crypto/common/Coin.h" #include "rapidjson/document.h" @@ -99,6 +100,7 @@ protected: protected: Algorithm m_algorithm; + Coin m_coin; private: diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 86b8067c..52aed25f 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -43,6 +43,7 @@ public: enum Keys { // common AlgorithmKey = 'a', + CoinKey = 1025, ApiWorkerIdKey = 4002, ApiIdKey = 4005, HttpPort = 4100, diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index b87466ab..b9189247 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -334,6 +334,9 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) if (algo) { job.setAlgorithm(algo); } + else if (m_pool.coin().isValid()) { + job.setAlgorithm(m_pool.coin().algorithm(job.blob()[0])); + } job.setHeight(Json::getUint64(params, "height")); @@ -426,7 +429,12 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo { if (!algorithm.isValid()) { if (!isQuiet()) { - LOG_ERR("[%s] Unknown/unsupported algorithm \"%s\" detected, reconnect", url(), algo); + if (algo == nullptr) { + LOG_ERR("[%s] unknown algorithm, make sure you set \"algo\" or \"coin\" option", url(), algo); + } + else { + LOG_ERR("[%s] unsupported algorithm \"%s\" detected, reconnect", url(), algo); + } } return false; @@ -436,7 +444,7 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo m_listener->onVerifyAlgorithm(this, algorithm, &ok); if (!ok && !isQuiet()) { - LOG_ERR("[%s] Incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algorithm.shortName()); + LOG_ERR("[%s] incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algorithm.shortName()); } return ok; diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 2b256a12..a1a3b611 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -73,6 +73,7 @@ public: inline uint8_t fixedByte() const { return *(m_blob + 42); } inline uint8_t index() const { return m_index; } inline void reset() { m_size = 0; m_diff = 0; } + inline void setAlgorithm(const Algorithm::Id id) { m_algorithm = id; } inline void setAlgorithm(const char *algo) { m_algorithm = algo; } inline void setClientId(const String &id) { m_clientId = id; } inline void setHeight(uint64_t height) { m_height = height; } diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index ba31c35d..1b9adfc4 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -48,6 +48,7 @@ namespace xmrig { static const char *kAlgo = "algo"; +static const char *kCoin = "coin"; static const char *kDaemon = "daemon"; static const char *kDaemonPollInterval = "daemon-poll-interval"; static const char *kEnabled = "enabled"; @@ -120,6 +121,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : m_fingerprint = Json::getString(object, kFingerprint); m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval); m_algorithm = Json::getString(object, kAlgo); + m_coin = Json::getString(object, kCoin); m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash)); @@ -186,6 +188,7 @@ bool xmrig::Pool::isEqual(const Pool &other) const && m_keepAlive == other.m_keepAlive && m_port == other.m_port && m_algorithm == other.m_algorithm + && m_coin == other.m_coin && m_fingerprint == other.m_fingerprint && m_host == other.m_host && m_password == other.m_password @@ -268,6 +271,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const Value obj(kObjectType); obj.AddMember(StringRef(kAlgo), m_algorithm.toJSON(), allocator); + obj.AddMember(StringRef(kCoin), m_coin.toJSON(), allocator); obj.AddMember(StringRef(kUrl), m_url.toJSON(), allocator); obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator); diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index 36c3ed1b..15d31ccc 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -32,7 +32,7 @@ #include "base/tools/String.h" -#include "crypto/common/Algorithm.h" +#include "crypto/common/Coin.h" #include "rapidjson/fwd.h" @@ -74,6 +74,7 @@ public: inline bool isTLS() const { return m_flags.test(FLAG_TLS); } inline bool isValid() const { return !m_host.isNull() && m_port > 0; } inline const Algorithm &algorithm() const { return m_algorithm; } + inline const Coin &coin() const { return m_coin; } inline const String &fingerprint() const { return m_fingerprint; } inline const String &host() const { return m_host; } inline const String &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; } @@ -107,6 +108,7 @@ private: bool parseIPv6(const char *addr); Algorithm m_algorithm; + Coin m_coin; int m_keepAlive; std::bitset m_flags; String m_fingerprint; diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index 4641ecd4..600c97ed 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -135,11 +135,12 @@ void xmrig::Pools::print() const { size_t i = 1; for (const Pool &pool : m_data) { - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " algo " WHITE_BOLD("%s"), + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " %s " WHITE_BOLD("%s"), i, (pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31), pool.url().data(), - pool.algorithm().isValid() ? pool.algorithm().shortName() : "auto" + pool.coin().isValid() ? "coin" : "algo", + pool.coin().isValid() ? pool.coin().name() : (pool.algorithm().isValid() ? pool.algorithm().shortName() : "auto") ); i++; diff --git a/src/config.json b/src/config.json index c9f53f26..3041407d 100644 --- a/src/config.json +++ b/src/config.json @@ -34,6 +34,7 @@ "pools": [ { "algo": null, + "coin": null, "url": "donate.v2.xmrig.com:3333", "user": "YOUR_WALLET_ADDRESS", "pass": "x", diff --git a/src/core/config/Config_default.h b/src/core/config/Config_default.h index c8b2e6e6..b811540a 100644 --- a/src/core/config/Config_default.h +++ b/src/core/config/Config_default.h @@ -68,6 +68,7 @@ R"===( "pools": [ { "algo": null, + "coin": null, "url": "donate.v2.xmrig.com:3333", "user": "YOUR_WALLET_ADDRESS", "pass": "x", diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index b7415f4d..649e6725 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -45,6 +45,7 @@ static const char short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S"; static const option options[] = { { "algo", 1, nullptr, IConfig::AlgorithmKey }, + { "coin", 1, nullptr, IConfig::CoinKey }, { "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, { "api-id", 1, nullptr, IConfig::ApiIdKey }, { "http-enabled", 0, nullptr, IConfig::HttpEnabledKey }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index b41ec6db..3f172427 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -60,6 +60,7 @@ Options:\n\ rx/wow, rx/loki\n" #endif "\ + --coin=COIN specify coin instead of algorithm\ -o, --url=URL URL of mining server\n\ -O, --userpass=U:P username:password pair for mining server\n\ -u, --user=USERNAME username for mining server\n\ diff --git a/src/crypto/common/Coin.cpp b/src/crypto/common/Coin.cpp new file mode 100644 index 00000000..f5a32851 --- /dev/null +++ b/src/crypto/common/Coin.cpp @@ -0,0 +1,103 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * 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/common/Coin.h" +#include "rapidjson/document.h" + + +#include + + +#ifdef _MSC_VER +# define strcasecmp _stricmp +#endif + + +namespace xmrig { + + +struct CoinName +{ + const char *name; + const Coin::Id id; +}; + + +static CoinName const coin_names[] = { + { "monero", Coin::MONERO }, + { "xmr", Coin::MONERO }, +}; + + +} /* namespace xmrig */ + + + +xmrig::Algorithm::Id xmrig::Coin::algorithm(uint8_t blobVersion) const +{ + if (id() == MONERO) { + return (blobVersion >= 12) ? Algorithm::RX_0 : Algorithm::CN_R; + } + + return Algorithm::INVALID; +} + + + +const char *xmrig::Coin::name() const +{ + for (const auto &i : coin_names) { + if (i.id == m_id) { + return i.name; + } + } + + return nullptr; +} + + +rapidjson::Value xmrig::Coin::toJSON() const +{ + using namespace rapidjson; + + return isValid() ? Value(StringRef(name())) : Value(kNullType); +} + + +xmrig::Coin::Id xmrig::Coin::parse(const char *name) +{ + if (name == nullptr || strlen(name) < 3) { + return INVALID; + } + + for (const auto &i : coin_names) { + if (strcasecmp(name, i.name) == 0) { + return i.id; + } + } + + return INVALID; +} diff --git a/src/crypto/common/Coin.h b/src/crypto/common/Coin.h new file mode 100644 index 00000000..779d60b8 --- /dev/null +++ b/src/crypto/common/Coin.h @@ -0,0 +1,75 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * 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_COIN_H +#define XMRIG_COIN_H + + +#include "crypto/common/Algorithm.h" +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +class Coin +{ +public: + enum Id : int { + INVALID = -1, + MONERO, + }; + + + Coin() = default; + inline Coin(const char *name) : m_id(parse(name)) {} + inline Coin(Id id) : m_id(id) {} + + + inline bool isEqual(const Coin &other) const { return m_id == other.m_id; } + inline bool isValid() const { return m_id != INVALID; } + inline Id id() const { return m_id; } + + Algorithm::Id algorithm(uint8_t blobVersion) const; + const char *name() const; + rapidjson::Value toJSON() const; + + inline bool operator!=(Coin::Id id) const { return m_id != id; } + inline bool operator!=(const Coin &other) const { return !isEqual(other); } + inline bool operator==(Coin::Id id) const { return m_id == id; } + inline bool operator==(const Coin &other) const { return isEqual(other); } + inline operator Coin::Id() const { return m_id; } + + static Id parse(const char *name); + +private: + Id m_id = INVALID; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_COIN_H */ From 550e3329092417928c0b2ec796d2a14698938f5f Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 27 Sep 2019 23:39:57 +0700 Subject: [PATCH 36/49] Fixed coin option in daemon mode. --- src/base/net/stratum/DaemonClient.cpp | 6 +++++- src/base/net/stratum/Pool.cpp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 0c141c7d..0870dc1d 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -25,7 +25,7 @@ #include -#include +#include #include "3rdparty/http-parser/http_parser.h" @@ -225,6 +225,10 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) job.setDiff(Json::getUint64(params, "difficulty")); job.setId(blocktemplate.data() + blocktemplate.size() - 32); + if (m_pool.coin().isValid()) { + job.setAlgorithm(m_pool.coin().algorithm(job.blob()[0])); + } + m_job = std::move(job); m_blocktemplate = std::move(blocktemplate); m_prevHash = Json::getString(params, "prev_hash"); diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index 1b9adfc4..15586fe8 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -174,7 +174,7 @@ bool xmrig::Pool::isEnabled() const } # endif - if (isDaemon() && !algorithm().isValid()) { + if (isDaemon() && (!algorithm().isValid() && !coin().isValid())) { return false; } From 7c463849ccfb17bea253f3ff08cb9a1103d4a93a Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 28 Sep 2019 02:02:20 +0700 Subject: [PATCH 37/49] Added config option "cpu/max-threads-hint" and command line option "--cpu-max-threads-hint". --- src/backend/common/Threads.h | 1 + src/backend/cpu/CpuConfig.cpp | 31 ++++++++-------- src/backend/cpu/CpuConfig.h | 3 +- src/backend/cpu/interfaces/ICpuInfo.h | 24 ++++++------ src/backend/cpu/platform/AdvancedCpuInfo.cpp | 19 +++++++--- src/backend/cpu/platform/AdvancedCpuInfo.h | 2 +- src/backend/cpu/platform/BasicCpuInfo.cpp | 2 +- src/backend/cpu/platform/BasicCpuInfo.h | 2 +- src/backend/cpu/platform/HwlocCpuInfo.cpp | 39 +++++++++++++++----- src/backend/cpu/platform/HwlocCpuInfo.h | 24 +++++++----- src/base/kernel/interfaces/IConfig.h | 1 + src/core/config/ConfigTransform.cpp | 3 ++ src/core/config/Config_platform.h | 2 + src/core/config/usage.h | 1 + 14 files changed, 97 insertions(+), 57 deletions(-) diff --git a/src/backend/common/Threads.h b/src/backend/common/Threads.h index afae184c..f73b22a0 100644 --- a/src/backend/common/Threads.h +++ b/src/backend/common/Threads.h @@ -44,6 +44,7 @@ class Threads public: inline bool has(const char *profile) const { return m_profiles.count(profile) > 0; } inline bool isDisabled(const Algorithm &algo) const { return m_disabled.count(algo) > 0; } + inline bool isEmpty() const { return m_profiles.empty(); } inline bool isExist(const Algorithm &algo) const { return isDisabled(algo) || m_aliases.count(algo) > 0 || has(algo.shortName()); } inline const T &get(const Algorithm &algo, bool strict = false) const { return get(profileName(algo, strict)); } inline void disable(const Algorithm &algo) { m_disabled.insert(algo); } diff --git a/src/backend/cpu/CpuConfig.cpp b/src/backend/cpu/CpuConfig.cpp index 7ea6a38b..8a8a76c6 100644 --- a/src/backend/cpu/CpuConfig.cpp +++ b/src/backend/cpu/CpuConfig.cpp @@ -35,6 +35,7 @@ static const char *kCn = "cn"; static const char *kEnabled = "enabled"; static const char *kHugePages = "huge-pages"; static const char *kHwAes = "hw-aes"; +static const char *kMaxThreadsHint = "max-threads-hint"; static const char *kPriority = "priority"; #ifdef XMRIG_FEATURE_ASM @@ -72,11 +73,6 @@ extern template class Threads; } -xmrig::CpuConfig::CpuConfig() -{ -} - - bool xmrig::CpuConfig::isHwAES() const { return (m_aes == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aes) == AES_HW; @@ -95,6 +91,10 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kHwAes), m_aes == AES_AUTO ? Value(kNullType) : Value(m_aes == AES_HW), allocator); obj.AddMember(StringRef(kPriority), priority() != -1 ? Value(priority()) : Value(kNullType), allocator); + if (m_threads.isEmpty()) { + obj.AddMember(StringRef(kMaxThreadsHint), m_limit, allocator); + } + # ifdef XMRIG_FEATURE_ASM obj.AddMember(StringRef(kAsm), m_assembly.toJSON(), allocator); # endif @@ -131,8 +131,9 @@ std::vector xmrig::CpuConfig::get(const Miner *miner, cons void xmrig::CpuConfig::read(const rapidjson::Value &value, uint32_t version) { if (value.IsObject()) { - m_enabled = Json::getBool(value, kEnabled, m_enabled); - m_hugePages = Json::getBool(value, kHugePages, m_hugePages); + m_enabled = Json::getBool(value, kEnabled, m_enabled); + m_hugePages = Json::getBool(value, kHugePages, m_hugePages); + m_limit = Json::getUint(value, kMaxThreadsHint, m_limit); setAesMode(Json::getValue(value, kHwAes)); setPriority(Json::getInt(value, kPriority, -1)); @@ -168,28 +169,28 @@ void xmrig::CpuConfig::generate() ICpuInfo *cpu = Cpu::info(); m_threads.disable(Algorithm::CN_0); - m_threads.move(kCn, cpu->threads(Algorithm::CN_0)); + m_threads.move(kCn, cpu->threads(Algorithm::CN_0, m_limit)); # ifdef XMRIG_ALGO_CN_GPU - m_threads.move(kCnGPU, cpu->threads(Algorithm::CN_GPU)); + m_threads.move(kCnGPU, cpu->threads(Algorithm::CN_GPU, m_limit)); # endif # ifdef XMRIG_ALGO_CN_LITE m_threads.disable(Algorithm::CN_LITE_0); - m_threads.move(kCnLite, cpu->threads(Algorithm::CN_LITE_1)); + m_threads.move(kCnLite, cpu->threads(Algorithm::CN_LITE_1, m_limit)); # endif # ifdef XMRIG_ALGO_CN_HEAVY - m_threads.move(kCnHeavy, cpu->threads(Algorithm::CN_HEAVY_0)); + m_threads.move(kCnHeavy, cpu->threads(Algorithm::CN_HEAVY_0, m_limit)); # endif # ifdef XMRIG_ALGO_CN_PICO - m_threads.move(kCnPico, cpu->threads(Algorithm::CN_PICO_0)); + m_threads.move(kCnPico, cpu->threads(Algorithm::CN_PICO_0, m_limit)); # endif # ifdef XMRIG_ALGO_RANDOMX - m_threads.move(kRx, cpu->threads(Algorithm::RX_0)); - m_threads.move(kRxWOW, cpu->threads(Algorithm::RX_WOW)); + m_threads.move(kRx, cpu->threads(Algorithm::RX_0, m_limit)); + m_threads.move(kRxWOW, cpu->threads(Algorithm::RX_WOW, m_limit)); # endif generateArgon2(); @@ -199,7 +200,7 @@ void xmrig::CpuConfig::generate() void xmrig::CpuConfig::generateArgon2() { # ifdef XMRIG_ALGO_ARGON2 - m_threads.move(kArgon2, Cpu::info()->threads(Algorithm::AR2_CHUKWA)); + m_threads.move(kArgon2, Cpu::info()->threads(Algorithm::AR2_CHUKWA, m_limit)); # endif } diff --git a/src/backend/cpu/CpuConfig.h b/src/backend/cpu/CpuConfig.h index 67010eea..27075425 100644 --- a/src/backend/cpu/CpuConfig.h +++ b/src/backend/cpu/CpuConfig.h @@ -44,7 +44,7 @@ public: AES_SOFT }; - CpuConfig(); + CpuConfig() = default; bool isHwAES() const; rapidjson::Value toJSON(rapidjson::Document &doc) const; @@ -74,6 +74,7 @@ private: int m_priority = -1; String m_argon2Impl; Threads m_threads; + uint32_t m_limit = 100; }; diff --git a/src/backend/cpu/interfaces/ICpuInfo.h b/src/backend/cpu/interfaces/ICpuInfo.h index 9bc3b11a..20e72391 100644 --- a/src/backend/cpu/interfaces/ICpuInfo.h +++ b/src/backend/cpu/interfaces/ICpuInfo.h @@ -45,18 +45,18 @@ public: inline constexpr static bool isX64() { return false; } # endif - virtual Assembly::Id assembly() const = 0; - virtual bool hasAES() const = 0; - virtual bool hasAVX2() const = 0; - virtual const char *backend() const = 0; - virtual const char *brand() const = 0; - virtual CpuThreads threads(const Algorithm &algorithm) const = 0; - virtual size_t cores() const = 0; - virtual size_t L2() const = 0; - virtual size_t L3() const = 0; - virtual size_t nodes() const = 0; - virtual size_t packages() const = 0; - virtual size_t threads() const = 0; + virtual Assembly::Id assembly() const = 0; + virtual bool hasAES() const = 0; + virtual bool hasAVX2() const = 0; + virtual const char *backend() const = 0; + virtual const char *brand() const = 0; + virtual CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const = 0; + virtual size_t cores() const = 0; + virtual size_t L2() const = 0; + virtual size_t L3() const = 0; + virtual size_t nodes() const = 0; + virtual size_t packages() const = 0; + virtual size_t threads() const = 0; }; diff --git a/src/backend/cpu/platform/AdvancedCpuInfo.cpp b/src/backend/cpu/platform/AdvancedCpuInfo.cpp index 26798895..5cae55e2 100644 --- a/src/backend/cpu/platform/AdvancedCpuInfo.cpp +++ b/src/backend/cpu/platform/AdvancedCpuInfo.cpp @@ -23,10 +23,10 @@ */ #include -#include -#include -#include -#include +#include +#include +#include +#include #include "3rdparty/libcpuid/libcpuid.h" @@ -109,7 +109,7 @@ xmrig::AdvancedCpuInfo::AdvancedCpuInfo() : } -xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm) const +xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const { if (threads() == 1) { return 1; @@ -153,5 +153,12 @@ xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm) co } # endif - return CpuThreads(std::max(std::min(count, threads()), 1), intensity); + if (limit > 0 && limit < 100) { + count = std::min(count, static_cast(round(threads() * (limit / 100.0)))); + } + else { + count = std::min(count, threads()); + } + + return CpuThreads(std::max(count, 1), intensity); } diff --git a/src/backend/cpu/platform/AdvancedCpuInfo.h b/src/backend/cpu/platform/AdvancedCpuInfo.h index 51b84c9f..e2909a91 100644 --- a/src/backend/cpu/platform/AdvancedCpuInfo.h +++ b/src/backend/cpu/platform/AdvancedCpuInfo.h @@ -38,7 +38,7 @@ public: AdvancedCpuInfo(); protected: - CpuThreads threads(const Algorithm &algorithm) const override; + CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override; inline Assembly::Id assembly() const override { return m_assembly; } inline bool hasAES() const override { return m_aes; } diff --git a/src/backend/cpu/platform/BasicCpuInfo.cpp b/src/backend/cpu/platform/BasicCpuInfo.cpp index 15ac8f40..db3741ee 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.cpp +++ b/src/backend/cpu/platform/BasicCpuInfo.cpp @@ -179,7 +179,7 @@ const char *xmrig::BasicCpuInfo::backend() const } -xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm) const +xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const { const size_t count = std::thread::hardware_concurrency(); diff --git a/src/backend/cpu/platform/BasicCpuInfo.h b/src/backend/cpu/platform/BasicCpuInfo.h index 6cf25714..4c68c5f8 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.h +++ b/src/backend/cpu/platform/BasicCpuInfo.h @@ -39,7 +39,7 @@ public: protected: const char *backend() const override; - CpuThreads threads(const Algorithm &algorithm) const override; + CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override; inline Assembly::Id assembly() const override { return m_assembly; } inline bool hasAES() const override { return m_aes; } diff --git a/src/backend/cpu/platform/HwlocCpuInfo.cpp b/src/backend/cpu/platform/HwlocCpuInfo.cpp index 9e503742..e87faf2d 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.cpp +++ b/src/backend/cpu/platform/HwlocCpuInfo.cpp @@ -29,6 +29,7 @@ #include +#include #include @@ -127,9 +128,7 @@ static inline bool isCacheExclusive(hwloc_obj_t obj) } // namespace xmrig -xmrig::HwlocCpuInfo::HwlocCpuInfo() : BasicCpuInfo(), - m_backend(), - m_cache() +xmrig::HwlocCpuInfo::HwlocCpuInfo() { m_threads = 0; @@ -149,7 +148,7 @@ xmrig::HwlocCpuInfo::HwlocCpuInfo() : BasicCpuInfo(), # endif const std::vector packages = findByType(hwloc_get_root_obj(m_topology), HWLOC_OBJ_PACKAGE); - if (packages.size()) { + if (!packages.empty()) { const char *value = hwloc_obj_get_info_by_name(packages[0], "CPUModel"); if (value) { strncpy(m_brand, value, 64); @@ -202,10 +201,10 @@ xmrig::HwlocCpuInfo::~HwlocCpuInfo() } -xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm) const +xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const { if (L2() == 0 && L3() == 0) { - return BasicCpuInfo::threads(algorithm); + return BasicCpuInfo::threads(algorithm, limit); } const unsigned depth = L3() > 0 ? 3 : 2; @@ -218,21 +217,37 @@ xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm) const findCache(hwloc_get_root_obj(m_topology), depth, depth, [&caches](hwloc_obj_t found) { caches.emplace_back(found); }); - for (hwloc_obj_t cache : caches) { - processTopLevelCache(cache, algorithm, threads); + if (limit > 0 && limit < 100 && !caches.empty()) { + const double maxTotalThreads = round(m_threads * (limit / 100.0)); + const auto maxPerCache = std::max(static_cast(round(maxTotalThreads / caches.size())), 1); + int remaining = std::max(static_cast(maxTotalThreads), 1); + + for (hwloc_obj_t cache : caches) { + processTopLevelCache(cache, algorithm, threads, std::min(maxPerCache, remaining)); + + remaining -= maxPerCache; + if (remaining <= 0) { + break; + } + } + } + else { + for (hwloc_obj_t cache : caches) { + processTopLevelCache(cache, algorithm, threads, 0); + } } if (threads.isEmpty()) { LOG_WARN("hwloc auto configuration for algorithm \"%s\" failed.", algorithm.shortName()); - return BasicCpuInfo::threads(algorithm); + return BasicCpuInfo::threads(algorithm, limit); } return threads; } -void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorithm &algorithm, CpuThreads &threads) const +void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorithm &algorithm, CpuThreads &threads, size_t limit) const { constexpr size_t oneMiB = 1024u * 1024u; @@ -296,6 +311,10 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith } # endif + if (limit > 0) { + cacheHashes = std::min(cacheHashes, limit); + } + if (cacheHashes >= PUs) { for (hwloc_obj_t core : cores) { const std::vector units = findByType(core, HWLOC_OBJ_PU); diff --git a/src/backend/cpu/platform/HwlocCpuInfo.h b/src/backend/cpu/platform/HwlocCpuInfo.h index 340864f5..ec4aea2c 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.h +++ b/src/backend/cpu/platform/HwlocCpuInfo.h @@ -27,10 +27,11 @@ #include "backend/cpu/platform/BasicCpuInfo.h" +#include "base/tools/Object.h" -typedef struct hwloc_obj *hwloc_obj_t; -typedef struct hwloc_topology *hwloc_topology_t; +using hwloc_obj_t = struct hwloc_obj *; +using hwloc_topology_t = struct hwloc_topology *; namespace xmrig { @@ -39,6 +40,9 @@ namespace xmrig { class HwlocCpuInfo : public BasicCpuInfo { public: + XMRIG_DISABLE_COPY_MOVE(HwlocCpuInfo) + + enum Feature : uint32_t { SET_THISTHREAD_MEMBIND = 1 }; @@ -51,7 +55,7 @@ public: static inline const std::vector &nodeIndexes() { return m_nodeIndexes; } protected: - CpuThreads threads(const Algorithm &algorithm) const override; + CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override; inline const char *backend() const override { return m_backend; } inline size_t cores() const override { return m_cores; } @@ -61,17 +65,17 @@ protected: inline size_t packages() const override { return m_packages; } private: - void processTopLevelCache(hwloc_obj_t obj, const Algorithm &algorithm, CpuThreads &threads) const; + void processTopLevelCache(hwloc_obj_t obj, const Algorithm &algorithm, CpuThreads &threads, size_t limit) const; static std::vector m_nodeIndexes; static uint32_t m_features; - char m_backend[20]; - hwloc_topology_t m_topology; - size_t m_cache[5]; - size_t m_cores = 0; - size_t m_nodes = 0; - size_t m_packages = 0; + char m_backend[20] = { 0 }; + hwloc_topology_t m_topology = nullptr; + size_t m_cache[5] = { 0 }; + size_t m_cores = 0; + size_t m_nodes = 0; + size_t m_packages = 0; }; diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 16863fff..8798de5f 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -88,6 +88,7 @@ public: AssemblyKey = 1015, RandomXInitKey = 1022, RandomXNumaKey = 1023, + CPUMaxThreadsKey = 1026, // xmrig amd OclPlatformKey = 1400, diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index e7bd383f..3bdbcac5 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -138,6 +138,9 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const return transformUint64(doc, key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); } + case IConfig::CPUMaxThreadsKey: /* --cpu-max-threads-hint */ + return set(doc, kCpu, "max-threads-hint", static_cast(strtol(arg, nullptr, 10))); + # ifdef XMRIG_FEATURE_ASM case IConfig::AssemblyKey: /* --asm */ return set(doc, kCpu, "asm", arg); diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index c05e84ce..b7f15daa 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -82,6 +82,8 @@ static const option options[] = { { "userpass", 1, nullptr, IConfig::UserpassKey }, { "rig-id", 1, nullptr, IConfig::RigIdKey }, { "no-cpu", 0, nullptr, IConfig::CPUKey }, + { "max-cpu-usage", 1, nullptr, IConfig::CPUMaxThreadsKey }, + { "cpu-max-threads-hint", 1, nullptr, IConfig::CPUMaxThreadsKey }, # ifdef XMRIG_FEATURE_TLS { "tls", 0, nullptr, IConfig::TlsKey }, { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index fc9695a3..0d7cdc5e 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -76,6 +76,7 @@ static inline const std::string &usage() u += " -v, --av=N algorithm variation, 0 auto select\n"; u += " --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n"; u += " --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n"; + u += " --cpu-max-threads-hint=N maximum CPU threads count (in percentage) hint for autoconfig\n"; u += " --no-huge-pages disable huge pages support\n"; u += " --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer\n"; From 0eb754d76ec5ff4af6c7a1713554012cf9667dda Mon Sep 17 00:00:00 2001 From: xmrig Date: Sat, 28 Sep 2019 02:22:38 +0700 Subject: [PATCH 38/49] Create CPU_MAX_USAGE.md --- doc/CPU_MAX_USAGE.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 doc/CPU_MAX_USAGE.md diff --git a/doc/CPU_MAX_USAGE.md b/doc/CPU_MAX_USAGE.md new file mode 100644 index 00000000..fccfd456 --- /dev/null +++ b/doc/CPU_MAX_USAGE.md @@ -0,0 +1,26 @@ +# Maximum CPU usage + +Please read this document carefully, `max-threads-hint` (was known as `max-cpu-usage`) option is most confusing option in the miner with many myth and legends. +This option is just hint for automatic configuration and can't precise define CPU usage. + +### Option definition +#### Config file: +```json +{ + ... + "cpu": { + "max-threads-hint": 100, + ... + }, + ... +} +``` + +#### Command line +`--cpu-max-threads-hint 100` + +### Known issues and usage + +* This option has no effect if miner already generated CPU configuration, to prevent config generation use `"autosave":false,`. +* Only threads count can be changed, for 1 core CPU this option has no effect, for 2 core CPU only 2 values possible 50% and 100%, for 4 cores: 25%, 50%, 75%, 100%. etc. +* You CPU may limited by other factors, eg cache. From 5ba8b43fb822be496408e61546477ee149ad8f0c Mon Sep 17 00:00:00 2001 From: xmrig Date: Sat, 28 Sep 2019 02:25:00 +0700 Subject: [PATCH 39/49] Update CPU.md --- doc/CPU.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/CPU.md b/doc/CPU.md index 4d1f0858..05c82809 100644 --- a/doc/CPU.md +++ b/doc/CPU.md @@ -94,3 +94,6 @@ Enable/configure or disable ASM optimizations. Possible values: `true`, `false`, #### `argon2-impl` (since v3.1.0) Allow override automatically detected Argon2 implementation, this option added mostly for debug purposes, default value `null` means autodetect. Other possible values: `"x86_64"`, `"SSE2"`, `"SSSE3"`, `"XOP"`, `"AVX2"`, `"AVX-512F"`. Manual selection has no safe guards, if you CPU not support required instuctions, miner will crash. + +#### `max-threads-hint` (since v4.2.0) +Maximum CPU threads count (in percentage) hint for autoconfig. [doc/CPU_MAX_USAGE.md](doc/CPU_MAX_USAGE.md) From 0eb5588454791993969b259fb01caf72c1cfbb0f Mon Sep 17 00:00:00 2001 From: xmrig Date: Sat, 28 Sep 2019 02:25:34 +0700 Subject: [PATCH 40/49] Update CPU.md --- doc/CPU.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/CPU.md b/doc/CPU.md index 05c82809..66745a66 100644 --- a/doc/CPU.md +++ b/doc/CPU.md @@ -96,4 +96,4 @@ Enable/configure or disable ASM optimizations. Possible values: `true`, `false`, Allow override automatically detected Argon2 implementation, this option added mostly for debug purposes, default value `null` means autodetect. Other possible values: `"x86_64"`, `"SSE2"`, `"SSSE3"`, `"XOP"`, `"AVX2"`, `"AVX-512F"`. Manual selection has no safe guards, if you CPU not support required instuctions, miner will crash. #### `max-threads-hint` (since v4.2.0) -Maximum CPU threads count (in percentage) hint for autoconfig. [doc/CPU_MAX_USAGE.md](doc/CPU_MAX_USAGE.md) +Maximum CPU threads count (in percentage) hint for autoconfig. [CPU_MAX_USAGE.md](CPU_MAX_USAGE.md) From 4c357d2d60ca55124192a9198fbbde6275463fb5 Mon Sep 17 00:00:00 2001 From: xmrig Date: Sat, 28 Sep 2019 02:32:02 +0700 Subject: [PATCH 41/49] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce58c88e..afebb248 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v4.2.0-beta +- Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork. +- Added config option `cpu/max-threads-hint` and command line option `--cpu-max-threads-hint`. + # v4.1.0-beta - **OpenCL backend disabled by default.**. - [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd. From 5b7f1fe85389f5d467440bf0d0e491b1eb4243a4 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 28 Sep 2019 02:34:10 +0700 Subject: [PATCH 42/49] Updated default config example. --- src/config.json | 1 + src/core/config/Config_default.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/config.json b/src/config.json index ee3c84ea..ec8ac419 100644 --- a/src/config.json +++ b/src/config.json @@ -23,6 +23,7 @@ "huge-pages": true, "hw-aes": null, "priority": null, + "max-threads-hint": 100, "asm": true, "argon2-impl": null, "cn/0": false, diff --git a/src/core/config/Config_default.h b/src/core/config/Config_default.h index 4410e199..00c4cf12 100644 --- a/src/core/config/Config_default.h +++ b/src/core/config/Config_default.h @@ -57,6 +57,7 @@ R"===( "huge-pages": true, "hw-aes": null, "priority": null, + "max-threads-hint": 100, "asm": true, "argon2-impl": null, "cn/0": false, From d086318f4e30f6bd1860d3832da089f28966a4e1 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 28 Sep 2019 03:25:03 +0700 Subject: [PATCH 43/49] Set "rx/0" as user visible RandomX name. --- src/crypto/common/Algorithm.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/crypto/common/Algorithm.cpp b/src/crypto/common/Algorithm.cpp index d3e3fa89..6b5e32c7 100644 --- a/src/crypto/common/Algorithm.cpp +++ b/src/crypto/common/Algorithm.cpp @@ -107,9 +107,8 @@ static AlgoName const algorithm_names[] = { { "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO_0 }, # endif # ifdef XMRIG_ALGO_RANDOMX + { "randomx/0", "rx/0", Algorithm::RX_0 }, { "randomx/test", "rx/test", Algorithm::RX_0 }, - { "randomx/0", "rx/0", Algorithm::RX_0 }, - { "randomx/0", "rx/0", Algorithm::RX_0 }, { "RandomX", "rx", Algorithm::RX_0 }, { "randomx/wow", "rx/wow", Algorithm::RX_WOW }, { "RandomWOW", nullptr, Algorithm::RX_WOW }, From e66eeefb148b5673a43b41d5fb502526d3ec7588 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 28 Sep 2019 18:20:56 +0700 Subject: [PATCH 44/49] Fixed build on macOS. --- src/backend/opencl/wrappers/OclDevice.cpp | 4 ++-- src/backend/opencl/wrappers/OclPlatform.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/opencl/wrappers/OclDevice.cpp b/src/backend/opencl/wrappers/OclDevice.cpp index b10713d4..67f8166b 100644 --- a/src/backend/opencl/wrappers/OclDevice.cpp +++ b/src/backend/opencl/wrappers/OclDevice.cpp @@ -59,7 +59,7 @@ extern bool ocl_vega_cn_generator(const OclDevice &device, const Algorithm &algo extern bool ocl_generic_cn_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads); -ocl_gen_config_fun generators[] = { +static ocl_gen_config_fun generators[] = { # ifdef XMRIG_ALGO_RANDOMX ocl_generic_rx_generator, # endif @@ -215,6 +215,6 @@ void xmrig::OclDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc) c out.AddMember("name", name().toJSON(doc), allocator); out.AddMember("bus_id", topology().toString().toJSON(doc), allocator); out.AddMember("cu", computeUnits(), allocator); - out.AddMember("global_mem", globalMemSize(), allocator); + out.AddMember("global_mem", static_cast(globalMemSize()), allocator); } #endif diff --git a/src/backend/opencl/wrappers/OclPlatform.cpp b/src/backend/opencl/wrappers/OclPlatform.cpp index 987ec5e3..601ee6fa 100644 --- a/src/backend/opencl/wrappers/OclPlatform.cpp +++ b/src/backend/opencl/wrappers/OclPlatform.cpp @@ -73,7 +73,7 @@ rapidjson::Value xmrig::OclPlatform::toJSON(rapidjson::Document &doc) const } Value out(kObjectType); - out.AddMember("index", index(), allocator); + out.AddMember("index", static_cast(index()), allocator); out.AddMember("profile", profile().toJSON(doc), allocator); out.AddMember("version", version().toJSON(doc), allocator); out.AddMember("name", name().toJSON(doc), allocator); From 680081b93bf89fea87726550fc17cbfbdea23f9b Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 28 Sep 2019 22:07:44 +0700 Subject: [PATCH 45/49] #1202 Fixed algorithm verification in donate strategy. --- src/core/Miner.cpp | 2 +- src/net/Network.cpp | 14 ++++-------- src/net/Network.h | 3 +++ src/net/strategies/DonateStrategy.cpp | 33 +++++++++++++++------------ src/net/strategies/DonateStrategy.h | 23 +++++++++++-------- 5 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index d5372422..b6b89948 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -97,7 +97,7 @@ public: bool isEnabled(const Algorithm &algorithm) const { for (IBackend *backend : backends) { - if (backend->isEnabled(algorithm)) { + if (backend->isEnabled() && backend->isEnabled(algorithm)) { return true; } } diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 2b3f4b5f..2fb40c6c 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -28,10 +28,10 @@ #endif #include -#include +#include +#include #include #include -#include #include "base/io/log/Log.h" @@ -83,11 +83,7 @@ xmrig::Network::~Network() JobResults::stop(); delete m_timer; - - if (m_donate) { - delete m_donate; - } - + delete m_donate; delete m_strategy; } @@ -304,8 +300,8 @@ void xmrig::Network::getResults(rapidjson::Value &reply, rapidjson::Document &do results.AddMember("hashes_total", m_state.total, allocator); Value best(kArrayType); - for (size_t i = 0; i < m_state.topDiff.size(); ++i) { - best.PushBack(m_state.topDiff[i], allocator); + for (uint64_t i : m_state.topDiff) { + best.PushBack(i, allocator); } results.AddMember("best", best, allocator); diff --git a/src/net/Network.h b/src/net/Network.h index 716ce610..7fd95e31 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -34,6 +34,7 @@ #include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/interfaces/ITimerListener.h" +#include "base/tools/Object.h" #include "interfaces/IJobResultListener.h" #include "net/NetworkState.h" #include "rapidjson/fwd.h" @@ -49,6 +50,8 @@ class IStrategy; class Network : public IJobResultListener, public IStrategyListener, public IBaseListener, public ITimerListener, public IApiListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Network) + Network(Controller *controller); ~Network() override; diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 4393cd46..3952d94e 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -24,7 +24,7 @@ #include -#include +#include #include @@ -58,17 +58,10 @@ static const char *kDonateHostTls = "donate.ssl.xmrig.com"; xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener *listener) : - m_tls(false), - m_userId(), m_donateTime(static_cast(controller->config()->pools().donateLevel()) * 60 * 1000), m_idleTime((100 - static_cast(controller->config()->pools().donateLevel())) * 60 * 1000), m_controller(controller), - m_proxy(nullptr), - m_strategy(nullptr), - m_listener(listener), - m_state(STATE_NEW), - m_now(0), - m_timestamp(0) + m_listener(listener) { uint8_t hash[200]; @@ -77,15 +70,15 @@ xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener Buffer::toHex(hash, 32, m_userId); # ifdef XMRIG_FEATURE_TLS - m_pools.push_back(Pool(kDonateHostTls, 443, m_userId, nullptr, 0, true, true)); + m_pools.emplace_back(kDonateHostTls, 443, m_userId, nullptr, 0, true, true); # endif - m_pools.push_back(Pool(kDonateHost, 3333, m_userId, nullptr, 0, true)); + m_pools.emplace_back(kDonateHost, 3333, m_userId, nullptr, 0, true); if (m_pools.size() > 1) { - m_strategy = new FailoverStrategy(m_pools, 1, 2, this, true); + m_strategy = new FailoverStrategy(m_pools, 10, 2, this, true); } else { - m_strategy = new SinglePoolStrategy(m_pools.front(), 1, 2, this, true); + m_strategy = new SinglePoolStrategy(m_pools.front(), 10, 2, this, true); } m_timer = new Timer(this); @@ -223,6 +216,18 @@ void xmrig::DonateStrategy::onLoginSuccess(IClient *client) } +void xmrig::DonateStrategy::onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok) +{ + m_listener->onVerifyAlgorithm(this, client, algorithm, ok); +} + + +void xmrig::DonateStrategy::onVerifyAlgorithm(IStrategy *, const IClient *client, const Algorithm &algorithm, bool *ok) +{ + m_listener->onVerifyAlgorithm(this, client, algorithm, ok); +} + + void xmrig::DonateStrategy::onTimer(const Timer *) { setState(isActive() ? STATE_WAIT : STATE_CONNECT); @@ -246,7 +251,7 @@ xmrig::Client *xmrig::DonateStrategy::createProxy() Pool pool(client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS()); pool.setAlgo(client->pool().algorithm()); - Client *proxy = new Client(-1, Platform::userAgent(), this); + auto proxy = new Client(-1, Platform::userAgent(), this); proxy->setPool(pool); proxy->setQuiet(true); diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index 134127bf..4c621f66 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -34,6 +34,7 @@ #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/interfaces/ITimerListener.h" #include "base/net/stratum/Pool.h" +#include "base/tools/Object.h" namespace xmrig { @@ -47,6 +48,8 @@ class IStrategyListener; class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener, public IClientListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(DonateStrategy) + DonateStrategy(Controller *controller, IStrategyListener *listener); ~DonateStrategy() override; @@ -57,8 +60,6 @@ protected: inline void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); } inline void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } inline void onResultAccepted(IStrategy *, IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } - inline void onVerifyAlgorithm(const IClient *, const Algorithm &, bool *) override {} - inline void onVerifyAlgorithm(IStrategy *, const IClient *, const Algorithm &, bool *) override {} inline void resume() override {} int64_t submit(const JobResult &result) override; @@ -74,6 +75,8 @@ protected: void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override; void onLogin(IStrategy *strategy, IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override; void onLoginSuccess(IClient *client) override; + void onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok) override; + void onVerifyAlgorithm(IStrategy *strategy, const IClient *client, const Algorithm &algorithm, bool *ok) override; void onTimer(const Timer *timer) override; @@ -96,19 +99,19 @@ private: void setState(State state); Algorithm m_algorithm; - bool m_tls; - char m_userId[65]; + bool m_tls = false; + char m_userId[65] = { 0 }; const uint64_t m_donateTime; const uint64_t m_idleTime; Controller *m_controller; - IClient *m_proxy; - IStrategy *m_strategy; + IClient *m_proxy = nullptr; + IStrategy *m_strategy = nullptr; IStrategyListener *m_listener; - State m_state; + State m_state = STATE_NEW; std::vector m_pools; - Timer *m_timer; - uint64_t m_now; - uint64_t m_timestamp; + Timer *m_timer = nullptr; + uint64_t m_now = 0; + uint64_t m_timestamp = 0; }; From 166d8dd53cd9837eee687ba35cae302104df1f4a Mon Sep 17 00:00:00 2001 From: xmrig Date: Sat, 28 Sep 2019 22:45:25 +0700 Subject: [PATCH 46/49] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index afebb248..e6aaeea6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # v4.2.0-beta +- [#1202](https://github.com/xmrig/xmrig/issues/1202) Fixed algorithm verification in donate strategy. - Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork. - Added config option `cpu/max-threads-hint` and command line option `--cpu-max-threads-hint`. From ac4cd3eb9be025a8dd0505df8c2c25c465cd0350 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 28 Sep 2019 23:10:07 +0700 Subject: [PATCH 47/49] v4.2.0 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index eb4ac706..0114a084 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 "4.2.0-evo" +#define APP_VERSION "4.2.0" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" From 66e48ed2d742a5547c37af1e549f4a88f3c1e58a Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 28 Sep 2019 23:26:03 +0700 Subject: [PATCH 48/49] Fixed ARM build. --- src/backend/cpu/platform/BasicCpuInfo_arm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/cpu/platform/BasicCpuInfo_arm.cpp b/src/backend/cpu/platform/BasicCpuInfo_arm.cpp index b241e197..e52bdf94 100644 --- a/src/backend/cpu/platform/BasicCpuInfo_arm.cpp +++ b/src/backend/cpu/platform/BasicCpuInfo_arm.cpp @@ -63,7 +63,7 @@ const char *xmrig::BasicCpuInfo::backend() const } -xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &) const +xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &, uint32_t) const { return CpuThreads(threads()); } From 467e5115b099990779f3594cb6d6c0c861d02f9e Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 28 Sep 2019 23:55:49 +0700 Subject: [PATCH 49/49] v4.2.0-beta --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 0114a084..f803340d 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 "4.2.0" +#define APP_VERSION "4.2.0-beta" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com"