* [PATCH v8 0/4] virtio-gpu: Add userptr support for compute workloads
@ 2026-09-18 9:59 Honglei Huang
2026-09-18 9:59 ` [PATCH v8 1/4] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability Honglei Huang
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Honglei Huang @ 2026-09-18 9:59 UTC (permalink / raw)
To: Dmitry Osipenko, Akihiko Odaki, David Airlie, Gerd Hoffmann
Cc: Gurchetan Singh, Chia-I Wu, Ray Huang, dri-devel, virtualization,
linux-kernel, Honglei Huang
Hello,
This series adds virtio-gpu userptr support for ROCm native compute
contexts. The guest kernel pins an existing userspace mapping with
FOLL_LONGTERM and exposes it to the host as ordinary CREATE_BLOB
backing entries, avoiding a second shmem allocation and memcpy.
A non-zero userptr field selects that path. Probe
VIRTGPU_PARAM_USERPTR before using the field so an older guest kernel
rejects the request instead of silently creating a shmem blob.
GPU-readonly backing is requested with the virtio CREATE_BLOB wire
flag VIRTIO_GPU_BLOB_FLAG_USE_READONLY (also
VIRTGPU_BLOB_FLAG_USE_READONLY). The device MUST NOT write such a
resource. The guest accepts that flag and pins without FOLL_WRITE
only when the device advertised VIRTIO_GPU_F_BLOB_READONLY
(VIRTGPU_PARAM_BLOB_READONLY). Otherwise CREATE_BLOB fails, matching
the CROSS_DEVICE host-capability check.
Patches overview:
1. Add VIRTIO_GPU_CAPSET_ROCM capability for compute workloads
2. Extend DRM/virtio UAPI with userptr, PARAM_USERPTR,
USE_READONLY, and F_BLOB_READONLY
3. Implement core userptr functionality with page management
4. Wire blob ioctl creation to userptr objects and probe the
readonly feature
Tests:
- Full OPENCL CTS tests passed on ROCm 5.7.0 in V2000 platform.
- Near 70% percentage of OPENCL CTS tests passed on ROCm 7.0 W7900 platform.
- most HIP catch tests passed on ROCm 7.0 W7900 platform.
- Some AI applications enabled on ROCm 7.0 W7900 platform.
- latest ROCm 7.14 and ROCm 10 testing is ongoing.
V8 changes:
- Drop guest-only USERPTR ioctl flags; a non-zero userptr field
selects the path
- Add VIRTGPU_PARAM_USERPTR so older kernels do not silently
ignore the new field
- Request GPU-readonly backing with virtio wire flag USE_READONLY
- Accept USE_READONLY and omit FOLL_WRITE only if the host
advertised VIRTIO_GPU_F_BLOB_READONLY
- Restore userptr blobs after hibernation without the shmem path
V7 changes:
- Mask guest-only DRM flags out of CREATE_BLOB wire blob_flags
- Clear userptr->pages after pin failure to avoid double-free
- DMA-map userptr SG only when virtio_gpu_use_dma_api() is required
- Use DMA_TO_DEVICE for readonly blobs
- Sync userptr SG for the device on TRANSFER_TO_HOST
- Mark writable pages dirty when unpinning
- Reject USERPTR unless blob_mem is VIRTGPU_BLOB_MEM_GUEST
- Disallow PRIME export of userptr objects
- Note that CAPSET_ROCM uses ID 8 because ID 7 is taken by VIRCL
V6 changes:
- Rebase onto drm-misc-next
- Keep USE_USERPTR / USERPTR_RDONLY as guest-only DRM flags; drop the
virtio wire-header patch (5 patches down to 4)
- Fix userptr lifetime, DMA mapping, memlock accounting, alignment
checks, and PRIME SG export
- Updated corresponding cover letter and commit messages
V5 changes:
- Add VIRTIO_GPU_BLOB_FLAG_USERPTR_RDONLY definition to patch 2
- Dropped unused VIRTIO_GPU_F_RESOURCE_USERPTR feature bit in patch 2
- Included VIRTIO_GPU_BLOB_FLAG_USERPTR_RDONLY in VIRTGPU_BLOB_FLAG_USE_MASK in patch 5
- Add check for userptr feature in patch 5 before creating userptr blob resource
- Updated corresponding cover letter and commit messages
V4 changes:
- Renamed VIRTIO_GPU_CAPSET_HSAKMT to VIRTIO_GPU_CAPSET_ROCM
- Remove userptr feature probing cause it can reuse the guest
blob resource code path, reduce patch count from 6 to 5
- Updated corresponding commit messages
- Consolidated userptr feature detection in final patch
- Update corresponding cover letter content
V3 changes:
- Split into focused patches for easier review
- Removed complex interval tree userptr management
- Simplified resource creation without deduplication
- Added VIRTGPU_PARAM_RESOURCE_USERPTR for feature detection
- Improved UAPI documentation and error handling
- Enhanced code quality with proper cleanup paths
- Removed MMU notifier dependencies for simplicity
- Fixed resource lifecycle management issues
V2: - Split add HSAKMT context and blob userptr resource to two patches.
- Remove MMU notifier related patches, cause use not moveable user space
memory with MMU notifier is not a good idea.
- Remove HSAKMT context check when create context, let all the context
support the userptr feature.
- Remove MMU notifier related content in cover letter.
- Add more comments for patch 6 in cover letter.
Previous version:
https://lore.kernel.org/dri-devel/20260917102540.1312102-1-honghuan@amd.com/
Honglei Huang (4):
drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability
drm/virtgpu api: add blob userptr resource
drm/virtio: implement userptr support for zero-copy memory access
drm/virtio: wire blob ioctl creation to userptr objects
drivers/gpu/drm/virtio/Makefile | 3 +-
drivers/gpu/drm/virtio/virtgpu_debugfs.c | 1 +
drivers/gpu/drm/virtio/virtgpu_drv.h | 43 +++
drivers/gpu/drm/virtio/virtgpu_ioctl.c | 35 ++-
drivers/gpu/drm/virtio/virtgpu_kms.c | 8 +-
drivers/gpu/drm/virtio/virtgpu_object.c | 22 ++
drivers/gpu/drm/virtio/virtgpu_userptr.c | 365 +++++++++++++++++++++++
drivers/gpu/drm/virtio/virtgpu_vq.c | 33 +-
include/uapi/drm/virtgpu_drm.h | 13 +
include/uapi/linux/virtio_gpu.h | 7 +
10 files changed, 513 insertions(+), 17 deletions(-)
create mode 100644 drivers/gpu/drm/virtio/virtgpu_userptr.c
base-commit: 766bfba0f3bae329f99b42dcabc3ef11fa368f0b
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v8 1/4] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability
2026-09-18 9:59 [PATCH v8 0/4] virtio-gpu: Add userptr support for compute workloads Honglei Huang
@ 2026-09-18 9:59 ` Honglei Huang
2026-09-18 9:59 ` [PATCH v8 2/4] drm/virtgpu api: add blob userptr resource Honglei Huang
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Honglei Huang @ 2026-09-18 9:59 UTC (permalink / raw)
To: Dmitry Osipenko, Akihiko Odaki, David Airlie, Gerd Hoffmann
Cc: Gurchetan Singh, Chia-I Wu, Ray Huang, dri-devel, virtualization,
linux-kernel, Honglei Huang
Add a new GPU capability set VIRTIO_GPU_CAPSET_ROCM to support
ROCm compute workloads in virtualized environments.
ROCm (Radeon Open Compute) is AMD's open-source software platform
for GPU compute and HPC workloads.
ID 7 is already used by VIRCL in the virgl/virtio-gpu stack, so
ROCm uses ID 8. A matching virtio-gpu specification change is in
progress to register this assignment.
Signed-off-by: Honglei Huang <honghuan@amd.com>
---
include/uapi/linux/virtio_gpu.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h
index 4f530d9005..3d4dfadc9d 100644
--- a/include/uapi/linux/virtio_gpu.h
+++ b/include/uapi/linux/virtio_gpu.h
@@ -321,6 +321,7 @@ struct virtio_gpu_cmd_submit {
#define VIRTIO_GPU_CAPSET_VENUS 4
#define VIRTIO_GPU_CAPSET_CROSS_DOMAIN 5
#define VIRTIO_GPU_CAPSET_DRM 6
+#define VIRTIO_GPU_CAPSET_ROCM 8
/* VIRTIO_GPU_CMD_GET_CAPSET_INFO */
struct virtio_gpu_get_capset_info {
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v8 2/4] drm/virtgpu api: add blob userptr resource
2026-09-18 9:59 [PATCH v8 0/4] virtio-gpu: Add userptr support for compute workloads Honglei Huang
2026-09-18 9:59 ` [PATCH v8 1/4] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability Honglei Huang
@ 2026-09-18 9:59 ` Honglei Huang
2026-09-18 12:12 ` Akihiko Odaki
2026-09-18 9:59 ` [PATCH v8 3/4] drm/virtio: implement userptr support for zero-copy memory access Honglei Huang
2026-09-18 9:59 ` [PATCH v8 4/4] drm/virtio: wire blob ioctl creation to userptr objects Honglei Huang
3 siblings, 1 reply; 7+ messages in thread
From: Honglei Huang @ 2026-09-18 9:59 UTC (permalink / raw)
To: Dmitry Osipenko, Akihiko Odaki, David Airlie, Gerd Hoffmann
Cc: Gurchetan Singh, Chia-I Wu, Ray Huang, dri-devel, virtualization,
linux-kernel, Honglei Huang
Add a userptr address field so userspace can request a blob backed
by an existing process mapping. A non-zero userptr selects that
path; probe VIRTGPU_PARAM_USERPTR before using the field.
GPU-readonly backing is requested with the virtio CREATE_BLOB wire
flag VIRTIO_GPU_BLOB_FLAG_USE_READONLY (also
VIRTGPU_BLOB_FLAG_USE_READONLY). The device MUST NOT write such a
resource. The guest pins without FOLL_WRITE only when the device
advertised VIRTIO_GPU_F_BLOB_READONLY (VIRTGPU_PARAM_BLOB_READONLY).
Signed-off-by: Honglei Huang <honghuan@amd.com>
---
include/uapi/drm/virtgpu_drm.h | 13 +++++++++++++
include/uapi/linux/virtio_gpu.h | 6 ++++++
2 files changed, 19 insertions(+)
diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h
index 95587e12ae..80f73b3276 100644
--- a/include/uapi/drm/virtgpu_drm.h
+++ b/include/uapi/drm/virtgpu_drm.h
@@ -99,6 +99,8 @@ struct drm_virtgpu_execbuffer {
#define VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs 7 /* Bitmask of supported capability set ids */
#define VIRTGPU_PARAM_EXPLICIT_DEBUG_NAME 8 /* Ability to set debug name from userspace */
#define VIRTGPU_PARAM_BLOB_ALIGNMENT 9 /* Device alignment requirements for blobs */
+#define VIRTGPU_PARAM_USERPTR 10 /* CREATE_BLOB userptr field is supported */
+#define VIRTGPU_PARAM_BLOB_READONLY 11 /* VIRTGPU_BLOB_FLAG_USE_READONLY is honored */
struct drm_virtgpu_getparam {
__u64 param;
@@ -186,6 +188,10 @@ struct drm_virtgpu_resource_create_blob {
#define VIRTGPU_BLOB_FLAG_USE_MAPPABLE 0x0001
#define VIRTGPU_BLOB_FLAG_USE_SHAREABLE 0x0002
#define VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
+/* Wire flag: device MUST NOT write. Guest pins without FOLL_WRITE.
+ * Rejected unless VIRTGPU_PARAM_BLOB_READONLY is 1.
+ */
+#define VIRTGPU_BLOB_FLAG_USE_READONLY 0x0008
/* zero is invalid blob_mem */
__u32 blob_mem;
__u32 blob_flags;
@@ -205,6 +211,13 @@ struct drm_virtgpu_resource_create_blob {
#define DRM_VIRTGPU_BLOB_FLAG_HINT_DEFER_MAPPING 0x0001
__u32 blob_hints;
__u32 pad2;
+
+ /*
+ * Guest VA to pin as blob backing. Non-zero selects the userptr
+ * path and is valid only with VIRTGPU_BLOB_MEM_GUEST. Must be 0
+ * otherwise. Probe VIRTGPU_PARAM_USERPTR before using this field.
+ */
+ __u64 userptr;
};
#define VIRTGPU_CONTEXT_PARAM_CAPSET_ID 0x0001
diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h
index 3d4dfadc9d..33f5332e59 100644
--- a/include/uapi/linux/virtio_gpu.h
+++ b/include/uapi/linux/virtio_gpu.h
@@ -72,6 +72,10 @@
* must be aligned to that value.
*/
#define VIRTIO_GPU_F_BLOB_ALIGNMENT 5
+/*
+ * VIRTIO_GPU_BLOB_FLAG_USE_READONLY
+ */
+#define VIRTIO_GPU_F_BLOB_READONLY 6
enum virtio_gpu_ctrl_type {
VIRTIO_GPU_UNDEFINED = 0,
@@ -415,6 +419,8 @@ struct virtio_gpu_resource_create_blob {
#define VIRTIO_GPU_BLOB_FLAG_USE_MAPPABLE 0x0001
#define VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE 0x0002
#define VIRTIO_GPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
+/* Device MUST NOT write. Driver may pin read-only guest pages. */
+#define VIRTIO_GPU_BLOB_FLAG_USE_READONLY 0x0008
/* zero is invalid blob mem */
__le32 blob_mem;
__le32 blob_flags;
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v8 3/4] drm/virtio: implement userptr support for zero-copy memory access
2026-09-18 9:59 [PATCH v8 0/4] virtio-gpu: Add userptr support for compute workloads Honglei Huang
2026-09-18 9:59 ` [PATCH v8 1/4] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability Honglei Huang
2026-09-18 9:59 ` [PATCH v8 2/4] drm/virtgpu api: add blob userptr resource Honglei Huang
@ 2026-09-18 9:59 ` Honglei Huang
2026-09-18 9:59 ` [PATCH v8 4/4] drm/virtio: wire blob ioctl creation to userptr objects Honglei Huang
3 siblings, 0 replies; 7+ messages in thread
From: Honglei Huang @ 2026-09-18 9:59 UTC (permalink / raw)
To: Dmitry Osipenko, Akihiko Odaki, David Airlie, Gerd Hoffmann
Cc: Gurchetan Singh, Chia-I Wu, Ray Huang, dri-devel, virtualization,
linux-kernel, Honglei Huang
Add userptr blob objects so the guest kernel can pin an existing
userspace mapping and advertise it as CREATE_BLOB backing entries.
- New virtio_gpu_object_userptr type for userptr resources
- Pin pages with pin_user_pages_fast() and FOLL_LONGTERM
- Omit FOLL_WRITE when VIRTGPU_BLOB_FLAG_USE_READONLY is set
- Charge FOLL_LONGTERM pins against RLIMIT_MEMLOCK
- DMA-map the scatterlist only when virtio_gpu_use_dma_api() is
required; use DMA_TO_DEVICE for USE_READONLY blobs
- Sync userptr SG for the device on TRANSFER_TO_HOST
- Mark writable pages dirty when unpinning
- Keep pages pinned until RESOURCE_UNREF is queued; drop them from
cleanup_object() on the unref response or on create failure
- Clear userptr->pages on pin failure to avoid double-free on cleanup
- Reject unaligned or overflowing userptr ranges at create time
- Disallow PRIME export of userptr objects
- Save CREATE_BLOB params and restore userptr resources after
hibernation without using the shmem restore path
Signed-off-by: Honglei Huang <honghuan@amd.com>
---
drivers/gpu/drm/virtio/Makefile | 3 +-
drivers/gpu/drm/virtio/virtgpu_drv.h | 43 +++
drivers/gpu/drm/virtio/virtgpu_object.c | 22 ++
drivers/gpu/drm/virtio/virtgpu_userptr.c | 365 +++++++++++++++++++++++
drivers/gpu/drm/virtio/virtgpu_vq.c | 33 +-
5 files changed, 456 insertions(+), 10 deletions(-)
create mode 100644 drivers/gpu/drm/virtio/virtgpu_userptr.c
diff --git a/drivers/gpu/drm/virtio/Makefile b/drivers/gpu/drm/virtio/Makefile
index d2e1788a82..fe7332a621 100644
--- a/drivers/gpu/drm/virtio/Makefile
+++ b/drivers/gpu/drm/virtio/Makefile
@@ -6,6 +6,7 @@
virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o virtgpu_vram.o \
virtgpu_display.o virtgpu_vq.o \
virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
- virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o virtgpu_submit.o
+ virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o virtgpu_submit.o \
+ virtgpu_userptr.o
obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 9df4c71173..e0941cc187 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -105,6 +105,7 @@ struct virtio_gpu_object_params {
uint32_t blob_flags;
uint64_t blob_id;
uint32_t blob_hints;
+ uint64_t userptr;
};
struct virtio_gpu_object {
@@ -138,12 +139,42 @@ struct virtio_gpu_object_vram {
struct drm_mm_node vram_node;
};
+struct virtio_gpu_object_userptr;
+
+struct virtio_gpu_object_userptr_ops {
+ int (*get_pages)(struct virtio_gpu_object_userptr *userptr);
+ void (*put_pages)(struct virtio_gpu_object_userptr *userptr);
+};
+
+struct virtio_gpu_object_userptr {
+ struct virtio_gpu_object base;
+ const struct virtio_gpu_object_userptr_ops *ops;
+ /* Protects pages and sgt. */
+ struct mutex lock;
+
+ uint64_t start;
+ uint32_t npages;
+ uint32_t bo_handle;
+ uint32_t flags;
+
+ struct virtio_gpu_device *vgdev;
+ struct drm_file *file;
+ struct page **pages;
+ struct sg_table *sgt;
+ bool dma_mapped;
+ enum dma_data_direction dma_dir;
+ struct mm_struct *mm;
+};
+
#define to_virtio_gpu_shmem(virtio_gpu_object) \
container_of((virtio_gpu_object), struct virtio_gpu_object_shmem, base)
#define to_virtio_gpu_vram(virtio_gpu_object) \
container_of((virtio_gpu_object), struct virtio_gpu_object_vram, base)
+#define to_virtio_gpu_userptr(virtio_gpu_object) \
+ container_of((virtio_gpu_object), struct virtio_gpu_object_userptr, base)
+
struct virtio_gpu_object_array {
struct ww_acquire_ctx ticket;
struct list_head next;
@@ -284,6 +315,7 @@ struct virtio_gpu_device {
bool has_host_visible;
bool has_context_init;
bool has_blob_alignment;
+ bool has_blob_readonly;
bool hibernated;
struct virtio_shm_region host_visible_region;
struct drm_mm host_visible_mm;
@@ -562,4 +594,15 @@ void virtio_gpu_vram_map_deferred(struct virtio_gpu_object_vram *vram);
int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
+/* virtgpu_userptr.c */
+int virtio_gpu_userptr_create(struct virtio_gpu_device *vgdev,
+ struct drm_file *file,
+ struct virtio_gpu_object_params *params,
+ struct virtio_gpu_object **bo_ptr);
+bool virtio_gpu_is_userptr(struct virtio_gpu_object *bo);
+void virtio_gpu_userptr_dma_sync_for_device(struct virtio_gpu_object *bo);
+int virtio_gpu_userptr_restore(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_object *bo,
+ struct virtio_gpu_mem_entry **ents,
+ unsigned int *nents);
#endif
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
index 49899485be..ab21494b1c 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -91,6 +91,16 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
drm_gem_free_mmap_offset(&vram->base.base.base);
drm_gem_object_release(&vram->base.base.base);
kfree(vram);
+ } else if (virtio_gpu_is_userptr(bo)) {
+ struct virtio_gpu_object_userptr *userptr =
+ to_virtio_gpu_userptr(bo);
+
+ mutex_lock(&userptr->lock);
+ userptr->ops->put_pages(userptr);
+ mutex_unlock(&userptr->lock);
+ mutex_destroy(&userptr->lock);
+ drm_gem_object_release(&userptr->base.base.base);
+ kfree(userptr);
} else {
drm_gem_object_release(&bo->base.base);
kfree(bo);
@@ -316,6 +326,18 @@ int virtio_gpu_object_restore_all(struct virtio_gpu_device *vgdev)
continue;
}
+ if (virtio_gpu_is_userptr(bo)) {
+ ret = virtio_gpu_userptr_restore(vgdev, bo, &ents,
+ &nents);
+ if (ret)
+ break;
+
+ virtio_gpu_cmd_resource_create_blob(vgdev, bo,
+ &bo->params,
+ ents, nents);
+ continue;
+ }
+
if (bo->params.blob || bo->attached) {
ret = virtio_gpu_object_shmem_init(vgdev, bo, &ents,
&nents);
diff --git a/drivers/gpu/drm/virtio/virtgpu_userptr.c b/drivers/gpu/drm/virtio/virtgpu_userptr.c
new file mode 100644
index 0000000000..ccfd96844e
--- /dev/null
+++ b/drivers/gpu/drm/virtio/virtgpu_userptr.c
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/dma-mapping.h>
+#include <linux/limits.h>
+#include <linux/mm.h>
+#include <linux/overflow.h>
+#include <linux/pid.h>
+#include <linux/sched/mm.h>
+#include <linux/sched/signal.h>
+#include <linux/vmalloc.h>
+
+#include "virtgpu_drv.h"
+#include <drm/drm_gem.h>
+
+static void virtio_gpu_userptr_free(struct drm_gem_object *obj)
+{
+ struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
+ struct virtio_gpu_device *vgdev = obj->dev->dev_private;
+
+ /*
+ * Keep pages pinned until RESOURCE_UNREF completes. The response
+ * callback calls virtio_gpu_cleanup_object(), which drops them.
+ */
+ if (bo->created) {
+ virtio_gpu_remove_from_restore_list(bo);
+ virtio_gpu_cmd_unref_resource(vgdev, bo, false);
+ virtio_gpu_notify(vgdev);
+ return;
+ }
+
+ virtio_gpu_cleanup_object(bo);
+}
+
+static struct dma_buf *
+virtio_gpu_userptr_prime_export(struct drm_gem_object *obj, int flags)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static const struct drm_gem_object_funcs virtio_gpu_userptr_funcs = {
+ .open = virtio_gpu_gem_object_open,
+ .close = virtio_gpu_gem_object_close,
+ .free = virtio_gpu_userptr_free,
+ .export = virtio_gpu_userptr_prime_export,
+};
+
+bool virtio_gpu_is_userptr(struct virtio_gpu_object *bo)
+{
+ return bo->base.base.funcs == &virtio_gpu_userptr_funcs;
+}
+
+void virtio_gpu_userptr_dma_sync_for_device(struct virtio_gpu_object *bo)
+{
+ struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(bo);
+ struct device *dev;
+
+ if (!userptr->dma_mapped)
+ return;
+
+ dev = drm_dev_dma_dev(userptr->base.base.base.dev);
+ dma_sync_sgtable_for_device(dev, userptr->sgt, DMA_TO_DEVICE);
+}
+
+static int
+virtio_gpu_userptr_get_pages(struct virtio_gpu_object_userptr *userptr)
+{
+ unsigned int flag = FOLL_LONGTERM;
+ unsigned int num_pages, pinned = 0;
+ int ret = 0;
+
+ if (userptr->pages)
+ return 0;
+
+ userptr->pages = kvmalloc_array(userptr->npages, sizeof(struct page *),
+ GFP_KERNEL);
+ if (!userptr->pages)
+ return -ENOMEM;
+
+ if (!(userptr->flags & VIRTGPU_BLOB_FLAG_USE_READONLY))
+ flag |= FOLL_WRITE;
+
+ do {
+ num_pages = userptr->npages - pinned;
+
+ ret = pin_user_pages_fast(userptr->start + pinned * PAGE_SIZE,
+ num_pages, flag,
+ userptr->pages + pinned);
+
+ if (ret < 0) {
+ if (pinned)
+ unpin_user_pages(userptr->pages, pinned);
+ kvfree(userptr->pages);
+ userptr->pages = NULL;
+ return ret;
+ }
+
+ pinned += ret;
+
+ } while (pinned < userptr->npages);
+
+ return 0;
+}
+
+static void
+virtio_gpu_userptr_unaccount(struct virtio_gpu_object_userptr *userptr)
+{
+ if (!userptr->mm)
+ return;
+
+ atomic64_sub(userptr->npages, &userptr->mm->pinned_vm);
+ mmdrop(userptr->mm);
+ userptr->mm = NULL;
+}
+
+static void
+virtio_gpu_userptr_put_pages(struct virtio_gpu_object_userptr *userptr)
+{
+ struct drm_device *dev = userptr->base.base.base.dev;
+
+ if (userptr->sgt) {
+ if (userptr->dma_mapped)
+ dma_unmap_sgtable(drm_dev_dma_dev(dev), userptr->sgt,
+ userptr->dma_dir, 0);
+ userptr->dma_mapped = false;
+ sg_free_table(userptr->sgt);
+ kfree(userptr->sgt);
+ userptr->sgt = NULL;
+ }
+
+ if (userptr->pages) {
+ bool dirty = !(userptr->flags & VIRTGPU_BLOB_FLAG_USE_READONLY);
+
+ unpin_user_pages_dirty_lock(userptr->pages, userptr->npages,
+ dirty);
+ kvfree(userptr->pages);
+ userptr->pages = NULL;
+ }
+
+ virtio_gpu_userptr_unaccount(userptr);
+}
+
+static int
+virtio_gpu_userptr_get_entries(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_object_userptr *userptr,
+ struct virtio_gpu_mem_entry **ents,
+ unsigned int *nents)
+{
+ bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
+ struct scatterlist *sg;
+ unsigned int count;
+ int si;
+
+ count = use_dma_api ? userptr->sgt->nents : userptr->sgt->orig_nents;
+ if (!count)
+ return -EINVAL;
+
+ *ents = kvmalloc_array(count, sizeof(**ents), GFP_KERNEL);
+ if (!*ents)
+ return -ENOMEM;
+
+ if (use_dma_api) {
+ for_each_sgtable_dma_sg(userptr->sgt, sg, si) {
+ (*ents)[si].addr = cpu_to_le64(sg_dma_address(sg));
+ (*ents)[si].length = cpu_to_le32(sg_dma_len(sg));
+ (*ents)[si].padding = 0;
+ }
+ } else {
+ for_each_sgtable_sg(userptr->sgt, sg, si) {
+ (*ents)[si].addr = cpu_to_le64(sg_phys(sg));
+ (*ents)[si].length = cpu_to_le32(sg->length);
+ (*ents)[si].padding = 0;
+ }
+ }
+
+ *nents = count;
+ return 0;
+}
+
+int virtio_gpu_userptr_restore(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_object *bo,
+ struct virtio_gpu_mem_entry **ents,
+ unsigned int *nents)
+{
+ struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(bo);
+ int ret;
+
+ mutex_lock(&userptr->lock);
+ if (!userptr->sgt || !userptr->pages) {
+ mutex_unlock(&userptr->lock);
+ return -EINVAL;
+ }
+
+ if (userptr->dma_mapped) {
+ struct device *dev = drm_dev_dma_dev(vgdev->ddev);
+
+ dma_unmap_sgtable(dev, userptr->sgt, userptr->dma_dir, 0);
+ userptr->dma_mapped = false;
+ ret = dma_map_sgtable(dev, userptr->sgt, userptr->dma_dir, 0);
+ if (ret) {
+ mutex_unlock(&userptr->lock);
+ return ret;
+ }
+ userptr->dma_mapped = true;
+ }
+
+ ret = virtio_gpu_userptr_get_entries(vgdev, userptr, ents, nents);
+ mutex_unlock(&userptr->lock);
+ return ret;
+}
+
+static int
+virtio_gpu_userptr_init(struct drm_device *dev, struct drm_file *file,
+ struct virtio_gpu_object_userptr *userptr,
+ struct virtio_gpu_object_params *params,
+ const struct virtio_gpu_object_userptr_ops *ops)
+{
+ struct drm_gem_object *obj;
+ int ret;
+
+ userptr->start = params->userptr;
+ userptr->npages = params->size >> PAGE_SHIFT;
+ userptr->flags = params->blob_flags;
+
+ mutex_init(&userptr->lock);
+ userptr->vgdev = dev->dev_private;
+ userptr->file = file;
+ userptr->ops = ops;
+
+ /*
+ * Allocate the resource id before GEM init so a failure here can
+ * unwind with a plain kfree and does not need a special id=0 guard
+ * in the shared resource_id_put helper.
+ */
+ ret = virtio_gpu_resource_id_get(userptr->vgdev,
+ &userptr->base.hw_res_handle);
+ if (ret) {
+ mutex_destroy(&userptr->lock);
+ return ret;
+ }
+
+ obj = &userptr->base.base.base;
+ obj->funcs = &virtio_gpu_userptr_funcs;
+
+ drm_gem_private_object_init(dev, obj, params->size);
+ INIT_LIST_HEAD(&userptr->base.restore_node);
+
+ return 0;
+}
+
+static const struct virtio_gpu_object_userptr_ops virtio_gpu_userptr_ops = {
+ .get_pages = virtio_gpu_userptr_get_pages,
+ .put_pages = virtio_gpu_userptr_put_pages,
+};
+
+int virtio_gpu_userptr_create(struct virtio_gpu_device *vgdev,
+ struct drm_file *file,
+ struct virtio_gpu_object_params *params,
+ struct virtio_gpu_object **bo_ptr)
+{
+ struct virtio_gpu_object_userptr *userptr;
+ struct virtio_gpu_mem_entry *ents = NULL;
+ struct sg_table *sgt;
+ struct mm_struct *mm;
+ unsigned long lock_limit;
+ unsigned long start;
+ unsigned long end;
+ s64 new_pinned;
+ unsigned int nents;
+ int ret;
+
+ *bo_ptr = NULL;
+
+ if (!params->size || !IS_ALIGNED(params->size, PAGE_SIZE) ||
+ params->userptr != (unsigned long)params->userptr)
+ return -EINVAL;
+
+ start = params->userptr;
+ if (!IS_ALIGNED(start, PAGE_SIZE) ||
+ check_add_overflow(start, (unsigned long)params->size, &end))
+ return -EINVAL;
+
+ if (!can_do_mlock())
+ return -EPERM;
+
+ if (params->size >> PAGE_SHIFT > INT_MAX)
+ return -E2BIG;
+
+ if (!access_ok((void __user *)start, params->size))
+ return -EFAULT;
+
+ userptr = kzalloc_obj(*userptr);
+ if (!userptr)
+ return -ENOMEM;
+
+ ret = virtio_gpu_userptr_init(vgdev->ddev, file, userptr, params,
+ &virtio_gpu_userptr_ops);
+ if (ret) {
+ kfree(userptr);
+ return ret;
+ }
+
+ mm = current->mm;
+ mmgrab(mm);
+ lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+ new_pinned = atomic64_add_return(userptr->npages, &mm->pinned_vm);
+ if (new_pinned < 0 ||
+ (new_pinned > lock_limit && !capable(CAP_IPC_LOCK))) {
+ atomic64_sub(userptr->npages, &mm->pinned_vm);
+ mmdrop(mm);
+ ret = new_pinned < 0 ? -EOVERFLOW : -ENOMEM;
+ goto err_cleanup;
+ }
+ userptr->mm = mm;
+
+ mutex_lock(&userptr->lock);
+ ret = userptr->ops->get_pages(userptr);
+ mutex_unlock(&userptr->lock);
+ if (ret)
+ goto err_cleanup;
+
+ sgt = drm_prime_pages_to_sg(vgdev->ddev, userptr->pages,
+ userptr->npages);
+ if (IS_ERR(sgt)) {
+ ret = PTR_ERR(sgt);
+ goto err_cleanup;
+ }
+
+ userptr->sgt = sgt;
+
+ /*
+ * Match shmem blobs: only DMA-map when the virtio DMA API is in
+ * use. Mapping unconditionally can create SWIOTLB bounce buffers
+ * that get copied back over guest pages on unmap even though the
+ * host was given sg_phys() addresses.
+ */
+ if (virtio_gpu_use_dma_api(vgdev->vdev)) {
+ enum dma_data_direction dir =
+ (userptr->flags & VIRTGPU_BLOB_FLAG_USE_READONLY) ?
+ DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
+
+ ret = dma_map_sgtable(drm_dev_dma_dev(vgdev->ddev), sgt,
+ dir, 0);
+ if (ret)
+ goto err_cleanup;
+
+ userptr->dma_dir = dir;
+ userptr->dma_mapped = true;
+ }
+
+ ret = virtio_gpu_userptr_get_entries(vgdev, userptr, &ents, &nents);
+ if (ret)
+ goto err_cleanup;
+
+ virtio_gpu_cmd_resource_create_blob(vgdev, &userptr->base, params, ents,
+ nents);
+
+ userptr->base.params = *params;
+ virtio_gpu_add_object_to_restore_list(vgdev, &userptr->base);
+
+ *bo_ptr = &userptr->base;
+ return 0;
+
+err_cleanup:
+ virtio_gpu_cleanup_object(&userptr->base);
+ return ret;
+}
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index c02c03c10d..dcbd7bb7a6 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -781,9 +781,14 @@ int virtio_gpu_panic_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
struct virtio_gpu_vbuffer *vbuf;
bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
- if (virtio_gpu_is_shmem(bo) && use_dma_api)
- dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
- bo->base.sgt, DMA_TO_DEVICE);
+ if (use_dma_api) {
+ if (virtio_gpu_is_shmem(bo))
+ dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
+ bo->base.sgt,
+ DMA_TO_DEVICE);
+ else if (virtio_gpu_is_userptr(bo))
+ virtio_gpu_userptr_dma_sync_for_device(bo);
+ }
cmd_p = virtio_gpu_panic_alloc_cmd_resp(vgdev, &vbuf, sizeof(*cmd_p));
memset(cmd_p, 0, sizeof(*cmd_p));
@@ -812,9 +817,14 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
struct virtio_gpu_vbuffer *vbuf;
bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
- if (virtio_gpu_is_shmem(bo) && use_dma_api)
- dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
- bo->base.sgt, DMA_TO_DEVICE);
+ if (use_dma_api) {
+ if (virtio_gpu_is_shmem(bo))
+ dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
+ bo->base.sgt,
+ DMA_TO_DEVICE);
+ else if (virtio_gpu_is_userptr(bo))
+ virtio_gpu_userptr_dma_sync_for_device(bo);
+ }
cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
memset(cmd_p, 0, sizeof(*cmd_p));
@@ -1245,9 +1255,14 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
struct virtio_gpu_vbuffer *vbuf;
bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
- if (virtio_gpu_is_shmem(bo) && use_dma_api)
- dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
- bo->base.sgt, DMA_TO_DEVICE);
+ if (use_dma_api) {
+ if (virtio_gpu_is_shmem(bo))
+ dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
+ bo->base.sgt,
+ DMA_TO_DEVICE);
+ else if (virtio_gpu_is_userptr(bo))
+ virtio_gpu_userptr_dma_sync_for_device(bo);
+ }
cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
memset(cmd_p, 0, sizeof(*cmd_p));
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v8 4/4] drm/virtio: wire blob ioctl creation to userptr objects
2026-09-18 9:59 [PATCH v8 0/4] virtio-gpu: Add userptr support for compute workloads Honglei Huang
` (2 preceding siblings ...)
2026-09-18 9:59 ` [PATCH v8 3/4] drm/virtio: implement userptr support for zero-copy memory access Honglei Huang
@ 2026-09-18 9:59 ` Honglei Huang
3 siblings, 0 replies; 7+ messages in thread
From: Honglei Huang @ 2026-09-18 9:59 UTC (permalink / raw)
To: Dmitry Osipenko, Akihiko Odaki, David Airlie, Gerd Hoffmann
Cc: Gurchetan Singh, Chia-I Wu, Ray Huang, dri-devel, virtualization,
linux-kernel, Honglei Huang
Integrate userptr into the blob resource creation ioctl.
- A non-zero userptr selects virtio_gpu_userptr_create()
- Reject userptr unless blob_mem is VIRTGPU_BLOB_MEM_GUEST
- Reject VIRTGPU_BLOB_FLAG_USE_READONLY unless the device
advertised VIRTIO_GPU_F_BLOB_READONLY
- Advertise VIRTGPU_PARAM_USERPTR and VIRTGPU_PARAM_BLOB_READONLY
Signed-off-by: Honglei Huang <honghuan@amd.com>
---
drivers/gpu/drm/virtio/virtgpu_debugfs.c | 1 +
drivers/gpu/drm/virtio/virtgpu_ioctl.c | 35 ++++++++++++++++++++----
drivers/gpu/drm/virtio/virtgpu_kms.c | 8 ++++--
3 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/virtio/virtgpu_debugfs.c b/drivers/gpu/drm/virtio/virtgpu_debugfs.c
index 3a68a16b58..b8b9b40584 100644
--- a/drivers/gpu/drm/virtio/virtgpu_debugfs.c
+++ b/drivers/gpu/drm/virtio/virtgpu_debugfs.c
@@ -55,6 +55,7 @@ static int virtio_gpu_features(struct seq_file *m, void *data)
vgdev->has_resource_assign_uuid);
virtio_gpu_add_bool(m, "blob resources", vgdev->has_resource_blob);
+ virtio_gpu_add_bool(m, "blob readonly", vgdev->has_blob_readonly);
virtio_gpu_add_bool(m, "context init", vgdev->has_context_init);
virtio_gpu_add_int(m, "cap sets", vgdev->num_capsets);
virtio_gpu_add_int(m, "scanouts", vgdev->num_scanouts);
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index 3d8e4ccdb7..3dc058e50e 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -36,7 +36,10 @@
#define VIRTGPU_BLOB_FLAG_USE_MASK (VIRTGPU_BLOB_FLAG_USE_MAPPABLE | \
VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
- VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
+ VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE | \
+ VIRTGPU_BLOB_FLAG_USE_READONLY)
+
+#define VIRTGPU_BLOB_HINT_MASK DRM_VIRTGPU_BLOB_FLAG_HINT_DEFER_MAPPING
/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */
static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,
@@ -122,6 +125,12 @@ static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
return -ENOENT;
value = vgdev->blob_alignment;
break;
+ case VIRTGPU_PARAM_USERPTR:
+ value = 1;
+ break;
+ case VIRTGPU_PARAM_BLOB_READONLY:
+ value = vgdev->has_blob_readonly ? 1 : 0;
+ break;
default:
return -EINVAL;
}
@@ -453,11 +462,23 @@ static int verify_blob(struct virtio_gpu_device *vgdev,
if (rc_blob->blob_flags & ~VIRTGPU_BLOB_FLAG_USE_MASK)
return -EINVAL;
+ if (rc_blob->blob_hints & ~VIRTGPU_BLOB_HINT_MASK)
+ return -EINVAL;
+
if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) {
if (!vgdev->has_resource_assign_uuid)
return -EINVAL;
}
+ if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_READONLY) {
+ if (!vgdev->has_blob_readonly)
+ return -EINVAL;
+ }
+
+ if (rc_blob->userptr &&
+ rc_blob->blob_mem != VIRTGPU_BLOB_MEM_GUEST)
+ return -EINVAL;
+
switch (rc_blob->blob_mem) {
case VIRTGPU_BLOB_MEM_GUEST:
*guest_blob = true;
@@ -495,6 +516,7 @@ static int verify_blob(struct virtio_gpu_device *vgdev,
params->blob = true;
params->blob_flags = rc_blob->blob_flags;
params->blob_hints = rc_blob->blob_hints;
+ params->userptr = rc_blob->userptr;
if (vgdev->has_blob_alignment &&
!IS_ALIGNED(params->size, vgdev->blob_alignment))
@@ -518,9 +540,10 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev,
struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
struct drm_virtgpu_resource_create_blob *rc_blob = data;
- if (verify_blob(vgdev, vfpriv, ¶ms, rc_blob,
- &guest_blob, &host3d_blob))
- return -EINVAL;
+ ret = verify_blob(vgdev, vfpriv, ¶ms, rc_blob,
+ &guest_blob, &host3d_blob);
+ if (ret)
+ return ret;
if (vgdev->has_virgl_3d)
virtio_gpu_create_context(dev, file);
@@ -538,7 +561,9 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev,
vfpriv->ctx_id, NULL, NULL);
}
- if (guest_blob)
+ if (guest_blob && params.userptr)
+ ret = virtio_gpu_userptr_create(vgdev, file, ¶ms, &bo);
+ else if (guest_blob)
ret = virtio_gpu_object_create(vgdev, ¶ms, &bo, NULL);
else if (!guest_blob && host3d_blob)
ret = virtio_gpu_vram_create(vgdev, ¶ms, &bo);
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 1d4d3bf46a..06c2bded49 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -249,15 +249,19 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
vgdev->blob_alignment = blob_alignment;
}
+ if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_BLOB_READONLY))
+ vgdev->has_blob_readonly = true;
+
DRM_INFO("features: %cvirgl %cedid %cresource_blob %chost_visible",
vgdev->has_virgl_3d ? '+' : '-',
vgdev->has_edid ? '+' : '-',
vgdev->has_resource_blob ? '+' : '-',
vgdev->has_host_visible ? '+' : '-');
- DRM_INFO("features: %ccontext_init %cblob_alignment\n",
+ DRM_INFO("features: %ccontext_init %cblob_alignment %cblob_readonly\n",
vgdev->has_context_init ? '+' : '-',
- vgdev->has_blob_alignment ? '+' : '-');
+ vgdev->has_blob_alignment ? '+' : '-',
+ vgdev->has_blob_readonly ? '+' : '-');
ret = virtio_gpu_find_vqs(vgdev);
if (ret) {
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v8 2/4] drm/virtgpu api: add blob userptr resource
2026-09-18 9:59 ` [PATCH v8 2/4] drm/virtgpu api: add blob userptr resource Honglei Huang
@ 2026-09-18 12:12 ` Akihiko Odaki
2026-09-18 15:48 ` Huang, Honglei
0 siblings, 1 reply; 7+ messages in thread
From: Akihiko Odaki @ 2026-09-18 12:12 UTC (permalink / raw)
To: Honglei Huang, Dmitry Osipenko, David Airlie, Gerd Hoffmann
Cc: Gurchetan Singh, Chia-I Wu, Ray Huang, dri-devel, virtualization,
linux-kernel
On 2026/09/18 18:59, Honglei Huang wrote:
> Add a userptr address field so userspace can request a blob backed
> by an existing process mapping. A non-zero userptr selects that
> path; probe VIRTGPU_PARAM_USERPTR before using the field.
>
> GPU-readonly backing is requested with the virtio CREATE_BLOB wire
> flag VIRTIO_GPU_BLOB_FLAG_USE_READONLY (also
> VIRTGPU_BLOB_FLAG_USE_READONLY). The device MUST NOT write such a
> resource. The guest pins without FOLL_WRITE only when the device
> advertised VIRTIO_GPU_F_BLOB_READONLY (VIRTGPU_PARAM_BLOB_READONLY).
>
> Signed-off-by: Honglei Huang <honghuan@amd.com>
> ---
> include/uapi/drm/virtgpu_drm.h | 13 +++++++++++++
> include/uapi/linux/virtio_gpu.h | 6 ++++++
> 2 files changed, 19 insertions(+)
>
> diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h
> index 95587e12ae..80f73b3276 100644
> --- a/include/uapi/drm/virtgpu_drm.h
> +++ b/include/uapi/drm/virtgpu_drm.h
> @@ -99,6 +99,8 @@ struct drm_virtgpu_execbuffer {
> #define VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs 7 /* Bitmask of supported capability set ids */
> #define VIRTGPU_PARAM_EXPLICIT_DEBUG_NAME 8 /* Ability to set debug name from userspace */
> #define VIRTGPU_PARAM_BLOB_ALIGNMENT 9 /* Device alignment requirements for blobs */
> +#define VIRTGPU_PARAM_USERPTR 10 /* CREATE_BLOB userptr field is supported */
> +#define VIRTGPU_PARAM_BLOB_READONLY 11 /* VIRTGPU_BLOB_FLAG_USE_READONLY is honored */
>
> struct drm_virtgpu_getparam {
> __u64 param;
> @@ -186,6 +188,10 @@ struct drm_virtgpu_resource_create_blob {
> #define VIRTGPU_BLOB_FLAG_USE_MAPPABLE 0x0001
> #define VIRTGPU_BLOB_FLAG_USE_SHAREABLE 0x0002
> #define VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
> +/* Wire flag: device MUST NOT write. Guest pins without FOLL_WRITE.
> + * Rejected unless VIRTGPU_PARAM_BLOB_READONLY is 1.
> + */
According to Documentation/process/coding-style.rst, the preferred style
for long (multi-line) comments is:
/*
* This is the preferred style for multi-line
* comments in the Linux kernel source code.
* Please use it consistently.
*
* Description: A column of asterisks on the left side,
* with beginning and ending almost-blank lines.
*/
So please avoid putting text on the same line as the opening /*.
Furthermore, because this is a UAPI header (defining the interface
between userspace and the kernel, rather than the guest and the host),
it should use terminology appropriate for userspace. Kernel-internal
implementation details like FOLL_WRITE and terms like "guest" shouldn't
be mentioned here.
That being said, I don't think this comment is necessary in the first
place. Anyone who needs to know the exact behavior will look at the
virtio specification. I recommend just dropping the comment entirely.
> +#define VIRTGPU_BLOB_FLAG_USE_READONLY 0x0008
> /* zero is invalid blob_mem */
> __u32 blob_mem;
> __u32 blob_flags;
> @@ -205,6 +211,13 @@ struct drm_virtgpu_resource_create_blob {
> #define DRM_VIRTGPU_BLOB_FLAG_HINT_DEFER_MAPPING 0x0001
> __u32 blob_hints;
> __u32 pad2;
> +
> + /*
> + * Guest VA to pin as blob backing. Non-zero selects the userptr
> + * path and is valid only with VIRTGPU_BLOB_MEM_GUEST. Must be 0
> + * otherwise. Probe VIRTGPU_PARAM_USERPTR before using this field.
> + */
This comment is useful since it discusses UAPI specifics. However,
please avoid the term "Guest VA". Since guest userspace has no concept
of a "host" or "PA" (physical address), simply saying "address" is
sufficient and more concise.
Regards,
Akihiko Odaki
> + __u64 userptr;
> };
>
> #define VIRTGPU_CONTEXT_PARAM_CAPSET_ID 0x0001
> diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h
> index 3d4dfadc9d..33f5332e59 100644
> --- a/include/uapi/linux/virtio_gpu.h
> +++ b/include/uapi/linux/virtio_gpu.h
> @@ -72,6 +72,10 @@
> * must be aligned to that value.
> */
> #define VIRTIO_GPU_F_BLOB_ALIGNMENT 5
> +/*
> + * VIRTIO_GPU_BLOB_FLAG_USE_READONLY
> + */
> +#define VIRTIO_GPU_F_BLOB_READONLY 6
>
> enum virtio_gpu_ctrl_type {
> VIRTIO_GPU_UNDEFINED = 0,
> @@ -415,6 +419,8 @@ struct virtio_gpu_resource_create_blob {
> #define VIRTIO_GPU_BLOB_FLAG_USE_MAPPABLE 0x0001
> #define VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE 0x0002
> #define VIRTIO_GPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
> +/* Device MUST NOT write. Driver may pin read-only guest pages. */
> +#define VIRTIO_GPU_BLOB_FLAG_USE_READONLY 0x0008
> /* zero is invalid blob mem */
> __le32 blob_mem;
> __le32 blob_flags;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v8 2/4] drm/virtgpu api: add blob userptr resource
2026-09-18 12:12 ` Akihiko Odaki
@ 2026-09-18 15:48 ` Huang, Honglei
0 siblings, 0 replies; 7+ messages in thread
From: Huang, Honglei @ 2026-09-18 15:48 UTC (permalink / raw)
To: Akihiko Odaki
Cc: Gurchetan Singh, Chia-I Wu, Ray Huang, dri-devel, virtualization,
linux-kernel, Dmitry Osipenko, David Airlie, Gerd Hoffmann
On 9/18/2026 8:12 PM, Akihiko Odaki wrote:
> On 2026/09/18 18:59, Honglei Huang wrote:
>> Add a userptr address field so userspace can request a blob backed
>> by an existing process mapping. A non-zero userptr selects that
>> path; probe VIRTGPU_PARAM_USERPTR before using the field.
>>
>> GPU-readonly backing is requested with the virtio CREATE_BLOB wire
>> flag VIRTIO_GPU_BLOB_FLAG_USE_READONLY (also
>> VIRTGPU_BLOB_FLAG_USE_READONLY). The device MUST NOT write such a
>> resource. The guest pins without FOLL_WRITE only when the device
>> advertised VIRTIO_GPU_F_BLOB_READONLY (VIRTGPU_PARAM_BLOB_READONLY).
>>
>> Signed-off-by: Honglei Huang <honghuan@amd.com>
>> ---
>> include/uapi/drm/virtgpu_drm.h | 13 +++++++++++++
>> include/uapi/linux/virtio_gpu.h | 6 ++++++
>> 2 files changed, 19 insertions(+)
>>
>> diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/
>> virtgpu_drm.h
>> index 95587e12ae..80f73b3276 100644
>> --- a/include/uapi/drm/virtgpu_drm.h
>> +++ b/include/uapi/drm/virtgpu_drm.h
>> @@ -99,6 +99,8 @@ struct drm_virtgpu_execbuffer {
>> #define VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs 7 /* Bitmask of supported
>> capability set ids */
>> #define VIRTGPU_PARAM_EXPLICIT_DEBUG_NAME 8 /* Ability to set debug
>> name from userspace */
>> #define VIRTGPU_PARAM_BLOB_ALIGNMENT 9 /* Device alignment
>> requirements for blobs */
>> +#define VIRTGPU_PARAM_USERPTR 10 /* CREATE_BLOB userptr field is
>> supported */
>> +#define VIRTGPU_PARAM_BLOB_READONLY 11 /*
>> VIRTGPU_BLOB_FLAG_USE_READONLY is honored */
>> struct drm_virtgpu_getparam {
>> __u64 param;
>> @@ -186,6 +188,10 @@ struct drm_virtgpu_resource_create_blob {
>> #define VIRTGPU_BLOB_FLAG_USE_MAPPABLE 0x0001
>> #define VIRTGPU_BLOB_FLAG_USE_SHAREABLE 0x0002
>> #define VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
>> +/* Wire flag: device MUST NOT write. Guest pins without FOLL_WRITE.
>> + * Rejected unless VIRTGPU_PARAM_BLOB_READONLY is 1.
>> + */
>
> According to Documentation/process/coding-style.rst, the preferred style
> for long (multi-line) comments is:
>
> /*
> * This is the preferred style for multi-line
> * comments in the Linux kernel source code.
> * Please use it consistently.
> *
> * Description: A column of asterisks on the left side,
> * with beginning and ending almost-blank lines.
> */
>
> So please avoid putting text on the same line as the opening /*.
>
> Furthermore, because this is a UAPI header (defining the interface
> between userspace and the kernel, rather than the guest and the host),
> it should use terminology appropriate for userspace. Kernel-internal
> implementation details like FOLL_WRITE and terms like "guest" shouldn't
> be mentioned here.
>
> That being said, I don't think this comment is necessary in the first
> place. Anyone who needs to know the exact behavior will look at the
> virtio specification. I recommend just dropping the comment entirely.
>
Thanks for the review, will remove this comment here.
>> +#define VIRTGPU_BLOB_FLAG_USE_READONLY 0x0008
>> /* zero is invalid blob_mem */
>> __u32 blob_mem;
>> __u32 blob_flags;
>> @@ -205,6 +211,13 @@ struct drm_virtgpu_resource_create_blob {
>> #define DRM_VIRTGPU_BLOB_FLAG_HINT_DEFER_MAPPING 0x0001
>> __u32 blob_hints;
>> __u32 pad2;
>> +
>> + /*
>> + * Guest VA to pin as blob backing. Non-zero selects the userptr
>> + * path and is valid only with VIRTGPU_BLOB_MEM_GUEST. Must be 0
>> + * otherwise. Probe VIRTGPU_PARAM_USERPTR before using this field.
>> + */
>
> This comment is useful since it discusses UAPI specifics. However,
> please avoid the term "Guest VA". Since guest userspace has no concept
> of a "host" or "PA" (physical address), simply saying "address" is
> sufficient and more concise.
Got it, will modify the comment in next version.
Regards,
Honglei
>
> Regards,
> Akihiko Odaki
>
>> + __u64 userptr;
>> };
>> #define VIRTGPU_CONTEXT_PARAM_CAPSET_ID 0x0001
>> diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/
>> virtio_gpu.h
>> index 3d4dfadc9d..33f5332e59 100644
>> --- a/include/uapi/linux/virtio_gpu.h
>> +++ b/include/uapi/linux/virtio_gpu.h
>> @@ -72,6 +72,10 @@
>> * must be aligned to that value.
>> */
>> #define VIRTIO_GPU_F_BLOB_ALIGNMENT 5
>> +/*
>> + * VIRTIO_GPU_BLOB_FLAG_USE_READONLY
>> + */
>> +#define VIRTIO_GPU_F_BLOB_READONLY 6
>> enum virtio_gpu_ctrl_type {
>> VIRTIO_GPU_UNDEFINED = 0,
>> @@ -415,6 +419,8 @@ struct virtio_gpu_resource_create_blob {
>> #define VIRTIO_GPU_BLOB_FLAG_USE_MAPPABLE 0x0001
>> #define VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE 0x0002
>> #define VIRTIO_GPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
>> +/* Device MUST NOT write. Driver may pin read-only guest pages. */
>> +#define VIRTIO_GPU_BLOB_FLAG_USE_READONLY 0x0008
>> /* zero is invalid blob mem */
>> __le32 blob_mem;
>> __le32 blob_flags;
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-18 15:48 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-18 9:59 [PATCH v8 0/4] virtio-gpu: Add userptr support for compute workloads Honglei Huang
2026-09-18 9:59 ` [PATCH v8 1/4] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability Honglei Huang
2026-09-18 9:59 ` [PATCH v8 2/4] drm/virtgpu api: add blob userptr resource Honglei Huang
2026-09-18 12:12 ` Akihiko Odaki
2026-09-18 15:48 ` Huang, Honglei
2026-09-18 9:59 ` [PATCH v8 3/4] drm/virtio: implement userptr support for zero-copy memory access Honglei Huang
2026-09-18 9:59 ` [PATCH v8 4/4] drm/virtio: wire blob ioctl creation to userptr objects Honglei Huang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®