diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 42 |
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 | } |