diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2017-10-11 01:00:34 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@ozlabs.org> | 2017-10-13 20:35:41 -0400 |
commit | 8f6a9f0d0604817f7c8d4376fd51718f1bf192ee (patch) | |
tree | 930fee4777158b8a8099c4e5a46cea4149572c11 | |
parent | 2cde3716321ec64a1faeaf567bd94100c7b4160f (diff) |
KVM: PPC: Book3S: Protect kvmppc_gpa_to_ua() with SRCU
kvmppc_gpa_to_ua() accesses KVM memory slot array via
srcu_dereference_check() and this produces warnings from RCU like below.
This extends the existing srcu_read_lock/unlock to cover that
kvmppc_gpa_to_ua() as well.
We did not hit this before as this lock is not needed for the realmode
handlers and hash guests would use the realmode path all the time;
however the radix guests are always redirected to the virtual mode
handlers and hence the warning.
[ 68.253798] ./include/linux/kvm_host.h:575 suspicious rcu_dereference_check() usage!
[ 68.253799]
other info that might help us debug this:
[ 68.253802]
rcu_scheduler_active = 2, debug_locks = 1
[ 68.253804] 1 lock held by qemu-system-ppc/6413:
[ 68.253806] #0: (&vcpu->mutex){+.+.}, at: [<c00800000e3c22f4>] vcpu_load+0x3c/0xc0 [kvm]
[ 68.253826]
stack backtrace:
[ 68.253830] CPU: 92 PID: 6413 Comm: qemu-system-ppc Tainted: G W 4.14.0-rc3-00553-g432dcba58e9c-dirty #72
[ 68.253833] Call Trace:
[ 68.253839] [c000000fd3d9f790] [c000000000b7fcc8] dump_stack+0xe8/0x160 (unreliable)
[ 68.253845] [c000000fd3d9f7d0] [c0000000001924c0] lockdep_rcu_suspicious+0x110/0x180
[ 68.253851] [c000000fd3d9f850] [c0000000000e825c] kvmppc_gpa_to_ua+0x26c/0x2b0
[ 68.253858] [c000000fd3d9f8b0] [c00800000e3e1984] kvmppc_h_put_tce+0x12c/0x2a0 [kvm]
Fixes: 121f80ba68f1 ("KVM: PPC: VFIO: Add in-kernel acceleration for VFIO")
Cc: stable@vger.kernel.org # v4.12+
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
-rw-r--r-- | arch/powerpc/kvm/book3s_64_vio.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c index 8f2da8bba737..4dffa611376d 100644 --- a/arch/powerpc/kvm/book3s_64_vio.c +++ b/arch/powerpc/kvm/book3s_64_vio.c | |||
@@ -478,28 +478,30 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | |||
478 | return ret; | 478 | return ret; |
479 | 479 | ||
480 | dir = iommu_tce_direction(tce); | 480 | dir = iommu_tce_direction(tce); |
481 | |||
482 | idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
483 | |||
481 | if ((dir != DMA_NONE) && kvmppc_gpa_to_ua(vcpu->kvm, | 484 | if ((dir != DMA_NONE) && kvmppc_gpa_to_ua(vcpu->kvm, |
482 | tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), &ua, NULL)) | 485 | tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), &ua, NULL)) { |
483 | return H_PARAMETER; | 486 | ret = H_PARAMETER; |
487 | goto unlock_exit; | ||
488 | } | ||
484 | 489 | ||
485 | entry = ioba >> stt->page_shift; | 490 | entry = ioba >> stt->page_shift; |
486 | 491 | ||
487 | list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { | 492 | list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { |
488 | if (dir == DMA_NONE) { | 493 | if (dir == DMA_NONE) |
489 | ret = kvmppc_tce_iommu_unmap(vcpu->kvm, | 494 | ret = kvmppc_tce_iommu_unmap(vcpu->kvm, |
490 | stit->tbl, entry); | 495 | stit->tbl, entry); |
491 | } else { | 496 | else |
492 | idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
493 | ret = kvmppc_tce_iommu_map(vcpu->kvm, stit->tbl, | 497 | ret = kvmppc_tce_iommu_map(vcpu->kvm, stit->tbl, |
494 | entry, ua, dir); | 498 | entry, ua, dir); |
495 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
496 | } | ||
497 | 499 | ||
498 | if (ret == H_SUCCESS) | 500 | if (ret == H_SUCCESS) |
499 | continue; | 501 | continue; |
500 | 502 | ||
501 | if (ret == H_TOO_HARD) | 503 | if (ret == H_TOO_HARD) |
502 | return ret; | 504 | goto unlock_exit; |
503 | 505 | ||
504 | WARN_ON_ONCE(1); | 506 | WARN_ON_ONCE(1); |
505 | kvmppc_clear_tce(stit->tbl, entry); | 507 | kvmppc_clear_tce(stit->tbl, entry); |
@@ -507,7 +509,10 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | |||
507 | 509 | ||
508 | kvmppc_tce_put(stt, entry, tce); | 510 | kvmppc_tce_put(stt, entry, tce); |
509 | 511 | ||
510 | return H_SUCCESS; | 512 | unlock_exit: |
513 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
514 | |||
515 | return ret; | ||
511 | } | 516 | } |
512 | EXPORT_SYMBOL_GPL(kvmppc_h_put_tce); | 517 | EXPORT_SYMBOL_GPL(kvmppc_h_put_tce); |
513 | 518 | ||