* [PATCH] arm64: KVM: Initialize vGIC before preempt-disabled section in kvm_reset_vcpu()
@ 2026-04-11 5:59 Deepanshu Kartikey
0 siblings, 0 replies; only message in thread
From: Deepanshu Kartikey @ 2026-04-11 5:59 UTC (permalink / raw)
To: maz, oupton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: drjones, christoffer.dall, linux-arm-kernel, kvmarm,
Deepanshu Kartikey, syzbot+12b178b7c756664d2518
kvm_reset_vcpu() calls kvm_timer_vcpu_reset() inside a preempt-disabled
section to avoid races with preempt notifiers that also call vcpu put/load.
However, kvm_timer_vcpu_reset() eventually calls kvm_vgic_inject_irq()
which triggers vgic_lazy_init() if the vGIC has not been initialized yet.
vgic_lazy_init() acquires a mutex and calls vgic_init() which invokes
synchronize_srcu_expedited() -- both of which may sleep. Sleeping inside
a preempt-disabled section is illegal and causes:
BUG: scheduling while atomic: syz.1.49/3699/0x00000002
Fix this by calling vgic_lazy_init() before preempt_disable(). On the
second call inside kvm_vgic_inject_irq(), vgic_initialized() will return
true and vgic_lazy_init() will return immediately without sleeping.
Fixes: e761a927bc9a ("KVM: arm/arm64: Reset the VCPU without preemption and vcpu state loaded")
Reported-by: syzbot+12b178b7c756664d2518@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=12b178b7c756664d2518
Tested-by: syzbot+12b178b7c756664d2518@syzkaller.appspotmail.com
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
arch/arm64/kvm/reset.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index b963fd975aac..4ee16b4a37b5 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -25,6 +25,7 @@
#include <asm/ptrace.h>
#include <asm/kvm_arm.h>
#include <asm/kvm_asm.h>
+#include "vgic/vgic.h"
#include <asm/kvm_emulate.h>
#include <asm/kvm_mmu.h>
#include <asm/kvm_nested.h>
@@ -198,6 +199,14 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
vcpu->arch.reset_state.reset = false;
spin_unlock(&vcpu->arch.mp_state_lock);
+
+ /*
+ * Initialize vGIC before entering preempt-disabled section.
+ * vgic_lazy_init() may sleep via mutex_lock, which is illegal
+ * inside preempt_disable(). Second call inside kvm_vgic_inject_irq
+ * will find vGIC already initialized and return immediately.
+ */
+ vgic_lazy_init(vcpu->kvm);
preempt_disable();
loaded = (vcpu->cpu != -1);
if (loaded)
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-04-11 5:59 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-11 5:59 [PATCH] arm64: KVM: Initialize vGIC before preempt-disabled section in kvm_reset_vcpu() Deepanshu Kartikey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox