We now have to pass our struct kvm into __kvm_gmem_get_pfn to know if a gfn is userfault-enabled or not. For faults on userfault-enabled gfns, indicate this to the caller by setting *pfn to KVM_PFN_ERR_USERFAULT. Architectures may use this to know to return a userfault to userspace, though they should be careful to set a value for *pfn before calling (e.g. KVM_PFN_ERR_FAULT). While we're at it, set *pfn to KVM_PFN_ERR_HWPOISON for accesses to poisoned gfns. Signed-off-by: James Houghton <jthoughton@xxxxxxxxxx> --- virt/kvm/guest_memfd.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c index 9148b9679bb1..ba7a981e3396 100644 --- a/virt/kvm/guest_memfd.c +++ b/virt/kvm/guest_memfd.c @@ -542,8 +542,9 @@ void kvm_gmem_unbind(struct kvm_memory_slot *slot) fput(file); } -static int __kvm_gmem_get_pfn(struct file *file, struct kvm_memory_slot *slot, - gfn_t gfn, kvm_pfn_t *pfn, int *max_order, bool prepare) +static int __kvm_gmem_get_pfn(struct kvm *kvm, struct file *file, + struct kvm_memory_slot *slot, gfn_t gfn, kvm_pfn_t *pfn, + int *max_order, bool prepare) { pgoff_t index = gfn - slot->base_gfn + slot->gmem.pgoff; struct kvm_gmem *gmem = file->private_data; @@ -551,6 +552,11 @@ static int __kvm_gmem_get_pfn(struct file *file, struct kvm_memory_slot *slot, struct page *page; int r; + if (gfn_has_userfault(kvm, gfn)) { + *pfn = KVM_PFN_ERR_USERFAULT; + return -EFAULT; + } + if (file != slot->gmem.file) { WARN_ON_ONCE(slot->gmem.file); return -EFAULT; @@ -567,6 +573,7 @@ static int __kvm_gmem_get_pfn(struct file *file, struct kvm_memory_slot *slot, return PTR_ERR(folio); if (folio_test_hwpoison(folio)) { + *pfn = KVM_PFN_ERR_HWPOISON; folio_unlock(folio); folio_put(folio); return -EHWPOISON; @@ -594,7 +601,7 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot, if (!file) return -EFAULT; - r = __kvm_gmem_get_pfn(file, slot, gfn, pfn, max_order, true); + r = __kvm_gmem_get_pfn(kvm, file, slot, gfn, pfn, max_order, true); fput(file); return r; } @@ -634,7 +641,8 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long break; } - ret = __kvm_gmem_get_pfn(file, slot, gfn, &pfn, &max_order, false); + ret = __kvm_gmem_get_pfn(kvm, file, slot, gfn, &pfn, + &max_order, false); if (ret) break; -- 2.45.2.993.g49e7a77208-goog