Implemented unified cryptonight and RandomX scratchpad memory.

This commit is contained in:
XMRig 2019-07-17 04:33:11 +07:00
parent 5699147aab
commit 20313cbc56
30 changed files with 434 additions and 297 deletions

60
src/crypto/cn/CnCtx.cpp Normal file
View file

@ -0,0 +1,60 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 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 2016-2019 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
* 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 <http://www.gnu.org/licenses/>.
*/
#include <limits>
#include "crypto/cn/CnCtx.h"
#include "crypto/cn/CryptoNight.h"
#include "crypto/common/Algorithm.h"
#include "crypto/common/portable/mm_malloc.h"
#include "crypto/common/VirtualMemory.h"
void xmrig::CnCtx::create(cryptonight_ctx **ctx, uint8_t *memory, size_t size, size_t count)
{
for (size_t i = 0; i < count; ++i) {
cryptonight_ctx *c = static_cast<cryptonight_ctx *>(_mm_malloc(sizeof(cryptonight_ctx), 4096));
c->memory = memory + (i * size);
c->generated_code = reinterpret_cast<cn_mainloop_fun_ms_abi>(VirtualMemory::allocateExecutableMemory(0x4000));
c->generated_code_data.algo = Algorithm::INVALID;
c->generated_code_data.height = std::numeric_limits<uint64_t>::max();
ctx[i] = c;
}
}
void xmrig::CnCtx::release(cryptonight_ctx **ctx, size_t count)
{
if (ctx[0] == nullptr) {
return;
}
for (size_t i = 0; i < count; ++i) {
_mm_free(ctx[i]);
}
}

52
src/crypto/cn/CnCtx.h Normal file
View file

@ -0,0 +1,52 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 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 2016-2019 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
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CN_CTX_H
#define XMRIG_CN_CTX_H
#include <stddef.h>
#include <stdint.h>
struct cryptonight_ctx;
namespace xmrig
{
class CnCtx
{
public:
static void create(cryptonight_ctx **ctx, uint8_t *memory, size_t size, size_t count);
static void release(cryptonight_ctx **ctx, size_t count);
};
} /* namespace xmrig */
#endif /* XMRIG_CN_CTX_H */

View file

@ -38,6 +38,15 @@ namespace xmrig {
class VirtualMemory
{
public:
inline VirtualMemory() {}
VirtualMemory(size_t size, bool hugePages = true, size_t align = 64);
~VirtualMemory();
inline bool isHugePages() const { return m_flags & HUGEPAGES; }
inline size_t hugePages() const { return isHugePages() ? (align(size()) / 2097152) : 0; }
inline size_t size() const { return m_size; }
inline uint8_t *scratchpad() const { return m_scratchpad; }
static void *allocateExecutableMemory(size_t size);
static void *allocateLargePagesMemory(size_t size);
static void flushInstructionCache(void *p, size_t size);
@ -46,6 +55,17 @@ public:
static void unprotectExecutableMemory(void *p, size_t size);
static inline constexpr size_t align(size_t pos, size_t align = 2097152) { return ((pos - 1) / align + 1) * align; }
private:
enum Flags {
HUGEPAGES_AVAILABLE = 1,
HUGEPAGES = 2,
LOCK = 4
};
int m_flags = 0;
size_t m_size = 0;
uint8_t *m_scratchpad = nullptr;
};

View file

@ -29,6 +29,7 @@
#include <sys/mman.h>
#include "crypto/common/portable/mm_malloc.h"
#include "crypto/common/VirtualMemory.h"
@ -37,6 +38,47 @@
#endif
xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, size_t align) :
m_size(VirtualMemory::align(size))
{
if (hugePages) {
m_scratchpad = static_cast<uint8_t*>(allocateLargePagesMemory(m_size));
if (m_scratchpad) {
m_flags |= HUGEPAGES;
madvise(m_scratchpad, size, MADV_RANDOM | MADV_WILLNEED);
if (mlock(m_scratchpad, m_size) == 0) {
m_flags |= LOCK;
}
return;
}
}
m_scratchpad = static_cast<uint8_t*>(_mm_malloc(m_size, align));
}
xmrig::VirtualMemory::~VirtualMemory()
{
if (!m_scratchpad) {
return;
}
if (isHugePages()) {
if (m_flags & LOCK) {
munlock(m_scratchpad, m_size);
}
freeLargePagesMemory(m_scratchpad, m_size);
}
else {
_mm_free(m_scratchpad);
}
}
void *xmrig::VirtualMemory::allocateExecutableMemory(size_t size)
{

View file

@ -32,6 +32,37 @@
#include "crypto/common/VirtualMemory.h"
xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, size_t align) :
m_size(VirtualMemory::align(size))
{
if (hugePages) {
m_scratchpad = static_cast<uint8_t*>(allocateLargePagesMemory(m_size));
if (m_scratchpad) {
m_flags |= HUGEPAGES;
return;
}
}
m_scratchpad = static_cast<uint8_t*>(_mm_malloc(m_size, align));
}
xmrig::VirtualMemory::~VirtualMemory()
{
if (!m_scratchpad) {
return;
}
if (isHugePages()) {
freeLargePagesMemory(m_scratchpad, m_size);
}
else {
_mm_free(m_scratchpad);
}
}
void *xmrig::VirtualMemory::allocateExecutableMemory(size_t size)
{
return VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

View file

@ -345,7 +345,7 @@ extern "C" {
delete dataset;
}
randomx_vm *randomx_create_vm(randomx_flags flags, randomx_cache *cache, randomx_dataset *dataset) {
randomx_vm *randomx_create_vm(randomx_flags flags, randomx_cache *cache, randomx_dataset *dataset, uint8_t *scratchpad) {
assert(cache != nullptr || (flags & RANDOMX_FLAG_FULL_MEM));
assert(cache == nullptr || cache->isInitialized());
assert(dataset != nullptr || !(flags & RANDOMX_FLAG_FULL_MEM));
@ -353,7 +353,7 @@ extern "C" {
randomx_vm *vm = nullptr;
try {
switch (flags & (RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES)) {
switch (flags & (RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES)) {
case RANDOMX_FLAG_DEFAULT:
vm = new randomx::InterpretedLightVmDefault();
break;
@ -386,49 +386,19 @@ extern "C" {
vm = new randomx::CompiledVmHardAes();
break;
case RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::InterpretedLightVmLargePage();
break;
case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::InterpretedVmLargePage();
break;
case RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::CompiledLightVmLargePage();
break;
case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::CompiledVmLargePage();
break;
case RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::InterpretedLightVmLargePageHardAes();
break;
case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::InterpretedVmLargePageHardAes();
break;
case RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::CompiledLightVmLargePageHardAes();
break;
case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::CompiledVmLargePageHardAes();
break;
default:
UNREACHABLE;
}
if(cache != nullptr)
if (cache != nullptr) {
vm->setCache(cache);
}
if(dataset != nullptr)
if (dataset != nullptr) {
vm->setDataset(dataset);
}
vm->allocate();
vm->setScratchpad(scratchpad);
}
catch (std::exception &ex) {
delete vm;

View file

@ -286,7 +286,7 @@ RANDOMX_EXPORT void randomx_release_dataset(randomx_dataset *dataset);
* (3) cache parameter is NULL and RANDOMX_FLAG_FULL_MEM is not set
* (4) dataset parameter is NULL and RANDOMX_FLAG_FULL_MEM is set
*/
RANDOMX_EXPORT randomx_vm *randomx_create_vm(randomx_flags flags, randomx_cache *cache, randomx_dataset *dataset);
RANDOMX_EXPORT randomx_vm *randomx_create_vm(randomx_flags flags, randomx_cache *cache, randomx_dataset *dataset, uint8_t *scratchpad);
/**
* Reinitializes a virtual machine with a new Cache. This function should be called anytime

View file

@ -95,43 +95,35 @@ void randomx_vm::initialize() {
namespace randomx {
alignas(16) volatile static rx_vec_i128 aesDummy;
template<class Allocator, bool softAes>
VmBase<Allocator, softAes>::~VmBase() {
Allocator::freeMemory(scratchpad, RANDOMX_SCRATCHPAD_L3_MAX_SIZE);
template<bool softAes>
VmBase<softAes>::~VmBase() {
}
template<class Allocator, bool softAes>
void VmBase<Allocator, softAes>::allocate() {
if (datasetPtr == nullptr)
template<bool softAes>
void VmBase<softAes>::setScratchpad(uint8_t *scratchpad) {
if (datasetPtr == nullptr) {
throw std::invalid_argument("Cache/Dataset not set");
if (!softAes) { //if hardware AES is not supported, it's better to fail now than to return a ticking bomb
rx_vec_i128 tmp = rx_load_vec_i128((const rx_vec_i128*)&aesDummy);
tmp = rx_aesenc_vec_i128(tmp, tmp);
rx_store_vec_i128((rx_vec_i128*)&aesDummy, tmp);
}
scratchpad = (uint8_t*)Allocator::allocMemory(RANDOMX_SCRATCHPAD_L3_MAX_SIZE);
this->scratchpad = scratchpad;
}
template<class Allocator, bool softAes>
void VmBase<Allocator, softAes>::getFinalResult(void* out, size_t outSize) {
template<bool softAes>
void VmBase<softAes>::getFinalResult(void* out, size_t outSize) {
hashAes1Rx4<softAes>(scratchpad, ScratchpadSize, &reg.a);
blake2b(out, outSize, &reg, sizeof(RegisterFile), nullptr, 0);
}
template<class Allocator, bool softAes>
void VmBase<Allocator, softAes>::initScratchpad(void* seed) {
template<bool softAes>
void VmBase<softAes>::initScratchpad(void* seed) {
fillAes1Rx4<softAes>(seed, ScratchpadSize, scratchpad);
}
template<class Allocator, bool softAes>
void VmBase<Allocator, softAes>::generateProgram(void* seed) {
template<bool softAes>
void VmBase<softAes>::generateProgram(void* seed) {
fillAes4Rx4<softAes>(seed, sizeof(program), &program);
}
template class VmBase<AlignedAllocator<CacheLineSize>, false>;
template class VmBase<AlignedAllocator<CacheLineSize>, true>;
template class VmBase<LargePageAllocator, false>;
template class VmBase<LargePageAllocator, true>;
}
template class VmBase<false>;
template class VmBase<true>;
}

View file

@ -33,26 +33,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "program.hpp"
/* Global namespace for C binding */
class randomx_vm {
class randomx_vm
{
public:
virtual ~randomx_vm() = 0;
virtual void allocate() = 0;
virtual void setScratchpad(uint8_t *scratchpad) = 0;
virtual void getFinalResult(void* out, size_t outSize) = 0;
virtual void setDataset(randomx_dataset* dataset) { }
virtual void setCache(randomx_cache* cache) { }
virtual void initScratchpad(void* seed) = 0;
virtual void run(void* seed) = 0;
void resetRoundingMode();
randomx::RegisterFile *getRegisterFile() {
return &reg;
}
const void* getScratchpad() {
return scratchpad;
}
const randomx::Program& getProgram()
{
return program;
}
protected:
void initialize();
alignas(64) randomx::Program program;
@ -69,15 +74,17 @@ protected:
namespace randomx {
template<class Allocator, bool softAes>
class VmBase : public randomx_vm {
template<bool softAes>
class VmBase : public randomx_vm
{
public:
~VmBase() override;
void allocate() override;
void setScratchpad(uint8_t *scratchpad) override;
void initScratchpad(void* seed) override;
void getFinalResult(void* out, size_t outSize) override;
protected:
void generateProgram(void* seed);
};
}
}

View file

@ -34,27 +34,25 @@ namespace randomx {
static_assert(sizeof(MemoryRegisters) == 2 * sizeof(addr_t) + sizeof(uintptr_t), "Invalid alignment of struct randomx::MemoryRegisters");
static_assert(sizeof(RegisterFile) == 256, "Invalid alignment of struct randomx::RegisterFile");
template<class Allocator, bool softAes>
void CompiledVm<Allocator, softAes>::setDataset(randomx_dataset* dataset) {
template<bool softAes>
void CompiledVm<softAes>::setDataset(randomx_dataset* dataset) {
datasetPtr = dataset;
}
template<class Allocator, bool softAes>
void CompiledVm<Allocator, softAes>::run(void* seed) {
VmBase<Allocator, softAes>::generateProgram(seed);
template<bool softAes>
void CompiledVm<softAes>::run(void* seed) {
VmBase<softAes>::generateProgram(seed);
randomx_vm::initialize();
compiler.generateProgram(program, config);
mem.memory = datasetPtr->memory + datasetOffset;
execute();
}
template<class Allocator, bool softAes>
void CompiledVm<Allocator, softAes>::execute() {
template<bool softAes>
void CompiledVm<softAes>::execute() {
compiler.getProgramFunc()(reg, mem, scratchpad, RandomX_CurrentConfig.ProgramIterations);
}
template class CompiledVm<AlignedAllocator<CacheLineSize>, false>;
template class CompiledVm<AlignedAllocator<CacheLineSize>, true>;
template class CompiledVm<LargePageAllocator, false>;
template class CompiledVm<LargePageAllocator, true>;
}
template class CompiledVm<false>;
template class CompiledVm<true>;
}

View file

@ -37,8 +37,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx {
template<class Allocator, bool softAes>
class CompiledVm : public VmBase<Allocator, softAes> {
template<bool softAes>
class CompiledVm : public VmBase<softAes>
{
public:
void* operator new(size_t size) {
void* ptr = AlignedAllocator<CacheLineSize>::allocMemory(size);
@ -46,27 +47,28 @@ namespace randomx {
throw std::bad_alloc();
return ptr;
}
void operator delete(void* ptr) {
AlignedAllocator<CacheLineSize>::freeMemory(ptr, sizeof(CompiledVm));
}
void setDataset(randomx_dataset* dataset) override;
void run(void* seed) override;
using VmBase<Allocator, softAes>::mem;
using VmBase<Allocator, softAes>::program;
using VmBase<Allocator, softAes>::config;
using VmBase<Allocator, softAes>::reg;
using VmBase<Allocator, softAes>::scratchpad;
using VmBase<Allocator, softAes>::datasetPtr;
using VmBase<Allocator, softAes>::datasetOffset;
using VmBase<softAes>::mem;
using VmBase<softAes>::program;
using VmBase<softAes>::config;
using VmBase<softAes>::reg;
using VmBase<softAes>::scratchpad;
using VmBase<softAes>::datasetPtr;
using VmBase<softAes>::datasetOffset;
protected:
void execute();
JitCompiler compiler;
};
using CompiledVmDefault = CompiledVm<AlignedAllocator<CacheLineSize>, true>;
using CompiledVmHardAes = CompiledVm<AlignedAllocator<CacheLineSize>, false>;
using CompiledVmLargePage = CompiledVm<LargePageAllocator, true>;
using CompiledVmLargePageHardAes = CompiledVm<LargePageAllocator, false>;
using CompiledVmDefault = CompiledVm<true>;
using CompiledVmHardAes = CompiledVm<false>;
}

View file

@ -32,23 +32,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx {
template<class Allocator, bool softAes>
void CompiledLightVm<Allocator, softAes>::setCache(randomx_cache* cache) {
template<bool softAes>
void CompiledLightVm<softAes>::setCache(randomx_cache* cache) {
cachePtr = cache;
mem.memory = cache->memory;
compiler.generateSuperscalarHash(cache->programs, cache->reciprocalCache);
}
template<class Allocator, bool softAes>
void CompiledLightVm<Allocator, softAes>::run(void* seed) {
VmBase<Allocator, softAes>::generateProgram(seed);
template<bool softAes>
void CompiledLightVm<softAes>::run(void* seed) {
VmBase<softAes>::generateProgram(seed);
randomx_vm::initialize();
compiler.generateProgramLight(program, config, datasetOffset);
CompiledVm<Allocator, softAes>::execute();
CompiledVm<softAes>::execute();
}
template class CompiledLightVm<AlignedAllocator<CacheLineSize>, false>;
template class CompiledLightVm<AlignedAllocator<CacheLineSize>, true>;
template class CompiledLightVm<LargePageAllocator, false>;
template class CompiledLightVm<LargePageAllocator, true>;
}
template class CompiledLightVm<false>;
template class CompiledLightVm<true>;
}

View file

@ -33,8 +33,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx {
template<class Allocator, bool softAes>
class CompiledLightVm : public CompiledVm<Allocator, softAes> {
template<bool softAes>
class CompiledLightVm : public CompiledVm<softAes>
{
public:
void* operator new(size_t size) {
void* ptr = AlignedAllocator<CacheLineSize>::allocMemory(size);
@ -42,23 +43,23 @@ namespace randomx {
throw std::bad_alloc();
return ptr;
}
void operator delete(void* ptr) {
AlignedAllocator<CacheLineSize>::freeMemory(ptr, sizeof(CompiledLightVm));
}
void setCache(randomx_cache* cache) override;
void setDataset(randomx_dataset* dataset) override { }
void run(void* seed) override;
using CompiledVm<Allocator, softAes>::mem;
using CompiledVm<Allocator, softAes>::compiler;
using CompiledVm<Allocator, softAes>::program;
using CompiledVm<Allocator, softAes>::config;
using CompiledVm<Allocator, softAes>::cachePtr;
using CompiledVm<Allocator, softAes>::datasetOffset;
using CompiledVm<softAes>::mem;
using CompiledVm<softAes>::compiler;
using CompiledVm<softAes>::program;
using CompiledVm<softAes>::config;
using CompiledVm<softAes>::cachePtr;
using CompiledVm<softAes>::datasetOffset;
};
using CompiledLightVmDefault = CompiledLightVm<AlignedAllocator<CacheLineSize>, true>;
using CompiledLightVmHardAes = CompiledLightVm<AlignedAllocator<CacheLineSize>, false>;
using CompiledLightVmLargePage = CompiledLightVm<LargePageAllocator, true>;
using CompiledLightVmLargePageHardAes = CompiledLightVm<LargePageAllocator, false>;
}
using CompiledLightVmDefault = CompiledLightVm<true>;
using CompiledLightVmHardAes = CompiledLightVm<false>;
}

View file

@ -33,21 +33,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx {
template<class Allocator, bool softAes>
void InterpretedVm<Allocator, softAes>::setDataset(randomx_dataset* dataset) {
template<bool softAes>
void InterpretedVm<softAes>::setDataset(randomx_dataset* dataset) {
datasetPtr = dataset;
mem.memory = dataset->memory;
}
template<class Allocator, bool softAes>
void InterpretedVm<Allocator, softAes>::run(void* seed) {
VmBase<Allocator, softAes>::generateProgram(seed);
template<bool softAes>
void InterpretedVm<softAes>::run(void* seed) {
VmBase<softAes>::generateProgram(seed);
randomx_vm::initialize();
execute();
}
template<class Allocator, bool softAes>
void InterpretedVm<Allocator, softAes>::execute() {
template<bool softAes>
void InterpretedVm<softAes>::execute() {
NativeRegisterFile nreg;
@ -106,20 +106,18 @@ namespace randomx {
rx_store_vec_f128(&reg.e[i].lo, nreg.e[i]);
}
template<class Allocator, bool softAes>
void InterpretedVm<Allocator, softAes>::datasetRead(uint64_t address, int_reg_t(&r)[RegistersCount]) {
template<bool softAes>
void InterpretedVm<softAes>::datasetRead(uint64_t address, int_reg_t(&r)[RegistersCount]) {
uint64_t* datasetLine = (uint64_t*)(mem.memory + address);
for (int i = 0; i < RegistersCount; ++i)
r[i] ^= datasetLine[i];
}
template<class Allocator, bool softAes>
void InterpretedVm<Allocator, softAes>::datasetPrefetch(uint64_t address) {
template<bool softAes>
void InterpretedVm<softAes>::datasetPrefetch(uint64_t address) {
rx_prefetch_nta(mem.memory + address);
}
template class InterpretedVm<AlignedAllocator<CacheLineSize>, false>;
template class InterpretedVm<AlignedAllocator<CacheLineSize>, true>;
template class InterpretedVm<LargePageAllocator, false>;
template class InterpretedVm<LargePageAllocator, true>;
}
template class InterpretedVm<false>;
template class InterpretedVm<true>;
}

View file

@ -38,38 +38,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx {
template<class Allocator, bool softAes>
class InterpretedVm : public VmBase<Allocator, softAes>, public BytecodeMachine {
template<bool softAes>
class InterpretedVm : public VmBase<softAes>, public BytecodeMachine {
public:
using VmBase<Allocator, softAes>::mem;
using VmBase<Allocator, softAes>::scratchpad;
using VmBase<Allocator, softAes>::program;
using VmBase<Allocator, softAes>::config;
using VmBase<Allocator, softAes>::reg;
using VmBase<Allocator, softAes>::datasetPtr;
using VmBase<Allocator, softAes>::datasetOffset;
using VmBase<softAes>::mem;
using VmBase<softAes>::scratchpad;
using VmBase<softAes>::program;
using VmBase<softAes>::config;
using VmBase<softAes>::reg;
using VmBase<softAes>::datasetPtr;
using VmBase<softAes>::datasetOffset;
void* operator new(size_t size) {
void* ptr = AlignedAllocator<CacheLineSize>::allocMemory(size);
if (ptr == nullptr)
throw std::bad_alloc();
return ptr;
}
void operator delete(void* ptr) {
AlignedAllocator<CacheLineSize>::freeMemory(ptr, sizeof(InterpretedVm));
}
void run(void* seed) override;
void setDataset(randomx_dataset* dataset) override;
protected:
virtual void datasetRead(uint64_t blockNumber, int_reg_t(&r)[RegistersCount]);
virtual void datasetPrefetch(uint64_t blockNumber);
private:
void execute();
InstructionByteCode bytecode[RANDOMX_PROGRAM_MAX_SIZE];
};
using InterpretedVmDefault = InterpretedVm<AlignedAllocator<CacheLineSize>, true>;
using InterpretedVmHardAes = InterpretedVm<AlignedAllocator<CacheLineSize>, false>;
using InterpretedVmLargePage = InterpretedVm<LargePageAllocator, true>;
using InterpretedVmLargePageHardAes = InterpretedVm<LargePageAllocator, false>;
}
using InterpretedVmDefault = InterpretedVm<true>;
using InterpretedVmHardAes = InterpretedVm<false>;
}

View file

@ -31,14 +31,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx {
template<class Allocator, bool softAes>
void InterpretedLightVm<Allocator, softAes>::setCache(randomx_cache* cache) {
template<bool softAes>
void InterpretedLightVm<softAes>::setCache(randomx_cache* cache) {
cachePtr = cache;
mem.memory = cache->memory;
}
template<class Allocator, bool softAes>
void InterpretedLightVm<Allocator, softAes>::datasetRead(uint64_t address, int_reg_t(&r)[8]) {
template<bool softAes>
void InterpretedLightVm<softAes>::datasetRead(uint64_t address, int_reg_t(&r)[8]) {
uint32_t itemNumber = address / CacheLineSize;
int_reg_t rl[8];
@ -48,8 +48,6 @@ namespace randomx {
r[q] ^= rl[q];
}
template class InterpretedLightVm<AlignedAllocator<CacheLineSize>, false>;
template class InterpretedLightVm<AlignedAllocator<CacheLineSize>, true>;
template class InterpretedLightVm<LargePageAllocator, false>;
template class InterpretedLightVm<LargePageAllocator, true>;
template class InterpretedLightVm<false>;
template class InterpretedLightVm<true>;
}

View file

@ -33,29 +33,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx {
template<class Allocator, bool softAes>
class InterpretedLightVm : public InterpretedVm<Allocator, softAes> {
template<bool softAes>
class InterpretedLightVm : public InterpretedVm<softAes> {
public:
using VmBase<Allocator, softAes>::mem;
using VmBase<Allocator, softAes>::cachePtr;
using VmBase<softAes>::mem;
using VmBase<softAes>::cachePtr;
void* operator new(size_t size) {
void* ptr = AlignedAllocator<CacheLineSize>::allocMemory(size);
if (ptr == nullptr)
throw std::bad_alloc();
return ptr;
}
void operator delete(void* ptr) {
AlignedAllocator<CacheLineSize>::freeMemory(ptr, sizeof(InterpretedLightVm));
}
void setDataset(randomx_dataset* dataset) override { }
void setCache(randomx_cache* cache) override;
protected:
void datasetRead(uint64_t address, int_reg_t(&r)[8]) override;
void datasetPrefetch(uint64_t address) override { }
};
using InterpretedLightVmDefault = InterpretedLightVm<AlignedAllocator<CacheLineSize>, true>;
using InterpretedLightVmHardAes = InterpretedLightVm<AlignedAllocator<CacheLineSize>, false>;
using InterpretedLightVmLargePage = InterpretedLightVm<LargePageAllocator, true>;
using InterpretedLightVmLargePageHardAes = InterpretedLightVm<LargePageAllocator, false>;
using InterpretedLightVmDefault = InterpretedLightVm<true>;
using InterpretedLightVmHardAes = InterpretedLightVm<false>;
}

View file

@ -31,12 +31,8 @@
#include "crypto/rx/RxVm.h"
xmrig::RxVm::RxVm(RxDataset *dataset, bool hugePages, bool softAes)
xmrig::RxVm::RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes)
{
if (hugePages) {
m_flags |= RANDOMX_FLAG_LARGE_PAGES;
}
if (!softAes) {
m_flags |= RANDOMX_FLAG_HARD_AES;
}
@ -49,17 +45,7 @@ xmrig::RxVm::RxVm(RxDataset *dataset, bool hugePages, bool softAes)
m_flags |= RANDOMX_FLAG_JIT;
}
m_vm = randomx_create_vm(static_cast<randomx_flags>(m_flags), dataset->cache()->get(), dataset->get());
if (!m_vm) {
m_flags &= ~RANDOMX_FLAG_LARGE_PAGES;
m_vm = randomx_create_vm(static_cast<randomx_flags>(m_flags), dataset->cache()->get(), dataset->get());
}
if (!m_vm) {
m_flags &= ~RANDOMX_FLAG_HARD_AES;
m_vm = randomx_create_vm(static_cast<randomx_flags>(m_flags), dataset->cache()->get(), dataset->get());
}
m_vm = randomx_create_vm(static_cast<randomx_flags>(m_flags), dataset->cache()->get(), dataset->get(), scratchpad);
}

View file

@ -44,7 +44,7 @@ class RxDataset;
class RxVm
{
public:
RxVm(RxDataset *dataset, bool hugePages, bool softAes);
RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes);
~RxVm();
inline randomx_vm *get() const { return m_vm; }