From nobody Tue Aug 25 20:22:29 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=infradead.org ARC-Seal: i=1; a=rsa-sha256; t=1783113860; cv=none; d=zohomail.com; s=zohoarc; b=CkTniZcumVKG9ukdDjBqVOV15fr9JGyzviUJzEVOyPv0QHGaCT/E2VbyJGVzfJ+Fmn//CMgnh8ex7e1z03lyIiXfRLoa9r3O0tSDSyqbHGWyG+9n2MdZabLQTghPaJgPDHRMP/0D6mgemCwcK5tsWxHhq+eIjrl7bt4iCsH3KfQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1783113860; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=mU5wFjlLT83r2DMLYPo2Un7WZ36IERFw89f8aTvqSMA=; b=KIMhBc3LIQ+7/vuVbTk0hCrHFSxwcCuMXIyZFTCIWiWQhF3X/HCkv844Tu4Br7ZxCBTslLtimasOb6vgv9LLeZacI0bUvzGF0Nzz7iFja/ARyLRriPo4Q9altfbGS5A6sVcG91gqlJgPZ88AxJDovJm4vB2TQVQJsFami/penpg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1783113860492111.79092481891496; Fri, 3 Jul 2026 14:24:20 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1353915.1609731 (Exim 4.92) (envelope-from ) id 1wflMi-0000rX-13; Fri, 03 Jul 2026 21:24:04 +0000 Received: by outflank-mailman (output) from mailman id 1353915.1609731; Fri, 03 Jul 2026 21:24:03 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wflMg-0000mz-Ut; Fri, 03 Jul 2026 21:24:02 +0000 Received: by outflank-mailman (input) for mailman id 1353915; Fri, 03 Jul 2026 21:23:58 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wflMb-0007x2-Fl for xen-devel@lists.xenproject.org; Fri, 03 Jul 2026 21:23:57 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wflMa-00CejO-SH; Fri, 03 Jul 2026 23:23:56 +0200 Received: from [10.42.69.3] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a482835-bab6-0a2a0a5309dd-0a2a45038b46-28 for ; Fri, 03 Jul 2026 23:23:56 +0200 Received: from [90.155.92.199] (helo=desiato.infradead.org) by tlsNG-33051d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a48286c-ec1a-0a2a45030019-5a9b5cc7915c-3 for ; Fri, 03 Jul 2026 23:23:56 +0200 Received: from [2001:8b0:10b:1::425] (helo=i7.infradead.org) by desiato.infradead.org with esmtpsa (Exim 4.99.2 #2 (Red Hat Linux)) id 1wflKd-000000059O5-3OG6; Fri, 03 Jul 2026 21:23:38 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.99.2 #2 (Red Hat Linux)) id 1wflKW-00000001ROq-2d0k; Fri, 03 Jul 2026 22:21:48 +0100 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=desiato.20200630 header.d=infradead.org header.i="@infradead.org" header.h="Sender:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:To:From" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:To:From:Reply-To: Cc:Content-Type:Content-ID:Content-Description; bh=mU5wFjlLT83r2DMLYPo2Un7WZ36IERFw89f8aTvqSMA=; b=pLhCX7LKJ9jL0Egq3v1CQ2lbNB 6geYPA9+pnJQWRXzcRMfmIi6LmGdMv7pThTm9NBNqZ3oV/CLIRofkA9ghaM+kloYstTg6rGJ/uqbr GnQswAHHEQt//Hy0gqdhdsn2erC1pWE0fd77SkDgRHk6MqST5sk0bwspbMRnNR5szbd7Ymj8VJCst YU9p6hcjeyn6NnLTlQsfhXC1nz4OCMMSxlp07pY7lLsSATOEAODpqxY33VaH+awEptGUnxzsC6wQA YeA0u9LEqIHNkVIvkPfmzrOZ2vz+0FVTFKbgwlsKGY+yYpSVLKz1UcRj/XZobe/0Q+GwKKYcpYyCW 9ykmkL4g==; From: David Woodhouse To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Vitaly Kuznetsov , Juergen Gross , Boris Ostrovsky , David Woodhouse , Paul Durrant , Jonathan Cameron , Sascha Bischoff , Marc Zyngier , Joey Gouly , Jack Allister , Dongli Zhang , joe.jin@oracle.com, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, xen-devel@lists.xenproject.org, linux-kselftest@vger.kernel.org Subject: [PATCH v6 16/36] KVM: x86: Restructure kvm_guest_time_update() for TSC upscaling Date: Fri, 3 Jul 2026 22:17:55 +0100 Message-ID: <20260703212145.343527-17-dwmw2@infradead.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260703212145.343527-1-dwmw2@infradead.org> References: <20260703212145.343527-1-dwmw2@infradead.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by desiato.infradead.org. See http://www.infradead.org/rpr.html X-purgate-ID: tlsNG-33051d/1783113836-BD1BE5D1-951A7974/0/0 X-purgate-type: clean X-purgate-size: 4893 X-ZohoMail-DKIM: pass (identity @infradead.org) X-ZM-MESSAGEID: 1783113860964158500 Content-Type: text/plain; charset="utf-8" From: David Woodhouse Restructure kvm_guest_time_update() so that kernel_ns/host_tsc are always "now" when doing TSC catchup, then swap in the master clock reference values afterward for the hv_clock. This makes the TSC upscaling code considerably simpler: the catchup adjustment is computed as the delta between what the guest TSC *should* be at "now" and what it actually is, rather than mixing "now" and "master clock reference" timestamps. The seqcount loop now also contains the kvm_get_time_and_clockread() call (matching get_kvmclock's pattern). Based on a suggestion by Sean Christopherson. Signed-off-by: David Woodhouse --- arch/x86/kvm/x86.c | 78 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 55fb19fb7a88..9dc4213f0fa5 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3349,45 +3349,60 @@ static void kvm_setup_guest_pvclock(struct pvclock_= vcpu_time_info *ref_hv_clock, int kvm_guest_time_update(struct kvm_vcpu *v) { struct pvclock_vcpu_time_info hv_clock =3D {}; - unsigned long flags; u64 tgt_tsc_hz; unsigned seq; struct kvm_vcpu_arch *vcpu =3D &v->arch; struct kvm_arch *ka =3D &v->kvm->arch; s64 kernel_ns; u64 tsc_timestamp, host_tsc; + u64 master_host_tsc =3D 0; + s64 master_kernel_ns =3D 0; + s64 kvmclock_offset =3D 0; bool use_master_clock; =20 - kernel_ns =3D 0; - host_tsc =3D 0; - /* * If the host uses TSC clock, then passthrough TSC as stable * to the guest. */ do { seq =3D read_seqcount_begin(&ka->pvclock_sc); + use_master_clock =3D ka->use_master_clock; + + /* + * The TSC read and the call to get_cpu_tsc_khz() must happen + * on the same CPU. + */ + get_cpu(); + + tgt_tsc_hz =3D (u64)get_cpu_tsc_khz() * 1000; + +#ifdef CONFIG_X86_64 + if (use_master_clock && + !kvm_get_time_and_clockread(&kernel_ns, &host_tsc) && + !read_seqcount_retry(&ka->pvclock_sc, seq)) + use_master_clock =3D false; +#endif + + put_cpu(); + if (use_master_clock) { - host_tsc =3D ka->master_cycle_now; - kernel_ns =3D ka->master_kernel_ns; + master_host_tsc =3D ka->master_cycle_now; + master_kernel_ns =3D ka->master_kernel_ns; + } else { + local_irq_disable(); + host_tsc =3D rdtsc(); + kernel_ns =3D get_kvmclock_base_ns(); + local_irq_enable(); } + + kvmclock_offset =3D ka->kvmclock_offset; } while (read_seqcount_retry(&ka->pvclock_sc, seq)); =20 - /* Keep irq disabled to prevent changes to the clock */ - local_irq_save(flags); - tgt_tsc_hz =3D (u64)get_cpu_tsc_khz() * 1000; if (unlikely(tgt_tsc_hz =3D=3D 0)) { - local_irq_restore(flags); kvm_make_request(KVM_REQ_CLOCK_UPDATE, v); return 1; } - if (!use_master_clock) { - host_tsc =3D rdtsc(); - kernel_ns =3D get_kvmclock_base_ns(); - } - - tsc_timestamp =3D kvm_read_l1_tsc(v, host_tsc); =20 /* * We may have to catch up the TSC to match elapsed wall clock @@ -3397,17 +3412,32 @@ int kvm_guest_time_update(struct kvm_vcpu *v) * entry to avoid unknown leaps of TSC even when running * again on the same CPU. This may cause apparent elapsed * time to disappear, and the guest to stand still or run - * very slowly. + * very slowly. */ if (vcpu->tsc_catchup) { - u64 tsc =3D compute_guest_tsc(v, kernel_ns); - if (tsc > tsc_timestamp) { - adjust_tsc_offset_guest(v, tsc - tsc_timestamp); - tsc_timestamp =3D tsc; - } + s64 adjustment; + + /* + * Calculate the delta between what the guest TSC *should* be + * and what it actually is according to kvm_read_l1_tsc(). + */ + adjustment =3D compute_guest_tsc(v, kernel_ns) - + kvm_read_l1_tsc(v, host_tsc); + if (adjustment > 0) + adjust_tsc_offset_guest(v, adjustment); } =20 - local_irq_restore(flags); + /* + * Now that TSC upscaling is out of the way, the remaining calculations + * are all relative to the reference time that's placed in hv_clock. + * If the master clock is NOT in use, the reference time is "now". If + * master clock is in use, the reference time comes from there. + */ + if (use_master_clock) { + host_tsc =3D master_host_tsc; + kernel_ns =3D master_kernel_ns; + } + tsc_timestamp =3D kvm_read_l1_tsc(v, host_tsc); =20 /* With all the info we got, fill in the values */ =20 @@ -3427,7 +3457,7 @@ int kvm_guest_time_update(struct kvm_vcpu *v) hv_clock.tsc_shift =3D vcpu->pvclock_tsc_shift; hv_clock.tsc_to_system_mul =3D vcpu->pvclock_tsc_mul; hv_clock.tsc_timestamp =3D tsc_timestamp; - hv_clock.system_time =3D kernel_ns + v->kvm->arch.kvmclock_offset; + hv_clock.system_time =3D kernel_ns + kvmclock_offset; vcpu->last_guest_tsc =3D tsc_timestamp; =20 /* If the host uses TSC clocksource, then it is stable */ --=20 2.54.0