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