Skip to content

Commit 0936cdf

Browse files
olysoneklenb
authored andcommitted
tools/power x86_energy_perf_policy: Input/output error in a VM
I've encountered an issue with x86_energy_perf_policy. If I run it on a machine that I'm told is a qemu-kvm virtual machine running inside a privileged container, I get the following error: x86_energy_perf_policy: /dev/cpu/0/msr offset 0x1ad read failed: Input/output error I get the same error in a Digital Ocean droplet, so that might be a similar environment. I created the following patch which is intended to give a more user-friendly message. It's based on a patch for turbostat from Prarit Bhargava that was posted some time ago. The patch is "[v2] turbostat: Running on virtual machine is not supported" [1]. Given my limited knowledge of the topic, I can't say with confidence that this is the right solution, though (that's why this is not an official patch submission). Also, I'm not sure what the convention with exit codes is in this tool. Also, instead of the error message, perhaps the tool should just not print anything in this case, which is how it behaves in a "regular" VM? [1] https://patchwork.kernel.org/patch/9868587/ Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com> Signed-off-by: Len Brown <len.brown@intel.com>
1 parent c315a09 commit 0936cdf

1 file changed

Lines changed: 54 additions & 13 deletions

File tree

tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,57 @@ void cmdline(int argc, char **argv)
622622
}
623623
}
624624

625+
/*
626+
* Open a file, and exit on failure
627+
*/
628+
FILE *fopen_or_die(const char *path, const char *mode)
629+
{
630+
FILE *filep = fopen(path, "r");
631+
632+
if (!filep)
633+
err(1, "%s: open failed", path);
634+
return filep;
635+
}
636+
637+
void err_on_hypervisor(void)
638+
{
639+
FILE *cpuinfo;
640+
char *flags, *hypervisor;
641+
char *buffer;
642+
643+
/* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */
644+
cpuinfo = fopen_or_die("/proc/cpuinfo", "ro");
645+
646+
buffer = malloc(4096);
647+
if (!buffer) {
648+
fclose(cpuinfo);
649+
err(-ENOMEM, "buffer malloc fail");
650+
}
651+
652+
if (!fread(buffer, 1024, 1, cpuinfo)) {
653+
fclose(cpuinfo);
654+
free(buffer);
655+
err(1, "Reading /proc/cpuinfo failed");
656+
}
657+
658+
flags = strstr(buffer, "flags");
659+
rewind(cpuinfo);
660+
fseek(cpuinfo, flags - buffer, SEEK_SET);
661+
if (!fgets(buffer, 4096, cpuinfo)) {
662+
fclose(cpuinfo);
663+
free(buffer);
664+
err(1, "Reading /proc/cpuinfo failed");
665+
}
666+
fclose(cpuinfo);
667+
668+
hypervisor = strstr(buffer, "hypervisor");
669+
670+
free(buffer);
671+
672+
if (hypervisor)
673+
err(-1,
674+
"not supported on this virtual machine");
675+
}
625676

626677
int get_msr(int cpu, int offset, unsigned long long *msr)
627678
{
@@ -635,8 +686,10 @@ int get_msr(int cpu, int offset, unsigned long long *msr)
635686
err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
636687

637688
retval = pread(fd, msr, sizeof(*msr), offset);
638-
if (retval != sizeof(*msr))
689+
if (retval != sizeof(*msr)) {
690+
err_on_hypervisor();
639691
err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
692+
}
640693

641694
if (debug > 1)
642695
fprintf(stderr, "get_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, *msr);
@@ -1086,18 +1139,6 @@ int update_cpu_msrs(int cpu)
10861139
return 0;
10871140
}
10881141

1089-
/*
1090-
* Open a file, and exit on failure
1091-
*/
1092-
FILE *fopen_or_die(const char *path, const char *mode)
1093-
{
1094-
FILE *filep = fopen(path, "r");
1095-
1096-
if (!filep)
1097-
err(1, "%s: open failed", path);
1098-
return filep;
1099-
}
1100-
11011142
unsigned int get_pkg_num(int cpu)
11021143
{
11031144
FILE *fp;

0 commit comments

Comments
 (0)