Re: [PATCH 1/1] turbostat: cpu9: msr offset 0x614 read failed: Input/output error

From: samasth . norway . ananda
Date: Thu Aug 25 2022 - 16:38:55 EST




On 1/24/22 10:04 AM, samasth.norway.ananda wrote:
I get the following error running Turbostat on an intel virtual machine.

turbostat.5.4.17-2136.300.7.el7uek.x86_64: cpu49: msr offset 0x614 read
failed: Input/output error

The below patch gives a more user friendly message. It is based on the
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]
and also similar to the patch for x86_energy_perf_policy posted by Ondřej Lysoněk.
The patch is “tools/power x86_energy_perf_policy: Input/output error in a VM"[2].

KVM disables MONITOR/MWAIT in __do_cpuid_func(). Hence no VM will have MWAIT
and hence turbostat will not be able to read any C-state related registers
like the failures we see when we run turbostat. Therefore, turbostat should
also gracefully error-out like x86_energy_perf_policy.c.

[1] https://patchwork.kernel.org/patch/9868587/
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=0936cdfbb527

Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@xxxxxxxxxx>
---
tools/power/x86/turbostat/turbostat.c | 68 ++++++++++++++++++++++-----
1 file changed, 55 insertions(+), 13 deletions(-)

diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 47d3ba895d6d..c2904c1c0830 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -538,14 +538,68 @@ int get_instr_count_fd(int cpu)
return fd_instr_count_percpu[cpu];
}
+/*
+ * * Open a file, and exit on failure
+ * */
+FILE *fopen_or_die(const char *path, const char *mode)
+{
+ FILE *filep = fopen(path, mode);
+
+ if (!filep)
+ err(1, "%s: open failed", path);
+ return filep;
+}
+
+void err_on_hypervisor(void)
+{
+ FILE *cpuinfo;
+ char *flags, *hypervisor;
+ char *buffer;
+
+ /* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */
+ cpuinfo = fopen_or_die("/proc/cpuinfo", "ro");
+
+ buffer = malloc(4096);
+ if (!buffer) {
+ fclose(cpuinfo);
+ err(-ENOMEM, "buffer malloc fail");
+ }
+
+ if (!fread(buffer, 1024, 1, cpuinfo)) {
+ fclose(cpuinfo);
+ free(buffer);
+ err(1, "Reading /proc/cpuinfo failed");
+ }
+
+ flags = strstr(buffer, "flags");
+ rewind(cpuinfo);
+ fseek(cpuinfo, flags - buffer, SEEK_SET);
+ if (!fgets(buffer, 4096, cpuinfo)) {
+ fclose(cpuinfo);
+ free(buffer);
+ err(1, "Reading /proc/cpuinfo failed");
+ }
+ fclose(cpuinfo);
+
+ hypervisor = strstr(buffer, "hypervisor");
+
+ free(buffer);
+
+ if (hypervisor)
+ err(-1,
+ "not supported on this virtual machine");
+}
+
int get_msr(int cpu, off_t offset, unsigned long long *msr)
{
ssize_t retval;
retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
- if (retval != sizeof *msr)
+ if (retval != sizeof *msr){
+ err_on_hypervisor();
err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);
+ }
return 0;
}
@@ -1858,18 +1912,6 @@ static unsigned long long rdtsc(void)
return low | ((unsigned long long)high) << 32;
}
-/*
- * Open a file, and exit on failure
- */
-FILE *fopen_or_die(const char *path, const char *mode)
-{
- FILE *filep = fopen(path, mode);
-
- if (!filep)
- err(1, "%s: open failed", path);
- return filep;
-}
-
/*
* snapshot_sysfs_counter()
*
A gentle reminder, I haven't received any response on this. Any comments/feedback/concern?

Thanks,
Samasth.
Oracle Linux Team.