2022-05-19 10:29:12

by Wanpeng Li

[permalink] [raw]
Subject: [PATCH] KVM: eventfd: Fix false positive RCU usage warning

From: Wanpeng Li <[email protected]>

The below is splatting when running kvm-unit-test.

=============================
WARNING: suspicious RCU usage
5.18.0-rc7 #5 Tainted: G IOE
-----------------------------
/home/kernel/linux/arch/x86/kvm/../../../virt/kvm/eventfd.c:80 RCU-list traversed in non-reader section!!

other info that might help us debug this:


rcu_scheduler_active = 2, debug_locks = 1
4 locks held by qemu-system-x86/35124:
#0: ffff9725391d80b8 (&vcpu->mutex){+.+.}-{4:4}, at: kvm_vcpu_ioctl+0x77/0x710 [kvm]
#1: ffffbd25cfb2a0b8 (&kvm->srcu){....}-{0:0}, at: vcpu_enter_guest+0xdeb/0x1900 [kvm]
#2: ffffbd25cfb2b920 (&kvm->irq_srcu){....}-{0:0}, at: kvm_hv_notify_acked_sint+0x79/0x1e0 [kvm]
#3: ffffbd25cfb2b920 (&kvm->irq_srcu){....}-{0:0}, at: irqfd_resampler_ack+0x5/0x110 [kvm]

stack backtrace:
CPU: 2 PID: 35124 Comm: qemu-system-x86 Tainted: G IOE 5.18.0-rc7 #5
Call Trace:
<TASK>
dump_stack_lvl+0x6c/0x9b
irqfd_resampler_ack+0xfd/0x110 [kvm]
kvm_notify_acked_gsi+0x32/0x90 [kvm]
kvm_hv_notify_acked_sint+0xc5/0x1e0 [kvm]
kvm_hv_set_msr_common+0xec1/0x1160 [kvm]
kvm_set_msr_common+0x7c3/0xf60 [kvm]
vmx_set_msr+0x394/0x1240 [kvm_intel]
kvm_set_msr_ignored_check+0x86/0x200 [kvm]
kvm_emulate_wrmsr+0x4f/0x1f0 [kvm]
vmx_handle_exit+0x6fb/0x7e0 [kvm_intel]
vcpu_enter_guest+0xe5a/0x1900 [kvm]
kvm_arch_vcpu_ioctl_run+0x16e/0xac0 [kvm]
kvm_vcpu_ioctl+0x279/0x710 [kvm]
__x64_sys_ioctl+0x83/0xb0
do_syscall_64+0x3b/0x90
entry_SYSCALL_64_after_hwframe+0x44/0xae

resampler-list is traversed using srcu_read_lock() in irqfd_resampler_ack,
let's fix this false positive by list_for_each_entry_srcu() instead and
lockdep expression srcu_read_lock_head() be passed as the cond argument.

Signed-off-by: Wanpeng Li <[email protected]>
---
virt/kvm/eventfd.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 59b1dd4a549e..2a3ed401ce46 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -77,7 +77,8 @@ irqfd_resampler_ack(struct kvm_irq_ack_notifier *kian)

idx = srcu_read_lock(&kvm->irq_srcu);

- list_for_each_entry_rcu(irqfd, &resampler->list, resampler_link)
+ list_for_each_entry_srcu(irqfd, &resampler->list, resampler_link,
+ srcu_read_lock_held(&kvm->irq_srcu))
eventfd_signal(irqfd->resamplefd, 1);

srcu_read_unlock(&kvm->irq_srcu, idx);
--
2.25.1