From patchwork Tue Jun 11 17:01:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10987845 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5A92B76 for ; Tue, 11 Jun 2019 17:03:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 47166285A8 for ; Tue, 11 Jun 2019 17:03:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3AF0928600; Tue, 11 Jun 2019 17:03:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 85445285A8 for ; Tue, 11 Jun 2019 17:03:07 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hak9T-0005g0-IV; Tue, 11 Jun 2019 17:01:39 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hak9R-0005fG-V0 for xen-devel@lists.xenproject.org; Tue, 11 Jun 2019 17:01:37 +0000 X-Inumbo-ID: 902b045e-8c6a-11e9-bc3d-bb4c0d3b4876 Received: from esa4.hc3370-68.iphmx.com (unknown [216.71.155.144]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 902b045e-8c6a-11e9-bc3d-bb4c0d3b4876; Tue, 11 Jun 2019 17:01:33 +0000 (UTC) Authentication-Results: esa4.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=paul.durrant@citrix.com; spf=Pass smtp.mailfrom=Paul.Durrant@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa4.hc3370-68.iphmx.com: no sender authenticity information available from domain of paul.durrant@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa4.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="paul.durrant@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa4.hc3370-68.iphmx.com: domain of Paul.Durrant@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa4.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="Paul.Durrant@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa4.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa4.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: 7FPgVj0AsAn5EEMIY4gxXIzWd/oh8qlGHaGeqCcZuptAm5H6GMNmkuJWHeIE6HPr5YD+uU2hyX LU0S5WjU/LRWnUE76Ste0FS7FdZW1OBJ59lo+ervfamsMOKNkIdfoUfWE3kjnUDwR3tLiHSZAz t1sOJhP8Dxdv6XMtLzbSKbKstuXfWKexSSlK2O6o5uLUaWhP/8qIZyjOjFCour10fJDMZH8uia MIOYTW7yIxIhDl1FF/sOkIbJxTvoNCEruEsMColhsOWn+YlwDcSEeoiv8/FN4lFABsGrSslYRo QWA= X-SBRS: 2.7 X-MesageID: 1599307 X-Ironport-Server: esa4.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.63,362,1557201600"; d="scan'208";a="1599307" From: Paul Durrant To: Date: Tue, 11 Jun 2019 18:01:27 +0100 Message-ID: <20190611170127.2650-1-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb671 MIME-Version: 1.0 Subject: [Xen-devel] [PATCH] viridian: unify time sources X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Paul Durrant , Wei Liu , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Jan Beulich Cc: Andrew Cooper Cc: Wei Liu Cc: "Roger Pau Monné" --- xen/arch/x86/hvm/viridian/time.c | 99 ++++++++++++------------------ xen/include/asm-x86/hvm/viridian.h | 1 - 2 files changed, 40 insertions(+), 60 deletions(-) diff --git a/xen/arch/x86/hvm/viridian/time.c b/xen/arch/x86/hvm/viridian/time.c index 2a3c9697d7..cc7d600023 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; @@ -62,8 +63,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; } @@ -77,6 +76,7 @@ static void update_reference_tsc(struct domain *d, bool initialize) * ticks per 100ns shifted left by 64. */ p->TscScale = ((10000ul << 32) / d->arch.tsc_khz) << 32; + p->TscOffset = trc->off; smp_wmb(); seq = p->TscSequence + 1; @@ -84,46 +84,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 +96,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 +113,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 +180,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 +269,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 +625,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,