From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.openvz.org (mail.openvz.org [69.168.225.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id 64C5B80E7E for ; Fri, 6 Nov 2026 13:44:41 +0000 (UTC) Received: from mail.openvz.org (localhost [127.0.0.1]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6A6DhKIg018605; Fri, 6 Nov 2026 16:43:21 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A6DhKIg018605 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="OwPMo+n/" Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6A6DhJKp018601 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Fri, 6 Nov 2026 16:43:19 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A6DhJKp018601 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-4a77c1cbd15so6803785e9.0 for ; Fri, 06 Nov 2026 05:43:19 -0800 (PST) X-Gm-Message-State: APuU4Z/gH5LFYTvKSkQ6xs01We6SviTWuD3aSWQc/R4tdRNsUs+GuBZA YHDU7BclrgPAPCtp6MCC+mgUAQSjDtj7tgL7HsmY0iJO410Jts+5Gd8a7rg6sh7bliCVBUGtmd5 K7ZD+zzO/dv0jTm7wSxQJ1403ZxjBhuXeN9sFFVPLHJGiSE08TNJIDA== X-Gm-Gg: AYBFou02GvUF023fjlztHHv0Z3kG655+58S/EOa63NylXj9dzBLpjz/MTS9z7YLf4hE Ql/zFJ7BhgchnO0rokvNtGTDE0N2LKTerHPAoTy/ayrqQqeNYJFSm7vgq2exYuf2XB/uWIpCmV4 hEbqqr46Yr5RNX5wIBFyOmSC4xf4++l86Ch4Q1SRq9aiTCRTthOuo5N017bxKjmPxUsYmtq90bG PeRjnWQtcwmkJ5eU6oAbQ7/h7ojQNonQo9qBxdbac54ptXObXcCwUciFO2G26xyGjMglxiX1ve+ ScmNYXBVOQtsu2nEBM3Aah3kMqkPnDRrYucZuCkQvE8df/KfW3EVSrT0QiIUoCKQX4lLpLxJF3v wyDBHCNCDiPdji93s9iWxr2OP X-Received: by 2002:a05:600c:310f:b0:4a7:7d22:c50c with SMTP id 5b1f17b1804b1-4b6dc6dec33mr41748735e9.2.1793972599125; Fri, 06 Nov 2026 05:43:19 -0800 (PST) X-Received: by 2002:a05:600c:310f:b0:4a7:7d22:c50c with SMTP id 5b1f17b1804b1-4b6dc6dec33mr41748205e9.2.1793972598585; Fri, 06 Nov 2026 05:43:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1793972598; cv=none; d=google.com; s=arc-20260327; b=rzg3fkHZWX1Pqaesu5T/c75jPMUaTUezz9G34PDWlFjJ6qnQVDOzfD/MoaVH4Wm3N6 imv9PszClV8XldLrmzCDLRQ6EXh027oL9UIgxnf7Vri/ZIz7DeKrUuK5XYflf+0dYHCp XloDllyxB4+GeodJuZNl0TubIDuBYXZu3BrCApYiT2fodswoOLjMBtsDgL0UETmuJS5t z0CY6KRhe9hM0JwqyKLoYcsxatgFfXULvkYS2opc0mO79P5jXKomjniJg+uO1ajAeSi2 CI0eppToyXzMcIuExm/q5DsYMY91882fa9MyRSdRsInD7iMDoWaGfFaQC1/3FC6waRhS zOeQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:dkim-signature; bh=Qwrn9AXzq8JL8+4X7QHXTHM4qZN2mH0gxwina1+IQmQ=; fh=WpT6aB7RBAGHZeWZzqAr71yzRFbPTYkPWKsRagLn48Q=; b=Bpk+qs8RY6e47p4CbcVDNcjYFTkqrOsx/uUq96Ia00ms6AYwWPPL+jqU9ivXqGhScV T+9ml46IX/aQHrYMMoTDxDEobpQcMoD4ws7OtSWy3NWLzYppLehFsA63NJpUEEjtVOum vnEWEw/lnmNVOHTEtjnVpBF5A1H7qHJcsqEsJZhW59pCN/jIB1RY7WWfmvndb7yjavsP Eiussax+WG39G0fSNcGaUefuzY2FARDjGQ8k3yrd2smJ8nsAVcwQFKvjfqfCzu9Pl537 wgk8VcsJ7d1DQn3SitsflVUm3V9BiR7XKOjFQIi7duEzdZEZNxW8mv2w909x50wStdeR 7aWw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b="OwPMo+n/"; spf=pass (google.com: domain of eva.kurchatova@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=eva.kurchatova@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com Received: from relay.virtuozzo.com (relay.virtuozzo.com. [130.117.225.111]) by mx.google.com with ESMTPS id ffacd0b85a97d-492d65b59e0si3726337f8f.73.2026.11.06.05.43.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 06 Nov 2026 05:43:18 -0800 (PST) Received-SPF: pass (google.com: domain of eva.kurchatova@virtuozzo.com designates 130.117.225.111 as permitted sender) client-ip=130.117.225.111; Authentication-Results: mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b="OwPMo+n/"; spf=pass (google.com: domain of eva.kurchatova@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=eva.kurchatova@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-ID:Date:Subject:From: Content-Type; bh=Qwrn9AXzq8JL8+4X7QHXTHM4qZN2mH0gxwina1+IQmQ=; b=OwPMo+n/Z1/I X+NK6np/YJTEsK1+2Ii2pMpu7do1Wu7BI3hn5UEQRRgxeA3wwR7Pchc6qULeVuhBjcyNfoO8TEvwN EVWbfOf4UoTshYvTqyGJe5DppEUKRQJVIierg7o8AEmo52jxIRppOH/lWa2YhHBrFjJfKP+UP843w WYx4mvxIcT4nG+w1CxwqFo1JRUtOJjNPIX1TWz2vzZTrKdaaNg5venotC/IVyR6IWgRiBdkBMEFtW e/eh2A3+pKw6FbmYwgY0vGQkxgUkkZ6bzIuiZlfrTI02x9nuwV2NsWuPJt5/lOLaXBXUUqSJWOhYo N0qjSt9sF7SbizwBMzbkxg==; Received: from ch-vpn.virtuozzo.com ([130.117.225.6] helo=LekKit-T14) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1xPK9u-00BGDk-0U; Fri, 06 Nov 2026 14:43:14 +0100 From: Eva Kurchatova To: khorenko@virtuozzo.com Date: Fri, 6 Nov 2026 15:43:07 +0200 Message-ID: <20261106134316.84189-1-eva.kurchatova@virtuozzo.com> X-Mailer: git-send-email 2.56.0 MIME-Version: 1.0 X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH hci-8.1] KVM: nVMX: Keep the emulated VMX-preemption timer on L1's TSC X-BeenThere: devel@openvz.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: OpenVZ development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: devel-bounces@openvz.org Errors-To: devel-bounces@openvz.org KVM emulates the VMX-preemption timer of L2 with an hrtimer, and turns the timer value into nanoseconds with the TSC frequency of the vCPU. The hrtimer runs on CLOCK_MONOTONIC, which NTP slews against the TSC, so the VM-exit comes late or early in L1's TSC while the host clock is slewed. vmx_preemption_timer_test then fails with "L2 PT expiry TSC > L2 TSC deadline" when the clock is slowed down, and with "L1 PT expiry TSC < L1 TSC deadline" when it is sped up. Arm the hrtimer an eighth early, and re-arm it from its callback until L1's TSC reaches the deadline that KVM keeps since commit 850448f35aaf ("KVM: nVMX: Fix VMX preemption timer migration"). Count the timer value that is left from that deadline when starting the timer and when saving it to vmcs12, as the hrtimer no longer tracks it. Fixes: f4124500c2c1 ("KVM: nVMX: Fully emulate preemption timer") https://virtuozzo.atlassian.net/browse/VSTOR-152991 Feature: fix ms/kvm Signed-off-by: Eva Kurchatova --- arch/x86/kvm/vmx/nested.c | 67 +++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 8c771d8c35e3..3f6a606e97a0 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -2206,15 +2206,51 @@ void nested_sync_vmcs12_to_shadow(struct kvm_vcpu *vcpu) vmx->nested.need_vmcs12_to_shadow_sync = false; } +/* Ticks left until L1's TSC reaches the deadline, at most the 32-bit value */ +static u64 vmx_preemption_timer_left(struct kvm_vcpu *vcpu) +{ + u64 deadline = to_vmx(vcpu)->nested.preemption_timer_deadline; + u64 now = kvm_read_l1_tsc(vcpu, rdtsc()) >> + VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE; + + return deadline > now ? min(deadline - now, (u64)U32_MAX) : 0; +} + +/* + * The hrtimer runs on CLOCK_MONOTONIC, which NTP may slew against the TSC by + * up to 10%: fire an eighth early while more than 100us are left, and let the + * callback re-arm until the deadline is reached. + */ +static ktime_t vmx_preemption_timer_expiry(struct kvm_vcpu *vcpu, u64 ticks) +{ + u64 ns = (ticks << VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE) * 1000000; + + do_div(ns, vcpu->arch.virtual_tsc_khz); + if (ns > 100 * NSEC_PER_USEC) + ns -= ns >> 3; + return ktime_add_ns(ktime_get(), ns); +} + +static void vmx_preemption_timer_expire(struct kvm_vcpu *vcpu) +{ + to_vmx(vcpu)->nested.preemption_timer_expired = true; + kvm_make_request(KVM_REQ_EVENT, vcpu); + kvm_vcpu_kick(vcpu); +} + static enum hrtimer_restart vmx_preemption_timer_fn(struct hrtimer *timer) { struct vcpu_vmx *vmx = container_of(timer, struct vcpu_vmx, nested.preemption_timer); + u64 left = vmx_preemption_timer_left(&vmx->vcpu); - vmx->nested.preemption_timer_expired = true; - kvm_make_request(KVM_REQ_EVENT, &vmx->vcpu); - kvm_vcpu_kick(&vmx->vcpu); + if (left) { + hrtimer_set_expires(timer, + vmx_preemption_timer_expiry(&vmx->vcpu, left)); + return HRTIMER_RESTART; + } + vmx_preemption_timer_expire(&vmx->vcpu); return HRTIMER_NORESTART; } @@ -2231,7 +2267,7 @@ static u64 vmx_calc_preemption_timer_value(struct kvm_vcpu *vcpu) vmcs12->vmx_preemption_timer_value + l1_scaled_tsc; vmx->nested.has_preemption_timer_deadline = true; } - return vmx->nested.preemption_timer_deadline - l1_scaled_tsc; + return vmx_preemption_timer_left(vcpu); } static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu, @@ -2244,18 +2280,15 @@ static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu, * a VMExit prior to executing any instructions in the guest. */ if (preemption_timeout == 0) { - vmx_preemption_timer_fn(&vmx->nested.preemption_timer); + vmx_preemption_timer_expire(vcpu); return; } if (vcpu->arch.virtual_tsc_khz == 0) return; - preemption_timeout <<= VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE; - preemption_timeout *= 1000000; - do_div(preemption_timeout, vcpu->arch.virtual_tsc_khz); hrtimer_start(&vmx->nested.preemption_timer, - ktime_add_ns(ktime_get(), preemption_timeout), + vmx_preemption_timer_expiry(vcpu, preemption_timeout), HRTIMER_MODE_ABS_PINNED); } @@ -4428,20 +4461,6 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu) return vmx_complete_nested_posted_interrupt(vcpu); } -static u32 vmx_get_preemption_timer_value(struct kvm_vcpu *vcpu) -{ - ktime_t remaining = - hrtimer_get_remaining(&to_vmx(vcpu)->nested.preemption_timer); - u64 value; - - if (ktime_to_ns(remaining) <= 0) - return 0; - - value = ktime_to_ns(remaining) * vcpu->arch.virtual_tsc_khz; - do_div(value, 1000000); - return value >> VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE; -} - static bool is_vmcs12_ext_field(unsigned long field) { switch (field) { @@ -4597,7 +4616,7 @@ static void sync_vmcs02_to_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) vmcs12->vm_exit_controls & VM_EXIT_SAVE_VMX_PREEMPTION_TIMER && !vmx->nested.nested_run_pending) vmcs12->vmx_preemption_timer_value = - vmx_get_preemption_timer_value(vcpu); + vmx_preemption_timer_left(vcpu); /* * In some cases (usually, nested EPT), L2 is allowed to change its -- 2.56.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel