X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=virt%2Fkvm%2Fkvm_main.c;h=f7445c3bcd90a260b36b239033457e2b6cb674b4;hb=f3cf800778e9e76b2387d00c9bfbc2e16efdb7ed;hp=3dcc2abbfc609f18fb3c4103babc093e0b2ef0bf;hpb=b8917b4ae44d1b945f6fba3d8ee6777edb44633b;p=platform%2Fkernel%2Flinux-starfive.git diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 3dcc2ab..f7445c3 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2175,6 +2175,13 @@ static bool vma_is_valid(struct vm_area_struct *vma, bool write_fault) return true; } +static int kvm_try_get_pfn(kvm_pfn_t pfn) +{ + if (kvm_is_reserved_pfn(pfn)) + return 1; + return get_page_unless_zero(pfn_to_page(pfn)); +} + static int hva_to_pfn_remapped(struct vm_area_struct *vma, unsigned long addr, bool *async, bool write_fault, bool *writable, @@ -2224,13 +2231,21 @@ static int hva_to_pfn_remapped(struct vm_area_struct *vma, * Whoever called remap_pfn_range is also going to call e.g. * unmap_mapping_range before the underlying pages are freed, * causing a call to our MMU notifier. + * + * Certain IO or PFNMAP mappings can be backed with valid + * struct pages, but be allocated without refcounting e.g., + * tail pages of non-compound higher order allocations, which + * would then underflow the refcount when the caller does the + * required put_page. Don't allow those pages here. */ - kvm_get_pfn(pfn); + if (!kvm_try_get_pfn(pfn)) + r = -EFAULT; out: pte_unmap_unlock(ptep, ptl); *p_pfn = pfn; - return 0; + + return r; } /*