From 59e8fdb9ed2273c52212143797b8c98b51593109 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Tue, 17 Dec 2019 23:55:22 +0100 Subject: [PATCH] Added bit masks for MSR registers --- src/crypto/rx/RxConfig.cpp | 2 +- src/crypto/rx/Rx_linux.cpp | 94 +++++++++++++++++++---------------- src/crypto/rx/Rx_win.cpp | 60 ++++++++++++---------- src/crypto/rx/msr/MsrItem.cpp | 1 + src/crypto/rx/msr/MsrItem.h | 4 +- 5 files changed, 90 insertions(+), 71 deletions(-) diff --git a/src/crypto/rx/RxConfig.cpp b/src/crypto/rx/RxConfig.cpp index 07600681..5472bfa5 100644 --- a/src/crypto/rx/RxConfig.cpp +++ b/src/crypto/rx/RxConfig.cpp @@ -64,7 +64,7 @@ constexpr size_t kMsrArraySize = 4; static const std::array msrPresets = { MsrItems(), - MsrItems{{ 0xC0011020, 0x0 }, { 0xC0011021, 0x40 }, { 0xC0011022, 0x510000 }, { 0xC001102b, 0x1808cc16 }}, + MsrItems{{ 0xC0011020, 0x0 }, { 0xC0011021, 0x40, ~0x20ULL }, { 0xC0011022, 0x510000 }, { 0xC001102b, 0x1808cc16 }}, MsrItems{{ 0x1a4, 0x6 }}, MsrItems() }; diff --git a/src/crypto/rx/Rx_linux.cpp b/src/crypto/rx/Rx_linux.cpp index 3b3a0f1f..46f13c04 100644 --- a/src/crypto/rx/Rx_linux.cpp +++ b/src/crypto/rx/Rx_linux.cpp @@ -58,48 +58,6 @@ static inline int dir_filter(const struct dirent *dirp) } -static bool wrmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t value) -{ - 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) { - return false; - } - - const bool success = pwrite(fd, &value, sizeof value, reg) == sizeof value; - - close(fd); - - return success; -} - - -static bool wrmsr_on_all_cpus(uint32_t reg, uint64_t value) -{ - 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)) { - ++errors; - } - - free(namelist[dir_entries]); - } - - free(namelist); - - if (errors) { - LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, tag, reg, value); - } - - return errors == 0; -} - - bool rdmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t &value) { char msr_file_name[64]{}; @@ -131,6 +89,56 @@ static MsrItem rdmsr(uint32_t reg) } +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 != uint64_t(-1)) { + 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) { + return false; + } + + const bool success = pwrite(fd, &value, sizeof value, reg) == sizeof value; + + close(fd); + + return success; +} + + +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, mask)) { + ++errors; + } + + free(namelist[dir_entries]); + } + + free(namelist); + + if (errors) { + LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, tag, reg, value); + } + + return errors == 0; +} + + static bool wrmsr_modprobe() { if (system("/sbin/modprobe msr > /dev/null 2>&1") != 0) { @@ -161,7 +169,7 @@ static bool wrmsr(const MsrItems &preset, bool save) } for (const auto &i : preset) { - if (!wrmsr_on_all_cpus(i.reg(), i.value())) { + if (!wrmsr_on_all_cpus(i.reg(), i.value(), i.mask())) { return false; } } diff --git a/src/crypto/rx/Rx_win.cpp b/src/crypto/rx/Rx_win.cpp index af2919b7..b4e7588d 100644 --- a/src/crypto/rx/Rx_win.cpp +++ b/src/crypto/rx/Rx_win.cpp @@ -196,31 +196,6 @@ static HANDLE wrmsr_install_driver() #define IOCTL_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS) -static bool wrmsr(HANDLE driver, 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; - *(reinterpret_cast(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 rdmsr(HANDLE driver, uint32_t reg, uint64_t &value) { DWORD size = 0; @@ -242,6 +217,39 @@ static MsrItem rdmsr(HANDLE driver, uint32_t reg) } +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 != uint64_t(-1)) { + uint64_t old_value; + if (rdmsr(driver, reg, old_value)) { + value = (value & mask) | (old_value & ~mask); + } + } + + input.reg = reg; + *(reinterpret_cast(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; @@ -275,7 +283,7 @@ static bool wrmsr(const MsrItems &preset, bool save) } for (const auto &i : preset) { - success = wrmsr(driver, i.reg(), i.value()); + success = wrmsr(driver, i.reg(), i.value(), i.mask()); } if (!success) { diff --git a/src/crypto/rx/msr/MsrItem.cpp b/src/crypto/rx/msr/MsrItem.cpp index b97498e9..97eb843f 100644 --- a/src/crypto/rx/msr/MsrItem.cpp +++ b/src/crypto/rx/msr/MsrItem.cpp @@ -45,6 +45,7 @@ xmrig::MsrItem::MsrItem(const rapidjson::Value &value) m_reg = strtoul(kv[0], nullptr, 0); m_value = strtoul(kv[1], nullptr, 0); + m_mask = (kv.size() > 2) ? strtoul(kv[2], nullptr, 0) : uint64_t(-1); } diff --git a/src/crypto/rx/msr/MsrItem.h b/src/crypto/rx/msr/MsrItem.h index ff04bdba..00527489 100644 --- a/src/crypto/rx/msr/MsrItem.h +++ b/src/crypto/rx/msr/MsrItem.h @@ -45,13 +45,14 @@ class MsrItem { public: inline MsrItem() = default; - inline MsrItem(uint32_t reg, uint64_t value) : m_reg(reg), m_value(value) {} + inline MsrItem(uint32_t reg, uint64_t value, uint64_t mask = uint64_t(-1)) : 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; @@ -59,6 +60,7 @@ public: private: uint32_t m_reg = 0; uint64_t m_value = 0; + uint64_t m_mask = uint64_t(-1); };