Fix for 1st-gen Ryzen crashes

This commit is contained in:
SChernykh 2019-12-27 12:40:38 +02:00
parent 99826a6b51
commit 3a2941b719
10 changed files with 102 additions and 9 deletions

View file

@ -74,6 +74,7 @@ bool xmrig::Rx::init(const Job &job, const RxConfig &config, const CpuConfig &cp
if (!osInitialized) {
msrInit(config);
SetupMainLoopExceptionFrame();
osInitialized = true;
}

View file

@ -57,9 +57,20 @@ public:
static void destroy();
static void init(IRxListener *listener);
static void setMainLoopBounds(const void* loopBegin, const void* loopEnd)
{
mainLoopBounds.first = loopBegin;
mainLoopBounds.second = loopEnd;
}
static const std::pair<const void*, const void*>& getMainLoopBounds() { return mainLoopBounds; }
private:
static void msrInit(const RxConfig &config);
static void msrDestroy();
static void SetupMainLoopExceptionFrame();
static thread_local std::pair<const void*, const void*> mainLoopBounds;
};

View file

@ -43,6 +43,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <ucontext.h>
namespace xmrig {
@ -178,6 +180,29 @@ static bool wrmsr(const MsrItems &preset, bool save)
}
static void MainLoopHandler(int sig, siginfo_t *info, void *ucontext)
{
# if defined(__x86_64__) || defined(__amd64__)
ucontext_t *ucp = (ucontext_t*) ucontext;
LOG_INFO(YELLOW_BOLD("%s at %p"), (sig == SIGSEGV) ? "SIGSEGV" : "SIGILL", ucp->uc_mcontext.gregs[REG_RIP]);
void* p = reinterpret_cast<void*>(ucp->uc_mcontext.gregs[REG_RIP]);
const std::pair<const void*, const void*>& loopBounds = xmrig::Rx::getMainLoopBounds();
if ((loopBounds.first <= p) && (p < loopBounds.second)) {
ucp->uc_mcontext.gregs[REG_RIP] = reinterpret_cast<size_t>(loopBounds.second);
}
else {
abort();
}
# endif
}
thread_local std::pair<const void*, const void*> Rx::mainLoopBounds = { nullptr, nullptr };
} // namespace xmrig
@ -208,3 +233,16 @@ void xmrig::Rx::msrDestroy()
LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts);
}
}
void xmrig::Rx::SetupMainLoopExceptionFrame()
{
# if defined(__x86_64__) || defined(__amd64__)
struct sigaction act = {};
act.sa_sigaction = MainLoopHandler;
act.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGSEGV, &act, nullptr);
sigaction(SIGILL, &act, nullptr);
# endif
}

View file

@ -303,6 +303,37 @@ static bool wrmsr(const MsrItems &preset, bool save)
}
static LONG WINAPI MainLoopHandler(_EXCEPTION_POINTERS *ExceptionInfo)
{
if (ExceptionInfo->ExceptionRecord->ExceptionCode == 0xC0000005) {
const char* accessType;
switch (ExceptionInfo->ExceptionRecord->ExceptionInformation[0]) {
case 0: accessType = "read"; break;
case 1: accessType = "write"; break;
case 8: accessType = "DEP violation"; break;
default: accessType = "unknown"; break;
}
LOG_INFO(YELLOW_BOLD("[THREAD %u] Access violation at 0x%p: %s at address 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionAddress, accessType, ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
}
else {
LOG_INFO(YELLOW_BOLD("[THREAD %u] Exception 0x%08X at 0x%p"), GetCurrentThreadId(), ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
}
void* p = reinterpret_cast<void*>(ExceptionInfo->ContextRecord->Rip);
const std::pair<const void*, const void*>& loopBounds = xmrig::Rx::getMainLoopBounds();
if ((loopBounds.first <= p) && (p < loopBounds.second)) {
ExceptionInfo->ContextRecord->Rip = reinterpret_cast<DWORD64>(loopBounds.second);
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
thread_local std::pair<const void*, const void*> Rx::mainLoopBounds = { nullptr, nullptr };
} // namespace xmrig
@ -333,3 +364,9 @@ void xmrig::Rx::msrDestroy()
LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts);
}
}
void xmrig::Rx::SetupMainLoopExceptionFrame()
{
AddVectoredExceptionHandler(1, MainLoopHandler);
}