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_skein.h
src/crypto/cn/CnAlgo.h
src/crypto/cn/CnCtx.h
src/crypto/cn/CnHash.h
src/crypto/cn/CryptoNight_monero.h
src/crypto/cn/CryptoNight_test.h
@ -100,6 +101,7 @@ set(SOURCES_CRYPTO
src/crypto/cn/c_groestl.c
src/crypto/cn/c_jh.c
src/crypto/cn/c_skein.c
src/crypto/cn/CnCtx.cpp
src/crypto/cn/CnHash.cpp
src/crypto/common/Algorithm.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"
bool Mem::m_enabled = true;
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
};
static MemInfo create(cryptonight_ctx **ctx, const xmrig::Algorithm &algorithm, size_t count);
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; }

View file

@ -144,7 +144,7 @@ void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &do
reply.AddMember("kind", APP_KIND, allocator);
reply.AddMember("ua", StringRef(Platform::userAgent()), 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);
}

View file

@ -42,9 +42,10 @@ class Worker : public IWorker
public:
Worker(size_t id, int64_t affinity, int priority);
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 timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); }
inline const VirtualMemory *memory() const override { return nullptr; }
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 timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); }
protected:
void storeStats();

View file

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

View file

@ -136,14 +136,10 @@ void xmrig::CpuBackend::printHashrate(bool details)
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())) {
return;
}
LOG_INFO(GREEN_BOLD_S "INIT");
const CpuConfig &cpu = d_ptr->controller->config()->cpu();
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->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();

View file

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

View file

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

View file

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