KVM: PPC: Propagate errors to the guest when failed instead of ignoring
authorAlexey Kardashevskiy <aik@ozlabs.ru>
Mon, 10 Sep 2018 08:29:11 +0000 (18:29 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 9 Oct 2018 05:04:27 +0000 (16:04 +1100)
At the moment if the PUT_TCE{_INDIRECT} handlers fail to update
the hardware tables, we print a warning once, clear the entry and
continue. This is so as at the time the assumption was that if
a VFIO device is hotplugged into the guest, and the userspace replays
virtual DMA mappings (i.e. TCEs) to the hardware tables and if this fails,
then there is nothing useful we can do about it.

However the assumption is not valid as these handlers are not called for
TCE replay (VFIO ioctl interface is used for that) and these handlers
are for new TCEs.

This returns an error to the guest if there is a request which cannot be
processed. By now the only possible failure must be H_TOO_HARD.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/kvm/book3s_64_vio.c
arch/powerpc/kvm/book3s_64_vio_hv.c

index 01e1994daff06e61049b8c12de5e3d125932bb03..8231b178eac6b4c0c3828e34dbd4fcb3ea37bede 100644 (file)
@@ -568,14 +568,10 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
                        ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, stit->tbl,
                                        entry, ua, dir);
 
-               if (ret == H_SUCCESS)
-                       continue;
-
-               if (ret == H_TOO_HARD)
+               if (ret != H_SUCCESS) {
+                       kvmppc_clear_tce(stit->tbl, entry);
                        goto unlock_exit;
-
-               WARN_ON_ONCE(1);
-               kvmppc_clear_tce(stit->tbl, entry);
+               }
        }
 
        kvmppc_tce_put(stt, entry, tce);
@@ -663,14 +659,10 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
                                        stit->tbl, entry + i, ua,
                                        iommu_tce_direction(tce));
 
-                       if (ret == H_SUCCESS)
-                               continue;
-
-                       if (ret == H_TOO_HARD)
+                       if (ret != H_SUCCESS) {
+                               kvmppc_clear_tce(stit->tbl, entry);
                                goto unlock_exit;
-
-                       WARN_ON_ONCE(1);
-                       kvmppc_clear_tce(stit->tbl, entry);
+                       }
                }
 
                kvmppc_tce_put(stt, entry + i, tce);
index 3c05fc22de0762a2ab3cd1f6faa86946e9e94c7d..ae147b5c75716a08a7c44c8469a2c2c9ab2d3727 100644 (file)
@@ -405,14 +405,10 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
                        ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
                                        stit->tbl, entry, ua, dir);
 
-               if (ret == H_SUCCESS)
-                       continue;
-
-               if (ret == H_TOO_HARD)
+               if (ret != H_SUCCESS) {
+                       kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
                        return ret;
-
-               WARN_ON_ONCE_RM(1);
-               kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
+               }
        }
 
        kvmppc_tce_put(stt, entry, tce);
@@ -558,14 +554,11 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
                                        stit->tbl, entry + i, ua,
                                        iommu_tce_direction(tce));
 
-                       if (ret == H_SUCCESS)
-                               continue;
-
-                       if (ret == H_TOO_HARD)
+                       if (ret != H_SUCCESS) {
+                               kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl,
+                                               entry);
                                goto unlock_exit;
-
-                       WARN_ON_ONCE_RM(1);
-                       kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
+                       }
                }
 
                kvmppc_tce_put(stt, entry + i, tce);