|
@@ -2147,6 +2147,7 @@ int kvm_dev_ioctl_check_extension(long ext)
|
|
|
case KVM_CAP_ASYNC_PF:
|
|
|
case KVM_CAP_GET_TSC_KHZ:
|
|
|
case KVM_CAP_PCI_2_3:
|
|
|
+ case KVM_CAP_KVMCLOCK_CTRL:
|
|
|
r = 1;
|
|
|
break;
|
|
|
case KVM_CAP_COALESCED_MMIO:
|
|
@@ -2597,6 +2598,23 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu,
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * kvm_set_guest_paused() indicates to the guest kernel that it has been
|
|
|
+ * stopped by the hypervisor. This function will be called from the host only.
|
|
|
+ * EINVAL is returned when the host attempts to set the flag for a guest that
|
|
|
+ * does not support pv clocks.
|
|
|
+ */
|
|
|
+static int kvm_set_guest_paused(struct kvm_vcpu *vcpu)
|
|
|
+{
|
|
|
+ struct pvclock_vcpu_time_info *src = &vcpu->arch.hv_clock;
|
|
|
+ if (!vcpu->arch.time_page)
|
|
|
+ return -EINVAL;
|
|
|
+ src->flags |= PVCLOCK_GUEST_STOPPED;
|
|
|
+ mark_page_dirty(vcpu->kvm, vcpu->arch.time >> PAGE_SHIFT);
|
|
|
+ kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
long kvm_arch_vcpu_ioctl(struct file *filp,
|
|
|
unsigned int ioctl, unsigned long arg)
|
|
|
{
|
|
@@ -2873,6 +2891,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
|
|
|
r = vcpu->arch.virtual_tsc_khz;
|
|
|
goto out;
|
|
|
}
|
|
|
+ case KVM_KVMCLOCK_CTRL: {
|
|
|
+ r = kvm_set_guest_paused(vcpu);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
default:
|
|
|
r = -EINVAL;
|
|
|
}
|