Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/dataset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,10 @@ namespace randomx {

void initCacheCompile(randomx_cache* cache, const void* key, size_t keySize) {
initCache(cache, key, keySize);
cache->jit->enableWriting();
cache->jit->generateSuperscalarHash(cache->programs, cache->reciprocalCache);
cache->jit->generateDatasetInitCode();
cache->jit->enableExecution();
}

constexpr uint64_t superscalarMul0 = 6364136223846793005ULL;
Expand Down
14 changes: 13 additions & 1 deletion src/jit_compiler_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ namespace randomx {
}

JitCompilerX86::JitCompilerX86() {
code = (uint8_t*)allocExecutableMemory(CodeSize);
code = (uint8_t*)allocMemoryPages(CodeSize);
memcpy(code, codePrologue, prologueSize);
memcpy(code + epilogueOffset, codeEpilogue, epilogueSize);
}
Expand All @@ -227,6 +227,18 @@ namespace randomx {
freePagedMemory(code, CodeSize);
}

void JitCompilerX86::enableAll() {
setPagesRWX(code, CodeSize);
}

void JitCompilerX86::enableWriting() {
setPagesRW(code, CodeSize);
}

void JitCompilerX86::enableExecution() {
setPagesRX(code, CodeSize);
}

void JitCompilerX86::generateProgram(Program& prog, ProgramConfiguration& pcfg) {
generateProgramPrologue(prog, pcfg);
memcpy(code + codePos, codeReadDataset, readDatasetSize);
Expand Down
3 changes: 3 additions & 0 deletions src/jit_compiler_x86.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ namespace randomx {
return code;
}
size_t getCodeSize();
void enableWriting();
void enableExecution();
void enableAll();
private:
static InstructionGeneratorX86 engine[256];
std::vector<int32_t> instructionOffsets;
Expand Down
56 changes: 48 additions & 8 deletions src/randomx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,21 @@ extern "C" {
break;

case RANDOMX_FLAG_JIT:
vm = new randomx::CompiledLightVmDefault();
if (flags & RANDOMX_FLAG_SECURE) {
vm = new randomx::CompiledLightVmDefaultSecure();
}
else {
vm = new randomx::CompiledLightVmDefault();
}
break;

case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT:
vm = new randomx::CompiledVmDefault();
if (flags & RANDOMX_FLAG_SECURE) {
vm = new randomx::CompiledVmDefaultSecure();
}
else {
vm = new randomx::CompiledVmDefault();
}
break;

case RANDOMX_FLAG_HARD_AES:
Expand All @@ -191,11 +201,21 @@ extern "C" {
break;

case RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES:
vm = new randomx::CompiledLightVmHardAes();
if (flags & RANDOMX_FLAG_SECURE) {
vm = new randomx::CompiledLightVmHardAesSecure();
}
else {
vm = new randomx::CompiledLightVmHardAes();
}
break;

case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES:
vm = new randomx::CompiledVmHardAes();
if (flags & RANDOMX_FLAG_SECURE) {
vm = new randomx::CompiledVmHardAesSecure();
}
else {
vm = new randomx::CompiledVmHardAes();
}
break;

case RANDOMX_FLAG_LARGE_PAGES:
Expand All @@ -207,11 +227,21 @@ extern "C" {
break;

case RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::CompiledLightVmLargePage();
if (flags & RANDOMX_FLAG_SECURE) {
vm = new randomx::CompiledLightVmLargePageSecure();
}
else {
vm = new randomx::CompiledLightVmLargePage();
}
break;

case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::CompiledVmLargePage();
if (flags & RANDOMX_FLAG_SECURE) {
vm = new randomx::CompiledVmLargePageSecure();
}
else {
vm = new randomx::CompiledVmLargePage();
}
break;

case RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES:
Expand All @@ -223,11 +253,21 @@ extern "C" {
break;

case RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES:
vm = new randomx::CompiledLightVmLargePageHardAes();
if (flags & RANDOMX_FLAG_SECURE) {
vm = new randomx::CompiledLightVmLargePageHardAesSecure();
}
else {
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();
if (flags & RANDOMX_FLAG_SECURE) {
vm = new randomx::CompiledVmLargePageHardAesSecure();
}
else {
vm = new randomx::CompiledVmLargePageHardAes();
}
break;

default:
Expand Down
7 changes: 5 additions & 2 deletions src/randomx.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ typedef enum {
RANDOMX_FLAG_HARD_AES = 2,
RANDOMX_FLAG_FULL_MEM = 4,
RANDOMX_FLAG_JIT = 8,
RANDOMX_FLAG_SECURE = 16
} randomx_flags;

typedef struct randomx_dataset randomx_dataset;
Expand Down Expand Up @@ -135,12 +136,14 @@ RANDOMX_EXPORT void randomx_release_dataset(randomx_dataset *dataset);
/**
* Creates and initializes a RandomX virtual machine.
*
* @param flags is any combination of these 4 flags (each flag can be set or not set):
* @param flags is any combination of these 5 flags (each flag can be set or not set):
* RANDOMX_FLAG_LARGE_PAGES - allocate scratchpad memory in large pages
* RANDOMX_FLAG_HARD_AES - virtual machine will use hardware accelerated AES
* RANDOMX_FLAG_FULL_MEM - virtual machine will use the full dataset
* RANDOMX_FLAG_JIT - virtual machine will use a JIT compiler
* The numeric values of the flags are ordered so that a higher value will provide
* RANDOMX_FLAG_SECURE - when combined with RANDOMX_FLAG_JIT, the JIT pages are never
* writable and executable at the same time (W^X policy)
* The numeric values of the first 4 flags are ordered so that a higher value will provide
* faster hash calculation and a lower numeric value will provide higher portability.
* Using RANDOMX_FLAG_DEFAULT (all flags not set) works on all platforms, but is the slowest.
* @param cache is a pointer to an initialized randomx_cache structure. Can be
Expand Down
11 changes: 9 additions & 2 deletions src/tests/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ void printUsage(const char* executable) {
std::cout << " --mine mining mode: 2080 MiB" << std::endl;
std::cout << " --verify verification mode: 256 MiB" << std::endl;
std::cout << " --jit x86-64 JIT compiled mode (default: interpreter)" << std::endl;
std::cout << " --secure W^X policy for JIT pages (default: off)" << std::endl;
std::cout << " --largePages use large pages" << std::endl;
std::cout << " --softAes use software AES (default: x86 AES-NI)" << std::endl;
std::cout << " --threads T use T threads (default: 1)" << std::endl;
Expand Down Expand Up @@ -126,7 +127,7 @@ void mine(randomx_vm* vm, std::atomic<uint32_t>& atomicNonce, AtomicHash& result
}

int main(int argc, char** argv) {
bool softAes, miningMode, verificationMode, help, largePages, jit;
bool softAes, miningMode, verificationMode, help, largePages, jit, secure;
int noncesCount, threadCount, initThreadCount;
uint64_t threadAffinity;
int32_t seedValue;
Expand All @@ -143,6 +144,7 @@ int main(int argc, char** argv) {
readOption("--largePages", argc, argv, largePages);
readOption("--jit", argc, argv, jit);
readOption("--help", argc, argv, help);
readOption("--secure", argc, argv, secure);

store32(&seed, seedValue);

Expand Down Expand Up @@ -171,7 +173,12 @@ int main(int argc, char** argv) {

if (jit) {
flags = (randomx_flags)(flags | RANDOMX_FLAG_JIT);
std::cout << " - JIT compiled mode" << std::endl;
std::cout << " - JIT compiled mode ";
if (secure) {
flags = (randomx_flags)(flags | RANDOMX_FLAG_SECURE);
std::cout << "(secure)";
}
std::cout << std::endl;
}
else {
std::cout << " - interpreted mode" << std::endl;
Expand Down
38 changes: 33 additions & 5 deletions src/virtual_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
#define PAGE_READONLY PROT_READ
#define PAGE_READWRITE (PROT_READ | PROT_WRITE)
#define PAGE_EXECUTE_READ (PROT_READ | PROT_EXEC)
#define PAGE_EXECUTE_READWRITE (PROT_READ | PROT_WRITE | PROT_EXEC)
#endif

#if defined(_WIN32) || defined(__CYGWIN__)
Expand Down Expand Up @@ -83,20 +87,44 @@ void setPrivilege(const char* pszPrivilege, BOOL bEnable) {
}
#endif

void* allocExecutableMemory(std::size_t bytes) {
void* allocMemoryPages(std::size_t bytes) {
void* mem;
#if defined(_WIN32) || defined(__CYGWIN__)
mem = VirtualAlloc(nullptr, bytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
mem = VirtualAlloc(nullptr, bytes, MEM_COMMIT, PAGE_READWRITE);
if (mem == nullptr)
throw std::runtime_error(getErrorMessage("allocExecutableMemory - VirtualAlloc"));
throw std::runtime_error(getErrorMessage("allocMemoryPages - VirtualAlloc"));
#else
mem = mmap(nullptr, bytes, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
mem = mmap(nullptr, bytes, PAGE_READWRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (mem == MAP_FAILED)
throw std::runtime_error("allocExecutableMemory - mmap failed");
throw std::runtime_error("allocMemoryPages - mmap failed");
#endif
return mem;
}

static inline void pageProtect(void* ptr, std::size_t bytes, int rules) {
#if defined(_WIN32) || defined(__CYGWIN__)
DWORD oldp;
if (!VirtualProtect(ptr, bytes, (DWORD)rules, &oldp)) {
throw std::runtime_error(getErrorMessage("VirtualProtect"));
}
#else
if (-1 == mprotect(ptr, bytes, rules))
throw std::runtime_error("mprotect failed");
#endif
}

void setPagesRW(void* ptr, std::size_t bytes) {
pageProtect(ptr, bytes, PAGE_READWRITE);
}

void setPagesRX(void* ptr, std::size_t bytes) {
pageProtect(ptr, bytes, PAGE_EXECUTE_READ);
}

void setPagesRWX(void* ptr, std::size_t bytes) {
pageProtect(ptr, bytes, PAGE_EXECUTE_READWRITE);
}

void* allocLargePagesMemory(std::size_t bytes) {
void* mem;
#if defined(_WIN32) || defined(__CYGWIN__)
Expand Down
5 changes: 4 additions & 1 deletion src/virtual_memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ constexpr std::size_t alignSize(std::size_t pos, std::size_t align) {
return ((pos - 1) / align + 1) * align;
}

void* allocExecutableMemory(std::size_t);
void* allocMemoryPages(std::size_t);
void setPagesRW(void*, std::size_t);
void setPagesRX(void*, std::size_t);
void setPagesRWX(void*, std::size_t);
void* allocLargePagesMemory(std::size_t);
void freePagedMemory(void*, std::size_t);
37 changes: 27 additions & 10 deletions src/vm_compiled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,44 @@ 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<class Allocator, bool softAes, bool secureJit>
CompiledVm<Allocator, softAes, secureJit>::CompiledVm() {
if (!secureJit) {
compiler.enableAll(); //make JIT buffer both writable and executable
}
}

template<class Allocator, bool softAes, bool secureJit>
void CompiledVm<Allocator, softAes, secureJit>::setDataset(randomx_dataset* dataset) {
datasetPtr = dataset;
}

template<class Allocator, bool softAes>
void CompiledVm<Allocator, softAes>::run(void* seed) {
template<class Allocator, bool softAes, bool secureJit>
void CompiledVm<Allocator, softAes, secureJit>::run(void* seed) {
VmBase<Allocator, softAes>::generateProgram(seed);
randomx_vm::initialize();
if (secureJit) {
compiler.enableWriting();
}
compiler.generateProgram(program, config);
if (secureJit) {
compiler.enableExecution();
}
mem.memory = datasetPtr->memory + datasetOffset;
execute();
}

template<class Allocator, bool softAes>
void CompiledVm<Allocator, softAes>::execute() {
template<class Allocator, bool softAes, bool secureJit>
void CompiledVm<Allocator, softAes, secureJit>::execute() {
compiler.getProgramFunc()(reg, mem, scratchpad, RANDOMX_PROGRAM_ITERATIONS);
}

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<AlignedAllocator<CacheLineSize>, false, false>;
template class CompiledVm<AlignedAllocator<CacheLineSize>, true, false>;
template class CompiledVm<LargePageAllocator, false, false>;
template class CompiledVm<LargePageAllocator, true, false>;
template class CompiledVm<AlignedAllocator<CacheLineSize>, false, true>;
template class CompiledVm<AlignedAllocator<CacheLineSize>, true, true>;
template class CompiledVm<LargePageAllocator, false, true>;
template class CompiledVm<LargePageAllocator, true, true>;
}
15 changes: 10 additions & 5 deletions src/vm_compiled.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

namespace randomx {

template<class Allocator, bool softAes>
template<class Allocator, bool softAes, bool secureJit>
class CompiledVm : public VmBase<Allocator, softAes> {
public:
void* operator new(size_t size) {
Expand All @@ -49,6 +49,7 @@ namespace randomx {
void operator delete(void* ptr) {
AlignedAllocator<CacheLineSize>::freeMemory(ptr, sizeof(CompiledVm));
}
CompiledVm();
void setDataset(randomx_dataset* dataset) override;
void run(void* seed) override;

Expand All @@ -65,8 +66,12 @@ namespace randomx {
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<AlignedAllocator<CacheLineSize>, true, false>;
using CompiledVmHardAes = CompiledVm<AlignedAllocator<CacheLineSize>, false, false>;
using CompiledVmLargePage = CompiledVm<LargePageAllocator, true, false>;
using CompiledVmLargePageHardAes = CompiledVm<LargePageAllocator, false, false>;
using CompiledVmDefaultSecure = CompiledVm<AlignedAllocator<CacheLineSize>, true, true>;
using CompiledVmHardAesSecure = CompiledVm<AlignedAllocator<CacheLineSize>, false, true>;
using CompiledVmLargePageSecure = CompiledVm<LargePageAllocator, true, true>;
using CompiledVmLargePageHardAesSecure = CompiledVm<LargePageAllocator, false, true>;
}
Loading