return hva + offset;
}
-void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v)
+static void kvm_xen_update_vcpu_time(struct kvm_vcpu *v,
+ struct pvclock_vcpu_time_info *guest_hv_clock)
{
struct kvm_vcpu_arch *vcpu = &v->arch;
- struct pvclock_vcpu_time_info *guest_hv_clock;
- void *hva = xen_vcpu_info(v);
- unsigned int offset;
-
- if (!hva)
- return;
-
- BUILD_BUG_ON(offsetof(struct shared_info, vcpu_info) != 0);
- BUILD_BUG_ON(offsetof(struct compat_shared_info, vcpu_info) != 0);
- BUILD_BUG_ON(sizeof(struct vcpu_info) != sizeof(struct compat_vcpu_info));
- BUILD_BUG_ON(offsetof(struct vcpu_info, time) !=
- offsetof(struct compat_vcpu_info, time));
-
- offset = v->vcpu_id * sizeof(struct vcpu_info);
- offset += offsetof(struct vcpu_info, time);
-
- guest_hv_clock = hva + offset;
if (guest_hv_clock->version & 1)
++guest_hv_clock->version;
guest_hv_clock->version = vcpu->hv_clock.version;
}
+void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v)
+{
+ struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(v);
+ struct vcpu_info *vcpu_info = xen_vcpu_info(v);
+
+ BUILD_BUG_ON(offsetof(struct shared_info, vcpu_info) != 0);
+ BUILD_BUG_ON(offsetof(struct compat_shared_info, vcpu_info) != 0);
+ BUILD_BUG_ON(sizeof(struct vcpu_info) != sizeof(struct compat_vcpu_info));
+ BUILD_BUG_ON(offsetof(struct vcpu_info, time) !=
+ offsetof(struct compat_vcpu_info, time));
+
+ if (likely(vcpu_info))
+ kvm_xen_update_vcpu_time(v, &vcpu_info->time);
+
+ /* Update secondary pvclock region if registered */
+ if (vcpu_xen->pv_time)
+ kvm_xen_update_vcpu_time(v, vcpu_xen->pv_time);
+}
+
static int vcpu_attr_loc(struct kvm_vcpu *vcpu, u16 type,
struct kvm_host_map **map, void ***hva, size_t *sz)
{
if (sz)
*sz = sizeof(struct vcpu_info);
return 0;
+
+ case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO:
+ *map = &vcpu->arch.xen.pv_time_map;
+ *hva = (void **)&vcpu->arch.xen.pv_time;
+ if (sz)
+ *sz = sizeof(struct pvclock_vcpu_time_info);
+ return 0;
}
return -EINVAL;
}
break;
}
+ case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO:
case KVM_XEN_ATTR_TYPE_VCPU_INFO: {
gpa_t gpa = data->u.vcpu_attr.gpa;
struct kvm_host_map *map;
break;
}
+ case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO:
case KVM_XEN_ATTR_TYPE_VCPU_INFO: {
struct kvm_host_map *map;
struct kvm_vcpu *v;
NULL, true, false);
vcpu_xen->vcpu_info = NULL;
}
+ if (vcpu_xen->pv_time) {
+ kvm_unmap_gfn(vcpu->kvm, &vcpu_xen->pv_time_map,
+ NULL, true, false);
+ vcpu_xen->pv_time = NULL;
+ }
}
void kvm_xen_destroy_vm(struct kvm *kvm)