Added ASM code patching when loading

For CNv2 variants with different iterations and memory size.
This commit is contained in:
SChernykh 2019-01-14 15:34:55 +01:00
parent 492449e9fb
commit 8b9d5cff91
19 changed files with 118 additions and 2034 deletions

View file

@ -31,6 +31,7 @@
#include "crypto/Asm.h"
#include "rapidjson/document.h"
#include "workers/CpuThread.h"
#include "Mem.h"
#if defined(XMRIG_ARM)
@ -54,6 +55,61 @@ xmrig::CpuThread::CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiw
}
#ifndef XMRIG_NO_ASM
template<typename T, typename U>
static void patchCode(T& dst, U src, const uint32_t iterations, const uint32_t mask)
{
const uint8_t* p = reinterpret_cast<const uint8_t*>(src);
size_t size = 0;
while (*(uint32_t*)(p + size) != 0x90909090) {
++size;
}
memcpy((void*) dst, (const void*) src, size);
uint8_t* patched_data = reinterpret_cast<uint8_t*>(dst);
for (size_t i = 0; i + sizeof(uint32_t) <= size; ++i) {
switch (*(uint32_t*)(patched_data + i)) {
case xmrig::CRYPTONIGHT_ITER:
*(uint32_t*)(patched_data + i) = iterations;
break;
case xmrig::CRYPTONIGHT_MASK:
*(uint32_t*)(patched_data + i) = mask;
break;
}
}
}
extern "C" void cnv2_mainloop_ivybridge_asm(cryptonight_ctx *ctx);
extern "C" void cnv2_mainloop_ryzen_asm(cryptonight_ctx *ctx);
extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx *ctx);
extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx* ctx0, cryptonight_ctx* ctx1);
xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ivybridge_asm = nullptr;
xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ryzen_asm = nullptr;
xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_bulldozer_asm = nullptr;
xmrig::CpuThread::cn_mainloop_double_fun cn_half_double_mainloop_sandybridge_asm = nullptr;
void xmrig::CpuThread::patchAsmVariants()
{
const int allocation_size = 65536;
uint8_t* base = reinterpret_cast<uint8_t*>(Mem::allocate_executable_memory(allocation_size));
cn_half_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x0000);
cn_half_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x1000);
cn_half_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x2000);
cn_half_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_double_fun> (base + 0x3000);
patchCode(cn_half_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK);
patchCode(cn_half_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK);
patchCode(cn_half_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK);
patchCode(cn_half_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK);
Mem::FlushInstructionCache(base, allocation_size);
}
#endif
bool xmrig::CpuThread::isSoftAES(AlgoVariant av)
{
return av == AV_SINGLE_SOFT || av == AV_DOUBLE_SOFT || av > AV_PENTA;

View file

@ -60,6 +60,12 @@ public:
CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly);
typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx **ctx);
typedef void (*cn_mainloop_fun)(cryptonight_ctx *ctx);
typedef void (*cn_mainloop_double_fun)(cryptonight_ctx *ctx1, cryptonight_ctx *ctx2);
# ifndef XMRIG_NO_ASM
static void patchAsmVariants();
# endif
static bool isSoftAES(AlgoVariant av);
static cn_hash_fun fn(Algo algorithm, AlgoVariant av, Variant variant, Assembly assembly);

View file

@ -168,6 +168,10 @@ void Workers::start(xmrig::Controller *controller)
LOG_NOTICE("--------------------------------------------------------------------------");
# endif
# ifndef XMRIG_NO_ASM
xmrig::CpuThread::patchAsmVariants();
# endif
m_controller = controller;
const std::vector<xmrig::IThread *> &threads = controller->config()->threads();