diff options
-rw-r--r-- | Documentation/kvm/api.txt | 36 | ||||
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 42 | ||||
-rw-r--r-- | include/linux/kvm.h | 10 |
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 | ||
620 | 4.27 KVM_GET_CLOCK | ||
621 | |||
622 | Capability: KVM_CAP_ADJUST_CLOCK | ||
623 | Architectures: x86 | ||
624 | Type: vm ioctl | ||
625 | Parameters: struct kvm_clock_data (out) | ||
626 | Returns: 0 on success, -1 on error | ||
627 | |||
628 | Gets the current timestamp of kvmclock as seen by the current guest. In | ||
629 | conjunction with KVM_SET_CLOCK, it is used to ensure monotonicity on scenarios | ||
630 | such as migration. | ||
631 | |||
632 | struct kvm_clock_data { | ||
633 | __u64 clock; /* kvmclock current value */ | ||
634 | __u32 flags; | ||
635 | __u32 pad[9]; | ||
636 | }; | ||
637 | |||
638 | 4.28 KVM_SET_CLOCK | ||
639 | |||
640 | Capability: KVM_CAP_ADJUST_CLOCK | ||
641 | Architectures: x86 | ||
642 | Type: vm ioctl | ||
643 | Parameters: struct kvm_clock_data (in) | ||
644 | Returns: 0 on success, -1 on error | ||
645 | |||
646 | Sets the current timestamp of kvmclock to the valued specific in its parameter. | ||
647 | In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios | ||
648 | such as migration. | ||
649 | |||
650 | struct kvm_clock_data { | ||
651 | __u64 clock; /* kvmclock current value */ | ||
652 | __u32 flags; | ||
653 | __u32 pad[9]; | ||
654 | }; | ||
655 | |||
620 | 5. The kvm_run structure | 656 | 5. The kvm_run structure |
621 | 657 | ||
622 | Application code obtains a pointer to the kvm_run structure by | 658 | Application 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 | ||
516 | struct 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 |