This commit is contained in:
commit
eb58aea9c7
48 changed files with 970 additions and 454 deletions
|
@ -113,7 +113,10 @@ static AlgoName const algorithm_names[] = {
|
|||
{ "DefyX", "defyx", Algorithm::DEFYX },
|
||||
{ "randomx/arq", "rx/arq", Algorithm::RX_ARQ },
|
||||
{ "RandomARQ", nullptr, Algorithm::RX_ARQ },
|
||||
{ "RandomV", "rx/v", Algorithm::RX_V },
|
||||
{ "randomx/sfx", "rx/sfx", Algorithm::RX_SFX },
|
||||
{ "RandomSFX", nullptr, Algorithm::RX_SFX },
|
||||
{ "randomx/v", "rx/v", Algorithm::RX_V },
|
||||
{ "RandomV", nullptr, Algorithm::RX_V },
|
||||
# endif
|
||||
# ifdef XMRIG_ALGO_ARGON2
|
||||
{ "argon2/chukwa", nullptr, Algorithm::AR2_CHUKWA },
|
||||
|
@ -141,6 +144,8 @@ size_t xmrig::Algorithm::l2() const
|
|||
case RX_0:
|
||||
case RX_V:
|
||||
case RX_LOKI:
|
||||
case RX_SFX:
|
||||
case RX_V:
|
||||
return 0x40000;
|
||||
|
||||
case RX_WOW:
|
||||
|
@ -180,6 +185,8 @@ size_t xmrig::Algorithm::l3() const
|
|||
case RX_0:
|
||||
case RX_V:
|
||||
case RX_LOKI:
|
||||
case RX_SFX:
|
||||
case RX_V:
|
||||
return oneMiB * 2;
|
||||
|
||||
case RX_WOW:
|
||||
|
@ -284,6 +291,8 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id)
|
|||
case RX_LOKI:
|
||||
case DEFYX:
|
||||
case RX_ARQ:
|
||||
case RX_SFX:
|
||||
case RX_V:
|
||||
return RANDOM_X;
|
||||
# endif
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ public:
|
|||
RX_LOKI, // "rx/loki" RandomXL (Loki).
|
||||
DEFYX, // "defyx" DefyX (Scala).
|
||||
RX_ARQ, // "rx/arq" RandomARQ (Arqma).
|
||||
RX_SFX, // "rx/sfx" RandomSFX (Safex Cash).
|
||||
RX_V, // "rx/v" RandomV (Monerov).
|
||||
AR2_CHUKWA, // "argon2/chukwa" Argon2id (Chukwa).
|
||||
AR2_WRKZ, // "argon2/wrkz" Argon2id (WRKZ)
|
||||
|
|
|
@ -289,6 +289,11 @@ namespace randomx {
|
|||
|
||||
JitCompilerX86::JitCompilerX86() {
|
||||
applyTweaks();
|
||||
|
||||
int32_t info[4];
|
||||
cpuid(1, info);
|
||||
hasAVX = ((info[2] & (1 << 27)) != 0) && ((info[2] & (1 << 28)) != 0);
|
||||
|
||||
allocatedCode = (uint8_t*)allocExecutableMemory(CodeSize * 2);
|
||||
// Shift code base address to improve caching - all threads will use different L2/L3 cache sets
|
||||
code = allocatedCode + (codeOffset.fetch_add(59 * 64) % CodeSize);
|
||||
|
@ -374,6 +379,10 @@ namespace randomx {
|
|||
code[codePos + 5] = 0xc0 + pcfg.readReg1;
|
||||
*(uint32_t*)(code + codePos + 10) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated;
|
||||
*(uint32_t*)(code + codePos + 20) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated;
|
||||
if (hasAVX) {
|
||||
uint32_t* p = (uint32_t*)(code + codePos + 29);
|
||||
*p = (*p & 0xFF000000U) | 0x0077F8C5U;
|
||||
}
|
||||
|
||||
codePos = prologueSize;
|
||||
memcpy(code + codePos - 48, &pcfg.eMask, sizeof(pcfg.eMask));
|
||||
|
|
|
@ -73,6 +73,7 @@ namespace randomx {
|
|||
uint32_t vm_flags;
|
||||
|
||||
static bool BranchesWithin32B;
|
||||
bool hasAVX;
|
||||
|
||||
static void applyTweaks();
|
||||
void generateProgramPrologue(Program&, ProgramConfiguration&);
|
||||
|
|
|
@ -94,6 +94,9 @@ DECL(randomx_program_prologue_first_load):
|
|||
ror rdx, 32
|
||||
and edx, RANDOMX_SCRATCHPAD_MASK
|
||||
stmxcsr dword ptr [rsp-20]
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
jmp DECL(randomx_program_loop_begin)
|
||||
|
||||
.balign 64
|
||||
|
|
|
@ -82,6 +82,9 @@ randomx_program_prologue_first_load PROC
|
|||
ror rdx, 32
|
||||
and edx, RANDOMX_SCRATCHPAD_MASK
|
||||
stmxcsr dword ptr [rsp-20]
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
jmp randomx_program_loop_begin
|
||||
randomx_program_prologue_first_load ENDP
|
||||
|
||||
|
|
|
@ -92,6 +92,11 @@ RandomX_ConfigurationArqma::RandomX_ConfigurationArqma()
|
|||
ScratchpadL3_Size = 262144;
|
||||
}
|
||||
|
||||
RandomX_ConfigurationSafex::RandomX_ConfigurationSafex()
|
||||
{
|
||||
ArgonSalt = "RandomSFX\x01";
|
||||
}
|
||||
|
||||
RandomX_ConfigurationV::RandomX_ConfigurationV()
|
||||
{
|
||||
ArgonSalt = "RandomV\x03";
|
||||
|
@ -272,6 +277,8 @@ RandomX_ConfigurationWownero RandomX_WowneroConfig;
|
|||
RandomX_ConfigurationV RandomX_VConfig;
|
||||
RandomX_ConfigurationLoki RandomX_LokiConfig;
|
||||
RandomX_ConfigurationArqma RandomX_ArqmaConfig;
|
||||
RandomX_ConfigurationSafex RandomX_SafexConfig;
|
||||
RandomX_ConfigurationV RandomX_VConfig;
|
||||
|
||||
RandomX_ConfigurationBase RandomX_CurrentConfig;
|
||||
|
||||
|
|
|
@ -183,12 +183,16 @@ struct RandomX_ConfigurationV : public RandomX_ConfigurationBase { RandomX_Confi
|
|||
struct RandomX_ConfigurationWownero : public RandomX_ConfigurationBase { RandomX_ConfigurationWownero(); };
|
||||
struct RandomX_ConfigurationLoki : public RandomX_ConfigurationBase { RandomX_ConfigurationLoki(); };
|
||||
struct RandomX_ConfigurationArqma : public RandomX_ConfigurationBase { RandomX_ConfigurationArqma(); };
|
||||
struct RandomX_ConfigurationSafex : public RandomX_ConfigurationBase { RandomX_ConfigurationSafex(); };
|
||||
struct RandomX_ConfigurationV : public RandomX_ConfigurationBase { RandomX_ConfigurationV(); };
|
||||
|
||||
extern RandomX_ConfigurationMonero RandomX_MoneroConfig;
|
||||
extern RandomX_ConfigurationV RandomX_VConfig;
|
||||
extern RandomX_ConfigurationWownero RandomX_WowneroConfig;
|
||||
extern RandomX_ConfigurationLoki RandomX_LokiConfig;
|
||||
extern RandomX_ConfigurationArqma RandomX_ArqmaConfig;
|
||||
extern RandomX_ConfigurationSafex RandomX_SafexConfig;
|
||||
extern RandomX_ConfigurationV RandomX_VConfig;
|
||||
|
||||
extern RandomX_ConfigurationBase RandomX_CurrentConfig;
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ bool xmrig::Rx::init(const Job &job, const RxConfig &config, const CpuConfig &cp
|
|||
}
|
||||
|
||||
if (!osInitialized) {
|
||||
osInit(config);
|
||||
msrInit(config);
|
||||
osInitialized = true;
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,10 @@ xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId)
|
|||
|
||||
void xmrig::Rx::destroy()
|
||||
{
|
||||
if (osInitialized) {
|
||||
msrDestroy();
|
||||
}
|
||||
|
||||
delete d_ptr;
|
||||
|
||||
d_ptr = nullptr;
|
||||
|
@ -115,8 +119,16 @@ void xmrig::Rx::init(IRxListener *listener)
|
|||
}
|
||||
|
||||
|
||||
#if (!defined(XMRIG_OS_LINUX) && !defined(_WIN32)) || defined(XMRIG_ARM)
|
||||
void xmrig::Rx::osInit(const RxConfig &)
|
||||
#ifndef XMRIG_FEATURE_MSR
|
||||
void xmrig::Rx::msrInit(const RxConfig &)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void xmrig::Rx::msrDestroy()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,8 @@ public:
|
|||
static void init(IRxListener *listener);
|
||||
|
||||
private:
|
||||
static void osInit(const RxConfig &config);
|
||||
static void msrInit(const RxConfig &config);
|
||||
static void msrDestroy();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -57,6 +57,12 @@ const RandomX_ConfigurationBase *xmrig::RxAlgo::base(Algorithm::Id algorithm)
|
|||
return &RandomX_ScalaConfig;
|
||||
break;
|
||||
|
||||
case Algorithm::RX_SFX:
|
||||
return &RandomX_SafexConfig;
|
||||
|
||||
case Algorithm::RX_V:
|
||||
return &RandomX_VConfig;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,15 @@ public:
|
|||
static uint32_t programIterations(Algorithm::Id algorithm);
|
||||
static uint32_t programSize(Algorithm::Id algorithm);
|
||||
static uint32_t version(Algorithm::Id algorithm);
|
||||
|
||||
static inline Algorithm::Id id(Algorithm::Id algorithm)
|
||||
{
|
||||
if (algorithm == Algorithm::RX_SFX || algorithm == Algorithm::RX_V) {
|
||||
return Algorithm::RX_0;
|
||||
}
|
||||
|
||||
return algorithm;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace xmrig {
|
|||
static const char *kInit = "init";
|
||||
static const char *kMode = "mode";
|
||||
static const char *kOneGbPages = "1gb-pages";
|
||||
static const char *kRdmsr = "rdmsr";
|
||||
static const char *kWrmsr = "wrmsr";
|
||||
|
||||
#ifdef XMRIG_FEATURE_HWLOC
|
||||
|
@ -57,6 +58,23 @@ static const char *kNUMA = "numa";
|
|||
|
||||
static const std::array<const char *, RxConfig::ModeMax> modeNames = { "auto", "fast", "light" };
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_MSR
|
||||
constexpr size_t kMsrArraySize = 4;
|
||||
|
||||
static const std::array<MsrItems, kMsrArraySize> msrPresets = {
|
||||
MsrItems(),
|
||||
MsrItems{{ 0xC0011020, 0x0 }, { 0xC0011021, 0x40, ~0x20ULL }, { 0xC0011022, 0x510000 }, { 0xC001102b, 0x1808cc16 }},
|
||||
MsrItems{{ 0x1a4, 0x6 }},
|
||||
MsrItems()
|
||||
};
|
||||
|
||||
static const std::array<const char *, kMsrArraySize> modNames = { "none", "ryzen", "intel", "custom" };
|
||||
|
||||
static_assert (kMsrArraySize == ICpuInfo::MSR_MOD_MAX, "kMsrArraySize and MSR_MOD_MAX mismatch");
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,7 +83,11 @@ bool xmrig::RxConfig::read(const rapidjson::Value &value)
|
|||
if (value.IsObject()) {
|
||||
m_threads = Json::getInt(value, kInit, m_threads);
|
||||
m_mode = readMode(Json::getValue(value, kMode));
|
||||
m_wrmsr = readMSR(Json::getValue(value, kWrmsr));
|
||||
m_rdmsr = Json::getBool(value, kRdmsr, m_rdmsr);
|
||||
|
||||
# ifdef XMRIG_FEATURE_MSR
|
||||
readMSR(Json::getValue(value, kWrmsr));
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_OS_LINUX
|
||||
m_oneGbPages = Json::getBool(value, kOneGbPages, m_oneGbPages);
|
||||
|
@ -109,13 +131,25 @@ rapidjson::Value xmrig::RxConfig::toJSON(rapidjson::Document &doc) const
|
|||
obj.AddMember(StringRef(kInit), m_threads, allocator);
|
||||
obj.AddMember(StringRef(kMode), StringRef(modeName()), allocator);
|
||||
obj.AddMember(StringRef(kOneGbPages), m_oneGbPages, allocator);
|
||||
obj.AddMember(StringRef(kRdmsr), m_rdmsr, allocator);
|
||||
|
||||
if (m_wrmsr < 0 || m_wrmsr == 6) {
|
||||
obj.AddMember(StringRef(kWrmsr), m_wrmsr == 6, allocator);
|
||||
# ifdef XMRIG_FEATURE_MSR
|
||||
if (!m_msrPreset.empty()) {
|
||||
Value wrmsr(kArrayType);
|
||||
wrmsr.Reserve(m_msrPreset.size(), allocator);
|
||||
|
||||
for (const auto &i : m_msrPreset) {
|
||||
wrmsr.PushBack(i.toJSON(doc), allocator);
|
||||
}
|
||||
|
||||
obj.AddMember(StringRef(kWrmsr), wrmsr, allocator);
|
||||
}
|
||||
else {
|
||||
obj.AddMember(StringRef(kWrmsr), m_wrmsr, allocator);
|
||||
}
|
||||
# else
|
||||
obj.AddMember(StringRef(kWrmsr), false, allocator);
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_FEATURE_HWLOC
|
||||
if (!m_nodeset.empty()) {
|
||||
|
@ -168,20 +202,71 @@ uint32_t xmrig::RxConfig::threads(uint32_t limit) const
|
|||
}
|
||||
|
||||
|
||||
int xmrig::RxConfig::readMSR(const rapidjson::Value &value) const
|
||||
#ifdef XMRIG_FEATURE_MSR
|
||||
const char *xmrig::RxConfig::msrPresetName() const
|
||||
{
|
||||
if (value.IsInt()) {
|
||||
return std::min(value.GetInt(), 15);
|
||||
}
|
||||
|
||||
if (value.IsBool() && !value.GetBool()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return m_wrmsr;
|
||||
return modNames[msrMod()];
|
||||
}
|
||||
|
||||
|
||||
const xmrig::MsrItems &xmrig::RxConfig::msrPreset() const
|
||||
{
|
||||
const auto mod = msrMod();
|
||||
|
||||
if (mod == ICpuInfo::MSR_MOD_CUSTOM) {
|
||||
return m_msrPreset;
|
||||
}
|
||||
|
||||
return msrPresets[mod];
|
||||
}
|
||||
|
||||
|
||||
uint32_t xmrig::RxConfig::msrMod() const
|
||||
{
|
||||
if (!wrmsr()) {
|
||||
return ICpuInfo::MSR_MOD_NONE;
|
||||
}
|
||||
|
||||
if (!m_msrPreset.empty()) {
|
||||
return ICpuInfo::MSR_MOD_CUSTOM;
|
||||
}
|
||||
|
||||
return Cpu::info()->msrMod();
|
||||
}
|
||||
|
||||
|
||||
void xmrig::RxConfig::readMSR(const rapidjson::Value &value)
|
||||
{
|
||||
if (value.IsBool()) {
|
||||
m_wrmsr = value.GetBool();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.IsInt() && Cpu::info()->vendor() == ICpuInfo::VENDOR_INTEL) {
|
||||
const int i = std::min(value.GetInt(), 15);
|
||||
if (i >= 0) {
|
||||
m_msrPreset.emplace_back(0x1a4, i);
|
||||
}
|
||||
else {
|
||||
m_wrmsr = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (value.IsArray()) {
|
||||
for (const auto &i : value.GetArray()) {
|
||||
MsrItem item(i);
|
||||
if (item.isValid()) {
|
||||
m_msrPreset.emplace_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
m_wrmsr = !m_msrPreset.empty();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
xmrig::RxConfig::Mode xmrig::RxConfig::readMode(const rapidjson::Value &value) const
|
||||
{
|
||||
if (value.IsUint()) {
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
#include "rapidjson/fwd.h"
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_MSR
|
||||
# include "crypto/rx/msr/MsrItem.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
@ -58,17 +63,32 @@ public:
|
|||
uint32_t threads(uint32_t limit = 100) const;
|
||||
|
||||
inline bool isOneGbPages() const { return m_oneGbPages; }
|
||||
inline int wrmsr() const { return m_wrmsr; }
|
||||
inline bool rdmsr() const { return m_rdmsr; }
|
||||
inline bool wrmsr() const { return m_wrmsr; }
|
||||
inline Mode mode() const { return m_mode; }
|
||||
|
||||
# ifdef XMRIG_FEATURE_MSR
|
||||
const char *msrPresetName() const;
|
||||
const MsrItems &msrPreset() const;
|
||||
# endif
|
||||
|
||||
private:
|
||||
int readMSR(const rapidjson::Value &value) const;
|
||||
# ifdef XMRIG_FEATURE_MSR
|
||||
uint32_t msrMod() const;
|
||||
void readMSR(const rapidjson::Value &value);
|
||||
|
||||
bool m_wrmsr = true;
|
||||
MsrItems m_msrPreset;
|
||||
# else
|
||||
bool m_wrmsr = false;
|
||||
# endif
|
||||
|
||||
Mode readMode(const rapidjson::Value &value) const;
|
||||
|
||||
bool m_numa = true;
|
||||
bool m_oneGbPages = false;
|
||||
bool m_rdmsr = true;
|
||||
int m_threads = -1;
|
||||
int m_wrmsr = 6;
|
||||
Mode m_mode = AutoMode;
|
||||
|
||||
# ifdef XMRIG_FEATURE_HWLOC
|
||||
|
|
|
@ -48,16 +48,8 @@
|
|||
namespace xmrig {
|
||||
|
||||
|
||||
enum MsrMod : uint32_t {
|
||||
MSR_MOD_NONE,
|
||||
MSR_MOD_RYZEN,
|
||||
MSR_MOD_INTEL,
|
||||
MSR_MOD_MAX
|
||||
};
|
||||
|
||||
|
||||
static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " ";
|
||||
static const std::array<const char *, MSR_MOD_MAX> modNames = { nullptr, "Ryzen", "Intel" };
|
||||
static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " ";
|
||||
static MsrItems savedState;
|
||||
|
||||
|
||||
static inline int dir_filter(const struct dirent *dirp)
|
||||
|
@ -66,10 +58,49 @@ static inline int dir_filter(const struct dirent *dirp)
|
|||
}
|
||||
|
||||
|
||||
static bool wrmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t value)
|
||||
bool rdmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t &value)
|
||||
{
|
||||
char msr_file_name[64]{};
|
||||
|
||||
sprintf(msr_file_name, "/dev/cpu/%u/msr", cpu);
|
||||
int fd = open(msr_file_name, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool success = pread(fd, &value, sizeof value, reg) == sizeof value;
|
||||
|
||||
close(fd);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
static MsrItem rdmsr(uint32_t reg)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
if (!rdmsr_on_cpu(reg, 0, value)) {
|
||||
LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot read MSR 0x%08" PRIx32, tag, reg);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return { reg, value };
|
||||
}
|
||||
|
||||
|
||||
static bool wrmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t value, uint64_t mask)
|
||||
{
|
||||
// If a bit in mask is set to 1, use new value, otherwise use old value
|
||||
if (mask != MsrItem::kNoMask) {
|
||||
uint64_t old_value;
|
||||
if (rdmsr_on_cpu(reg, cpu, old_value)) {
|
||||
value = (value & mask) | (old_value & ~mask);
|
||||
}
|
||||
}
|
||||
|
||||
char msr_file_name[64]{};
|
||||
|
||||
sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
|
||||
int fd = open(msr_file_name, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
|
@ -84,14 +115,14 @@ static bool wrmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t value)
|
|||
}
|
||||
|
||||
|
||||
static bool wrmsr_on_all_cpus(uint32_t reg, uint64_t value)
|
||||
static bool wrmsr_on_all_cpus(uint32_t reg, uint64_t value, uint64_t mask)
|
||||
{
|
||||
struct dirent **namelist;
|
||||
int dir_entries = scandir("/dev/cpu", &namelist, dir_filter, 0);
|
||||
int errors = 0;
|
||||
|
||||
while (dir_entries--) {
|
||||
if (!wrmsr_on_cpu(reg, strtoul(namelist[dir_entries]->d_name, nullptr, 10), value)) {
|
||||
if (!wrmsr_on_cpu(reg, strtoul(namelist[dir_entries]->d_name, nullptr, 10), value, mask)) {
|
||||
++errors;
|
||||
}
|
||||
|
||||
|
@ -120,42 +151,60 @@ static bool wrmsr_modprobe()
|
|||
}
|
||||
|
||||
|
||||
static bool wrmsr(const MsrItems &preset, bool save)
|
||||
{
|
||||
if (!wrmsr_modprobe()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (save) {
|
||||
for (const auto &i : preset) {
|
||||
auto item = rdmsr(i.reg());
|
||||
LOG_VERBOSE(CLEAR "%s" CYAN_BOLD("0x%08" PRIx32) CYAN(":0x%016" PRIx64) CYAN_BOLD(" -> 0x%016" PRIx64), tag, i.reg(), item.value(), i.value());
|
||||
|
||||
if (item.isValid()) {
|
||||
savedState.emplace_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &i : preset) {
|
||||
if (!wrmsr_on_all_cpus(i.reg(), i.value(), i.mask())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
void xmrig::Rx::osInit(const RxConfig &config)
|
||||
void xmrig::Rx::msrInit(const RxConfig &config)
|
||||
{
|
||||
if (config.wrmsr() < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MsrMod mod = MSR_MOD_NONE;
|
||||
if (Cpu::info()->assembly() == Assembly::RYZEN) {
|
||||
mod = MSR_MOD_RYZEN;
|
||||
}
|
||||
else if (Cpu::info()->vendor() == ICpuInfo::VENDOR_INTEL) {
|
||||
mod = MSR_MOD_INTEL;
|
||||
}
|
||||
|
||||
if (mod == MSR_MOD_NONE) {
|
||||
const auto &preset = config.msrPreset();
|
||||
if (preset.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
if (!wrmsr_modprobe()) {
|
||||
if (wrmsr(preset, config.rdmsr())) {
|
||||
LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for \"%s\" preset has been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, config.msrPresetName(), Chrono::steadyMSecs() - ts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void xmrig::Rx::msrDestroy()
|
||||
{
|
||||
if (savedState.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mod == MSR_MOD_RYZEN) {
|
||||
wrmsr_on_all_cpus(0xC0011020, 0);
|
||||
wrmsr_on_all_cpus(0xC0011021, 0x40);
|
||||
wrmsr_on_all_cpus(0xC0011022, 0x510000);
|
||||
wrmsr_on_all_cpus(0xC001102b, 0x1808cc16);
|
||||
}
|
||||
else if (mod == MSR_MOD_INTEL) {
|
||||
wrmsr_on_all_cpus(0x1a4, config.wrmsr());
|
||||
}
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for %s has been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, modNames[mod], Chrono::steadyMSecs() - ts);
|
||||
if (!wrmsr(savedState, false)) {
|
||||
LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts);
|
||||
}
|
||||
}
|
||||
|
|
335
src/crypto/rx/Rx_win.cpp
Normal file
335
src/crypto/rx/Rx_win.cpp
Normal file
|
@ -0,0 +1,335 @@
|
|||
/* 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 tevador <tevador@gmail.com>
|
||||
* Copyright 2000 Transmeta Corporation <https://github.com/intel/msr-tools>
|
||||
* Copyright 2004-2008 H. Peter Anvin <https://github.com/intel/msr-tools>
|
||||
* Copyright 2007-2009 hiyohiyo <https://openlibsys.org>, <hiyohiyo@crystalmark.info>
|
||||
* 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 "crypto/rx/Rx.h"
|
||||
#include "backend/cpu/Cpu.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "base/kernel/Platform.h"
|
||||
#include "base/tools/Chrono.h"
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
|
||||
|
||||
#include <Windows.h>
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
|
||||
#define SERVICE_NAME L"WinRing0_1_2_0"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
static bool reuseDriver = false;
|
||||
static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " ";
|
||||
static MsrItems savedState;
|
||||
|
||||
|
||||
static SC_HANDLE hManager;
|
||||
static SC_HANDLE hService;
|
||||
|
||||
|
||||
static bool wrmsr_uninstall_driver()
|
||||
{
|
||||
if (!hService) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
if (!reuseDriver) {
|
||||
SERVICE_STATUS serviceStatus;
|
||||
|
||||
if (!ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus)) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (!DeleteService(hService)) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to remove WinRing0 driver, error %u", tag, GetLastError());
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
CloseServiceHandle(hService);
|
||||
hService = nullptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static HANDLE wrmsr_install_driver()
|
||||
{
|
||||
DWORD err = 0;
|
||||
|
||||
hManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS);
|
||||
if (!hManager) {
|
||||
err = GetLastError();
|
||||
|
||||
if (err == ERROR_ACCESS_DENIED) {
|
||||
LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "to write MSR registers Administrator privileges required.", tag);
|
||||
}
|
||||
else {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to open service control manager, error %u", tag, err);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<wchar_t> dir;
|
||||
dir.resize(MAX_PATH);
|
||||
do {
|
||||
dir.resize(dir.size() * 2);
|
||||
GetModuleFileNameW(nullptr, dir.data(), dir.size());
|
||||
err = GetLastError();
|
||||
} while (err == ERROR_INSUFFICIENT_BUFFER);
|
||||
|
||||
if (err != ERROR_SUCCESS) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to get path to driver, error %u", tag, err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto it = dir.end(); it != dir.begin(); --it) {
|
||||
if ((*it == L'\\') || (*it == L'/')) {
|
||||
++it;
|
||||
*it = L'\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring driverPath = dir.data();
|
||||
driverPath += L"WinRing0x64.sys";
|
||||
|
||||
hService = OpenServiceW(hManager, SERVICE_NAME, SERVICE_ALL_ACCESS);
|
||||
if (hService) {
|
||||
LOG_WARN(CLEAR "%s" YELLOW("service ") YELLOW_BOLD("WinRing0_1_2_0") YELLOW(" is already exists"), tag);
|
||||
|
||||
SERVICE_STATUS status;
|
||||
const auto rc = QueryServiceStatus(hService, &status);
|
||||
|
||||
if (rc && Log::isVerbose()) {
|
||||
DWORD dwBytesNeeded;
|
||||
|
||||
QueryServiceConfigA(hService, nullptr, 0, &dwBytesNeeded);
|
||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
std::vector<BYTE> buffer(dwBytesNeeded);
|
||||
auto config = reinterpret_cast<LPQUERY_SERVICE_CONFIGA>(buffer.data());
|
||||
|
||||
if (QueryServiceConfigA(hService, config, buffer.size(), &dwBytesNeeded)) {
|
||||
LOG_INFO(CLEAR "%s" YELLOW("service path: ") YELLOW_BOLD("\"%s\""), tag, config->lpBinaryPathName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rc && status.dwCurrentState == SERVICE_RUNNING) {
|
||||
reuseDriver = true;
|
||||
}
|
||||
else if (!wrmsr_uninstall_driver()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reuseDriver) {
|
||||
hService = CreateServiceW(hManager, SERVICE_NAME, SERVICE_NAME, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, driverPath.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
if (!hService) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to install WinRing0 driver, error %u", tag, GetLastError());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!StartService(hService, 0, nullptr)) {
|
||||
err = GetLastError();
|
||||
if (err != ERROR_SERVICE_ALREADY_RUNNING) {
|
||||
if (err == ERROR_FILE_NOT_FOUND) {
|
||||
LOG_ERR(CLEAR "%s" RED("failed to start WinRing0 driver: ") RED_BOLD("\"WinRing0x64.sys not found\""), tag);
|
||||
}
|
||||
else {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to start WinRing0 driver, error %u", tag, err);
|
||||
}
|
||||
|
||||
wrmsr_uninstall_driver();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE hDriver = CreateFileW(L"\\\\.\\" SERVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (!hDriver) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to connect to WinRing0 driver, error %u", tag, GetLastError());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return hDriver;
|
||||
}
|
||||
|
||||
|
||||
#define IOCTL_READ_MSR CTL_CODE(40000, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
|
||||
static bool rdmsr(HANDLE driver, uint32_t reg, uint64_t &value)
|
||||
{
|
||||
DWORD size = 0;
|
||||
|
||||
return DeviceIoControl(driver, IOCTL_READ_MSR, ®, sizeof(reg), &value, sizeof(value), &size, nullptr) != 0;
|
||||
}
|
||||
|
||||
|
||||
static MsrItem rdmsr(HANDLE driver, uint32_t reg)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
if (!rdmsr(driver, reg, value)) {
|
||||
LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot read MSR 0x%08" PRIx32, tag, reg);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return { reg, value };
|
||||
}
|
||||
|
||||
|
||||
static bool wrmsr(HANDLE driver, uint32_t reg, uint64_t value, uint64_t mask)
|
||||
{
|
||||
struct {
|
||||
uint32_t reg = 0;
|
||||
uint32_t value[2]{};
|
||||
} input;
|
||||
|
||||
static_assert(sizeof(input) == 12, "Invalid struct size for WinRing0 driver");
|
||||
|
||||
// If a bit in mask is set to 1, use new value, otherwise use old value
|
||||
if (mask != MsrItem::kNoMask) {
|
||||
uint64_t old_value;
|
||||
if (rdmsr(driver, reg, old_value)) {
|
||||
value = (value & mask) | (old_value & ~mask);
|
||||
}
|
||||
}
|
||||
|
||||
input.reg = reg;
|
||||
*(reinterpret_cast<uint64_t*>(input.value)) = value;
|
||||
|
||||
DWORD output;
|
||||
DWORD k;
|
||||
|
||||
if (!DeviceIoControl(driver, IOCTL_WRITE_MSR, &input, sizeof(input), &output, sizeof(output), &k, nullptr)) {
|
||||
LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, tag, reg, value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool wrmsr(const MsrItems &preset, bool save)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
HANDLE driver = wrmsr_install_driver();
|
||||
if (!driver) {
|
||||
wrmsr_uninstall_driver();
|
||||
|
||||
if (hManager) {
|
||||
CloseServiceHandle(hManager);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (save) {
|
||||
for (const auto &i : preset) {
|
||||
auto item = rdmsr(driver, i.reg());
|
||||
LOG_VERBOSE(CLEAR "%s" CYAN_BOLD("0x%08" PRIx32) CYAN(":0x%016" PRIx64) CYAN_BOLD(" -> 0x%016" PRIx64), tag, i.reg(), item.value(), i.value());
|
||||
|
||||
if (item.isValid()) {
|
||||
savedState.emplace_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::thread wrmsr_thread([driver, &preset, &success]() {
|
||||
for (uint32_t i = 0, n = Cpu::info()->threads(); i < n; ++i) {
|
||||
if (!Platform::setThreadAffinity(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto &i : preset) {
|
||||
success = wrmsr(driver, i.reg(), i.value(), i.mask());
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrmsr_thread.join();
|
||||
|
||||
CloseHandle(driver);
|
||||
|
||||
wrmsr_uninstall_driver();
|
||||
CloseServiceHandle(hManager);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
void xmrig::Rx::msrInit(const RxConfig &config)
|
||||
{
|
||||
const auto &preset = config.msrPreset();
|
||||
if (preset.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
if (wrmsr(preset, config.rdmsr())) {
|
||||
LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for \"%s\" preset has been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, config.msrPresetName(), Chrono::steadyMSecs() - ts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void xmrig::Rx::msrDestroy()
|
||||
{
|
||||
if (savedState.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
if (!wrmsr(savedState, false)) {
|
||||
LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to restore initial state" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts);
|
||||
}
|
||||
}
|
|
@ -1,255 +0,0 @@
|
|||
/* 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 tevador <tevador@gmail.com>
|
||||
* Copyright 2000 Transmeta Corporation <https://github.com/intel/msr-tools>
|
||||
* Copyright 2004-2008 H. Peter Anvin <https://github.com/intel/msr-tools>
|
||||
* Copyright 2007-2009 hiyohiyo <https://openlibsys.org>, <hiyohiyo@crystalmark.info>
|
||||
* 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 "crypto/rx/Rx.h"
|
||||
#include "backend/cpu/Cpu.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "base/kernel/Platform.h"
|
||||
#include "base/tools/Chrono.h"
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
|
||||
|
||||
#include <Windows.h>
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
|
||||
#define SERVICE_NAME L"WinRing0_1_2_0"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
enum MsrMod : uint32_t {
|
||||
MSR_MOD_NONE,
|
||||
MSR_MOD_RYZEN,
|
||||
MSR_MOD_INTEL,
|
||||
MSR_MOD_MAX
|
||||
};
|
||||
|
||||
|
||||
static const char *tag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ") " ";
|
||||
static const std::array<const char *, MSR_MOD_MAX> modNames = { nullptr, "Ryzen", "Intel" };
|
||||
|
||||
|
||||
static SC_HANDLE hManager;
|
||||
static SC_HANDLE hService;
|
||||
|
||||
|
||||
static bool wrmsr_uninstall_driver()
|
||||
{
|
||||
if (!hService) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
SERVICE_STATUS serviceStatus;
|
||||
|
||||
if (!ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus)) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to stop WinRing0 driver, error %u", tag, GetLastError());
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (!DeleteService(hService)) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to remove WinRing0 driver, error %u", tag, GetLastError());
|
||||
result = false;
|
||||
}
|
||||
|
||||
CloseServiceHandle(hService);
|
||||
hService = nullptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static HANDLE wrmsr_install_driver()
|
||||
{
|
||||
DWORD err = 0;
|
||||
|
||||
hManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS);
|
||||
if (!hManager) {
|
||||
err = GetLastError();
|
||||
|
||||
if (err == ERROR_ACCESS_DENIED) {
|
||||
LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "to write MSR registers Administrator privileges required.", tag);
|
||||
}
|
||||
else {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to open service control manager, error %u", tag, err);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<wchar_t> dir;
|
||||
dir.resize(MAX_PATH);
|
||||
do {
|
||||
dir.resize(dir.size() * 2);
|
||||
GetModuleFileNameW(nullptr, dir.data(), dir.size());
|
||||
err = GetLastError();
|
||||
} while (err == ERROR_INSUFFICIENT_BUFFER);
|
||||
|
||||
if (err != ERROR_SUCCESS) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to get path to driver, error %u", tag, err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto it = dir.end(); it != dir.begin(); --it) {
|
||||
if ((*it == L'\\') || (*it == L'/')) {
|
||||
++it;
|
||||
*it = L'\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring driverPath = dir.data();
|
||||
driverPath += L"WinRing0x64.sys";
|
||||
|
||||
hService = OpenServiceW(hManager, SERVICE_NAME, SERVICE_ALL_ACCESS);
|
||||
if (hService && !wrmsr_uninstall_driver()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hService = CreateServiceW(hManager, SERVICE_NAME, SERVICE_NAME, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, driverPath.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
if (!hService) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to install WinRing0 driver, error %u", tag, GetLastError());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!StartService(hService, 0, nullptr)) {
|
||||
err = GetLastError();
|
||||
if (err != ERROR_SERVICE_ALREADY_RUNNING) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to start WinRing0 driver, error %u", tag, err);
|
||||
|
||||
CloseServiceHandle(hService);
|
||||
hService = nullptr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE hDriver = CreateFileW(L"\\\\.\\" SERVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (!hDriver) {
|
||||
LOG_ERR(CLEAR "%s" RED_S "failed to connect to WinRing0 driver, error %u", tag, GetLastError());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return hDriver;
|
||||
}
|
||||
|
||||
|
||||
#define IOCTL_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
|
||||
static bool wrmsr(HANDLE hDriver, uint32_t reg, uint64_t value) {
|
||||
struct {
|
||||
uint32_t reg = 0;
|
||||
uint32_t value[2]{};
|
||||
} input;
|
||||
|
||||
static_assert(sizeof(input) == 12, "Invalid struct size for WinRing0 driver");
|
||||
|
||||
input.reg = reg;
|
||||
*((uint64_t*)input.value) = value;
|
||||
|
||||
DWORD output;
|
||||
DWORD k;
|
||||
|
||||
if (!DeviceIoControl(hDriver, IOCTL_WRITE_MSR, &input, sizeof(input), &output, sizeof(output), &k, nullptr)) {
|
||||
LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, tag, reg, value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
void xmrig::Rx::osInit(const RxConfig &config)
|
||||
{
|
||||
if ((config.wrmsr() < 0) || !ICpuInfo::isX64()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MsrMod mod = MSR_MOD_NONE;
|
||||
if (Cpu::info()->assembly() == Assembly::RYZEN) {
|
||||
mod = MSR_MOD_RYZEN;
|
||||
}
|
||||
else if (Cpu::info()->vendor() == ICpuInfo::VENDOR_INTEL) {
|
||||
mod = MSR_MOD_INTEL;
|
||||
}
|
||||
|
||||
if (mod == MSR_MOD_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
HANDLE hDriver = wrmsr_install_driver();
|
||||
if (!hDriver) {
|
||||
wrmsr_uninstall_driver();
|
||||
|
||||
if (hManager) {
|
||||
CloseServiceHandle(hManager);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::thread wrmsr_thread([hDriver, mod, &config]() {
|
||||
for (uint32_t i = 0, n = Cpu::info()->threads(); i < n; ++i) {
|
||||
Platform::setThreadAffinity(i);
|
||||
|
||||
if (mod == MSR_MOD_RYZEN) {
|
||||
wrmsr(hDriver, 0xC0011020, 0);
|
||||
wrmsr(hDriver, 0xC0011021, 0x40);
|
||||
wrmsr(hDriver, 0xC0011022, 0x510000);
|
||||
wrmsr(hDriver, 0xC001102b, 0x1808cc16);
|
||||
}
|
||||
else if (mod == MSR_MOD_INTEL) {
|
||||
wrmsr(hDriver, 0x1a4, config.wrmsr());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrmsr_thread.join();
|
||||
|
||||
CloseHandle(hDriver);
|
||||
|
||||
wrmsr_uninstall_driver();
|
||||
CloseServiceHandle(hManager);
|
||||
|
||||
LOG_NOTICE(CLEAR "%s" GREEN_BOLD_S "register values for %s has been set successfully" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, modNames[mod], Chrono::steadyMSecs() - ts);
|
||||
}
|
72
src/crypto/rx/msr/MsrItem.cpp
Normal file
72
src/crypto/rx/msr/MsrItem.cpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* 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 tevador <tevador@gmail.com>
|
||||
* 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 "crypto/rx/msr/MsrItem.h"
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
xmrig::MsrItem::MsrItem(const rapidjson::Value &value)
|
||||
{
|
||||
if (!value.IsString()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto kv = String(value.GetString()).split(':');
|
||||
if (kv.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_reg = strtoul(kv[0], nullptr, 0);
|
||||
m_value = strtoull(kv[1], nullptr, 0);
|
||||
m_mask = (kv.size() > 2) ? strtoull(kv[2], nullptr, 0) : kNoMask;
|
||||
}
|
||||
|
||||
|
||||
rapidjson::Value xmrig::MsrItem::toJSON(rapidjson::Document &doc) const
|
||||
{
|
||||
return toString().toJSON(doc);
|
||||
}
|
||||
|
||||
|
||||
xmrig::String xmrig::MsrItem::toString() const
|
||||
{
|
||||
constexpr size_t size = 48;
|
||||
|
||||
auto buf = new char[size]();
|
||||
|
||||
if (m_mask != kNoMask) {
|
||||
snprintf(buf, size, "0x%" PRIx32 ":0x%" PRIx64 ":0x%" PRIx64, m_reg, m_value, m_mask);
|
||||
}
|
||||
else {
|
||||
snprintf(buf, size, "0x%" PRIx32 ":0x%" PRIx64, m_reg, m_value);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
76
src/crypto/rx/msr/MsrItem.h
Normal file
76
src/crypto/rx/msr/MsrItem.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* 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 tevador <tevador@gmail.com>
|
||||
* 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_MSRITEM_H
|
||||
#define XMRIG_MSRITEM_H
|
||||
|
||||
|
||||
#include "base/tools/String.h"
|
||||
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace xmrig
|
||||
{
|
||||
|
||||
|
||||
class RxDataset;
|
||||
|
||||
|
||||
class MsrItem
|
||||
{
|
||||
public:
|
||||
constexpr static uint64_t kNoMask = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
inline MsrItem() = default;
|
||||
inline MsrItem(uint32_t reg, uint64_t value, uint64_t mask = kNoMask) : m_reg(reg), m_value(value), m_mask(mask) {}
|
||||
|
||||
MsrItem(const rapidjson::Value &value);
|
||||
|
||||
inline bool isValid() const { return m_reg > 0; }
|
||||
inline uint32_t reg() const { return m_reg; }
|
||||
inline uint64_t value() const { return m_value; }
|
||||
inline uint64_t mask() const { return m_mask; }
|
||||
|
||||
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
||||
String toString() const;
|
||||
|
||||
private:
|
||||
uint32_t m_reg = 0;
|
||||
uint64_t m_value = 0;
|
||||
uint64_t m_mask = kNoMask;
|
||||
};
|
||||
|
||||
|
||||
using MsrItems = std::vector<MsrItem>;
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_MSRITEM_H */
|
Loading…
Add table
Add a link
Reference in a new issue