aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlauber Costa <glommer@redhat.com>2009-10-16 15:28:36 -0400
committerAvi Kivity <avi@redhat.com>2009-12-03 02:32:19 -0500
commitafbcf7ab8d1bc8c2d04792f6d9e786e0adeb328d (patch)
tree14320a1c768562139a550fd0c576d6d52829d9ec
parentcd5a2685de4a642fd0bd763e8c19711ef08dbe27 (diff)
KVM: allow userspace to adjust kvmclock offset
When we migrate a kvm guest that uses pvclock between two hosts, we may suffer a large skew. This is because there can be significant differences between the monotonic clock of the hosts involved. When a new host with a much larger monotonic time starts running the guest, the view of time will be significantly impacted. Situation is much worse when we do the opposite, and migrate to a host with a smaller monotonic clock. This proposed ioctl will allow userspace to inform us what is the monotonic clock value in the source host, so we can keep the time skew short, and more importantly, never goes backwards. Userspace may also need to trigger the current data, since from the first migration onwards, it won't be reflected by a simple call to clock_gettime() anymore. [marcelo: future-proof abi with a flags field] [jan: fix KVM_GET_CLOCK by clearing flags field instead of checking it] Signed-off-by: Glauber Costa <glommer@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Documentation/kvm/api.txt36
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/kvm/x86.c42
-rw-r--r--include/linux/kvm.h10
4 files changed, 88 insertions, 1 deletions
diff --git a/Documentation/kvm/api.txt b/Documentation/kvm/api.txt
index 3e8684e48506..36594ba57723 100644
--- a/Documentation/kvm/api.txt
+++ b/Documentation/kvm/api.txt
@@ -617,6 +617,42 @@ struct kvm_xen_hvm_config {
617 __u8 pad2[30]; 617 __u8 pad2[30];
618}; 618};
619 619
6204.27 KVM_GET_CLOCK
621
622Capability: KVM_CAP_ADJUST_CLOCK
623Architectures: x86
624Type: vm ioctl
625Parameters: struct kvm_clock_data (out)
626Returns: 0 on success, -1 on error
627
628Gets the current timestamp of kvmclock as seen by the current guest. In
629conjunction with KVM_SET_CLOCK, it is used to ensure monotonicity on scenarios
630such as migration.
631
632struct kvm_clock_data {
633 __u64 clock; /* kvmclock current value */
634 __u32 flags;
635 __u32 pad[9];
636};
637
6384.28 KVM_SET_CLOCK
639
640Capability: KVM_CAP_ADJUST_CLOCK
641Architectures: x86
642Type: vm ioctl
643Parameters: struct kvm_clock_data (in)
644Returns: 0 on success, -1 on error
645
646Sets the current timestamp of kvmclock to the valued specific in its parameter.
647In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios
648such as migration.
649
650struct kvm_clock_data {
651 __u64 clock; /* kvmclock current value */
652 __u32 flags;
653 __u32 pad[9];
654};
655
6205. The kvm_run structure 6565. The kvm_run structure
621 657
622Application code obtains a pointer to the kvm_run structure by 658Application code obtains a pointer to the kvm_run structure by
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 4d994ad5051a..0558ff8c32ae 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -413,6 +413,7 @@ struct kvm_arch{
413 413
414 unsigned long irq_sources_bitmap; 414 unsigned long irq_sources_bitmap;
415 u64 vm_init_tsc; 415 u64 vm_init_tsc;
416 s64 kvmclock_offset;
416 417
417 struct kvm_xen_hvm_config xen_hvm_config; 418 struct kvm_xen_hvm_config xen_hvm_config;
418}; 419};
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 13f30aac460b..e16cdc9ec0c1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -680,7 +680,8 @@ static void kvm_write_guest_time(struct kvm_vcpu *v)
680 /* With all the info we got, fill in the values */ 680 /* With all the info we got, fill in the values */
681 681
682 vcpu->hv_clock.system_time = ts.tv_nsec + 682 vcpu->hv_clock.system_time = ts.tv_nsec +
683 (NSEC_PER_SEC * (u64)ts.tv_sec); 683 (NSEC_PER_SEC * (u64)ts.tv_sec) + v->kvm->arch.kvmclock_offset;
684
684 /* 685 /*
685 * The interface expects us to write an even number signaling that the 686 * The interface expects us to write an even number signaling that the
686 * update is finished. Since the guest won't see the intermediate 687 * update is finished. Since the guest won't see the intermediate
@@ -1262,6 +1263,7 @@ int kvm_dev_ioctl_check_extension(long ext)
1262 case KVM_CAP_PIT_STATE2: 1263 case KVM_CAP_PIT_STATE2:
1263 case KVM_CAP_SET_IDENTITY_MAP_ADDR: 1264 case KVM_CAP_SET_IDENTITY_MAP_ADDR:
1264 case KVM_CAP_XEN_HVM: 1265 case KVM_CAP_XEN_HVM:
1266 case KVM_CAP_ADJUST_CLOCK:
1265 r = 1; 1267 r = 1;
1266 break; 1268 break;
1267 case KVM_CAP_COALESCED_MMIO: 1269 case KVM_CAP_COALESCED_MMIO:
@@ -2468,6 +2470,44 @@ long kvm_arch_vm_ioctl(struct file *filp,
2468 r = 0; 2470 r = 0;
2469 break; 2471 break;
2470 } 2472 }
2473 case KVM_SET_CLOCK: {
2474 struct timespec now;
2475 struct kvm_clock_data user_ns;
2476 u64 now_ns;
2477 s64 delta;
2478
2479 r = -EFAULT;
2480 if (copy_from_user(&user_ns, argp, sizeof(user_ns)))
2481 goto out;
2482
2483 r = -EINVAL;
2484 if (user_ns.flags)
2485 goto out;
2486
2487 r = 0;
2488 ktime_get_ts(&now);
2489 now_ns = timespec_to_ns(&now);
2490 delta = user_ns.clock - now_ns;
2491 kvm->arch.kvmclock_offset = delta;
2492 break;
2493 }
2494 case KVM_GET_CLOCK: {
2495 struct timespec now;
2496 struct kvm_clock_data user_ns;
2497 u64 now_ns;
2498
2499 ktime_get_ts(&now);
2500 now_ns = timespec_to_ns(&now);
2501 user_ns.clock = kvm->arch.kvmclock_offset + now_ns;
2502 user_ns.flags = 0;
2503
2504 r = -EFAULT;
2505 if (copy_to_user(argp, &user_ns, sizeof(user_ns)))
2506 goto out;
2507 r = 0;
2508 break;
2509 }
2510
2471 default: 2511 default:
2472 ; 2512 ;
2473 } 2513 }
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index b694c1d2f918..6ed1a12ed526 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -439,6 +439,7 @@ struct kvm_ioeventfd {
439#ifdef __KVM_HAVE_XEN_HVM 439#ifdef __KVM_HAVE_XEN_HVM
440#define KVM_CAP_XEN_HVM 38 440#define KVM_CAP_XEN_HVM 38
441#endif 441#endif
442#define KVM_CAP_ADJUST_CLOCK 39
442 443
443#ifdef KVM_CAP_IRQ_ROUTING 444#ifdef KVM_CAP_IRQ_ROUTING
444 445
@@ -512,6 +513,12 @@ struct kvm_irqfd {
512 __u8 pad[20]; 513 __u8 pad[20];
513}; 514};
514 515
516struct kvm_clock_data {
517 __u64 clock;
518 __u32 flags;
519 __u32 pad[9];
520};
521
515/* 522/*
516 * ioctls for VM fds 523 * ioctls for VM fds
517 */ 524 */
@@ -562,6 +569,9 @@ struct kvm_irqfd {
562#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78) 569#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)
563#define KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd) 570#define KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd)
564#define KVM_XEN_HVM_CONFIG _IOW(KVMIO, 0x7a, struct kvm_xen_hvm_config) 571#define KVM_XEN_HVM_CONFIG _IOW(KVMIO, 0x7a, struct kvm_xen_hvm_config)
572#define KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data)
573#define KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data)
574
565 575
566/* 576/*
567 * ioctls for vcpu fds 577 * ioctls for vcpu fds