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

View file

@ -54,6 +54,7 @@ set(HEADERS_CRYPTO
src/crypto/cn/c_jh.h src/crypto/cn/c_jh.h
src/crypto/cn/c_skein.h src/crypto/cn/c_skein.h
src/crypto/cn/CnAlgo.h src/crypto/cn/CnAlgo.h
src/crypto/cn/CnCtx.h
src/crypto/cn/CnHash.h src/crypto/cn/CnHash.h
src/crypto/cn/CryptoNight_monero.h src/crypto/cn/CryptoNight_monero.h
src/crypto/cn/CryptoNight_test.h src/crypto/cn/CryptoNight_test.h
@ -100,6 +101,7 @@ set(SOURCES_CRYPTO
src/crypto/cn/c_groestl.c src/crypto/cn/c_groestl.c
src/crypto/cn/c_jh.c src/crypto/cn/c_jh.c
src/crypto/cn/c_skein.c src/crypto/cn/c_skein.c
src/crypto/cn/CnCtx.cpp
src/crypto/cn/CnHash.cpp src/crypto/cn/CnHash.cpp
src/crypto/common/Algorithm.cpp src/crypto/common/Algorithm.cpp
src/crypto/common/keccak.cpp src/crypto/common/keccak.cpp

View file

@ -24,59 +24,8 @@
*/ */
#include <limits>
#include "crypto/cn/CryptoNight.h"
#include "crypto/common/portable/mm_malloc.h"
#include "crypto/common/VirtualMemory.h"
#include "Mem.h" #include "Mem.h"
bool Mem::m_enabled = true; bool Mem::m_enabled = true;
int Mem::m_flags = 0; int Mem::m_flags = 0;
MemInfo Mem::create(cryptonight_ctx **ctx, const xmrig::Algorithm &algorithm, size_t count)
{
using namespace xmrig;
constexpr CnAlgo<Algorithm::CN_0> props;
MemInfo info;
info.size = props.memory(algorithm.id()) * count;
constexpr const size_t align_size = 2 * 1024 * 1024;
info.size = ((info.size + align_size - 1) / align_size) * align_size;
info.pages = info.size / align_size;
allocate(info, m_enabled);
for (size_t i = 0; i < count; ++i) {
cryptonight_ctx *c = static_cast<cryptonight_ctx *>(_mm_malloc(sizeof(cryptonight_ctx), 4096));
c->memory = info.memory + (i * props.memory(algorithm.id()));
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;
}
return info;
}
void Mem::release(cryptonight_ctx **ctx, size_t count, MemInfo &info)
{
if (info.memory == nullptr) {
return;
}
release(info);
for (size_t i = 0; i < count; ++i) {
_mm_free(ctx[i]);
}
}

View file

@ -56,9 +56,7 @@ public:
Lock = 4 Lock = 4
}; };
static MemInfo create(cryptonight_ctx **ctx, const xmrig::Algorithm &algorithm, size_t count);
static void init(bool enabled); static void init(bool enabled);
static void release(cryptonight_ctx **ctx, size_t count, MemInfo &info);
static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; } static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; }

View file

@ -144,7 +144,7 @@ void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &do
reply.AddMember("kind", APP_KIND, allocator); reply.AddMember("kind", APP_KIND, allocator);
reply.AddMember("ua", StringRef(Platform::userAgent()), allocator); reply.AddMember("ua", StringRef(Platform::userAgent()), allocator);
reply.AddMember("cpu", cpu, allocator); reply.AddMember("cpu", cpu, allocator);
reply.AddMember("hugepages", WorkersLegacy::hugePages() > 0, allocator); reply.AddMember("hugepages", false, allocator); // FIXME hugepages
reply.AddMember("donate_level", m_base->config()->pools().donateLevel(), allocator); reply.AddMember("donate_level", m_base->config()->pools().donateLevel(), allocator);
} }

View file

@ -42,6 +42,7 @@ class Worker : public IWorker
public: public:
Worker(size_t id, int64_t affinity, int priority); Worker(size_t id, int64_t affinity, int priority);
inline const VirtualMemory *memory() const override { return nullptr; }
inline size_t id() const override { return m_id; } inline size_t id() const override { return m_id; }
inline uint64_t hashCount() const override { return m_hashCount.load(std::memory_order_relaxed); } inline uint64_t hashCount() const override { return m_hashCount.load(std::memory_order_relaxed); }
inline uint64_t timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); } inline uint64_t timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); }

View file

@ -32,12 +32,16 @@
namespace xmrig { namespace xmrig {
class VirtualMemory;
class IWorker class IWorker
{ {
public: public:
virtual ~IWorker() = default; virtual ~IWorker() = default;
virtual bool selfTest() = 0; virtual bool selfTest() = 0;
virtual const VirtualMemory *memory() const = 0;
virtual size_t id() const = 0; virtual size_t id() const = 0;
virtual uint64_t hashCount() const = 0; virtual uint64_t hashCount() const = 0;
virtual uint64_t timestamp() const = 0; virtual uint64_t timestamp() const = 0;

View file

@ -136,14 +136,10 @@ void xmrig::CpuBackend::printHashrate(bool details)
void xmrig::CpuBackend::setJob(const Job &job) void xmrig::CpuBackend::setJob(const Job &job)
{ {
LOG_WARN("PROFILE %s %zu", d_ptr->controller->config()->cpu().threads().profileName(job.algorithm()).data(), job.algorithm().memory());
if (d_ptr->isReady(job.algorithm())) { if (d_ptr->isReady(job.algorithm())) {
return; return;
} }
LOG_INFO(GREEN_BOLD_S "INIT");
const CpuConfig &cpu = d_ptr->controller->config()->cpu(); const CpuConfig &cpu = d_ptr->controller->config()->cpu();
const Threads<CpuThread> &threads = cpu.threads(); const Threads<CpuThread> &threads = cpu.threads();
@ -151,7 +147,11 @@ void xmrig::CpuBackend::setJob(const Job &job)
d_ptr->profileName = threads.profileName(job.algorithm()); d_ptr->profileName = threads.profileName(job.algorithm());
d_ptr->threads = threads.get(d_ptr->profileName); d_ptr->threads = threads.get(d_ptr->profileName);
LOG_INFO(BLUE_BG_S " %zu ", d_ptr->threads.size()); LOG_INFO(GREEN_BOLD("CPU") " use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"),
d_ptr->profileName.data(),
d_ptr->threads.size(),
d_ptr->algo.memory() / 1024
);
d_ptr->workers.stop(); d_ptr->workers.stop();

View file

@ -29,8 +29,10 @@
#include "backend/cpu/CpuWorker.h" #include "backend/cpu/CpuWorker.h"
#include "core/Miner.h" #include "core/Miner.h"
#include "crypto/cn/CnCtx.h"
#include "crypto/cn/CryptoNight_test.h" #include "crypto/cn/CryptoNight_test.h"
#include "crypto/common/Nonce.h" #include "crypto/common/Nonce.h"
#include "crypto/common/VirtualMemory.h"
#include "crypto/rx/Rx.h" #include "crypto/rx/Rx.h"
#include "crypto/rx/RxVm.h" #include "crypto/rx/RxVm.h"
#include "net/JobResults.h" #include "net/JobResults.h"
@ -56,18 +58,18 @@ xmrig::CpuWorker<N>::CpuWorker(size_t index, const CpuLaunchData &data) :
m_assembly(data.assembly), m_assembly(data.assembly),
m_hwAES(data.hwAES), m_hwAES(data.hwAES),
m_av(data.av()), m_av(data.av()),
m_miner(data.miner) m_miner(data.miner),
m_ctx()
{ {
if (m_algorithm.family() != Algorithm::RANDOM_X) { m_memory = new VirtualMemory(m_algorithm.memory() * N, data.hugePages);
m_memory = Mem::create(m_ctx, m_algorithm, N);
}
} }
template<size_t N> template<size_t N>
xmrig::CpuWorker<N>::~CpuWorker() xmrig::CpuWorker<N>::~CpuWorker()
{ {
Mem::release(m_ctx, N, m_memory); CnCtx::release(m_ctx, N);
delete m_memory;
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
delete m_vm; delete m_vm;
@ -81,7 +83,7 @@ void xmrig::CpuWorker<N>::allocateRandomX_VM()
{ {
if (!m_vm) { if (!m_vm) {
RxDataset *dataset = Rx::dataset(m_job.currentJob().seedHash(), m_job.currentJob().algorithm()); RxDataset *dataset = Rx::dataset(m_job.currentJob().seedHash(), m_job.currentJob().algorithm());
m_vm = new RxVm(dataset, true, !m_hwAES); m_vm = new RxVm(dataset, m_memory->scratchpad(), !m_hwAES);
} }
} }
#endif #endif
@ -90,6 +92,14 @@ void xmrig::CpuWorker<N>::allocateRandomX_VM()
template<size_t N> template<size_t N>
bool xmrig::CpuWorker<N>::selfTest() bool xmrig::CpuWorker<N>::selfTest()
{ {
# ifdef XMRIG_ALGO_RANDOMX
if (m_algorithm.family() == Algorithm::RANDOM_X) {
return true;
}
# endif
allocateCnCtx();
if (m_algorithm.family() == Algorithm::CN) { if (m_algorithm.family() == Algorithm::CN) {
const bool rc = verify(Algorithm::CN_0, test_output_v0) && const bool rc = verify(Algorithm::CN_0, test_output_v0) &&
verify(Algorithm::CN_1, test_output_v1) && verify(Algorithm::CN_1, test_output_v1) &&
@ -136,12 +146,6 @@ bool xmrig::CpuWorker<N>::selfTest()
} }
# endif # endif
# ifdef XMRIG_ALGO_RANDOMX
if (m_algorithm.family() == Algorithm::RANDOM_X) {
return true;
}
# endif
return false; return false;
} }
@ -172,7 +176,6 @@ void xmrig::CpuWorker<N>::start()
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
if (job.algorithm().family() == Algorithm::RANDOM_X) { if (job.algorithm().family() == Algorithm::RANDOM_X) {
allocateRandomX_VM();
randomx_calculate_hash(m_vm->get(), m_job.blob(), job.size(), m_hash); randomx_calculate_hash(m_vm->get(), m_job.blob(), job.size(), m_hash);
} }
else else
@ -262,10 +265,29 @@ bool CpuWorker<1>::verify2(const Algorithm &algorithm, const uint8_t *referenceV
} // namespace xmrig } // namespace xmrig
template<size_t N>
void xmrig::CpuWorker<N>::allocateCnCtx()
{
if (m_ctx[0] == nullptr) {
CnCtx::create(m_ctx, m_memory->scratchpad(), m_memory->size(), N);
}
}
template<size_t N> template<size_t N>
void xmrig::CpuWorker<N>::consumeJob() void xmrig::CpuWorker<N>::consumeJob()
{ {
m_job.add(m_miner->job(), Nonce::sequence(Nonce::CPU), kReserveCount); m_job.add(m_miner->job(), Nonce::sequence(Nonce::CPU), kReserveCount);
# ifdef XMRIG_ALGO_RANDOMX
if (m_job.currentJob().algorithm().family() == Algorithm::RANDOM_X) {
allocateRandomX_VM();
}
else
# endif
{
allocateCnCtx();
}
} }

View file

@ -48,12 +48,12 @@ public:
CpuWorker(size_t index, const CpuLaunchData &data); CpuWorker(size_t index, const CpuLaunchData &data);
~CpuWorker() override; ~CpuWorker() override;
inline const MemInfo &memory() const { return m_memory; }
protected: protected:
bool selfTest() override; bool selfTest() override;
void start() override; void start() override;
inline const VirtualMemory *memory() const override { return m_memory; }
private: private:
inline cn_hash_fun fn(const Algorithm &algorithm) const { return CnHash::fn(algorithm, m_av, m_assembly); } inline cn_hash_fun fn(const Algorithm &algorithm) const { return CnHash::fn(algorithm, m_av, m_assembly); }
@ -63,6 +63,7 @@ private:
bool verify(const Algorithm &algorithm, const uint8_t *referenceValue); bool verify(const Algorithm &algorithm, const uint8_t *referenceValue);
bool verify2(const Algorithm &algorithm, const uint8_t *referenceValue); bool verify2(const Algorithm &algorithm, const uint8_t *referenceValue);
void allocateCnCtx();
void consumeJob(); void consumeJob();
const Algorithm m_algorithm; const Algorithm m_algorithm;
@ -71,8 +72,8 @@ private:
const CnHash::AlgoVariant m_av; const CnHash::AlgoVariant m_av;
const Miner *m_miner; const Miner *m_miner;
cryptonight_ctx *m_ctx[N]; cryptonight_ctx *m_ctx[N];
MemInfo m_memory;
uint8_t m_hash[N * 32]; uint8_t m_hash[N * 32];
VirtualMemory *m_memory = nullptr;
WorkerJob<N> m_job; WorkerJob<N> m_job;
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX

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 class VirtualMemory
{ {
public: 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 *allocateExecutableMemory(size_t size);
static void *allocateLargePagesMemory(size_t size); static void *allocateLargePagesMemory(size_t size);
static void flushInstructionCache(void *p, 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 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; } 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 <sys/mman.h>
#include "crypto/common/portable/mm_malloc.h"
#include "crypto/common/VirtualMemory.h" #include "crypto/common/VirtualMemory.h"
@ -37,6 +38,47 @@
#endif #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) void *xmrig::VirtualMemory::allocateExecutableMemory(size_t size)
{ {

View file

@ -32,6 +32,37 @@
#include "crypto/common/VirtualMemory.h" #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) void *xmrig::VirtualMemory::allocateExecutableMemory(size_t size)
{ {
return VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); return VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

View file

@ -345,7 +345,7 @@ extern "C" {
delete dataset; 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 || (flags & RANDOMX_FLAG_FULL_MEM));
assert(cache == nullptr || cache->isInitialized()); assert(cache == nullptr || cache->isInitialized());
assert(dataset != nullptr || !(flags & RANDOMX_FLAG_FULL_MEM)); assert(dataset != nullptr || !(flags & RANDOMX_FLAG_FULL_MEM));
@ -353,7 +353,7 @@ extern "C" {
randomx_vm *vm = nullptr; randomx_vm *vm = nullptr;
try { 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: case RANDOMX_FLAG_DEFAULT:
vm = new randomx::InterpretedLightVmDefault(); vm = new randomx::InterpretedLightVmDefault();
break; break;
@ -386,49 +386,19 @@ extern "C" {
vm = new randomx::CompiledVmHardAes(); vm = new randomx::CompiledVmHardAes();
break; 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: default:
UNREACHABLE; UNREACHABLE;
} }
if(cache != nullptr) if (cache != nullptr) {
vm->setCache(cache); vm->setCache(cache);
}
if(dataset != nullptr) if (dataset != nullptr) {
vm->setDataset(dataset); vm->setDataset(dataset);
}
vm->allocate(); vm->setScratchpad(scratchpad);
} }
catch (std::exception &ex) { catch (std::exception &ex) {
delete vm; 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 * (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 * (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 * 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 { namespace randomx {
alignas(16) volatile static rx_vec_i128 aesDummy; template<bool softAes>
VmBase<softAes>::~VmBase() {
template<class Allocator, bool softAes>
VmBase<Allocator, softAes>::~VmBase() {
Allocator::freeMemory(scratchpad, RANDOMX_SCRATCHPAD_L3_MAX_SIZE);
} }
template<class Allocator, bool softAes> template<bool softAes>
void VmBase<Allocator, softAes>::allocate() { void VmBase<softAes>::setScratchpad(uint8_t *scratchpad) {
if (datasetPtr == nullptr) if (datasetPtr == nullptr) {
throw std::invalid_argument("Cache/Dataset not set"); 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);
} }
template<class Allocator, bool softAes> this->scratchpad = scratchpad;
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); hashAes1Rx4<softAes>(scratchpad, ScratchpadSize, &reg.a);
blake2b(out, outSize, &reg, sizeof(RegisterFile), nullptr, 0); blake2b(out, outSize, &reg, sizeof(RegisterFile), nullptr, 0);
} }
template<class Allocator, bool softAes> template<bool softAes>
void VmBase<Allocator, softAes>::initScratchpad(void* seed) { void VmBase<softAes>::initScratchpad(void* seed) {
fillAes1Rx4<softAes>(seed, ScratchpadSize, scratchpad); fillAes1Rx4<softAes>(seed, ScratchpadSize, scratchpad);
} }
template<class Allocator, bool softAes> template<bool softAes>
void VmBase<Allocator, softAes>::generateProgram(void* seed) { void VmBase<softAes>::generateProgram(void* seed) {
fillAes4Rx4<softAes>(seed, sizeof(program), &program); fillAes4Rx4<softAes>(seed, sizeof(program), &program);
} }
template class VmBase<AlignedAllocator<CacheLineSize>, false>; template class VmBase<false>;
template class VmBase<AlignedAllocator<CacheLineSize>, true>; template class VmBase<true>;
template class VmBase<LargePageAllocator, false>;
template class VmBase<LargePageAllocator, true>;
} }

View file

@ -33,26 +33,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "program.hpp" #include "program.hpp"
/* Global namespace for C binding */ /* Global namespace for C binding */
class randomx_vm { class randomx_vm
{
public: public:
virtual ~randomx_vm() = 0; 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 getFinalResult(void* out, size_t outSize) = 0;
virtual void setDataset(randomx_dataset* dataset) { } virtual void setDataset(randomx_dataset* dataset) { }
virtual void setCache(randomx_cache* cache) { } virtual void setCache(randomx_cache* cache) { }
virtual void initScratchpad(void* seed) = 0; virtual void initScratchpad(void* seed) = 0;
virtual void run(void* seed) = 0; virtual void run(void* seed) = 0;
void resetRoundingMode(); void resetRoundingMode();
randomx::RegisterFile *getRegisterFile() { randomx::RegisterFile *getRegisterFile() {
return &reg; return &reg;
} }
const void* getScratchpad() { const void* getScratchpad() {
return scratchpad; return scratchpad;
} }
const randomx::Program& getProgram() const randomx::Program& getProgram()
{ {
return program; return program;
} }
protected: protected:
void initialize(); void initialize();
alignas(64) randomx::Program program; alignas(64) randomx::Program program;
@ -69,13 +74,15 @@ protected:
namespace randomx { namespace randomx {
template<class Allocator, bool softAes> template<bool softAes>
class VmBase : public randomx_vm { class VmBase : public randomx_vm
{
public: public:
~VmBase() override; ~VmBase() override;
void allocate() override; void setScratchpad(uint8_t *scratchpad) override;
void initScratchpad(void* seed) override; void initScratchpad(void* seed) override;
void getFinalResult(void* out, size_t outSize) override; void getFinalResult(void* out, size_t outSize) override;
protected: protected:
void generateProgram(void* seed); 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(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"); static_assert(sizeof(RegisterFile) == 256, "Invalid alignment of struct randomx::RegisterFile");
template<class Allocator, bool softAes> template<bool softAes>
void CompiledVm<Allocator, softAes>::setDataset(randomx_dataset* dataset) { void CompiledVm<softAes>::setDataset(randomx_dataset* dataset) {
datasetPtr = dataset; datasetPtr = dataset;
} }
template<class Allocator, bool softAes> template<bool softAes>
void CompiledVm<Allocator, softAes>::run(void* seed) { void CompiledVm<softAes>::run(void* seed) {
VmBase<Allocator, softAes>::generateProgram(seed); VmBase<softAes>::generateProgram(seed);
randomx_vm::initialize(); randomx_vm::initialize();
compiler.generateProgram(program, config); compiler.generateProgram(program, config);
mem.memory = datasetPtr->memory + datasetOffset; mem.memory = datasetPtr->memory + datasetOffset;
execute(); execute();
} }
template<class Allocator, bool softAes> template<bool softAes>
void CompiledVm<Allocator, softAes>::execute() { void CompiledVm<softAes>::execute() {
compiler.getProgramFunc()(reg, mem, scratchpad, RandomX_CurrentConfig.ProgramIterations); compiler.getProgramFunc()(reg, mem, scratchpad, RandomX_CurrentConfig.ProgramIterations);
} }
template class CompiledVm<AlignedAllocator<CacheLineSize>, false>; template class CompiledVm<false>;
template class CompiledVm<AlignedAllocator<CacheLineSize>, true>; template class CompiledVm<true>;
template class CompiledVm<LargePageAllocator, false>;
template class CompiledVm<LargePageAllocator, true>;
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -31,12 +31,8 @@
#include "crypto/rx/RxVm.h" #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) { if (!softAes) {
m_flags |= RANDOMX_FLAG_HARD_AES; 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_flags |= RANDOMX_FLAG_JIT;
} }
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);
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());
}
} }

View file

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

View file

@ -67,24 +67,24 @@ xmrig::Controller *WorkersLegacy::m_controller = nullptr;
//} //}
size_t WorkersLegacy::hugePages() //size_t WorkersLegacy::hugePages()
{ //{
uv_mutex_lock(&m_mutex); // uv_mutex_lock(&m_mutex);
const size_t hugePages = m_status.hugePages; // const size_t hugePages = m_status.hugePages;
uv_mutex_unlock(&m_mutex); // uv_mutex_unlock(&m_mutex);
return hugePages; // return hugePages;
} //}
size_t WorkersLegacy::threads() //size_t WorkersLegacy::threads()
{ //{
uv_mutex_lock(&m_mutex); // uv_mutex_lock(&m_mutex);
const size_t threads = m_status.threads; // const size_t threads = m_status.threads;
uv_mutex_unlock(&m_mutex); // uv_mutex_unlock(&m_mutex);
return threads; // return threads;
} //}
//void Workers::pause() //void Workers::pause()
@ -186,24 +186,24 @@ void WorkersLegacy::start(xmrig::Controller *controller)
//} //}
#ifdef XMRIG_FEATURE_API //#ifdef XMRIG_FEATURE_API
void WorkersLegacy::threadsSummary(rapidjson::Document &doc) //void WorkersLegacy::threadsSummary(rapidjson::Document &doc)
{ //{
uv_mutex_lock(&m_mutex); // uv_mutex_lock(&m_mutex);
const uint64_t pages[2] = { m_status.hugePages, m_status.pages }; // const uint64_t pages[2] = { m_status.hugePages, m_status.pages };
const uint64_t memory = m_status.ways * xmrig::CnAlgo<>::memory(m_status.algo); // const uint64_t memory = m_status.ways * xmrig::CnAlgo<>::memory(m_status.algo);
uv_mutex_unlock(&m_mutex); // uv_mutex_unlock(&m_mutex);
auto &allocator = doc.GetAllocator(); // auto &allocator = doc.GetAllocator();
rapidjson::Value hugepages(rapidjson::kArrayType); // rapidjson::Value hugepages(rapidjson::kArrayType);
hugepages.PushBack(pages[0], allocator); // hugepages.PushBack(pages[0], allocator);
hugepages.PushBack(pages[1], allocator); // hugepages.PushBack(pages[1], allocator);
doc.AddMember("hugepages", hugepages, allocator); // doc.AddMember("hugepages", hugepages, allocator);
doc.AddMember("memory", memory, allocator); // doc.AddMember("memory", memory, allocator);
} //}
#endif //#endif
//void WorkersLegacy::onTick(uv_timer_t *) //void WorkersLegacy::onTick(uv_timer_t *)

View file

@ -55,8 +55,8 @@ namespace xmrig {
class WorkersLegacy class WorkersLegacy
{ {
public: public:
static size_t hugePages(); // static size_t hugePages();
static size_t threads(); // static size_t threads();
// static void pause(); // static void pause();
// static void printHashrate(bool detail); // static void printHashrate(bool detail);
// static void setEnabled(bool enabled); // static void setEnabled(bool enabled);
@ -68,9 +68,9 @@ public:
// static inline bool isEnabled() { return m_enabled; } // static inline bool isEnabled() { return m_enabled; }
// static inline Hashrate *hashrate() { return m_hashrate; } // static inline Hashrate *hashrate() { return m_hashrate; }
# ifdef XMRIG_FEATURE_API //# ifdef XMRIG_FEATURE_API
static void threadsSummary(rapidjson::Document &doc); // static void threadsSummary(rapidjson::Document &doc);
# endif //# endif
private: private:
// static void onReady(void *arg); // static void onReady(void *arg);