Added bit masks for MSR registers

This commit is contained in:
SChernykh 2019-12-17 23:55:22 +01:00
parent 5142a406b0
commit 59e8fdb9ed
5 changed files with 90 additions and 71 deletions

View file

@ -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;
}
}