Skip to content

Commit ab8b65b

Browse files
Qian Caipaulusmack
authored andcommitted
KVM: PPC: Book3S: Fix some RCU-list locks
It is unsafe to traverse kvm->arch.spapr_tce_tables and stt->iommu_tables without the RCU read lock held. Also, add cond_resched_rcu() in places with the RCU read lock held that could take a while to finish. arch/powerpc/kvm/book3s_64_vio.c:76 RCU-list traversed in non-reader section!! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 no locks held by qemu-kvm/4265. stack backtrace: CPU: 96 PID: 4265 Comm: qemu-kvm Not tainted 5.7.0-rc4-next-20200508+ #2 Call Trace: [c000201a8690f720] [c000000000715948] dump_stack+0xfc/0x174 (unreliable) [c000201a8690f770] [c0000000001d9470] lockdep_rcu_suspicious+0x140/0x164 [c000201a8690f7f0] [c008000010b9fb48] kvm_spapr_tce_release_iommu_group+0x1f0/0x220 [kvm] [c000201a8690f870] [c008000010b8462c] kvm_spapr_tce_release_vfio_group+0x54/0xb0 [kvm] [c000201a8690f8a0] [c008000010b84710] kvm_vfio_destroy+0x88/0x140 [kvm] [c000201a8690f8f0] [c008000010b7d488] kvm_put_kvm+0x370/0x600 [kvm] [c000201a8690f990] [c008000010b7e3c0] kvm_vm_release+0x38/0x60 [kvm] [c000201a8690f9c0] [c0000000005223f4] __fput+0x124/0x330 [c000201a8690fa20] [c000000000151cd8] task_work_run+0xb8/0x130 [c000201a8690fa70] [c0000000001197e8] do_exit+0x4e8/0xfa0 [c000201a8690fb70] [c00000000011a374] do_group_exit+0x64/0xd0 [c000201a8690fbb0] [c000000000132c90] get_signal+0x1f0/0x1200 [c000201a8690fcc0] [c000000000020690] do_notify_resume+0x130/0x3c0 [c000201a8690fda0] [c000000000038d64] syscall_exit_prepare+0x1a4/0x280 [c000201a8690fe20] [c00000000000c8f8] system_call_common+0xf8/0x278 ==== arch/powerpc/kvm/book3s_64_vio.c:368 RCU-list traversed in non-reader section!! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 2 locks held by qemu-kvm/4264: #0: c000201ae2d000d8 (&vcpu->mutex){+.+.}-{3:3}, at: kvm_vcpu_ioctl+0xdc/0x950 [kvm] #1: c000200c9ed0c468 (&kvm->srcu){....}-{0:0}, at: kvmppc_h_put_tce+0x88/0x340 [kvm] ==== arch/powerpc/kvm/book3s_64_vio.c:108 RCU-list traversed in non-reader section!! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 1 lock held by qemu-kvm/4257: #0: c000200b1b363a40 (&kv->lock){+.+.}-{3:3}, at: kvm_vfio_set_attr+0x598/0x6c0 [kvm] ==== arch/powerpc/kvm/book3s_64_vio.c:146 RCU-list traversed in non-reader section!! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 1 lock held by qemu-kvm/4257: #0: c000200b1b363a40 (&kv->lock){+.+.}-{3:3}, at: kvm_vfio_set_attr+0x598/0x6c0 [kvm] Signed-off-by: Qian Cai <[email protected]> Signed-off-by: Paul Mackerras <[email protected]>
1 parent 0aca8a5 commit ab8b65b

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

arch/powerpc/kvm/book3s_64_vio.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ extern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm,
7373
struct kvmppc_spapr_tce_iommu_table *stit, *tmp;
7474
struct iommu_table_group *table_group = NULL;
7575

76+
rcu_read_lock();
7677
list_for_each_entry_rcu(stt, &kvm->arch.spapr_tce_tables, list) {
7778

7879
table_group = iommu_group_get_iommudata(grp);
@@ -87,7 +88,9 @@ extern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm,
8788
kref_put(&stit->kref, kvm_spapr_tce_liobn_put);
8889
}
8990
}
91+
cond_resched_rcu();
9092
}
93+
rcu_read_unlock();
9194
}
9295

9396
extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
@@ -105,12 +108,14 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
105108
if (!f.file)
106109
return -EBADF;
107110

111+
rcu_read_lock();
108112
list_for_each_entry_rcu(stt, &kvm->arch.spapr_tce_tables, list) {
109113
if (stt == f.file->private_data) {
110114
found = true;
111115
break;
112116
}
113117
}
118+
rcu_read_unlock();
114119

115120
fdput(f);
116121

@@ -143,21 +148,25 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
143148
if (!tbl)
144149
return -EINVAL;
145150

151+
rcu_read_lock();
146152
list_for_each_entry_rcu(stit, &stt->iommu_tables, next) {
147153
if (tbl != stit->tbl)
148154
continue;
149155

150156
if (!kref_get_unless_zero(&stit->kref)) {
151157
/* stit is being destroyed */
152158
iommu_tce_table_put(tbl);
159+
rcu_read_unlock();
153160
return -ENOTTY;
154161
}
155162
/*
156163
* The table is already known to this KVM, we just increased
157164
* its KVM reference counter and can return.
158165
*/
166+
rcu_read_unlock();
159167
return 0;
160168
}
169+
rcu_read_unlock();
161170

162171
stit = kzalloc(sizeof(*stit), GFP_KERNEL);
163172
if (!stit) {
@@ -365,18 +374,19 @@ static long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *stt,
365374
if (kvmppc_tce_to_ua(stt->kvm, tce, &ua))
366375
return H_TOO_HARD;
367376

377+
rcu_read_lock();
368378
list_for_each_entry_rcu(stit, &stt->iommu_tables, next) {
369379
unsigned long hpa = 0;
370380
struct mm_iommu_table_group_mem_t *mem;
371381
long shift = stit->tbl->it_page_shift;
372382

373383
mem = mm_iommu_lookup(stt->kvm->mm, ua, 1ULL << shift);
374-
if (!mem)
375-
return H_TOO_HARD;
376-
377-
if (mm_iommu_ua_to_hpa(mem, ua, shift, &hpa))
384+
if (!mem || mm_iommu_ua_to_hpa(mem, ua, shift, &hpa)) {
385+
rcu_read_unlock();
378386
return H_TOO_HARD;
387+
}
379388
}
389+
rcu_read_unlock();
380390

381391
return H_SUCCESS;
382392
}

0 commit comments

Comments
 (0)