From: "Jason J. Herne" <jjherne@xxxxxxxxxxxxxxxxxx> Enable KVM_SET_CLOCK and KVM_GET_CLOCK ioctls on s390 for managing guest Time Of Day clock value. Signed-off-by: Jason J. Herne <jjherne@xxxxxxxxxxxxxxxxxx> Reviewed-by: David Hildenbrand <dahi@xxxxxxxxxxxxxxxxxx> --- Documentation/virtual/kvm/api.txt | 4 +-- arch/s390/kvm/kvm-s390.c | 74 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 7610eaa..f7eb604 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -745,7 +745,7 @@ struct kvm_xen_hvm_config { 4.29 KVM_GET_CLOCK Capability: KVM_CAP_ADJUST_CLOCK -Architectures: x86 +Architectures: x86, s390 Type: vm ioctl Parameters: struct kvm_clock_data (out) Returns: 0 on success, -1 on error @@ -764,7 +764,7 @@ struct kvm_clock_data { 4.30 KVM_SET_CLOCK Capability: KVM_CAP_ADJUST_CLOCK -Architectures: x86 +Architectures: x86, s390 Type: vm ioctl Parameters: struct kvm_clock_data (in) Returns: 0 on success, -1 on error diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 55aade4..774a2a6 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -31,6 +31,7 @@ #include <asm/switch_to.h> #include <asm/facility.h> #include <asm/sclp.h> +#include<asm/timex.h> #include "kvm-s390.h" #include "gaccess.h" @@ -159,6 +160,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_S390_IRQCHIP: case KVM_CAP_VM_ATTRIBUTES: case KVM_CAP_MP_STATE: + case KVM_CAP_ADJUST_CLOCK: r = 1; break; case KVM_CAP_NR_VCPUS: @@ -328,6 +330,56 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) return ret; } +static int kvm_s390_get_guest_tod(struct kvm *kvm, + struct kvm_clock_data *user_clock) +{ + u64 current_host_tod; + u64 epoch = 0; + struct kvm_vcpu *vcpu; + unsigned int vcpu_idx; + int r; + + /* All vcpu's epochs are in sync. Just Grab the 1st one */ + kvm_for_each_vcpu(vcpu_idx, vcpu, kvm) { + epoch = vcpu->arch.sie_block->epoch; + break; + } + + r = store_tod_clock(¤t_host_tod); + if (r) + return r; + + user_clock->clock = current_host_tod + epoch; + return 0; +} + +/* +Set the guest's effective TOD clock to the given value. The guest's +TOD clock is determined by the following formula: gtod = host_tod + epoch. +NOTE: Even though the epoch value is associated with a vcpu, there is only +one TOD clock and epoch value per guest. All vcpu's epoch values must be kept +synchronized. +*/ +static int kvm_s390_set_guest_tod(struct kvm *kvm, + struct kvm_clock_data *user_clock) +{ + u64 current_host_tod, epoch; + struct kvm_vcpu *vcpu; + unsigned int vcpu_idx; + int r; + + r = store_tod_clock(¤t_host_tod); + if (r) + return r; + + epoch = user_clock->clock - current_host_tod; + + kvm_for_each_vcpu(vcpu_idx, vcpu, kvm) + vcpu->arch.sie_block->epoch = epoch; + + return 0; +} + long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -387,6 +439,28 @@ long kvm_arch_vm_ioctl(struct file *filp, r = kvm_s390_vm_has_attr(kvm, &attr); break; } + case KVM_GET_CLOCK: { + struct kvm_clock_data user_clock; + + r = kvm_s390_get_guest_tod(kvm, &user_clock); + if (r) + break; + + if (copy_to_user(argp, &user_clock, sizeof(user_clock))) + r = -EFAULT; + + break; + } + case KVM_SET_CLOCK: { + struct kvm_clock_data user_clock; + + r = -EFAULT; + if (copy_from_user(&user_clock, argp, + sizeof(struct kvm_clock_data))) + break; + r = kvm_s390_set_guest_tod(kvm, &user_clock); + break; + } default: r = -ENOTTY; } -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html