FAILED: patch "[PATCH] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired" failed to apply to 6.6-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x e800decd9c0ac4349bcd8f8f9b29fd21fe93165e
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026072610-waking-easiest-e330@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e800decd9c0ac4349bcd8f8f9b29fd21fe93165e Mon Sep 17 00:00:00 2001
From: Venkatesh Srinivas <[email protected]>
Date: Wed, 15 Jul 2026 23:42:35 +0000
Subject: [PATCH] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired
on KVM_RUN
On Intel platforms with a VMX preemption timer and APICv, if a VMM calls KVM_GET_LAPIC before KVM_GET_MSRS to save the vCPU state, it is possible to lose a pending timer interrupt.
If the thread running these ioctls is migrated to another core after calling KVM_GET_LAPIC but before KVM_GET_MSRS and the guest is using their LAPIC timer in TSC-deadline mode, not only does the save LAPIC state not carry the pending interrupt, the TSCDEADLINE MSR will be zeroed.
After migration across CPUs, KVM_GET_MSRS calls vcpu_load, posting the interrupt and clearing the MSR:vcpu_load() ->
kvm_arch_vcpu_load() ->
kvm_lapic_restart_hv_timer() ->
start_hv_timer() ->
apic_timer_expired() ->
kvm_apic_inject_pending_timer_irqs()
. post interrupt into the LAPIC state
. clear IA32_TSCDEADLINEThe saved LAPIC state will be missing the pending interrupt and the saved MSR will be zero. Oops.
Fix by only posting an interrupt when we're attempting to enter the guest (vcpu->wants_to_run == true), not for vcpu_load from other paths.
Message-ID: <[email protected]>
arch/x86/kvm/lapic.c +1 -1
@@ -2052,7 +2052,7 @@ static void apic_timer_expired(struct kvm_lapic *apic, bool from_timer_fn)if (apic_lvtt_tscdeadline (apic) || ktimer->hv_timer_in_use) ktimer->expired_tscdeadline = ktimer->tscdeadline; -if (!from_timer_fn && apic->apicv_active) { +if (!from_timer_fn && apic->apicv_active && vcpu->wants_to_run) {WARN_ON (kvm_get_running_vcpu () != vcpu);kvm_apic_inject_pending_timer_irqs (apic);return ;
Sasha Levin
maintainerPATCH 1/2 KVM: Introduce vcpu->wants_to_run
From: David Matlack <[email protected]>
[ Upstream commit a6816314af5749cd88944bfdceb270c627cdf348 ]
Introduce vcpu->wants_to_run to indicate when a vCPU is in its core run loop, i.e. when the vCPU is running the KVM_RUN ioctl and immediate_exit was not set.
Replace all references to vcpu->run->immediate_exit with !vcpu->wants_to_run to avoid TOCTOU races with userspace. For example, a malicious userspace could invoked KVM_RUN with immediate_exit=true and then after KVM reads it to set wants_to_run=false, flip it to false. This would result in the vCPU running in KVM_RUN with wants_to_run=false. This wouldn't cause any real bugs today but is a dangerous landmine.
Stable-dep-of: e800decd9c0a ("KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN")
--- arch/arm64/kvm/arm.c | 2 +- arch/mips/kvm/mips.c | 2 +- arch/powerpc/kvm/powerpc.c | 2 +- arch/riscv/kvm/vcpu.c | 2 +- arch/s390/kvm/kvm-s390.c | 2 +- arch/x86/kvm/x86.c | 4 ++-- include/linux/kvm_host.h | 1 + virt/kvm/kvm_main.c | 3 +++ 8 files changed, 11 insertions(+), 7 deletions(-)
arch/arm64/kvm/arm.c +1 -1
@@ -915,7 +915,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)vcpu_load (vcpu); -if (run->immediate_exit) { +if (!vcpu->wants_to_run) { ret = -EINTR ; goto out; }
arch/mips/kvm/mips.c +1 -1
@@ -436,7 +436,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) vcpu->mmio_needed =0 ; } -if (vcpu->run->immediate_exit) +if (!vcpu->wants_to_run) goto out;lose_fpu (1 );
arch/powerpc/kvm/powerpc.c +1 -1
@@ -1858,7 +1858,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)kvm_sigset_activate (vcpu); -if (run->immediate_exit) +if (!vcpu->wants_to_run) r = -EINTR ;else r =kvmppc_vcpu_run (vcpu);
arch/riscv/kvm/vcpu.c +1 -1
@@ -676,7 +676,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)return ret; } -if (run->immediate_exit) { +if (!vcpu->wants_to_run) {kvm_vcpu_srcu_read_unlock (vcpu);return -EINTR ; }
arch/s390/kvm/kvm-s390.c +1 -1
@@ -5048,7 +5048,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)if (vcpu->kvm->arch.pv.dumping)return -EINVAL ; -if (kvm_run->immediate_exit) +if (!vcpu->wants_to_run)return -EINTR ; if (kvm_run->kvm_valid_regs & ~KVM_SYNC_S390_VALID_FIELDS ||
arch/x86/kvm/x86.c +2 -2
@@ -11224,7 +11224,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)kvm_vcpu_srcu_read_lock (vcpu);if (unlikely (vcpu->arch.mp_state ==KVM_MP_STATE_UNINITIALIZED )) { -if (kvm_run->immediate_exit) { +if (!vcpu->wants_to_run) { r = -EINTR ; goto out; }
@@ -11302,7 +11302,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)WARN_ON_ONCE (vcpu->mmio_needed); } -if (kvm_run->immediate_exit) { +if (!vcpu->wants_to_run) { r = -EINTR ; goto out; }
include/linux/kvm_host.h +1 -0
@@ -378,6 +378,7 @@ struct kvm_vcpu { bool dy_eligible; } spin_loop;#endif +bool wants_to_run;bool preempted;bool ready;struct kvm_vcpu_arch arch;
virt/kvm/kvm_main.c +3 -0
@@ -4160,7 +4160,10 @@ static long kvm_vcpu_ioctl(struct file *filp,synchronize_rcu ();put_pid (oldpid); } + vcpu->wants_to_run = !READ_ONCE (vcpu->run->immediate_exit); r =kvm_arch_vcpu_ioctl_run (vcpu); + vcpu->wants_to_run = false; +trace_kvm_userspace_exit (vcpu->run->exit_reason, r);break ; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN
From: Venkatesh Srinivas <[email protected]>
[ Upstream commit e800decd9c0ac4349bcd8f8f9b29fd21fe93165e ]
On Intel platforms with a VMX preemption timer and APICv, if a VMM calls KVM_GET_LAPIC before KVM_GET_MSRS to save the vCPU state, it is possible to lose a pending timer interrupt.
If the thread running these ioctls is migrated to another core after calling KVM_GET_LAPIC but before KVM_GET_MSRS and the guest is using their LAPIC timer in TSC-deadline mode, not only does the save LAPIC state not carry the pending interrupt, the TSCDEADLINE MSR will be zeroed.
After migration across CPUs, KVM_GET_MSRS calls vcpu_load, posting the interrupt and clearing the MSR:vcpu_load() ->
kvm_arch_vcpu_load() ->
kvm_lapic_restart_hv_timer() ->
start_hv_timer() ->
apic_timer_expired() ->
kvm_apic_inject_pending_timer_irqs()
. post interrupt into the LAPIC state
. clear IA32_TSCDEADLINEThe saved LAPIC state will be missing the pending interrupt and the saved MSR will be zero. Oops.
Fix by only posting an interrupt when we're attempting to enter the guest (vcpu->wants_to_run == true), not for vcpu_load from other paths.
Message-ID: <[email protected]>
--- arch/x86/kvm/lapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/lapic.c +1 -1
@@ -1912,7 +1912,7 @@ static void apic_timer_expired(struct kvm_lapic *apic, bool from_timer_fn)if (apic_lvtt_tscdeadline (apic) || ktimer->hv_timer_in_use) ktimer->expired_tscdeadline = ktimer->tscdeadline; -if (!from_timer_fn && apic->apicv_active) { +if (!from_timer_fn && apic->apicv_active && vcpu->wants_to_run) {WARN_ON (kvm_get_running_vcpu () != vcpu);kvm_apic_inject_pending_timer_irqs (apic);return ;
Signature · 1 line
2.53.0