|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2] viridian: unify time sources
Ping?
> -----Original Message-----
> From: Paul Durrant <paul.durrant@xxxxxxxxxx>
> Sent: 17 June 2019 09:24
> To: xen-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Paul Durrant <Paul.Durrant@xxxxxxxxxx>; Jan Beulich <jbeulich@xxxxxxxx>;
> Andrew Cooper
> <Andrew.Cooper3@xxxxxxxxxx>; Wei Liu <wl@xxxxxxx>; Roger Pau Monne
> <roger.pau@xxxxxxxxxx>
> Subject: [PATCH v2] viridian: unify time sources
>
> Currently, the time_ref_count enlightened time source maintains an offset
> such that time is frozen when the domain paused, but the reference_tsc
> enlightened time source does not. After migrate, the reference_tsc source
> may become invalidated (e.g. because of host cpu frequency mismatch) which
> will cause Windows to fall back to time_ref_count. Thus, the guest will
> observe a jump in time equivalent to the offset.
>
> This patch unifies the two enlightened time sources such that the same
> offset applies to both of them. Also, it's not really necessary to have
> two different functions to calculating a 10MHz counter value, time_now() and
> raw_trc_val(), so this patch removes the latter implementation. The
> unification also allows removal of the reference_tsc_valid flag.
>
> Whilst in the area, this patch also takes the opportunity to constify a few
> pointers which were missed in earlier patches.
>
> Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
> ---
> Cc: Jan Beulich <jbeulich@xxxxxxxx>
> Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> Cc: Wei Liu <wl@xxxxxxx>
> Cc: "Roger Pau Monné" <roger.pau@xxxxxxxxxx>
>
> v2:
> - Expand comments above newly added TscOffset setting
> ---
> xen/arch/x86/hvm/viridian/time.c | 105 +++++++++++++----------------
> xen/include/asm-x86/hvm/viridian.h | 1 -
> 2 files changed, 45 insertions(+), 61 deletions(-)
>
> diff --git a/xen/arch/x86/hvm/viridian/time.c
> b/xen/arch/x86/hvm/viridian/time.c
> index 2a3c9697d7..28e3d88ca9 100644
> --- a/xen/arch/x86/hvm/viridian/time.c
> +++ b/xen/arch/x86/hvm/viridian/time.c
> @@ -26,9 +26,10 @@ typedef struct _HV_REFERENCE_TSC_PAGE
> uint64_t Reserved2[509];
> } HV_REFERENCE_TSC_PAGE, *PHV_REFERENCE_TSC_PAGE;
>
> -static void update_reference_tsc(struct domain *d, bool initialize)
> +static void update_reference_tsc(const struct domain *d, bool initialize)
> {
> struct viridian_domain *vd = d->arch.hvm.viridian;
> + const struct viridian_time_ref_count *trc = &vd->time_ref_count;
> const struct viridian_page *rt = &vd->reference_tsc;
> HV_REFERENCE_TSC_PAGE *p = rt->ptr;
> uint32_t seq;
> @@ -44,7 +45,9 @@ static void update_reference_tsc(struct domain *d, bool
> initialize)
> * with this, allowing vtsc to be turned off, but support for this is
> * not yet present in the hypervisor. Thus is it is possible that
> * migrating a Windows VM between hosts of differing TSC frequencies
> - * may result in large differences in guest performance.
> + * may result in large differences in guest performance. Any jump in
> + * TSC due to migration down-time can, however, be compensated for by
> + * setting the TscOffset value (see below).
> */
> if ( !host_tsc_is_safe() || d->arch.vtsc )
> {
> @@ -62,8 +65,6 @@ static void update_reference_tsc(struct domain *d, bool
> initialize)
>
> printk(XENLOG_G_INFO "d%d: VIRIDIAN REFERENCE_TSC: invalidated\n",
> d->domain_id);
> -
> - vd->reference_tsc_valid = false;
> return;
> }
>
> @@ -75,8 +76,11 @@ static void update_reference_tsc(struct domain *d, bool
> initialize)
> *
> * Windows uses a 100ns tick, so we need a scale which is cpu
> * ticks per 100ns shifted left by 64.
> + * The offset value is calculated on restore after migration and
> + * ensures that Windows will not see a large jump in ReferenceTime.
> */
> p->TscScale = ((10000ul << 32) / d->arch.tsc_khz) << 32;
> + p->TscOffset = trc->off;
> smp_wmb();
>
> seq = p->TscSequence + 1;
> @@ -84,46 +88,6 @@ static void update_reference_tsc(struct domain *d, bool
> initialize)
> seq = 1;
>
> p->TscSequence = seq;
> - vd->reference_tsc_valid = true;
> -}
> -
> -static int64_t raw_trc_val(const struct domain *d)
> -{
> - uint64_t tsc;
> - struct time_scale tsc_to_ns;
> -
> - tsc = hvm_get_guest_tsc(pt_global_vcpu_target(d));
> -
> - /* convert tsc to count of 100ns periods */
> - set_time_scale(&tsc_to_ns, d->arch.tsc_khz * 1000ul);
> - return scale_delta(tsc, &tsc_to_ns) / 100ul;
> -}
> -
> -static void time_ref_count_freeze(const struct domain *d)
> -{
> - struct viridian_time_ref_count *trc =
> - &d->arch.hvm.viridian->time_ref_count;
> -
> - if ( test_and_clear_bit(_TRC_running, &trc->flags) )
> - trc->val = raw_trc_val(d) + trc->off;
> -}
> -
> -static void time_ref_count_thaw(const struct domain *d)
> -{
> - struct viridian_time_ref_count *trc =
> - &d->arch.hvm.viridian->time_ref_count;
> -
> - if ( !d->is_shutting_down &&
> - !test_and_set_bit(_TRC_running, &trc->flags) )
> - trc->off = (int64_t)trc->val - raw_trc_val(d);
> -}
> -
> -static int64_t time_ref_count(const struct domain *d)
> -{
> - struct viridian_time_ref_count *trc =
> - &d->arch.hvm.viridian->time_ref_count;
> -
> - return raw_trc_val(d) + trc->off;
> }
>
> /*
> @@ -136,7 +100,7 @@ static int64_t time_ref_count(const struct domain *d)
> * 128 bit number which is then shifted 64 times to the right to obtain
> * the high 64 bits."
> */
> -static uint64_t scale_tsc(uint64_t tsc, uint64_t scale, uint64_t offset)
> +static uint64_t scale_tsc(uint64_t tsc, uint64_t scale, int64_t offset)
> {
> uint64_t result;
>
> @@ -153,22 +117,46 @@ static uint64_t scale_tsc(uint64_t tsc, uint64_t scale,
> uint64_t offset)
> return result + offset;
> }
>
> -static uint64_t time_now(struct domain *d)
> +static uint64_t trc_val(const struct domain *d, int64_t offset)
> {
> uint64_t tsc, scale;
>
> - /*
> - * If the reference TSC page is not enabled, or has been invalidated
> - * fall back to the partition reference counter.
> - */
> - if ( !d->arch.hvm.viridian->reference_tsc_valid )
> - return time_ref_count(d);
> -
> - /* Otherwise compute reference time in the same way the guest would */
> tsc = hvm_get_guest_tsc(pt_global_vcpu_target(d));
> scale = ((10000ul << 32) / d->arch.tsc_khz) << 32;
>
> - return scale_tsc(tsc, scale, 0);
> + return scale_tsc(tsc, scale, offset);
> +}
> +
> +static void time_ref_count_freeze(const struct domain *d)
> +{
> + struct viridian_time_ref_count *trc =
> + &d->arch.hvm.viridian->time_ref_count;
> +
> + if ( test_and_clear_bit(_TRC_running, &trc->flags) )
> + trc->val = trc_val(d, trc->off);
> +}
> +
> +static void time_ref_count_thaw(const struct domain *d)
> +{
> + struct viridian_domain *vd = d->arch.hvm.viridian;
> + struct viridian_time_ref_count *trc = &vd->time_ref_count;
> +
> + if ( d->is_shutting_down ||
> + test_and_set_bit(_TRC_running, &trc->flags) )
> + return;
> +
> + trc->off = (int64_t)trc->val - trc_val(d, 0);
> +
> + if ( vd->reference_tsc.msr.enabled )
> + update_reference_tsc(d, false);
> +}
> +
> +static int64_t time_ref_count(const struct domain *d)
> +{
> + const struct viridian_time_ref_count *trc =
> + &d->arch.hvm.viridian->time_ref_count;
> +
> + return trc_val(d, trc->off);
> }
>
> static void stop_stimer(struct viridian_stimer *vs)
> @@ -196,7 +184,7 @@ static void start_stimer(struct viridian_stimer *vs)
> const struct vcpu *v = vs->v;
> struct viridian_vcpu *vv = v->arch.hvm.viridian;
> unsigned int stimerx = vs - &vv->stimer[0];
> - int64_t now = time_now(v->domain);
> + int64_t now = time_ref_count(v->domain);
> int64_t expiration;
> s_time_t timeout;
>
> @@ -285,7 +273,7 @@ static void poll_stimer(struct vcpu *v, unsigned int
> stimerx)
>
> if ( !viridian_synic_deliver_timer_msg(v, vs->config.sintx,
> stimerx, vs->expiration,
> - time_now(v->domain)) )
> + time_ref_count(v->domain)) )
> return;
>
> clear_bit(stimerx, &vv->stimer_pending);
> @@ -641,10 +629,7 @@ void viridian_time_load_domain_ctxt(
> vd->reference_tsc.msr.raw = ctxt->reference_tsc;
>
> if ( vd->reference_tsc.msr.enabled )
> - {
> viridian_map_guest_page(d, &vd->reference_tsc);
> - update_reference_tsc(d, false);
> - }
> }
>
> /*
> diff --git a/xen/include/asm-x86/hvm/viridian.h
> b/xen/include/asm-x86/hvm/viridian.h
> index 54e46cc4c4..010c8b58d4 100644
> --- a/xen/include/asm-x86/hvm/viridian.h
> +++ b/xen/include/asm-x86/hvm/viridian.h
> @@ -116,7 +116,6 @@ struct viridian_domain
> union viridian_page_msr hypercall_gpa;
> struct viridian_time_ref_count time_ref_count;
> struct viridian_page reference_tsc;
> - bool reference_tsc_valid;
> };
>
> void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf,
> --
> 2.20.1.2.gb21ebb671
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |