aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
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 /arch/x86/kvm/x86.c
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>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c42
1 files changed, 41 insertions, 1 deletions
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 }