diff options
Diffstat (limited to 'arch/powerpc/kvm/book3s_64_mmu_hv.c')
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_hv.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index c615617..efd5a6b 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -81,7 +81,7 @@ struct kvm_resize_hpt { int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order) { unsigned long hpt = 0; - int cma = 0; + int resv = 0, cma = 0; struct page *page = NULL; struct revmap_entry *rev; unsigned long npte; @@ -89,11 +89,17 @@ int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order) if ((order < PPC_MIN_HPT_ORDER) || (order > PPC_MAX_HPT_ORDER)) return -EINVAL; - page = kvm_alloc_hpt_cma(1ul << (order - PAGE_SHIFT)); - if (page) { - hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); + hpt = kvmhv_alloc_resv_hpt(order); + if (hpt) { memset((void *)hpt, 0, (1ul << order)); - cma = 1; + resv = 1; + } else { + page = kvm_alloc_hpt_cma(1ul << (order - PAGE_SHIFT)); + if (page) { + hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); + memset((void *)hpt, 0, (1ul << order)); + cma = 1; + } } if (!hpt) @@ -109,7 +115,9 @@ int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order) /* Allocate reverse map array */ rev = vmalloc(array_size(npte, sizeof(struct revmap_entry))); if (!rev) { - if (cma) + if (resv) + kvmhv_release_resv_hpt(hpt, order); + else if (cma) kvm_free_hpt_cma(page, 1 << (order - PAGE_SHIFT)); else free_pages(hpt, order - PAGE_SHIFT); @@ -118,6 +126,7 @@ int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order) info->order = order; info->virt = hpt; + info->resv = resv; info->cma = cma; info->rev = rev; @@ -191,7 +200,9 @@ void kvmppc_free_hpt(struct kvm_hpt_info *info) { vfree(info->rev); info->rev = NULL; - if (info->cma) + if (info->resv) + kvmhv_release_resv_hpt(info->virt, info->order); + else if (info->cma) kvm_free_hpt_cma(virt_to_page(info->virt), 1 << (info->order - PAGE_SHIFT)); else if (info->virt) |