Re: Intercepting RDTSC instruction by causing a VMEXIT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Apr 17, 2021, Arnabjyoti Kalita wrote:
> Hello all,
> 
> I'm having a requirement to record values obtained by reading tsc clock.
> 
> The command line I use to start QEMU in KVM mode is as below -
> 
> sudo ./qemu-system-x86_64 -m 1024 --machine pc-i440fx-2.5 -cpu
> qemu64,-vme,-x2apic,-kvmclock,+lahf_lm,+3dnowprefetch,+vmx -enable-kvm
> -netdev tap,id=tap1,ifname=tap0,script=no,downscript=no -device
> virtio-net-pci,netdev=tap1,mac=00:00:00:00:00:00 -drive
> file=~/os_images_for_qemu/ubuntu-16.04.server.qcow2,format=qcow2,if=none,id=img-direct
> -device virtio-blk-pci,drive=img-direct
> 
> I am using QEMU version 2.11.92 and the guest kernel is a
> 4.4.0-116-generic. I use the CPU model "qemu64" because I have a
> requirement to create a snapshot of this guest and load the snapshot
> in TCG mode. The generic CPU model helps, in this regard.
> 
> Now when the guest is running, I want to intercept all rdtsc
> instructions and record the tsc clock values. I know that for this to
> happen, the CPU_BASED_RDTSC_EXITING flag needs to exist for the
> particular CPU model.
> 
> How do I start adding support for causing VMEXIT upon rdtsc execution?

This requires a KVM change.  The below should do the trick.

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index c05e6e2854b5..f000728e4319 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -2453,7 +2453,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
              CPU_BASED_MWAIT_EXITING |
              CPU_BASED_MONITOR_EXITING |
              CPU_BASED_INVLPG_EXITING |
-             CPU_BASED_RDPMC_EXITING;
+             CPU_BASED_RDPMC_EXITING |
+             CPU_BASED_RDTSC_EXITING;

        opt = CPU_BASED_TPR_SHADOW |
              CPU_BASED_USE_MSR_BITMAPS |
@@ -5194,6 +5195,15 @@ static int handle_invlpg(struct kvm_vcpu *vcpu)
        return kvm_skip_emulated_instruction(vcpu);
 }

+static int handle_rdtsc(struct kvm_vcpu *vcpu)
+{
+       u64 tsc = kvm_read_l1_tsc(vcpu, rdtsc());
+
+       kvm_rax_write(vcpu, tsc & -1u);
+       kvm_rdx_write(vcpu, (tsc >> 32) & -1u);
+       return kvm_skip_emulated_instruction(vcpu);
+}
+
 static int handle_apic_access(struct kvm_vcpu *vcpu)
 {
        if (likely(fasteoi)) {
@@ -5605,6 +5615,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
        [EXIT_REASON_INVD]                    = kvm_emulate_invd,
        [EXIT_REASON_INVLPG]                  = handle_invlpg,
        [EXIT_REASON_RDPMC]                   = kvm_emulate_rdpmc,
+       [EXIT_REASON_RDTSC]                   = handle_rdtsc,
        [EXIT_REASON_VMCALL]                  = kvm_emulate_hypercall,
        [EXIT_REASON_VMCLEAR]                 = handle_vmx_instruction,
        [EXIT_REASON_VMLAUNCH]                = handle_vmx_instruction,
 
> I see that a fairly recent commit in QEMU helps adding nested VMX
> controls to named CPU models, but not "qemu64". Can I extend this
> commit to add these controls to "qemu64" as well? Will making this
> change immediately add support for intercepting VMEXITS for "qemu64"
> CPU?

Are you actually running a nested guest?



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux