aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2014-02-04 19:25:35 +1100
committerCrístian Viana <vianac@linux.vnet.ibm.com>2014-02-04 21:33:43 -0200
commitab1f773ffd1518b64ff5c2310e4538d3286b4f47 (patch)
tree88572f47b08e671b85dbb251a163b15bc6490ba1
parent8733f0d760e5c50929312778d9375d91d6e61371 (diff)
downloadpowerkvm-ab1f773ffd1518b64ff5c2310e4538d3286b4f47.tar.gz
vfio: remove redundant put_page() when failed in real mode
This fixes one of the corner cases which produced wrong backtrack from put_page(). BZ: 103055 Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
-rw-r--r--arch/powerpc/kvm/book3s_64_vio.c12
-rw-r--r--arch/powerpc/kvm/book3s_64_vio_hv.c5
2 files changed, 9 insertions, 8 deletions
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
index 65557562ecfb7..ead2e9979f8cd 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -554,16 +554,16 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
if (tt && ((ioba + (npages << IOMMU_PAGE_SHIFT)) > tt->window_size))
return H_PARAMETER;
- if (vcpu->arch.tce_rm_fail != TCERM_NONE)
- put_page(pfn_to_page(tce_list >> PAGE_SHIFT));
-
- if (vcpu->arch.tce_rm_fail == TCERM_PUTLISTPAGE)
- return H_SUCCESS;
-
tces = kvmppc_gpa_to_hva_and_get(vcpu, tce_list, &pg, NULL);
if (tces == ERROR_ADDR)
return H_TOO_HARD;
+ if ((vcpu->arch.tce_rm_fail != TCERM_GETLISTPAGE) && pg)
+ put_page(pg);
+
+ if (vcpu->arch.tce_rm_fail == TCERM_PUTLISTPAGE)
+ goto put_list_page_exit;
+
if (grp) {
ret = kvmppc_h_put_tce_indirect_iommu(vcpu,
grp, ioba, tces, npages);
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
index ba16a7322fa98..c2eb0137a29f7 100644
--- a/arch/powerpc/kvm/book3s_64_vio_hv.c
+++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -293,7 +293,6 @@ static long kvmppc_rm_h_put_tce_indirect_iommu(struct kvm_vcpu *vcpu,
int i, ret;
unsigned long hpa;
struct iommu_table *tbl = iommu_group_get_iommudata(grp);
- struct page *pg = NULL;
if (!tbl)
return H_RESCINDED;
@@ -307,6 +306,8 @@ static long kvmppc_rm_h_put_tce_indirect_iommu(struct kvm_vcpu *vcpu,
/* Translate TCEs and go get_page() */
for (i = 0; i < npages; ++i) {
+ struct page *pg = NULL;
+
hpa = kvmppc_rm_gpa_to_hpa_and_get(vcpu, tces[i], &pg);
if (hpa == ERROR_ADDR) {
vcpu->arch.tce_tmp_hpas[i] = 0xBAADF00D; /* poison */
@@ -416,7 +417,7 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
tces = kvmppc_rm_gpa_to_hpa_and_get(vcpu, tce_list, &pg);
if (tces == ERROR_ADDR) {
- vcpu->arch.tce_rm_fail = pg ? TCERM_GETLISTPAGE : TCERM_NONE;
+ vcpu->arch.tce_rm_fail = pg ? TCERM_NONE : TCERM_GETLISTPAGE;
return H_TOO_HARD;
}