From 4b617ab7bdb5a72c3303ed3b1904f9ffc9730cd7 Mon Sep 17 00:00:00 2001 From: Richard Diamond Date: Sat, 30 Nov 2019 19:06:11 -0600 Subject: [PATCH] Fix 1st gen AMD Ryzen segfault issue. XMRig wasn't clearing the cache after codegen, causing this issue due to a stale instruction cache. Oddly, this issue never occurred on my 1950x, only my 1800x. --- src/crypto/common/VirtualMemory_unix.cpp | 8 ++++++++ src/crypto/randomx/jit_compiler_x86.cpp | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/src/crypto/common/VirtualMemory_unix.cpp b/src/crypto/common/VirtualMemory_unix.cpp index 3d099c76..74a050cf 100644 --- a/src/crypto/common/VirtualMemory_unix.cpp +++ b/src/crypto/common/VirtualMemory_unix.cpp @@ -69,11 +69,19 @@ void *xmrig::VirtualMemory::allocateLargePagesMemory(size_t size) return mem == MAP_FAILED ? nullptr : mem; } +# ifndef HAVE_BUILTIN_CLEAR_CACHE +// Even though Clang doesn't provide __builtin___clear_cache, compiler-rt, +// which is part of the LLVM project, still defines this function, same as libgcc. +// So calling this should do the same thing as the builtin. +extern "C" void __clear_cache(void* start, void* end); +# endif void xmrig::VirtualMemory::flushInstructionCache(void *p, size_t size) { # ifdef HAVE_BUILTIN_CLEAR_CACHE __builtin___clear_cache(reinterpret_cast(p), reinterpret_cast(p) + size); +# else + __clear_cache(p, (void*)((char*)p + size)); # endif } diff --git a/src/crypto/randomx/jit_compiler_x86.cpp b/src/crypto/randomx/jit_compiler_x86.cpp index 2a342535..157d3e98 100644 --- a/src/crypto/randomx/jit_compiler_x86.cpp +++ b/src/crypto/randomx/jit_compiler_x86.cpp @@ -29,6 +29,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include "crypto/common/VirtualMemory.h" #include "crypto/randomx/jit_compiler_x86.hpp" #include "crypto/randomx/jit_compiler_x86_static.hpp" #include "crypto/randomx/superscalar.hpp" @@ -218,6 +219,7 @@ namespace randomx { memcpy(code + codePos, RandomX_CurrentConfig.codeReadDatasetTweaked, readDatasetSize); codePos += readDatasetSize; generateProgramEpilogue(prog, pcfg); + xmrig::VirtualMemory::flushInstructionCache(code, getCodeSize()); } void JitCompilerX86::generateProgramLight(Program& prog, ProgramConfiguration& pcfg, uint32_t datasetOffset) { @@ -229,6 +231,7 @@ namespace randomx { emit32(superScalarHashOffset - (codePos + 4), code, codePos); emit(codeReadDatasetLightSshFin, readDatasetLightFinSize, code, codePos); generateProgramEpilogue(prog, pcfg); + xmrig::VirtualMemory::flushInstructionCache(code, getCodeSize()); } template @@ -258,6 +261,7 @@ namespace randomx { } } emitByte(RET, code, codePos); + xmrig::VirtualMemory::flushInstructionCache(code, getCodeSize()); } template @@ -265,6 +269,7 @@ namespace randomx { void JitCompilerX86::generateDatasetInitCode() { memcpy(code, codeDatasetInit, datasetInitSize); + xmrig::VirtualMemory::flushInstructionCache(code, getCodeSize()); } void JitCompilerX86::generateProgramPrologue(Program& prog, ProgramConfiguration& pcfg) {