Skip to content

Commit f4e61f0

Browse files
Wanpeng Libonzini
Wanpeng Li
authored andcommitted
x86/kvm: Fix broken irq restoration in kvm_wait
After commit 997acaf (lockdep: report broken irq restoration), the guest splatting below during boot: raw_local_irq_restore() called with IRQs enabled WARNING: CPU: 1 PID: 169 at kernel/locking/irqflag-debug.c:10 warn_bogus_irq_restore+0x26/0x30 Modules linked in: hid_generic usbhid hid CPU: 1 PID: 169 Comm: systemd-udevd Not tainted 5.11.0+ #25 RIP: 0010:warn_bogus_irq_restore+0x26/0x30 Call Trace: kvm_wait+0x76/0x90 __pv_queued_spin_lock_slowpath+0x285/0x2e0 do_raw_spin_lock+0xc9/0xd0 _raw_spin_lock+0x59/0x70 lockref_get_not_dead+0xf/0x50 __legitimize_path+0x31/0x60 legitimize_root+0x37/0x50 try_to_unlazy_next+0x7f/0x1d0 lookup_fast+0xb0/0x170 path_openat+0x165/0x9b0 do_filp_open+0x99/0x110 do_sys_openat2+0x1f1/0x2e0 do_sys_open+0x5c/0x80 __x64_sys_open+0x21/0x30 do_syscall_64+0x32/0x50 entry_SYSCALL_64_after_hwframe+0x44/0xae The new consistency checking, expects local_irq_save() and local_irq_restore() to be paired and sanely nested, and therefore expects local_irq_restore() to be called with irqs disabled. The irqflags handling in kvm_wait() which ends up doing: local_irq_save(flags); safe_halt(); local_irq_restore(flags); instead triggers it. This patch fixes it by using local_irq_disable()/enable() directly. Cc: Thomas Gleixner <[email protected]> Reported-by: Dmitry Vyukov <[email protected]> Signed-off-by: Wanpeng Li <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent c2162e1 commit f4e61f0

File tree

1 file changed

+10
-13
lines changed

1 file changed

+10
-13
lines changed

arch/x86/kernel/kvm.c

+10-13
Original file line numberDiff line numberDiff line change
@@ -836,28 +836,25 @@ static void kvm_kick_cpu(int cpu)
836836

837837
static void kvm_wait(u8 *ptr, u8 val)
838838
{
839-
unsigned long flags;
840-
841839
if (in_nmi())
842840
return;
843841

844-
local_irq_save(flags);
845-
846-
if (READ_ONCE(*ptr) != val)
847-
goto out;
848-
849842
/*
850843
* halt until it's our turn and kicked. Note that we do safe halt
851844
* for irq enabled case to avoid hang when lock info is overwritten
852845
* in irq spinlock slowpath and no spurious interrupt occur to save us.
853846
*/
854-
if (arch_irqs_disabled_flags(flags))
855-
halt();
856-
else
857-
safe_halt();
847+
if (irqs_disabled()) {
848+
if (READ_ONCE(*ptr) == val)
849+
halt();
850+
} else {
851+
local_irq_disable();
858852

859-
out:
860-
local_irq_restore(flags);
853+
if (READ_ONCE(*ptr) == val)
854+
safe_halt();
855+
856+
local_irq_enable();
857+
}
861858
}
862859

863860
#ifdef CONFIG_X86_32

0 commit comments

Comments
 (0)