mirror of
https://github.com/xmrig/xmrig.git
synced 2024-11-18 00:37:46 +00:00
Added bit masks for MSR registers
This commit is contained in:
parent
5142a406b0
commit
59e8fdb9ed
5 changed files with 90 additions and 71 deletions
|
@ -64,7 +64,7 @@ constexpr size_t kMsrArraySize = 4;
|
|||
|
||||
static const std::array<MsrItems, kMsrArraySize> 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()
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<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 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<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;
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue