@@ -410,6 +410,7 @@ struct kvm_arch{
unsigned long irq_sources_bitmap;
u64 vm_init_tsc;
+ s64 kvmclock_offset;
};
struct kvm_vm_stat {
@@ -699,7 +699,8 @@ static void kvm_write_guest_time(struct kvm_vcpu *v)
/* With all the info we got, fill in the values */
vcpu->hv_clock.system_time = ts.tv_nsec +
- (NSEC_PER_SEC * (u64)ts.tv_sec);
+ (NSEC_PER_SEC * (u64)ts.tv_sec) + v->kvm->arch.kvmclock_offset;
+
/*
* The interface expects us to write an even number signaling that the
* update is finished. Since the guest won't see the intermediate
@@ -2441,6 +2442,38 @@ long kvm_arch_vm_ioctl(struct file *filp,
r = 0;
break;
}
+ case KVM_SET_CLOCK: {
+ struct timespec now;
+ struct kvm_clock_data user_ns;
+ u64 now_ns;
+ s64 delta;
+
+ r = -EFAULT;
+ if (copy_from_user(&user_ns, argp, sizeof(user_ns)))
+ goto out;
+
+ r = 0;
+ ktime_get_ts(&now);
+ now_ns = timespec_to_ns(&now);
+ delta = user_ns.clock - now_ns;
+ kvm->arch.kvmclock_offset = delta;
+ break;
+ }
+ case KVM_GET_CLOCK: {
+ struct timespec now;
+ struct kvm_clock_data user_ns;
+ u64 now_ns;
+
+ ktime_get_ts(&now);
+ now_ns = timespec_to_ns(&now);
+ user_ns.clock = kvm->arch.kvmclock_offset + now_ns;
+
+ if (copy_to_user(argp, &user_ns, sizeof(user_ns)))
+ r = -EFAULT;
+
+ break;
+ }
+
default:
;
}
@@ -497,6 +497,11 @@ struct kvm_irqfd {
__u8 pad[20];
};
+struct kvm_clock_data {
+ __u64 clock;
+ __u64 pad[2];
+};
+
/*
* ioctls for VM fds
*/
@@ -546,6 +551,8 @@ struct kvm_irqfd {
#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)
#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)
#define KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd)
+#define KVM_SET_CLOCK _IOW(KVMIO, 0x7a, struct kvm_clock_data)
+#define KVM_GET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data)
/*
* ioctls for vcpu fds