@@ -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;
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@google.com> --- virt/kvm/guest_memfd.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)