kvm: x86: export TSC information to user-space
authorLuiz Capitulino <lcapitulino@redhat.com>
Fri, 16 Sep 2016 14:27:36 +0000 (10:27 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 16 Sep 2016 14:57:48 +0000 (16:57 +0200)
This commit exports the following information to
user-space via the newly created per-vcpu debugfs
directory:

 - TSC offset (as a signed number)
 - TSC scaling ratio
 - TSC scaling ratio fractinal bits

The original intention of this commit was to
export only the TSC offset, but the TSC scaling
information is exported for completeness.

We need to retrieve the TSC offset from user-space
in order to support the merging of host and guest
traces in trace-cmd. Today, we use the kvm_write_tsc_offset
tracepoint, but it has a number of problems (mainly,
it requires a running VM to be rebooted, ftrace setup,
and also tracepoints are not supposed to be ABIs).

The merging of host and guest traces is explained
in more detail in this thread:

 [Qemu-devel] [RFC] host and guest kernel trace merging
 https://lists.nongnu.org/archive/html/qemu-devel/2016-03/msg00887.html

This commit creates the following files in debugfs:

/sys/kernel/debug/kvm/66828-10/vcpu0/tsc-offset
/sys/kernel/debug/kvm/66828-10/vcpu0/tsc-scaling-ratio
/sys/kernel/debug/kvm/66828-10/vcpu0/tsc-scaling-ratio-frac-bits

The last two are only created if TSC scaling is supported.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/debugfs.c

index bb5e9f635dde4b79c9eac391373b7735034e05a0..c19c7ede9bd6c8c8058a8a147f7e65c391a85bf0 100644 (file)
@@ -8,13 +8,62 @@
  *
  */
 #include <linux/kvm_host.h>
+#include <linux/debugfs.h>
 
 bool kvm_arch_has_vcpu_debugfs(void)
 {
-       return false;
+       return true;
 }
 
+static int vcpu_get_tsc_offset(void *data, u64 *val)
+{
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data;
+       *val = vcpu->arch.tsc_offset;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_offset_fops, vcpu_get_tsc_offset, NULL, "%lld\n");
+
+static int vcpu_get_tsc_scaling_ratio(void *data, u64 *val)
+{
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data;
+       *val = vcpu->arch.tsc_scaling_ratio;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_fops, vcpu_get_tsc_scaling_ratio, NULL, "%llu\n");
+
+static int vcpu_get_tsc_scaling_frac_bits(void *data, u64 *val)
+{
+       *val = kvm_tsc_scaling_ratio_frac_bits;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_frac_fops, vcpu_get_tsc_scaling_frac_bits, NULL, "%llu\n");
+
 int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
 {
+       struct dentry *ret;
+
+       ret = debugfs_create_file("tsc-offset", 0444,
+                                                       vcpu->debugfs_dentry,
+                                                       vcpu, &vcpu_tsc_offset_fops);
+       if (!ret)
+               return -ENOMEM;
+
+       if (kvm_has_tsc_control) {
+               ret = debugfs_create_file("tsc-scaling-ratio", 0444,
+                                                       vcpu->debugfs_dentry,
+                                                       vcpu, &vcpu_tsc_scaling_fops);
+               if (!ret)
+                       return -ENOMEM;
+               ret = debugfs_create_file("tsc-scaling-ratio-frac-bits", 0444,
+                                                       vcpu->debugfs_dentry,
+                                                       vcpu, &vcpu_tsc_scaling_frac_fops);
+               if (!ret)
+                       return -ENOMEM;
+
+       }
+
        return 0;
 }