FAILED: patch "[PATCH] KVM: arm64: Turn vcpu->arch.pause into a counter" failed to apply to 5.15-stable tree
Subsystems (3)
Sasha Levin
maintainerThe patch below does not apply to the 5.15-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-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x e64309198eda29415a95113def92aa40196cd422
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '[email protected]' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From e64309198eda29415a95113def92aa40196cd422 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <[email protected]>
Date: Thu, 15 Oct 2026 11:05:36 +0100
Subject: [PATCH] KVM: arm64: Turn vcpu->arch.pause into a counter
We have situations where we can call kvm_arm_halt_guest() without holding config_lock, which means that halt and resume can overlap in funny ways when called from separate contexts, and result in situations where a vcpu is resumed while other parts of KVM assume it is halted. Consequences are left to the imagination of the reader.
Fix this sorry situation by turning kvm_vcpu_arch::pause into an atomic counter, which makes the races described above harmless.
--- arch/arm64/include/asm/kvm_host.h | 7 +++---- arch/arm64/kvm/arm.c | 21 ++++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-)
arch/arm64/include/asm/kvm_host.h +3 -4
@@ -889,11 +889,10 @@ struct kvm_vcpu_arch {/* * Don't run the guest (internal implementation need). * -* Contrary to the flags above, this is set/cleared outside of -* a vcpu context, and thus cannot be mixed with the flags -* themselves (or the flag accesses need to be made atomic). +* Contrary to the flags above, this is updated outside of +* a vcpu context, and thus cannot be mixed with the flags. */ -bool pause; +atomic_t pause;/* * We maintain more than a single set of debug registers to support
arch/arm64/kvm/arm.c +12 -9
@@ -565,6 +565,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)kvm_arm_pvtime_vcpu_init (&vcpu->arch); vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu; +atomic_set (&vcpu->arch.pause,0 );/* * This vCPU may have been created after mpidr_data was initialized.
@@ -839,6 +840,11 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,return ret; } +static bool vcpu_can_run (struct kvm_vcpu *vcpu) +{ +return !kvm_arm_vcpu_stopped (vcpu) && !atomic_read (&vcpu->arch.pause); +} +/** * kvm_arch_vcpu_runnable - determine if the vcpu can be scheduled * @v: The VCPU pointer
@@ -854,8 +860,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) (kvm_timer_should_notify_user (v) || kvm_pmu_should_notify_user(v))); -return ((irq_lines ||kvm_vgic_vcpu_pending_irq (v)) - && !kvm_arm_vcpu_stopped (v) && !v->arch.pause); +return ((irq_lines ||kvm_vgic_vcpu_pending_irq (v)) &&vcpu_can_run (v)); }bool kvm_arch_vcpu_in_kernel (struct kvm_vcpu *vcpu)
@@ -1018,7 +1023,7 @@ void kvm_arm_halt_guest(struct kvm *kvm)struct kvm_vcpu *vcpu;kvm_for_each_vcpu (i, vcpu, kvm) - vcpu->arch.pause = true; +atomic_inc (&vcpu->arch.pause);kvm_make_all_cpus_request (kvm,KVM_REQ_SLEEP ); }
@@ -1028,8 +1033,8 @@ void kvm_arm_resume_guest(struct kvm *kvm)struct kvm_vcpu *vcpu;kvm_for_each_vcpu (i, vcpu, kvm) { - vcpu->arch.pause = false; -__kvm_vcpu_wake_up (vcpu); +if (atomic_dec_and_test (&vcpu->arch.pause)) +__kvm_vcpu_wake_up (vcpu); } }
@@ -1037,11 +1042,9 @@ static void kvm_vcpu_sleep(struct kvm_vcpu *vcpu) {struct rcuwait *wait =kvm_arch_vcpu_get_wait (vcpu); -rcuwait_wait_event (wait, - (!kvm_arm_vcpu_stopped (vcpu)) && (!vcpu->arch.pause), -TASK_INTERRUPTIBLE ); +rcuwait_wait_event (wait,vcpu_can_run (vcpu),TASK_INTERRUPTIBLE ); -if (kvm_arm_vcpu_stopped (vcpu) || vcpu->arch.pause) { +if (!vcpu_can_run (vcpu)) {/* Awaken to handle a signal, request we sleep again later. */ kvm_make_request (KVM_REQ_SLEEP , vcpu); }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 1/1 KVM: arm64: Turn vcpu->arch.pause into a counter
From: Marc Zyngier <[email protected]>
[ Upstream commit e64309198eda29415a95113def92aa40196cd422 ]
We have situations where we can call kvm_arm_halt_guest() without holding config_lock, which means that halt and resume can overlap in funny ways when called from separate contexts, and result in situations where a vcpu is resumed while other parts of KVM assume it is halted. Consequences are left to the imagination of the reader.
Fix this sorry situation by turning kvm_vcpu_arch::pause into an atomic counter, which makes the races described above harmless.
--- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/arm.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-)
arch/arm64/include/asm/kvm_host.h +1 -1
@@ -368,7 +368,7 @@ struct kvm_vcpu_arch {bool power_off;/* Don't run the guest (internal implementation need) */ -bool pause; +atomic_t pause;/* Cache some mmu pages needed inside spinlock regions */ struct kvm_mmu_memory_cache mmu_page_cache;
arch/arm64/kvm/arm.c +7 -6
@@ -336,6 +336,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)kvm_arm_pvtime_vcpu_init (&vcpu->arch); vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu; +atomic_set (&vcpu->arch.pause,0 ); err =kvm_vgic_vcpu_init (vcpu);if (err)
@@ -496,7 +497,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) {bool irq_lines = *vcpu_hcr (v) & (HCR_VI |HCR_VF );return ((irq_lines ||kvm_vgic_vcpu_pending_irq (v)) - && !v->arch.power_off && !v->arch.pause); + && !v->arch.power_off && !atomic_read (&v->arch.pause)); }bool kvm_arch_vcpu_in_kernel (struct kvm_vcpu *vcpu)
@@ -636,7 +637,7 @@ void kvm_arm_halt_guest(struct kvm *kvm)struct kvm_vcpu *vcpu;kvm_for_each_vcpu (i, vcpu, kvm) - vcpu->arch.pause = true; +atomic_inc (&vcpu->arch.pause);kvm_make_all_cpus_request (kvm,KVM_REQ_SLEEP ); }
@@ -646,8 +647,8 @@ void kvm_arm_resume_guest(struct kvm *kvm)struct kvm_vcpu *vcpu;kvm_for_each_vcpu (i, vcpu, kvm) { - vcpu->arch.pause = false; -rcuwait_wake_up (kvm_arch_vcpu_get_wait (vcpu)); +if (atomic_dec_and_test (&vcpu->arch.pause)) +rcuwait_wake_up (kvm_arch_vcpu_get_wait (vcpu)); } }
@@ -656,10 +657,10 @@ static void vcpu_req_sleep(struct kvm_vcpu *vcpu)struct rcuwait *wait =kvm_arch_vcpu_get_wait (vcpu);rcuwait_wait_event (wait, - (!vcpu->arch.power_off) &&(!vcpu->arch.pause), + !vcpu->arch.power_off && !atomic_read (&vcpu->arch.pause),TASK_INTERRUPTIBLE ); -if (vcpu->arch.power_off || vcpu->arch.pause) { +if (vcpu->arch.power_off ||atomic_read (&vcpu->arch.pause)) {/* Awaken to handle a signal, request we sleep again later. */ kvm_make_request (KVM_REQ_SLEEP , vcpu); }
Signature · 1 line
2.53.0