This commit is contained in:
MoneroOcean 2020-01-20 18:24:56 +07:00
commit b4c93b7ff6
97 changed files with 6697 additions and 6013 deletions

View file

@ -111,6 +111,7 @@ public:
# ifdef XMRIG_ALGO_CN_PICO
case Algorithm::CN_PICO_0:
case Algorithm::CN_PICO_TLO:
return CN_ITER / 8;
# endif
@ -171,6 +172,7 @@ public:
case Algorithm::CN_DOUBLE:
# ifdef XMRIG_ALGO_CN_PICO
case Algorithm::CN_PICO_0:
case Algorithm::CN_PICO_TLO:
# endif
return Algorithm::CN_2;
@ -217,6 +219,7 @@ template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_RWZ>::iterations() con
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_ZLS>::iterations() const { return 0x60000; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_GPU>::iterations() const { return 0xC000; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_0>::iterations() const { return CN_ITER / 8; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_TLO>::iterations() const { return CN_ITER / 8; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_LITE_0>::memory() const { return CN_MEMORY / 2; }
@ -225,6 +228,7 @@ template<> constexpr inline size_t CnAlgo<Algorithm::CN_HEAVY_0>::memory() const
template<> constexpr inline size_t CnAlgo<Algorithm::CN_HEAVY_TUBE>::memory() const { return CN_MEMORY * 2; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_HEAVY_XHV>::memory() const { return CN_MEMORY * 2; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_PICO_0>::memory() const { return CN_MEMORY / 8; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_PICO_TLO>::memory() const { return CN_MEMORY / 8; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_GPU>::mask() const { return 0x1FFFC0; }

View file

@ -79,6 +79,11 @@ cn_mainloop_fun cn_trtl_mainloop_ryzen_asm = nullptr;
cn_mainloop_fun cn_trtl_mainloop_bulldozer_asm = nullptr;
cn_mainloop_fun cn_trtl_double_mainloop_sandybridge_asm = nullptr;
cn_mainloop_fun cn_tlo_mainloop_ivybridge_asm = nullptr;
cn_mainloop_fun cn_tlo_mainloop_ryzen_asm = nullptr;
cn_mainloop_fun cn_tlo_mainloop_bulldozer_asm = nullptr;
cn_mainloop_fun cn_tlo_double_mainloop_sandybridge_asm = nullptr;
cn_mainloop_fun cn_zls_mainloop_ivybridge_asm = nullptr;
cn_mainloop_fun cn_zls_mainloop_ryzen_asm = nullptr;
cn_mainloop_fun cn_zls_mainloop_bulldozer_asm = nullptr;
@ -128,7 +133,7 @@ static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t ma
static void patchAsmVariants()
{
const int allocation_size = 65536;
const int allocation_size = 81920;
auto base = static_cast<uint8_t *>(VirtualMemory::allocateExecutableMemory(allocation_size));
cn_half_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x0000);
@ -153,6 +158,13 @@ static void patchAsmVariants()
cn_double_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xE000);
cn_double_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xF000);
# ifdef XMRIG_ALGO_CN_PICO
cn_tlo_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x10000);
cn_tlo_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x11000);
cn_tlo_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x12000);
cn_tlo_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x13000);
# endif
{
constexpr uint32_t ITER = CnAlgo<Algorithm::CN_HALF>().iterations();
@ -172,6 +184,16 @@ static void patchAsmVariants()
patchCode(cn_trtl_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER, MASK);
patchCode(cn_trtl_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER, MASK);
}
{
constexpr uint32_t ITER = CnAlgo<Algorithm::CN_PICO_TLO>().iterations();
constexpr uint32_t MASK = CnAlgo<Algorithm::CN_PICO_TLO>().mask();
patchCode(cn_tlo_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, ITER, MASK);
patchCode(cn_tlo_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, ITER, MASK);
patchCode(cn_tlo_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER, MASK);
patchCode(cn_tlo_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER, MASK);
}
# endif
{
@ -244,6 +266,8 @@ xmrig::CnHash::CnHash()
# ifdef XMRIG_ALGO_CN_PICO
ADD_FN(Algorithm::CN_PICO_0);
ADD_FN_ASM(Algorithm::CN_PICO_0);
ADD_FN(Algorithm::CN_PICO_TLO);
ADD_FN_ASM(Algorithm::CN_PICO_TLO);
# endif
# ifdef XMRIG_ALGO_ARGON2

View file

@ -338,6 +338,21 @@ const static uint8_t test_output_pico_trtl[160] = {
0xA1, 0xE7, 0x53, 0x85, 0xFB, 0x72, 0xDD, 0x75, 0x90, 0x39, 0xB2, 0x3D, 0xC3, 0x08, 0x2C, 0xD5,
0x01, 0x08, 0x27, 0x75, 0x86, 0xB9, 0xBB, 0x9B, 0xDF, 0xEA, 0x49, 0xDE, 0x46, 0xCB, 0x83, 0x45
};
// "cn-pico/tlo"
const static uint8_t test_output_pico_tlo[160] = {
0x99, 0x75, 0xF2, 0xC1, 0xB3, 0xB4, 0x54, 0x34, 0xA4, 0x93, 0x86, 0x21, 0x30, 0x97, 0xF3, 0x1B,
0xB4, 0xB9, 0xA6, 0x58, 0x6A, 0x7E, 0x81, 0xF4, 0x42, 0x9F, 0x6D, 0x5F, 0x65, 0xC3, 0x8D, 0x1A,
0xFC, 0x67, 0xDF, 0xCC, 0xB5, 0xFC, 0x90, 0xD7, 0x85, 0x5A, 0xE9, 0x03, 0x36, 0x1E, 0xAB, 0xD7,
0x6F, 0x1E, 0x40, 0xA2, 0x2A, 0x72, 0xAD, 0x3E, 0xF2, 0xD6, 0xAD, 0x27, 0xB5, 0xA6, 0x0C, 0xE5,
0x1C, 0xB1, 0x53, 0xE9, 0x70, 0x7D, 0x69, 0xF1, 0xE1, 0x55, 0x28, 0x45, 0xF5, 0x76, 0x56, 0xE5,
0x10, 0x0D, 0xEA, 0xFD, 0xD9, 0xD6, 0xAF, 0x0F, 0x47, 0x0C, 0x0D, 0xA2, 0x10, 0x16, 0x43, 0xEE,
0x25, 0x2C, 0x07, 0x3A, 0x64, 0x29, 0x16, 0xFF, 0xF5, 0xA5, 0x0B, 0xA2, 0xE0, 0xBD, 0xDC, 0xCE,
0x93, 0x3F, 0xEF, 0x6B, 0x08, 0xF4, 0x4D, 0x6A, 0x6E, 0x14, 0x13, 0x10, 0x98, 0x11, 0xE1, 0x13,
0xF6, 0x9D, 0x3D, 0x31, 0xC4, 0x3A, 0xA9, 0x44, 0x4C, 0x38, 0xAB, 0xB5, 0x4B, 0xD9, 0xFB, 0xE6,
0x98, 0xB9, 0x46, 0xE2, 0x00, 0xEB, 0x56, 0x33, 0x1E, 0xBC, 0xEB, 0xF1, 0xF6, 0x88, 0xD3, 0xF0
};
#endif

View file

@ -794,6 +794,11 @@ extern cn_mainloop_fun cn_trtl_mainloop_ryzen_asm;
extern cn_mainloop_fun cn_trtl_mainloop_bulldozer_asm;
extern cn_mainloop_fun cn_trtl_double_mainloop_sandybridge_asm;
extern cn_mainloop_fun cn_tlo_mainloop_ivybridge_asm;
extern cn_mainloop_fun cn_tlo_mainloop_ryzen_asm;
extern cn_mainloop_fun cn_tlo_mainloop_bulldozer_asm;
extern cn_mainloop_fun cn_tlo_double_mainloop_sandybridge_asm;
extern cn_mainloop_fun cn_zls_mainloop_ivybridge_asm;
extern cn_mainloop_fun cn_zls_mainloop_ryzen_asm;
extern cn_mainloop_fun cn_zls_mainloop_bulldozer_asm;
@ -879,6 +884,17 @@ inline void cryptonight_single_hash_asm(const uint8_t *__restrict__ input, size_
cn_trtl_mainloop_bulldozer_asm(ctx);
}
}
else if (ALGO == Algorithm::CN_PICO_TLO) {
if (ASM == Assembly::INTEL) {
cn_tlo_mainloop_ivybridge_asm(ctx);
}
else if (ASM == Assembly::RYZEN) {
cn_tlo_mainloop_ryzen_asm(ctx);
}
else {
cn_tlo_mainloop_bulldozer_asm(ctx);
}
}
# endif
else if (ALGO == Algorithm::CN_RWZ) {
cnv2_rwz_mainloop_asm(ctx);
@ -944,6 +960,9 @@ inline void cryptonight_double_hash_asm(const uint8_t *__restrict__ input, size_
else if (ALGO == Algorithm::CN_PICO_0) {
cn_trtl_double_mainloop_sandybridge_asm(ctx);
}
else if (ALGO == Algorithm::CN_PICO_TLO) {
cn_tlo_double_mainloop_sandybridge_asm(ctx);
}
# endif
else if (ALGO == Algorithm::CN_RWZ) {
cnv2_rwz_double_mainloop_asm(ctx);

View file

@ -101,6 +101,10 @@ static AlgoName const algorithm_names[] = {
{ "cryptonight-turtle", "cn-trtl", Algorithm::CN_PICO_0 },
{ "cryptonight-ultralite", "cn-ultralite", Algorithm::CN_PICO_0 },
{ "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO_0 },
{ "cryptonight-pico/tlo", "cn-pico/tlo", Algorithm::CN_PICO_TLO },
{ "cryptonight/ultra", "cn/ultra", Algorithm::CN_PICO_TLO },
{ "cryptonight-talleo", "cn-talleo", Algorithm::CN_PICO_TLO },
{ "cryptonight_talleo", "cn_talleo", Algorithm::CN_PICO_TLO },
# endif
# ifdef XMRIG_ALGO_RANDOMX
{ "randomx/0", "rx/0", Algorithm::RX_0 },
@ -115,8 +119,6 @@ static AlgoName const algorithm_names[] = {
{ "RandomARQ", nullptr, Algorithm::RX_ARQ },
{ "randomx/sfx", "rx/sfx", Algorithm::RX_SFX },
{ "RandomSFX", nullptr, Algorithm::RX_SFX },
{ "randomx/v", "rx/v", Algorithm::RX_V },
{ "RandomV", nullptr, Algorithm::RX_V },
# endif
# ifdef XMRIG_ALGO_ARGON2
{ "argon2/chukwa", nullptr, Algorithm::AR2_CHUKWA },
@ -144,7 +146,6 @@ size_t xmrig::Algorithm::l2() const
case RX_0:
case RX_LOKI:
case RX_SFX:
case RX_V:
return 0x40000;
case RX_WOW:
@ -184,7 +185,6 @@ size_t xmrig::Algorithm::l3() const
case RX_0:
case RX_LOKI:
case RX_SFX:
case RX_V:
return oneMiB * 2;
case RX_WOW:
@ -279,6 +279,7 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id)
# ifdef XMRIG_ALGO_CN_PICO
case CN_PICO_0:
case CN_PICO_TLO:
return CN_PICO;
# endif
@ -289,7 +290,6 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id)
case DEFYX:
case RX_ARQ:
case RX_SFX:
case RX_V:
return RANDOM_X;
# endif

View file

@ -62,14 +62,14 @@ public:
CN_HEAVY_0, // "cn-heavy/0" CryptoNight-Heavy (4 MB).
CN_HEAVY_TUBE, // "cn-heavy/tube" CryptoNight-Heavy (modified, TUBE only).
CN_HEAVY_XHV, // "cn-heavy/xhv" CryptoNight-Heavy (modified, Haven Protocol only).
CN_PICO_0, // "cn-pico" CryptoNight Turtle (TRTL)
CN_PICO_0, // "cn-pico" CryptoNight-Pico
CN_PICO_TLO, // "cn-pico/tlo" CryptoNight-Pico (TLO)
RX_0, // "rx/0" RandomX (reference configuration).
RX_WOW, // "rx/wow" RandomWOW (Wownero).
RX_LOKI, // "rx/loki" RandomXL (Loki).
DEFYX, // "defyx" DefyX (Scala).
RX_ARQ, // "rx/arq" RandomARQ (Arqma).
RX_SFX, // "rx/sfx" RandomSFX (Safex Cash).
RX_V, // "rx/v" RandomV (Monerov).
AR2_CHUKWA, // "argon2/chukwa" Argon2id (Chukwa).
AR2_WRKZ, // "argon2/wrkz" Argon2id (WRKZ)
MAX

View file

@ -6,9 +6,9 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2018-2019 tevador <tevador@gmail.com>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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
@ -46,9 +46,6 @@ namespace xmrig {
static IMemoryPool *pool = nullptr;
static std::mutex mutex;
constexpr size_t twoMiB = 2U * 1024U * 1024U;
constexpr size_t oneGiB = 1024U * 1024U * 1024U;
} // namespace xmrig

View file

@ -6,9 +6,9 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2018-2019 tevador <tevador@gmail.com>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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

View file

@ -1,4 +1,5 @@
;# save VM register values
add rsp, 24
pop rcx
mov qword ptr [rcx+0], r8
mov qword ptr [rcx+8], r9

View file

@ -1,5 +1,5 @@
lea rcx, [rsi+rax]
push rcx
mov [rsp+8], rcx
xor r8, qword ptr [rcx+0]
xor r9, qword ptr [rcx+8]
xor r10, qword ptr [rcx+16]
@ -9,7 +9,7 @@
xor r14, qword ptr [rcx+48]
xor r15, qword ptr [rcx+56]
lea rcx, [rsi+rdx]
push rcx
mov [rsp+16], rcx
cvtdq2pd xmm0, qword ptr [rcx+0]
cvtdq2pd xmm1, qword ptr [rcx+8]
cvtdq2pd xmm2, qword ptr [rcx+16]

View file

@ -1,4 +1,4 @@
pop rcx
mov rcx, [rsp+16]
mov qword ptr [rcx+0], r8
mov qword ptr [rcx+8], r9
mov qword ptr [rcx+16], r10
@ -7,7 +7,7 @@
mov qword ptr [rcx+40], r13
mov qword ptr [rcx+48], r14
mov qword ptr [rcx+56], r15
pop rcx
mov rcx, [rsp+8]
xorpd xmm0, xmm4
xorpd xmm1, xmm5
xorpd xmm2, xmm6

View file

@ -36,6 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "crypto/randomx/program.hpp"
#include "crypto/randomx/reciprocal.h"
#include "crypto/randomx/virtual_memory.hpp"
#include "crypto/rx/Rx.h"
#ifdef _MSC_VER
# include <intrin.h>
@ -168,8 +169,8 @@ namespace randomx {
static const uint8_t REX_MAXPD[] = { 0x66, 0x41, 0x0f, 0x5f };
static const uint8_t REX_DIVPD[] = { 0x66, 0x41, 0x0f, 0x5e };
static const uint8_t SQRTPD[] = { 0x66, 0x0f, 0x51 };
static const uint8_t AND_OR_MOV_LDMXCSR[] = { 0x25, 0x00, 0x60, 0x00, 0x00, 0x0D, 0xC0, 0x9F, 0x00, 0x00, 0x89, 0x44, 0x24, 0xFC, 0x0F, 0xAE, 0x54, 0x24, 0xFC };
static const uint8_t AND_OR_MOV_LDMXCSR_RYZEN[] = { 0x25, 0x00, 0x60, 0x00, 0x00, 0x0D, 0xC0, 0x9F, 0x00, 0x00, 0x3B, 0x44, 0x24, 0xFC, 0x74, 0x09, 0x89, 0x44, 0x24, 0xFC, 0x0F, 0xAE, 0x54, 0x24, 0xFC };
static const uint8_t AND_OR_MOV_LDMXCSR[] = { 0x25, 0x00, 0x60, 0x00, 0x00, 0x0D, 0xC0, 0x9F, 0x00, 0x00, 0x89, 0x04, 0x24, 0x0F, 0xAE, 0x14, 0x24 };
static const uint8_t AND_OR_MOV_LDMXCSR_RYZEN[] = { 0x25, 0x00, 0x60, 0x00, 0x00, 0x0D, 0xC0, 0x9F, 0x00, 0x00, 0x3B, 0x04, 0x24, 0x74, 0x07, 0x89, 0x04, 0x24, 0x0F, 0xAE, 0x14, 0x24 };
static const uint8_t ROL_RAX[] = { 0x48, 0xc1, 0xc0 };
static const uint8_t XOR_ECX_ECX[] = { 0x33, 0xC9 };
static const uint8_t REX_CMP_R32I[] = { 0x41, 0x81 };
@ -299,6 +300,10 @@ namespace randomx {
code = allocatedCode + (codeOffset.fetch_add(59 * 64) % CodeSize);
memcpy(code, codePrologue, prologueSize);
memcpy(code + epilogueOffset, codeEpilogue, epilogueSize);
# ifdef XMRIG_FIX_RYZEN
mainLoopBounds.first = code + prologueSize;
mainLoopBounds.second = code + epilogueOffset;
# endif
}
JitCompilerX86::~JitCompilerX86() {
@ -380,10 +385,14 @@ namespace randomx {
*(uint32_t*)(code + codePos + 10) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated;
*(uint32_t*)(code + codePos + 20) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated;
if (hasAVX) {
uint32_t* p = (uint32_t*)(code + codePos + 29);
uint32_t* p = (uint32_t*)(code + codePos + 32);
*p = (*p & 0xFF000000U) | 0x0077F8C5U;
}
# ifdef XMRIG_FIX_RYZEN
xmrig::Rx::setMainLoopBounds(mainLoopBounds);
# endif
codePos = prologueSize;
memcpy(code + codePos - 48, &pcfg.eMask, sizeof(pcfg.eMask));
memcpy(code + codePos, codeLoopLoad, loopLoadSize);
@ -398,9 +407,10 @@ namespace randomx {
}
for (int i = 0, n = static_cast<int>(RandomX_CurrentConfig.ProgramSize); i < n; ++i) {
Instruction instr = prog(i);
Instruction& instr = prog(i);
const uint8_t opcode = instr.opcode;
*((uint64_t*)&instr) &= (uint64_t(-1) - (0xFFFF << 8)) | ((RegistersCount - 1) << 8) | ((RegistersCount - 1) << 16);
(this->*(engine[instr.opcode]))(instr);
(this->*(engine[opcode]))(instr);
}
emit(REX_MOV_RR, code, codePos);
@ -596,32 +606,22 @@ namespace randomx {
codePos = pos;
}
static const uint32_t template_IADD_M[8] = {
0x0604034c,
0x060c034c,
0x0614034c,
0x061c034c,
0x0624034c,
0x062c034c,
0x0634034c,
0x063c034c,
};
void JitCompilerX86::h_IADD_M(const Instruction& instr) {
uint8_t* const p = code;
int pos = codePos;
if (instr.src != instr.dst) {
const uint32_t dst = instr.dst;
if (instr.src != dst) {
genAddressReg<true>(instr, p, pos);
emit32(template_IADD_M[instr.dst], p, pos);
emit32(0x0604034c + (dst << 19), p, pos);
}
else {
emit(REX_ADD_RM, p, pos);
emitByte(0x86 + 8 * instr.dst, p, pos);
emitByte(0x86 + (dst << 3), p, pos);
genAddressImm(instr, p, pos);
}
registerUsage[instr.dst] = pos;
registerUsage[dst] = pos;
codePos = pos;
}
@ -651,19 +651,18 @@ namespace randomx {
uint8_t* const p = code;
int pos = codePos;
if (instr.src != instr.dst) {
const uint32_t dst = instr.dst;
if (instr.src != dst) {
genAddressReg<true>(instr, p, pos);
emit(REX_SUB_RM, p, pos);
emitByte(0x04 + 8 * instr.dst, p, pos);
emitByte(0x06, p, pos);
emit32(0x06042b4c + (dst << 19), p, pos);
}
else {
emit(REX_SUB_RM, p, pos);
emitByte(0x86 + 8 * instr.dst, p, pos);
emitByte(0x86 + (dst << 3), p, pos);
genAddressImm(instr, p, pos);
}
registerUsage[instr.dst] = pos;
registerUsage[dst] = pos;
codePos = pos;
}
@ -1051,14 +1050,12 @@ namespace randomx {
}
}
emit(REX_ADD_I, p, pos);
emitByte(0xc0 + reg, p, pos);
*(uint32_t*)(p + pos) = 0x00c08149 + (reg << 16);
const int shift = instr.getModCond() + RandomX_CurrentConfig.JumpOffset;
const uint32_t imm = (instr.getImm32() | (1UL << shift)) & ~(1UL << (shift - 1));
emit32(imm, p, pos);
emit(REX_TEST, p, pos);
emitByte(0xc0 + reg, p, pos);
emit32(RandomX_CurrentConfig.ConditionMask_Calculated << shift, p, pos);
*(uint32_t*)(p + pos + 3) = (instr.getImm32() | (1UL << shift)) & ~(1UL << (shift - 1));
*(uint32_t*)(p + pos + 7) = 0x00c0f749 + (reg << 16);
*(uint32_t*)(p + pos + 10) = RandomX_CurrentConfig.ConditionMask_Calculated << shift;
pos += 14;
if (jmp_offset >= -128) {
emitByte(JZ_SHORT, p, pos);
@ -1085,9 +1082,7 @@ namespace randomx {
int pos = codePos;
genAddressRegDst(instr, p, pos);
emit(REX_MOV_MR, p, pos);
emitByte(0x04 + 8 * instr.src, p, pos);
emitByte(0x06, p, pos);
emit32(0x0604894c + (static_cast<uint32_t>(instr.src) << 19), p, pos);
codePos = pos;
}

View file

@ -69,6 +69,9 @@ namespace randomx {
int registerUsage[RegistersCount];
uint8_t* allocatedCode;
uint8_t* code;
# ifdef XMRIG_FIX_RYZEN
std::pair<const void*, const void*> mainLoopBounds;
# endif
int32_t codePos;
uint32_t vm_flags;

View file

@ -93,7 +93,8 @@ DECL(randomx_program_prologue_first_load):
and eax, RANDOMX_SCRATCHPAD_MASK
ror rdx, 32
and edx, RANDOMX_SCRATCHPAD_MASK
stmxcsr dword ptr [rsp-20]
sub rsp, 24
stmxcsr dword ptr [rsp]
nop
nop
nop

View file

@ -81,7 +81,8 @@ randomx_program_prologue_first_load PROC
and eax, RANDOMX_SCRATCHPAD_MASK
ror rdx, 32
and edx, RANDOMX_SCRATCHPAD_MASK
stmxcsr dword ptr [rsp-20]
sub rsp, 24
stmxcsr dword ptr [rsp]
nop
nop
nop

View file

@ -97,11 +97,6 @@ RandomX_ConfigurationSafex::RandomX_ConfigurationSafex()
ArgonSalt = "RandomSFX\x01";
}
RandomX_ConfigurationV::RandomX_ConfigurationV()
{
ArgonSalt = "RandomV\x03";
}
RandomX_ConfigurationBase::RandomX_ConfigurationBase()
: ArgonMemory(262144)
, ArgonIterations(3)
@ -279,13 +274,16 @@ RandomX_ConfigurationWownero RandomX_WowneroConfig;
RandomX_ConfigurationLoki RandomX_LokiConfig;
RandomX_ConfigurationArqma RandomX_ArqmaConfig;
RandomX_ConfigurationSafex RandomX_SafexConfig;
RandomX_ConfigurationV RandomX_VConfig;
RandomX_ConfigurationBase RandomX_CurrentConfig;
extern "C" {
randomx_cache *randomx_create_cache(randomx_flags flags, uint8_t *memory) {
if (!memory) {
return nullptr;
}
randomx_cache *cache = nullptr;
try {
@ -330,6 +328,10 @@ extern "C" {
}
randomx_dataset *randomx_create_dataset(uint8_t *memory) {
if (!memory) {
return nullptr;
}
auto dataset = new randomx_dataset();
dataset->memory = memory;

View file

@ -183,14 +183,12 @@ struct RandomX_ConfigurationWownero : public RandomX_ConfigurationBase { RandomX
struct RandomX_ConfigurationLoki : public RandomX_ConfigurationBase { RandomX_ConfigurationLoki(); };
struct RandomX_ConfigurationArqma : public RandomX_ConfigurationBase { RandomX_ConfigurationArqma(); };
struct RandomX_ConfigurationSafex : public RandomX_ConfigurationBase { RandomX_ConfigurationSafex(); };
struct RandomX_ConfigurationV : public RandomX_ConfigurationBase { RandomX_ConfigurationV(); };
extern RandomX_ConfigurationMonero RandomX_MoneroConfig;
extern RandomX_ConfigurationWownero RandomX_WowneroConfig;
extern RandomX_ConfigurationLoki RandomX_LokiConfig;
extern RandomX_ConfigurationArqma RandomX_ArqmaConfig;
extern RandomX_ConfigurationSafex RandomX_SafexConfig;
extern RandomX_ConfigurationV RandomX_VConfig;
extern RandomX_ConfigurationBase RandomX_CurrentConfig;

View file

@ -74,6 +74,7 @@ bool xmrig::Rx::init(const Job &job, const RxConfig &config, const CpuConfig &cp
if (!osInitialized) {
msrInit(config);
setupMainLoopExceptionFrame();
osInitialized = true;
}
@ -131,4 +132,8 @@ void xmrig::Rx::msrDestroy()
#endif
#ifndef XMRIG_FIX_RYZEN
void xmrig::Rx::setupMainLoopExceptionFrame()
{
}
#endif

View file

@ -57,9 +57,14 @@ public:
static void destroy();
static void init(IRxListener *listener);
# ifdef XMRIG_FIX_RYZEN
static void setMainLoopBounds(const std::pair<const void*, const void*>& bounds);
# endif
private:
static void msrInit(const RxConfig &config);
static void msrDestroy();
static void setupMainLoopExceptionFrame();
};

View file

@ -57,9 +57,6 @@ const RandomX_ConfigurationBase *xmrig::RxAlgo::base(Algorithm::Id algorithm)
case Algorithm::RX_SFX:
return &RandomX_SafexConfig;
case Algorithm::RX_V:
return &RandomX_VConfig;
default:
break;
}

View file

@ -54,7 +54,7 @@ public:
static inline Algorithm::Id id(Algorithm::Id algorithm)
{
if (algorithm == Algorithm::RX_SFX || algorithm == Algorithm::RX_V) {
if (algorithm == Algorithm::RX_SFX) {
return Algorithm::RX_0;
}

View file

@ -48,13 +48,11 @@ public:
XMRIG_DISABLE_COPY_MOVE(RxBasicStoragePrivate)
inline RxBasicStoragePrivate() = default;
inline ~RxBasicStoragePrivate()
{
delete m_dataset;
}
inline ~RxBasicStoragePrivate() { deleteDataset(); }
inline bool isReady(const Job &job) const { return m_ready && m_seed == job; }
inline RxDataset *dataset() const { return m_dataset; }
inline void deleteDataset() { delete m_dataset; m_dataset = nullptr; }
inline void setSeed(const RxSeed &seed)
@ -69,12 +67,22 @@ public:
}
inline void createDataset(bool hugePages, bool oneGbPages, RxConfig::Mode mode)
inline bool createDataset(bool hugePages, bool oneGbPages, RxConfig::Mode mode)
{
const uint64_t ts = Chrono::steadyMSecs();
m_dataset = new RxDataset(hugePages, oneGbPages, true, mode, 0);
if (!m_dataset->cache()->get()) {
deleteDataset();
LOG_INFO("%s" RED_BOLD("failed to allocate RandomX memory") BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - ts);
return false;
}
printAllocStatus(ts);
return true;
}
@ -82,11 +90,11 @@ public:
{
const uint64_t ts = Chrono::steadyMSecs();
m_dataset->init(m_seed.data(), threads, priority);
m_ready = m_dataset->init(m_seed.data(), threads, priority);
LOG_INFO("%s" GREEN_BOLD("dataset ready") BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - ts);
m_ready = true;
if (m_ready) {
LOG_INFO("%s" GREEN_BOLD("dataset ready") BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - ts);
}
}
@ -136,6 +144,12 @@ xmrig::RxBasicStorage::~RxBasicStorage()
}
bool xmrig::RxBasicStorage::isAllocated() const
{
return d_ptr->dataset() && d_ptr->dataset()->cache() && d_ptr->dataset()->cache()->get();
}
xmrig::HugePagesInfo xmrig::RxBasicStorage::hugePages() const
{
if (!d_ptr->dataset()) {
@ -160,8 +174,8 @@ void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool huge
{
d_ptr->setSeed(seed);
if (!d_ptr->dataset()) {
d_ptr->createDataset(hugePages, oneGbPages, mode);
if (!d_ptr->dataset() && !d_ptr->createDataset(hugePages, oneGbPages, mode)) {
return;
}
d_ptr->initDataset(threads, priority);

View file

@ -48,6 +48,7 @@ public:
~RxBasicStorage() override;
protected:
bool isAllocated() const override;
HugePagesInfo hugePages() const override;
RxDataset *dataset(const Job &job, uint32_t nodeId) const override;
void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override;

View file

@ -30,9 +30,7 @@
#include "crypto/randomx/randomx.h"
static_assert(RANDOMX_FLAG_JIT == 8, "RANDOMX_FLAG_JIT flag mismatch");
static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mismatch");
static_assert(RANDOMX_FLAG_JIT == 8, "RANDOMX_FLAG_JIT flag mismatch");
xmrig::RxCache::RxCache(bool hugePages, uint32_t nodeId)
@ -64,9 +62,14 @@ bool xmrig::RxCache::init(const Buffer &seed)
}
m_seed = seed;
randomx_init_cache(m_cache, m_seed.data(), m_seed.size());
return true;
if (m_cache) {
randomx_init_cache(m_cache, m_seed.data(), m_seed.size());
return true;
}
return false;
}
@ -78,6 +81,10 @@ xmrig::HugePagesInfo xmrig::RxCache::hugePages() const
void xmrig::RxCache::create(uint8_t *memory)
{
if (!memory) {
return;
}
m_cache = randomx_create_cache(RANDOMX_FLAG_JIT, memory);
if (!m_cache) {

View file

@ -65,7 +65,7 @@ constexpr size_t kMsrArraySize = 4;
static const std::array<MsrItems, kMsrArraySize> msrPresets = {
MsrItems(),
MsrItems{{ 0xC0011020, 0x0 }, { 0xC0011021, 0x40, ~0x20ULL }, { 0xC0011022, 0x510000 }, { 0xC001102b, 0x1808cc16 }},
MsrItems{{ 0x1a4, 0x6 }},
MsrItems{{ 0x1a4, 0xf }},
MsrItems()
};

View file

@ -88,7 +88,7 @@ xmrig::RxDataset::~RxDataset()
bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads, int priority)
{
if (!m_cache) {
if (!m_cache || !m_cache->get()) {
return false;
}

View file

@ -120,7 +120,7 @@ public:
}
inline void createDatasets(bool hugePages, bool oneGbPages)
inline bool createDatasets(bool hugePages, bool oneGbPages)
{
const uint64_t ts = Chrono::steadyMSecs();
@ -133,6 +133,10 @@ public:
if (isCacheRequired()) {
std::thread thread(allocateCache, this, m_nodeset.front(), hugePages);
thread.join();
if (!m_cache) {
return false;
}
}
if (m_datasets.empty()) {
@ -149,6 +153,8 @@ public:
}
m_allocated = true;
return true;
}
@ -237,6 +243,13 @@ private:
bindToNUMANode(nodeId);
auto cache = new RxCache(hugePages, nodeId);
if (!cache->get()) {
delete cache;
LOG_INFO("%s" RED_BOLD("failed to allocate RandomX memory") BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - ts);
return;
}
std::lock_guard<std::mutex> lock(mutex);
d_ptr->m_cache = cache;
@ -336,6 +349,12 @@ xmrig::RxNUMAStorage::~RxNUMAStorage()
}
bool xmrig::RxNUMAStorage::isAllocated() const
{
return d_ptr->isAllocated();
}
xmrig::HugePagesInfo xmrig::RxNUMAStorage::hugePages() const
{
if (!d_ptr->isAllocated()) {
@ -360,8 +379,8 @@ void xmrig::RxNUMAStorage::init(const RxSeed &seed, uint32_t threads, bool hugeP
{
d_ptr->setSeed(seed);
if (!d_ptr->isAllocated()) {
d_ptr->createDatasets(hugePages, oneGbPages);
if (!d_ptr->isAllocated() && !d_ptr->createDatasets(hugePages, oneGbPages)) {
return;
}
d_ptr->initDatasets(threads, priority);

View file

@ -51,6 +51,7 @@ public:
~RxNUMAStorage() override;
protected:
bool isAllocated() const override;
HugePagesInfo hugePages() const override;
RxDataset *dataset(const Job &job, uint32_t nodeId) const override;
void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override;

View file

@ -126,7 +126,7 @@ void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector<uint32_t> &no
bool xmrig::RxQueue::isReadyUnsafe(const Job &job) const
{
return m_storage != nullptr && m_state == STATE_IDLE && m_seed == job;
return m_storage != nullptr && m_storage->isAllocated() && m_state == STATE_IDLE && m_seed == job;
}

View file

@ -43,6 +43,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <ucontext.h>
namespace xmrig {
@ -178,6 +180,33 @@ static bool wrmsr(const MsrItems &preset, bool save)
}
#ifdef XMRIG_FIX_RYZEN
static thread_local std::pair<const void*, const void*> mainLoopBounds = { nullptr, nullptr };
static void MainLoopHandler(int sig, siginfo_t *info, void *ucontext)
{
ucontext_t *ucp = (ucontext_t*) ucontext;
LOG_VERBOSE(YELLOW_BOLD("%s at %p"), (sig == SIGSEGV) ? "SIGSEGV" : "SIGILL", ucp->uc_mcontext.gregs[REG_RIP]);
void* p = reinterpret_cast<void*>(ucp->uc_mcontext.gregs[REG_RIP]);
const std::pair<const void*, const void*>& loopBounds = mainLoopBounds;
if ((loopBounds.first <= p) && (p < loopBounds.second)) {
ucp->uc_mcontext.gregs[REG_RIP] = reinterpret_cast<size_t>(loopBounds.second);
}
else {
abort();
}
}
void Rx::setMainLoopBounds(const std::pair<const void*, const void*>& bounds)
{
mainLoopBounds = bounds;
}
#endif
} // namespace xmrig
@ -208,3 +237,15 @@ void xmrig::Rx::msrDestroy()
LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts);
}
}
void xmrig::Rx::setupMainLoopExceptionFrame()
{
# ifdef XMRIG_FIX_RYZEN
struct sigaction act = {};
act.sa_sigaction = MainLoopHandler;
act.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGSEGV, &act, nullptr);
sigaction(SIGILL, &act, nullptr);
# endif
}

View file

@ -303,6 +303,43 @@ static bool wrmsr(const MsrItems &preset, bool save)
}
#ifdef XMRIG_FIX_RYZEN
static thread_local std::pair<const void*, const void*> mainLoopBounds = { nullptr, nullptr };
static LONG WINAPI MainLoopHandler(_EXCEPTION_POINTERS *ExceptionInfo)
{
if (ExceptionInfo->ExceptionRecord->ExceptionCode == 0xC0000005) {
const char* accessType;
switch (ExceptionInfo->ExceptionRecord->ExceptionInformation[0]) {
case 0: accessType = "read"; break;
case 1: accessType = "write"; break;
case 8: accessType = "DEP violation"; break;
default: accessType = "unknown"; break;
}
LOG_VERBOSE(YELLOW_BOLD("[THREAD %u] Access violation at 0x%p: %s at address 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionAddress, accessType, ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
}
else {
LOG_VERBOSE(YELLOW_BOLD("[THREAD %u] Exception 0x%08X at 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
}
void* p = reinterpret_cast<void*>(ExceptionInfo->ContextRecord->Rip);
const std::pair<const void*, const void*>& loopBounds = mainLoopBounds;
if ((loopBounds.first <= p) && (p < loopBounds.second)) {
ExceptionInfo->ContextRecord->Rip = reinterpret_cast<DWORD64>(loopBounds.second);
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
void Rx::setMainLoopBounds(const std::pair<const void*, const void*>& bounds)
{
mainLoopBounds = bounds;
}
#endif
} // namespace xmrig
@ -333,3 +370,11 @@ void xmrig::Rx::msrDestroy()
LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts);
}
}
void xmrig::Rx::setupMainLoopExceptionFrame()
{
# ifdef XMRIG_FIX_RYZEN
AddVectoredExceptionHandler(1, MainLoopHandler);
# endif
}