[PATCH RFC v3 59/88] vfio: Dispatch guest_memfd get_pfn provider op via vfio_device_ops
From: Ackerley Tng via B4 Relay
Date: Fri Nov 06 2026 - 19:52:09 EST
From: Ackerley Tng <ackerleytng@xxxxxxxxxx>
When servicing guest stage-2 page faults or host userspace page faults
on guest_memfd memory backed by a VFIO resource descriptor, guest_memfd
invokes the .get_pfn provider operation under the shared filemap
invalidation lock.
Implement .get_pfn on vfio_device_gmem_provider_ops to dispatch to the
bus driver's .gmem_get_pfn callback on struct vfio_device_ops. Return
-EOPNOTSUPP if the bus driver does not implement the callback. The core
dispatch path avoids acquiring dev_set->lock to satisfy the requirement
that provider callbacks do not acquire locks held during revocation.
Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>
---
drivers/vfio/vfio_main.c | 16 ++++++++++++++++
include/linux/vfio.h | 3 +++
2 files changed, 19 insertions(+)
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 618daf8bdaf80..93bd0a200ad22 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -1589,9 +1589,25 @@ static void vfio_device_gmem_release(void *provider)
fput(file);
}
+static int vfio_device_gmem_get_pfn(void *provider, pgoff_t index,
+ unsigned long *pfn, int *max_order,
+ u64 *pfn_attrs)
+{
+ struct file *file = provider;
+ struct vfio_device_file *df = file->private_data;
+ struct vfio_device *device = df->device;
+
+ if (!device->ops->gmem_get_pfn)
+ return -EOPNOTSUPP;
+
+ return device->ops->gmem_get_pfn(device, index, pfn, max_order,
+ pfn_attrs);
+}
+
static const struct guest_memfd_provider_operations vfio_device_gmem_provider_ops = {
.attach = vfio_device_gmem_attach,
.release = vfio_device_gmem_release,
+ .get_pfn = vfio_device_gmem_get_pfn,
};
#endif
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 65dc2cb523351..51e04b980a381 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -122,6 +122,9 @@ struct guest_memfd_provider_operations;
struct vfio_device_ops {
int (*gmem_attach)(struct vfio_device *device);
void (*gmem_release)(struct vfio_device *device);
+ int (*gmem_get_pfn)(struct vfio_device *device, pgoff_t index,
+ unsigned long *pfn, int *max_order,
+ u64 *pfn_attrs);
char *name;
int (*init)(struct vfio_device *vdev);
void (*release)(struct vfio_device *vdev);
--
2.56.0.455.g6c5a503b38-goog