On 12/14/20 8:39 AM, David Woodhouse wrote: > From: Joao Martins <joao.m.martins@xxxxxxxxxx> > > Allow the Xen emulated guest the ability to register secondary > vcpu time information. On Xen guests this is used in order to be > mapped to userspace and hence allow vdso gettimeofday to work. > > In doing so, move kvm_xen_set_pvclock_page() logic to > kvm_xen_update_vcpu_time() and have the former a top-level > function which updates primary vcpu time info (in struct vcpu_info) > and secondary one. > > Signed-off-by: Joao Martins <joao.m.martins@xxxxxxxxxx> > Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx> > --- > arch/x86/include/asm/kvm_host.h | 2 ++ > arch/x86/kvm/x86.c | 2 ++ > arch/x86/kvm/xen.c | 26 ++++++++++++++++++++++++++ > include/uapi/linux/kvm.h | 1 + > 4 files changed, 31 insertions(+) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 56c00a9441a3..b7dfcb4de92a 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -524,7 +524,9 @@ struct kvm_vcpu_hv { > struct kvm_vcpu_xen { > u64 hypercall_rip; > bool vcpu_info_set; > + bool vcpu_time_info_set; > struct gfn_to_hva_cache vcpu_info_cache; > + struct gfn_to_hva_cache vcpu_time_info_cache; > }; > > struct kvm_vcpu_arch { > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index cbdc05bb53bd..2234fdf49d82 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -2729,6 +2729,8 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) > if (vcpu->xen.vcpu_info_set) > kvm_setup_pvclock_page(v, &vcpu->xen.vcpu_info_cache, > offsetof(struct compat_vcpu_info, time)); > + if (vcpu->xen.vcpu_time_info_set) > + kvm_setup_pvclock_page(v, &vcpu->xen.vcpu_time_info_cache, 0); > if (v == kvm_get_vcpu(v->kvm, 0)) > kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock); > return 0; > diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c > index d2055b60fdc1..1cca46effec8 100644 > --- a/arch/x86/kvm/xen.c > +++ b/arch/x86/kvm/xen.c > @@ -95,6 +95,21 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) > kvm_make_request(KVM_REQ_CLOCK_UPDATE, v); > break; > > + case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO: > + v = kvm_get_vcpu_by_id(kvm, data->u.vcpu_attr.vcpu_id); > + if (!v) > + return -EINVAL; > + > + r = kvm_gfn_to_hva_cache_init(kvm, &v->arch.xen.vcpu_time_info_cache, > + data->u.vcpu_attr.gpa, > + sizeof(struct pvclock_vcpu_time_info)); > + if (r) > + return r; > + > + v->arch.xen.vcpu_time_info_set = true; Same comment as shared_info: we probably don't need vcpu_time_info_set if we piggyback on the gfn_to_hva cache setting its @gpa field. > + kvm_make_request(KVM_REQ_CLOCK_UPDATE, v); > + break; > + > default: > break; > } > @@ -131,6 +146,17 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) > } > break; > > + case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO: > + v = kvm_get_vcpu_by_id(kvm, data->u.vcpu_attr.vcpu_id); > + if (!v) > + return -EINVAL; > + > + if (v->arch.xen.vcpu_time_info_set) { > + data->u.vcpu_attr.gpa = v->arch.xen.vcpu_time_info_cache.gpa; > + r = 0; > + } > + break; > + > default: > break; > } > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h > index 87d150992f48..f60c5c61761c 100644 > --- a/include/uapi/linux/kvm.h > +++ b/include/uapi/linux/kvm.h > @@ -1599,6 +1599,7 @@ struct kvm_xen_hvm_attr { > #define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 > #define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 > #define KVM_XEN_ATTR_TYPE_VCPU_INFO 0x2 > +#define KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO 0x3 > > /* Secure Encrypted Virtualization command */ > enum sev_cmd_id { >