diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2014-01-22 14:42:57 +1100 |
---|---|---|
committer | Eli Qiao <taget@linux.vnet.ibm.com> | 2014-01-22 11:58:02 +0800 |
commit | 5dd5f6f94556a52effa6a89ba7c4a19f3782f70d (patch) | |
tree | 6dff71fe505011c9a32e29da52aad9eedf6bc01f | |
parent | 15402dd3ce509f2c92f5448ac57c08799c2c6988 (diff) | |
download | powerpc-5dd5f6f94556a52effa6a89ba7c4a19f3782f70d.tar.gz |
vfio: fix virtmode handler
The existing handler assumes that the first failed TCE entry's host
physical address is saved in the tce_tmp_hpas cache but it is not so
the virtmode handler has to read it from the TCE list again so does
this patch.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
-rw-r--r-- | arch/powerpc/kvm/book3s_64_vio.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_vio_hv.c | 6 |
2 files changed, 9 insertions, 1 deletions
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c index 2d4f912dbb7e78..65557562ecfb73 100644 --- a/arch/powerpc/kvm/book3s_64_vio.c +++ b/arch/powerpc/kvm/book3s_64_vio.c @@ -433,7 +433,9 @@ static long kvmppc_h_put_tce_indirect_iommu(struct kvm_vcpu *vcpu, return H_RESCINDED; if (vcpu->arch.tce_rm_fail == TCERM_GETPAGE) { - unsigned long tmp = vcpu->arch.tce_tmp_hpas[vcpu->arch.tce_tmp_num]; + unsigned long tmp; + if (get_user(tmp, tces + vcpu->arch.tce_tmp_num)) + return H_HARDWARE; put_page(pfn_to_page(tmp >> PAGE_SHIFT)); } diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c index 6b54a0c9f50af2..ba16a7322fa985 100644 --- a/arch/powerpc/kvm/book3s_64_vio_hv.c +++ b/arch/powerpc/kvm/book3s_64_vio_hv.c @@ -167,8 +167,13 @@ static unsigned long kvmppc_rm_hugepage_gpa_to_hpa( /* * Converts guest physical address to host physical address. + * * Tries to increase page counter via get_page_unless_zero() and * returns ERROR_ADDR if failed. + * + * Returns ERROR_ADDR if the page has gone before we increased + * page use counter. *pg may not be NULL if put_page_unless_one() + * failed to put the page. */ static unsigned long kvmppc_rm_gpa_to_hpa_and_get(struct kvm_vcpu *vcpu, unsigned long gpa, struct page **pg) @@ -304,6 +309,7 @@ static long kvmppc_rm_h_put_tce_indirect_iommu(struct kvm_vcpu *vcpu, for (i = 0; i < npages; ++i) { hpa = kvmppc_rm_gpa_to_hpa_and_get(vcpu, tces[i], &pg); if (hpa == ERROR_ADDR) { + vcpu->arch.tce_tmp_hpas[i] = 0xBAADF00D; /* poison */ vcpu->arch.tce_tmp_num = i; vcpu->arch.tce_rm_fail = pg ? TCERM_GETPAGE : TCERM_NONE; |