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 5FDAF8017D for ; Fri, 6 Nov 2026 15:17:06 +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 6A6FFfLq019208; Fri, 6 Nov 2026 18:15:42 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A6FFfLq019208 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="ojCk+ONF" Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6A6FFd1F019204 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Fri, 6 Nov 2026 18:15:40 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A6FFd1F019204 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-49090fde23aso776473f8f.2 for ; Fri, 06 Nov 2026 07:15:40 -0800 (PST) X-Gm-Message-State: APuU4Z/LCR34dZEO8vQ0bdJQ1jtFF1D0Kycku0p3nK3ZqE6lyvf+Fzs3 gCEK34vgGaWaV3UlTeXq9iInu+AunDw+ymRnNu6/KWKNxDZWx4Y0aWkhUEmOgmdEF9oyBxxaSDO +/CcYh4hREve9nxl6/EDZ7zKnWJ9sTJjpf4WZPydUX+cqxhF1JHvzRg== X-Gm-Gg: AYBFou0qAxa3V1Z5EXDLzcD/yevgxAN5hJrGx2wzyzJjNke5Qk+Bsx0z9ncFpdTH/ek qww4MsGh+ekmqawpZBx7t0kByIT0bPMhv5xAplwqD5Myo36vJJzGCyhWh7SzuVZLswGIVzNW93W lV76zRLTMwG8j+qFdbJMNP7rXsVm1bCVQtRrnoPcqtApaJS0Bq+XFXdlGXlCx3Fmx7MwrfNWanH hyrcUdtESSoxaJ9cPKds7L2B4M0WaX4yp8YLUVISJfvtypN5rIesUfnwucqOCuwTkqG9wCC59Lm I97Y+HtV0eDid1ez9ukDBV9B79AJCns8F3FpBYcUcTthKvB/617DCdw7oIIAKq/ORxzeE3SYWAo U0PPWXqL5ai7wUSUloEmv31xBBw== X-Received: by 2002:a05:6000:2dc9:b0:48c:7f18:c85e with SMTP id ffacd0b85a97d-492778d2076mr5981954f8f.45.1793978139563; Fri, 06 Nov 2026 07:15:39 -0800 (PST) X-Received: by 2002:a05:6000:2dc9:b0:48c:7f18:c85e with SMTP id ffacd0b85a97d-492778d2076mr5981896f8f.45.1793978139038; Fri, 06 Nov 2026 07:15:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1793978139; cv=none; d=google.com; s=arc-20260327; b=Ayuo9gHmUXrHtMIzNPcseFryu5S3GaXaUpSKa5rzgwwWL70cRDgjfjmU8H/OdDsPJ9 a03fYT+aeeH97eGYh4dRm4Qaeu7cYBtEYd4w3eue9LFWGb9DsRvWnsBpW+Z7Nc1qoJ/K sp4dosUL4L4dbEafF183c++M2zZAi5CYLgiQgDV+okxDUioxhOzpWDDQH6TbiNCiHFg1 GcY/CWlP+3d/Z99xxP2FERFX+mXATXMgUFhS13FD809mdFsoS7tPUDOKmZG8/irKXKi8 L+WSGva3NEGVj+poXC1nz7mI4xiCHychRpub1EHkqiGmZLjt1z4+UYSk+qyZNtsO1wwh RQjw== 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=b17vergI4uaKKMHcnwlscFsFD+Nv1l2WOYKxKZLIVMo=; fh=WpT6aB7RBAGHZeWZzqAr71yzRFbPTYkPWKsRagLn48Q=; b=Raa8EKX7t54qKAU1TeJbzr7t4aBCP0MDQtS8uuETHFAdZ1kbgmY3FJ/pfO3F5D07tJ rFzyHcAKzMuZC3RelNr0rvOBQx3UjGyZil/4AVzt/IVl5qS28HuTcW/81j+V+KafwK2Y K2Sz4N2wptr7VD2SEIMXjLpEaiyTUjg69DjZ5Fxd6zgXL/eqAiknT1kkG9NL5vS8xBtW 3MUgozLLH5G/pCGjqJT7dMKMStMDhUBNDQWqWUmVVEsrtj05lw4sM+oPgUpv5Ez4JMiz BXxuqiM6jkUG7QYcLPyyKGES2mlsRnB9m2XyiRXxkLqb1+4tbekDvbib0kxATbTDslqu LYwg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=ojCk+ONF; 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-493d2eec843si112819f8f.163.2026.11.06.07.15.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 06 Nov 2026 07:15:38 -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=ojCk+ONF; 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=b17vergI4uaKKMHcnwlscFsFD+Nv1l2WOYKxKZLIVMo=; b=ojCk+ONFHjq5 r4X9VgoBb6wksV0TYcU2sLL42pqWRwmM7fYbvOsSD81Tfzy6CI+8t5AHn9Y7Pxu8Qgri4pCkFVM27 pdxVQiFuABitHzPn2rYycRa6BdXIfI9nwzMQP7lI5s4pq0oZLB/y2HJppqNlX5Za35P/0my0WF2Ma o4dFhy4SIcvAGsEqpmYP6g/JySL+6EhV1XBK+0iyig6LamdQBu0TDYVRmXmdggTpZFT/Oe6Zu5jQO qdRn3T8WKSq78lMmT2GMAdgKLAPQej9T9j/LeeKfGmKgXFLKzUUqppN2gt+W+2PEC51x6VAxspCuo dYfCaBg0P67Po8NeT6b4ZQ==; 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 1xPLbG-00D1zp-1h; Fri, 06 Nov 2026 16:15:34 +0100 From: Eva Kurchatova To: khorenko@virtuozzo.com Date: Fri, 6 Nov 2026 17:09:10 +0200 Message-ID: <20261106151535.138563-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 v2] 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 L2's VMX-preemption timer with an hrtimer, but the hrtimer runs on CLOCK_MONOTONIC, which NTP slews against the TSC. The VM-exit then comes late or early in L1's TSC, and vmx_preemption_timer_test fails. Arm the hrtimer an eighth early while more than 100us are left, and re-arm it from its callback until L1's TSC reaches the deadline kept since commit 850448f35aaf ("KVM: nVMX: Fix VMX preemption timer migration"). Count the timer value left from that deadline too, and wait for a running callback when moving the timer to another CPU. Fixes: f4124500c2c1 ("KVM: nVMX: Fully emulate preemption timer") https://virtuozzo.atlassian.net/browse/VSTOR-152991 Feature: fix ms/kvm Signed-off-by: Eva Kurchatova --- Changes in v2: - Read L1's TSC once in vmx_calc_preemption_timer_value(), so that the value it returns is counted from the same sample as the deadline it sets. - Use hrtimer_cancel() in vmx_migrate_timers(): the callback may now re-arm the timer, and hrtimer_try_to_cancel() gives up on a running callback, which left the timer on the CPU the vCPU had left. - Keep vmx_get_preemption_timer_value(), now counted from the deadline, so that its caller is unchanged. - Correct naming, and that the skew only stretches the last 100us. - Shorter commit message. Link to v1: http://lore.virtuozzo.com/kernel/010701a1b11e8c72-26d4b079-ff6d-48b4-8769-7d3abff2e701-000000@eu-central-1.amazonses.com/T/#t arch/x86/kvm/vmx/nested.c | 73 ++++++++++++++++++++++++++++----------- arch/x86/kvm/vmx/vmx.c | 3 +- 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 8c771d8c35e3..85161d3ee80d 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -2206,15 +2206,59 @@ void nested_sync_vmcs12_to_shadow(struct kvm_vcpu *vcpu) vmx->nested.need_vmcs12_to_shadow_sync = false; } +/* L1's TSC in ticks of the emulated timer */ +static u64 vmx_preemption_timer_now(struct kvm_vcpu *vcpu) +{ + return kvm_read_l1_tsc(vcpu, rdtsc()) >> + VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE; +} + +/* Ticks left from @now to the deadline, at most the 32-bit timer value */ +static u64 vmx_preemption_timer_left(struct kvm_vcpu *vcpu, u64 now) +{ + u64 deadline = to_vmx(vcpu)->nested.preemption_timer_deadline; + + return deadline > now ? min(deadline - now, (u64)U32_MAX) : 0; +} + +/* + * The hrtimer runs on CLOCK_MONOTONIC, which adjtimex may skew 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. The skew then only stretches + * the last 100us. + */ +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); + struct kvm_vcpu *vcpu = &vmx->vcpu; + u64 now = vmx_preemption_timer_now(vcpu); + u64 left = vmx_preemption_timer_left(vcpu, now); - 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(vcpu, left)); + return HRTIMER_RESTART; + } + vmx_preemption_timer_expire(vcpu); return HRTIMER_NORESTART; } @@ -2223,15 +2267,14 @@ static u64 vmx_calc_preemption_timer_value(struct kvm_vcpu *vcpu) struct vcpu_vmx *vmx = to_vmx(vcpu); struct vmcs12 *vmcs12 = get_vmcs12(vcpu); - u64 l1_scaled_tsc = kvm_read_l1_tsc(vcpu, rdtsc()) >> - VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE; + u64 l1_scaled_tsc = vmx_preemption_timer_now(vcpu); if (!vmx->nested.has_preemption_timer_deadline) { vmx->nested.preemption_timer_deadline = 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, l1_scaled_tsc); } static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu, @@ -2244,18 +2287,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); } @@ -4430,16 +4470,7 @@ static int vmx_check_nested_events(struct kvm_vcpu *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; + return vmx_preemption_timer_left(vcpu, vmx_preemption_timer_now(vcpu)); } static bool is_vmcs12_ext_field(unsigned long field) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 00ec97314037..ca554e79ae53 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8182,7 +8182,8 @@ void vmx_migrate_timers(struct kvm_vcpu *vcpu) if (is_guest_mode(vcpu)) { struct hrtimer *timer = &to_vmx(vcpu)->nested.preemption_timer; - if (hrtimer_try_to_cancel(timer) == 1) + /* Wait for a running callback, it may re-arm the timer */ + if (hrtimer_cancel(timer)) hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED); } } -- 2.56.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel