aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s_hv.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2012-05-08 20:24:08 +1000
committerAvi Kivity <avi@redhat.com>2012-05-08 17:54:08 +0300
commitde6c0b02d4d7bdf2587e679a6ddbb71b7d68bb89 (patch)
treed1b7cb647d6282052768c4a1e5a37fb88cd482f5 /arch/powerpc/kvm/book3s_hv.c
parentKVM: Do not take reference to mm during async #PF (diff)
downloadlinux-dev-de6c0b02d4d7bdf2587e679a6ddbb71b7d68bb89.tar.xz
linux-dev-de6c0b02d4d7bdf2587e679a6ddbb71b7d68bb89.zip
KVM: PPC: Book3S HV: Fix refcounting of hugepages
The H_REGISTER_VPA hcall implementation in HV Power KVM needs to pin some guest memory pages into host memory so that they can be safely accessed from usermode. It does this used get_user_pages_fast(). When the VPA is unregistered, or the VCPUs are cleaned up, these pages are released using put_page(). However, the get_user_pages() is invoked on the specific memory are of the VPA which could lie within hugepages. In case the pinned page is huge, we explicitly find the head page of the compound page before calling put_page() on it. At least with the latest kernel, this is not correct. put_page() already handles finding the correct head page of a compound, and also deals with various counts on the individual tail page which are important for transparent huge pages. We don't support transparent hugepages on Power, but even so, bypassing this count maintenance can lead (when the VM ends) to a hugepage being released back to the pool with a non-zero mapcount on one of the tail pages. This can then lead to a bad_page() when the page is released from the hugepage pool. This removes the explicit compound_head() call to correct this bug. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org> Acked-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to '')
-rw-r--r--arch/powerpc/kvm/book3s_hv.c2
1 files changed, 0 insertions, 2 deletions
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 01294a5099dd..108d1f580177 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1192,8 +1192,6 @@ static void unpin_slot(struct kvm *kvm, int slot_id)
continue;
pfn = physp[j] >> PAGE_SHIFT;
page = pfn_to_page(pfn);
- if (PageHuge(page))
- page = compound_head(page);
SetPageDirty(page);
put_page(page);
}