* [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
@ 2026-01-15 7:58 Honglei Huang
2026-01-15 7:58 ` [PATCH v4 1/5] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability Honglei Huang
` (5 more replies)
0 siblings, 6 replies; 15+ messages in thread
From: Honglei Huang @ 2026-01-15 7:58 UTC (permalink / raw)
To: David Airlie, Gerd Hoffmann, Dmitry Osipenko, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Simona Vetter, Ray.Huang
Cc: Gurchetan Singh, odaki, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang
From: Honglei Huang <honghuan@amd.com>
Hello,
This series adds virtio-gpu userptr support to enable ROCm native
context for compute workloads. The userptr feature allows the host to
directly access guest userspace memory without memcpy overhead, which is
essential for GPU compute performance.
The userptr implementation provides buffer-based zero-copy memory access.
This approach pins guest userspace pages and exposes them to the host
via scatter-gather tables, enabling efficient compute operations.
Key features:
- Zero-copy memory access between guest userspace and host GPU
- Read-only and read-write userptr support
- Runtime feature detection via VIRTGPU_PARAM_RESOURCE_USERPTR
- ROCm capset support for ROCm stack integration
- Proper page lifecycle management with FOLL_LONGTERM pinning
Patches overview:
1. Add VIRTIO_GPU_CAPSET_ROCM capability for compute workloads
2. Add virtio-gpu API definitions for userptr blob resources
3. Extend DRM UAPI with comprehensive userptr support
4. Implement core userptr functionality with page management
5. Integrate userptr into blob resource creation and advertise to userspace
Performance: In popular compute benchmarks, this implementation achieves
approximately 70% efficiency compared to bare metal OpenCL performance on
AMD V2000 hardware, achieves 92% efficiency on AMD W7900 hardware.
Testing: Verified with ROCm stack and OpenCL applications in VIRTIO virtualized
environments.
- 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.
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.
Honglei Huang (5):
drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability
virtio-gpu api: add blob userptr resource
drm/virtgpu api: add blob userptr resource
drm/virtio: implement userptr support for zero-copy memory access
drm/virtio: advertise base userptr feature to userspace
drivers/gpu/drm/virtio/Makefile | 3 +-
drivers/gpu/drm/virtio/virtgpu_drv.h | 33 ++++
drivers/gpu/drm/virtio/virtgpu_ioctl.c | 9 +-
drivers/gpu/drm/virtio/virtgpu_object.c | 6 +
drivers/gpu/drm/virtio/virtgpu_userptr.c | 231 +++++++++++++++++++++++
include/uapi/drm/virtgpu_drm.h | 9 +
include/uapi/linux/virtio_gpu.h | 7 +
7 files changed, 295 insertions(+), 3 deletions(-)
create mode 100644 drivers/gpu/drm/virtio/virtgpu_userptr.c
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 1/5] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability
2026-01-15 7:58 [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Honglei Huang
@ 2026-01-15 7:58 ` Honglei Huang
2026-01-15 7:58 ` [PATCH v4 2/5] virtio-gpu api: add blob userptr resource Honglei Huang
` (4 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Honglei Huang @ 2026-01-15 7:58 UTC (permalink / raw)
To: David Airlie, Gerd Hoffmann, Dmitry Osipenko, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Simona Vetter, Ray.Huang
Cc: Gurchetan Singh, odaki, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang
From: Honglei Huang <honghuan@amd.com>
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.
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 be109777d..fbd1838d6 100644
--- a/include/uapi/linux/virtio_gpu.h
+++ b/include/uapi/linux/virtio_gpu.h
@@ -313,6 +313,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] 15+ messages in thread
* [PATCH v4 2/5] virtio-gpu api: add blob userptr resource
2026-01-15 7:58 [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Honglei Huang
2026-01-15 7:58 ` [PATCH v4 1/5] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability Honglei Huang
@ 2026-01-15 7:58 ` Honglei Huang
2026-01-15 7:58 ` [PATCH v4 3/5] drm/virtgpu " Honglei Huang
` (3 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Honglei Huang @ 2026-01-15 7:58 UTC (permalink / raw)
To: David Airlie, Gerd Hoffmann, Dmitry Osipenko, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Simona Vetter, Ray.Huang
Cc: Gurchetan Singh, odaki, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang
From: Honglei Huang <Honglei1.Huang@amd.com>
Add a new resource for blob resource, called userptr, used for let
host access guest user space memory, to acquire buffer based userptr
feature in virtio GPU.
- New flag VIRTIO_GPU_BLOB_FLAG_USE_USERPTR used in blob create
to indicate the blob create ioctl is used for create a userptr
blob resource.
- New resource type VIRTIO_GPU_F_RESOURCE_USERPTR is for feature
check and probe.
Signed-off-by: Honglei Huang <Honglei1.Huang@amd.com>
---
include/uapi/linux/virtio_gpu.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h
index fbd1838d6..bf2d5f137 100644
--- a/include/uapi/linux/virtio_gpu.h
+++ b/include/uapi/linux/virtio_gpu.h
@@ -65,6 +65,11 @@
*/
#define VIRTIO_GPU_F_CONTEXT_INIT 4
+/*
+ * VIRTGPU_BLOB_FLAG_USE_USERPTR
+ */
+#define VIRTIO_GPU_F_RESOURCE_USERPTR 5
+
enum virtio_gpu_ctrl_type {
VIRTIO_GPU_UNDEFINED = 0,
@@ -406,6 +411,7 @@ 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
+#define VIRTIO_GPU_BLOB_FLAG_USE_USERPTR 0x0008
/* zero is invalid blob mem */
__le32 blob_mem;
__le32 blob_flags;
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 3/5] drm/virtgpu api: add blob userptr resource
2026-01-15 7:58 [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Honglei Huang
2026-01-15 7:58 ` [PATCH v4 1/5] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability Honglei Huang
2026-01-15 7:58 ` [PATCH v4 2/5] virtio-gpu api: add blob userptr resource Honglei Huang
@ 2026-01-15 7:58 ` Honglei Huang
2026-01-15 7:58 ` [PATCH v4 4/5] drm/virtio: implement userptr support for zero-copy memory access Honglei Huang
` (2 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Honglei Huang @ 2026-01-15 7:58 UTC (permalink / raw)
To: David Airlie, Gerd Hoffmann, Dmitry Osipenko, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Simona Vetter, Ray.Huang
Cc: Gurchetan Singh, odaki, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang
From: Honglei Huang <Honglei1.Huang@amd.com>
Extend the virtgpu UAPI to support userptr blob resources, enabling
the host to directly access guest userspace memory without data
copying. This is essential for compute workloads where memcpy overhead
between host and guest is unacceptable.
UAPI Changes:
- Add VIRTGPU_BLOB_FLAG_USE_USERPTR flag to enable userptr mode
- Add VIRTGPU_BLOB_FLAG_USERPTR_RDONLY flag for read-only access
- Add 'userptr' field to drm_virtgpu_resource_create_blob structure
to pass guest userspace virtual address
The userptr field contains the guest userspace virtual address that
will be pinned by the driver during resource creation and unpinned on
destruction. The driver validates the address, pins the pages, and
provides the physical addresses to the host via scatter-gather table.
Signed-off-by: Honglei Huang <Honglei1.Huang@amd.com>
---
include/uapi/drm/virtgpu_drm.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h
index 9debb320c..fdae50e39 100644
--- a/include/uapi/drm/virtgpu_drm.h
+++ b/include/uapi/drm/virtgpu_drm.h
@@ -185,6 +185,8 @@ 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
+#define VIRTGPU_BLOB_FLAG_USE_USERPTR 0x0008
+#define VIRTGPU_BLOB_FLAG_USERPTR_RDONLY 0x0010
/* zero is invalid blob_mem */
__u32 blob_mem;
__u32 blob_flags;
@@ -200,6 +202,13 @@ struct drm_virtgpu_resource_create_blob {
__u32 cmd_size;
__u64 cmd;
__u64 blob_id;
+
+ /*
+ * userptr: guest userspace memory address for VIRTGPU_BLOB_FLAG_USE_USERPTR.
+ * Must be 0 if VIRTGPU_BLOB_FLAG_USE_USERPTR is not set.
+ * The driver will pin the user pages and allow the host to access them.
+ */
+ __u64 userptr;
};
#define VIRTGPU_CONTEXT_PARAM_CAPSET_ID 0x0001
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 4/5] drm/virtio: implement userptr support for zero-copy memory access
2026-01-15 7:58 [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Honglei Huang
` (2 preceding siblings ...)
2026-01-15 7:58 ` [PATCH v4 3/5] drm/virtgpu " Honglei Huang
@ 2026-01-15 7:58 ` Honglei Huang
2026-01-15 7:58 ` [PATCH v4 5/5] drm/virtio: advertise base userptr feature to userspace Honglei Huang
2026-01-15 9:20 ` [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Akihiko Odaki
5 siblings, 0 replies; 15+ messages in thread
From: Honglei Huang @ 2026-01-15 7:58 UTC (permalink / raw)
To: David Airlie, Gerd Hoffmann, Dmitry Osipenko, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Simona Vetter, Ray.Huang
Cc: Gurchetan Singh, odaki, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang
From: Honglei Huang <Honglei1.Huang@amd.com>
Add userptr support to enable host direct access to guest userspace
memory, eliminating copy overhead for compute workloads.
Implementation:
- New virtio_gpu_object_userptr type for userptr resources
- Pin pages with pin_user_pages_fast() and FOLL_LONGTERM
- Build scatter-gather table for host access via blob resource
- Support read-only mode (VIRTGPU_BLOB_FLAG_USERPTR_RDONLY)
The pages are pinned at resource creation and unpinned at destruction.
Follow-up patches will add ioctl integration and feature detection.
Signed-off-by: Honglei Huang <Honglei1.Huang@amd.com>
---
drivers/gpu/drm/virtio/Makefile | 3 +-
drivers/gpu/drm/virtio/virtgpu_drv.h | 33 ++++
drivers/gpu/drm/virtio/virtgpu_object.c | 6 +
drivers/gpu/drm/virtio/virtgpu_userptr.c | 231 +++++++++++++++++++++++
4 files changed, 272 insertions(+), 1 deletion(-)
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 d2e1788a8..fe7332a62 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 f17660a71..808a6e65b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -84,6 +84,7 @@ struct virtio_gpu_object_params {
uint32_t blob_mem;
uint32_t blob_flags;
uint64_t blob_id;
+ uint64_t userptr;
};
struct virtio_gpu_object {
@@ -113,12 +114,38 @@ 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);
+ void (*release)(struct virtio_gpu_object_userptr *userptr);
+};
+struct virtio_gpu_object_userptr {
+ struct virtio_gpu_object base;
+ const struct virtio_gpu_object_userptr_ops *ops;
+ 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;
+};
+
#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;
@@ -512,4 +539,10 @@ void virtio_gpu_vram_unmap_dma_buf(struct device *dev,
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);
#endif
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
index e6363c887..da702301b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -80,6 +80,12 @@ 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);
+
+ drm_gem_object_release(&userptr->base.base.base);
+ kfree(userptr);
} else {
drm_gem_object_release(&bo->base.base);
kfree(bo);
diff --git a/drivers/gpu/drm/virtio/virtgpu_userptr.c b/drivers/gpu/drm/virtio/virtgpu_userptr.c
new file mode 100644
index 000000000..f6c211e9d
--- /dev/null
+++ b/drivers/gpu/drm/virtio/virtgpu_userptr.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/pid.h>
+#include <linux/vmalloc.h>
+
+#include "virtgpu_drv.h"
+#include "drm/drm_gem.h"
+
+static struct sg_table *
+virtio_gpu_userptr_get_sg_table(struct drm_gem_object *obj);
+
+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;
+ struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(bo);
+
+ if (bo->created) {
+ userptr->ops->release(userptr);
+
+ virtio_gpu_cmd_unref_resource(vgdev, bo);
+ virtio_gpu_notify(vgdev);
+ }
+
+ mutex_destroy(&userptr->lock);
+}
+
+static void virtio_gpu_userptr_object_close(struct drm_gem_object *obj,
+ struct drm_file *file)
+{
+ virtio_gpu_gem_object_close(obj, file);
+}
+
+static const struct drm_gem_object_funcs virtio_gpu_userptr_funcs = {
+ .open = virtio_gpu_gem_object_open,
+ .close = virtio_gpu_userptr_object_close,
+ .free = virtio_gpu_userptr_free,
+ .get_sg_table = virtio_gpu_userptr_get_sg_table,
+};
+
+bool virtio_gpu_is_userptr(struct virtio_gpu_object *bo)
+{
+ return bo->base.base.funcs == &virtio_gpu_userptr_funcs;
+}
+
+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_USERPTR_RDONLY))
+ 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);
+ return ret;
+ }
+
+ pinned += ret;
+
+ } while (pinned < userptr->npages);
+
+ return 0;
+}
+
+static void
+virtio_gpu_userptr_put_pages(struct virtio_gpu_object_userptr *userptr)
+{
+ if (userptr->pages) {
+ unpin_user_pages(userptr->pages, userptr->npages);
+ kvfree(userptr->pages);
+ userptr->pages = NULL;
+ }
+
+ if (userptr->sgt) {
+ sg_free_table(userptr->sgt);
+ kfree(userptr->sgt);
+ userptr->sgt = NULL;
+ }
+}
+
+static void
+virtio_gpu_userptr_release(struct virtio_gpu_object_userptr *userptr)
+{
+ mutex_lock(&userptr->lock);
+ userptr->ops->put_pages(userptr);
+ mutex_unlock(&userptr->lock);
+}
+
+static struct sg_table *
+virtio_gpu_userptr_get_sg_table(struct drm_gem_object *obj)
+{
+ struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
+ struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(bo);
+ int ret;
+
+ mutex_lock(&userptr->lock);
+ if (!userptr->pages) {
+ ret = userptr->ops->get_pages(userptr);
+ if (ret) {
+ mutex_unlock(&userptr->lock);
+ return ERR_PTR(ret);
+ }
+ }
+
+ if (!userptr->sgt)
+ userptr->sgt = drm_prime_pages_to_sg(NULL, userptr->pages,
+ userptr->npages);
+ mutex_unlock(&userptr->lock);
+
+ return userptr->sgt;
+}
+
+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)
+{
+ uint32_t page_offset;
+ uint64_t aligned_size;
+ uint64_t aligned_addr;
+ int ret;
+ struct drm_gem_object *obj;
+
+ page_offset = params->userptr & (PAGE_SIZE - 1UL);
+ aligned_addr = params->userptr - page_offset;
+ aligned_size = roundup(page_offset + params->size, PAGE_SIZE);
+
+ userptr->start = aligned_addr;
+ userptr->npages = aligned_size >> PAGE_SHIFT;
+ userptr->flags = params->blob_flags;
+
+ mutex_init(&userptr->lock);
+ userptr->vgdev = dev->dev_private;
+ userptr->file = file;
+ userptr->ops = ops;
+
+ obj = &userptr->base.base.base;
+ obj->funcs = &virtio_gpu_userptr_funcs;
+
+ drm_gem_private_object_init(dev, obj, aligned_size);
+
+ ret = virtio_gpu_resource_id_get(userptr->vgdev,
+ &userptr->base.hw_res_handle);
+
+ return ret;
+}
+
+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,
+ .release = virtio_gpu_userptr_release,
+};
+
+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;
+ int ret, si;
+ struct sg_table *sgt;
+ struct scatterlist *sg;
+ struct virtio_gpu_mem_entry *ents;
+
+ if (!params->size)
+ return -EINVAL;
+
+ if (!access_ok((char __user *)(unsigned long)params->userptr,
+ params->size))
+ return -EFAULT;
+
+ userptr = kzalloc(sizeof(*userptr), GFP_KERNEL);
+ if (!userptr)
+ return -ENOMEM;
+
+ ret = virtio_gpu_userptr_init(vgdev->ddev, file, userptr, params,
+ &virtio_gpu_userptr_ops);
+ if (ret)
+ goto failed_free;
+
+ sgt = virtio_gpu_userptr_get_sg_table(&userptr->base.base.base);
+ if (IS_ERR(sgt)) {
+ ret = PTR_ERR(sgt);
+ goto failed_free;
+ }
+
+ ents = kvmalloc_array(sgt->nents, sizeof(struct virtio_gpu_mem_entry),
+ GFP_KERNEL);
+ if (!ents) {
+ ret = -ENOMEM;
+ goto failed_free;
+ }
+
+ for_each_sgtable_sg(sgt, sg, si) {
+ (ents)[si].addr = cpu_to_le64(sg_phys(sg));
+ (ents)[si].length = cpu_to_le32(sg->length);
+ (ents)[si].padding = 0;
+ }
+
+ virtio_gpu_cmd_resource_create_blob(vgdev, &userptr->base, params, ents,
+ sgt->nents);
+
+ *bo_ptr = &userptr->base;
+ return 0;
+
+failed_free:
+ kfree(userptr);
+ return ret;
+}
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 5/5] drm/virtio: advertise base userptr feature to userspace
2026-01-15 7:58 [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Honglei Huang
` (3 preceding siblings ...)
2026-01-15 7:58 ` [PATCH v4 4/5] drm/virtio: implement userptr support for zero-copy memory access Honglei Huang
@ 2026-01-15 7:58 ` Honglei Huang
2026-01-15 9:20 ` [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Akihiko Odaki
5 siblings, 0 replies; 15+ messages in thread
From: Honglei Huang @ 2026-01-15 7:58 UTC (permalink / raw)
To: David Airlie, Gerd Hoffmann, Dmitry Osipenko, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Simona Vetter, Ray.Huang
Cc: Gurchetan Singh, odaki, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang
From: Honglei Huang <Honglei1.Huang@amd.com>
Integrate userptr functionality into the blob resource creation path:
- Add userptr flags to VIRTGPU_BLOB_FLAG_USE_MASK for validation
- Route userptr requests to virtio_gpu_userptr_create()
- Pass userptr address from ioctl to params structure
With this change, userspace can create userptr blob resources by setting
VIRTGPU_BLOB_FLAG_USE_USERPTR flag and providing a valid userptr address.
Signed-off-by: Honglei Huang <Honglei1.Huang@amd.com>
---
drivers/gpu/drm/virtio/virtgpu_ioctl.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index c33c05736..e49f5c89b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -36,7 +36,9 @@
#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_USERPTR | \
+ VIRTGPU_BLOB_FLAG_USERPTR_RDONLY)
/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */
static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,
@@ -489,6 +491,7 @@ static int verify_blob(struct virtio_gpu_device *vgdev,
params->size = rc_blob->size;
params->blob = true;
params->blob_flags = rc_blob->blob_flags;
+ params->userptr = rc_blob->userptr;
return 0;
}
@@ -527,8 +530,10 @@ 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_object_create(vgdev, ¶ms, &bo, NULL);
+ else if (guest_blob && params.userptr)
+ ret = virtio_gpu_userptr_create(vgdev, file, ¶ms, &bo);
else if (!guest_blob && host3d_blob)
ret = virtio_gpu_vram_create(vgdev, ¶ms, &bo);
else
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
2026-01-15 7:58 [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Honglei Huang
` (4 preceding siblings ...)
2026-01-15 7:58 ` [PATCH v4 5/5] drm/virtio: advertise base userptr feature to userspace Honglei Huang
@ 2026-01-15 9:20 ` Akihiko Odaki
2026-01-16 7:20 ` Honglei Huang
5 siblings, 1 reply; 15+ messages in thread
From: Akihiko Odaki @ 2026-01-15 9:20 UTC (permalink / raw)
To: Honglei Huang, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Ray.Huang
Cc: Gurchetan Singh, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang
On 2026/01/15 16:58, Honglei Huang wrote:
> From: Honglei Huang <honghuan@amd.com>
>
> Hello,
>
> This series adds virtio-gpu userptr support to enable ROCm native
> context for compute workloads. The userptr feature allows the host to
> directly access guest userspace memory without memcpy overhead, which is
> essential for GPU compute performance.
>
> The userptr implementation provides buffer-based zero-copy memory access.
> This approach pins guest userspace pages and exposes them to the host
> via scatter-gather tables, enabling efficient compute operations.
This description looks identical with what
VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST does so there should be some
explanation how it makes difference.
I have already pointed out this when reviewing the QEMU patches[1], but
I note that here too, since QEMU is just a middleman and this matter is
better discussed by Linux and virglrenderer developers.
[1]
https://lore.kernel.org/qemu-devel/35a8add7-da49-4833-9e69-d213f52c771a@amd.com/
>
> Key features:
> - Zero-copy memory access between guest userspace and host GPU
> - Read-only and read-write userptr support
> - Runtime feature detection via VIRTGPU_PARAM_RESOURCE_USERPTR
> - ROCm capset support for ROCm stack integration
> - Proper page lifecycle management with FOLL_LONGTERM pinning
>
> Patches overview:
> 1. Add VIRTIO_GPU_CAPSET_ROCM capability for compute workloads
> 2. Add virtio-gpu API definitions for userptr blob resources
> 3. Extend DRM UAPI with comprehensive userptr support
> 4. Implement core userptr functionality with page management
> 5. Integrate userptr into blob resource creation and advertise to userspace
>
> Performance: In popular compute benchmarks, this implementation achieves
> approximately 70% efficiency compared to bare metal OpenCL performance on
> AMD V2000 hardware, achieves 92% efficiency on AMD W7900 hardware.
>
> Testing: Verified with ROCm stack and OpenCL applications in VIRTIO virtualized
> environments.
> - 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.
>
> 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.
>
> Honglei Huang (5):
> drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability
> virtio-gpu api: add blob userptr resource
> drm/virtgpu api: add blob userptr resource
> drm/virtio: implement userptr support for zero-copy memory access
> drm/virtio: advertise base userptr feature to userspace
>
> drivers/gpu/drm/virtio/Makefile | 3 +-
> drivers/gpu/drm/virtio/virtgpu_drv.h | 33 ++++
> drivers/gpu/drm/virtio/virtgpu_ioctl.c | 9 +-
> drivers/gpu/drm/virtio/virtgpu_object.c | 6 +
> drivers/gpu/drm/virtio/virtgpu_userptr.c | 231 +++++++++++++++++++++++
> include/uapi/drm/virtgpu_drm.h | 9 +
> include/uapi/linux/virtio_gpu.h | 7 +
> 7 files changed, 295 insertions(+), 3 deletions(-)
> create mode 100644 drivers/gpu/drm/virtio/virtgpu_userptr.c
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
2026-01-15 9:20 ` [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Akihiko Odaki
@ 2026-01-16 7:20 ` Honglei Huang
2026-01-16 8:54 ` Akihiko Odaki
0 siblings, 1 reply; 15+ messages in thread
From: Honglei Huang @ 2026-01-16 7:20 UTC (permalink / raw)
To: Akihiko Odaki
Cc: Gurchetan Singh, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang, David Airlie, Ray.Huang,
Gerd Hoffmann, Dmitry Osipenko, Thomas Zimmermann, Maxime Ripard,
Maarten Lankhorst, Simona Vetter
On 2026/1/15 17:20, Akihiko Odaki wrote:
> On 2026/01/15 16:58, Honglei Huang wrote:
>> From: Honglei Huang <honghuan@amd.com>
>>
>> Hello,
>>
>> This series adds virtio-gpu userptr support to enable ROCm native
>> context for compute workloads. The userptr feature allows the host to
>> directly access guest userspace memory without memcpy overhead, which is
>> essential for GPU compute performance.
>>
>> The userptr implementation provides buffer-based zero-copy memory access.
>> This approach pins guest userspace pages and exposes them to the host
>> via scatter-gather tables, enabling efficient compute operations.
>
> This description looks identical with what
> VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST does so there should be some
> explanation how it makes difference.
>
> I have already pointed out this when reviewing the QEMU patches[1], but
> I note that here too, since QEMU is just a middleman and this matter is
> better discussed by Linux and virglrenderer developers.
>
> [1] https://lore.kernel.org/qemu-devel/35a8add7-da49-4833-9e69-
> d213f52c771a@amd.com/
>
Thanks for raising this important point about the distinction between
VIRTGPU_BLOB_FLAG_USE_USERPTR and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST.
I might not have explained it clearly previously.
The key difference is memory ownership and lifecycle:
BLOB_MEM_HOST3D_GUEST:
- Kernel allocates memory (drm_gem_shmem_create)
- Userspace accesses via mmap(GEM_BO)
- Use case: Graphics resources (Vulkan/OpenGL)
BLOB_FLAG_USE_USERPTR:
- Userspace pre-allocates memory (malloc/mmap)
- Kernel only get existing pages
- Use case: Compute workloads (ROCm/CUDA) with large datasets, like
GPU needs load a big model file 10G+, UMD mmap the fd file, then give
the mmap ptr into userspace then driver do not need a another copy.
But if the shmem is used, the userspace needs copy the file data into a
shmem mmap ptr there is a copy overhead.
Userptr:
file -> open/mmap -> userspace ptr -> driver
shmem:
user alloc shmem ──→ mmap shmem ──→ shmem userspace ptr -> driver
↑
│ copy
│
file ──→ open/mmap ──→ file userptr ──────────┘
For compute workloads, this matters significantly:
Without userptr: malloc(8GB) → alloc GEM BO → memcpy 8GB → compute →
memcpy 8GB back
With userptr: malloc(8GB) → create userptr BO → compute (zero-copy)
The explicit flag serves three purposes:
1. Although both send scatter-gather entries to host. The flag makes the
intent unambiguous.
2. Ensures consistency between flag and userptr address field.
3. Future HMM support: There is a plan to upgrade userptr implementation
to use Heterogeneous Memory Management for better GPU coherency and
dynamic page migration. The flag provides a clean path to future upgrade.
I understand the concern about API complexity. I'll defer to the
virtio-gpu maintainers for the final decision on whether this design is
acceptable or if they prefer an alternative approach.
Regards,
Honglei Huang
>>
>> Key features:
>> - Zero-copy memory access between guest userspace and host GPU
>> - Read-only and read-write userptr support
>> - Runtime feature detection via VIRTGPU_PARAM_RESOURCE_USERPTR
>> - ROCm capset support for ROCm stack integration
>> - Proper page lifecycle management with FOLL_LONGTERM pinning
>>
>> Patches overview:
>> 1. Add VIRTIO_GPU_CAPSET_ROCM capability for compute workloads
>> 2. Add virtio-gpu API definitions for userptr blob resources
>> 3. Extend DRM UAPI with comprehensive userptr support
>> 4. Implement core userptr functionality with page management
>> 5. Integrate userptr into blob resource creation and advertise to
>> userspace
>>
>> Performance: In popular compute benchmarks, this implementation achieves
>> approximately 70% efficiency compared to bare metal OpenCL performance on
>> AMD V2000 hardware, achieves 92% efficiency on AMD W7900 hardware.
>>
>> Testing: Verified with ROCm stack and OpenCL applications in VIRTIO
>> virtualized
>> environments.
>> - 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.
>>
>> 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.
>>
>> Honglei Huang (5):
>> drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability
>> virtio-gpu api: add blob userptr resource
>> drm/virtgpu api: add blob userptr resource
>> drm/virtio: implement userptr support for zero-copy memory access
>> drm/virtio: advertise base userptr feature to userspace
>>
>> drivers/gpu/drm/virtio/Makefile | 3 +-
>> drivers/gpu/drm/virtio/virtgpu_drv.h | 33 ++++
>> drivers/gpu/drm/virtio/virtgpu_ioctl.c | 9 +-
>> drivers/gpu/drm/virtio/virtgpu_object.c | 6 +
>> drivers/gpu/drm/virtio/virtgpu_userptr.c | 231 +++++++++++++++++++++++
>> include/uapi/drm/virtgpu_drm.h | 9 +
>> include/uapi/linux/virtio_gpu.h | 7 +
>> 7 files changed, 295 insertions(+), 3 deletions(-)
>> create mode 100644 drivers/gpu/drm/virtio/virtgpu_userptr.c
>>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
2026-01-16 7:20 ` Honglei Huang
@ 2026-01-16 8:54 ` Akihiko Odaki
2026-01-16 9:39 ` Honglei Huang
0 siblings, 1 reply; 15+ messages in thread
From: Akihiko Odaki @ 2026-01-16 8:54 UTC (permalink / raw)
To: Honglei Huang
Cc: Gurchetan Singh, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang, David Airlie, Ray.Huang,
Gerd Hoffmann, Dmitry Osipenko, Thomas Zimmermann, Maxime Ripard,
Maarten Lankhorst, Simona Vetter
On 2026/01/16 16:20, Honglei Huang wrote:
>
>
> On 2026/1/15 17:20, Akihiko Odaki wrote:
>> On 2026/01/15 16:58, Honglei Huang wrote:
>>> From: Honglei Huang <honghuan@amd.com>
>>>
>>> Hello,
>>>
>>> This series adds virtio-gpu userptr support to enable ROCm native
>>> context for compute workloads. The userptr feature allows the host to
>>> directly access guest userspace memory without memcpy overhead, which is
>>> essential for GPU compute performance.
>>>
>>> The userptr implementation provides buffer-based zero-copy memory
>>> access.
>>> This approach pins guest userspace pages and exposes them to the host
>>> via scatter-gather tables, enabling efficient compute operations.
>>
>> This description looks identical with what
>> VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST does so there should be some
>> explanation how it makes difference.
>>
>> I have already pointed out this when reviewing the QEMU patches[1],
>> but I note that here too, since QEMU is just a middleman and this
>> matter is better discussed by Linux and virglrenderer developers.
>>
>> [1] https://lore.kernel.org/qemu-devel/35a8add7-da49-4833-9e69-
>> d213f52c771a@amd.com/
>>
>
> Thanks for raising this important point about the distinction between
> VIRTGPU_BLOB_FLAG_USE_USERPTR and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST.
> I might not have explained it clearly previously.
>
> The key difference is memory ownership and lifecycle:
>
> BLOB_MEM_HOST3D_GUEST:
> - Kernel allocates memory (drm_gem_shmem_create)
> - Userspace accesses via mmap(GEM_BO)
> - Use case: Graphics resources (Vulkan/OpenGL)
>
> BLOB_FLAG_USE_USERPTR:
> - Userspace pre-allocates memory (malloc/mmap)
"Kernel allocates memory" and "userspace pre-allocates memory" is a bit
ambiguous phrasing. Either way, the userspace requests the kernel to map
memory with a system call, brk() or mmap().
> - Kernel only get existing pages
> - Use case: Compute workloads (ROCm/CUDA) with large datasets, like
> GPU needs load a big model file 10G+, UMD mmap the fd file, then give
> the mmap ptr into userspace then driver do not need a another copy.
> But if the shmem is used, the userspace needs copy the file data into a
> shmem mmap ptr there is a copy overhead.
>
> Userptr:
>
> file -> open/mmap -> userspace ptr -> driver
>
> shmem:
>
> user alloc shmem ──→ mmap shmem ──→ shmem userspace ptr -> driver
> ↑
> │ copy
> │
> file ──→ open/mmap ──→ file userptr ──────────┘
>
>
> For compute workloads, this matters significantly:
> Without userptr: malloc(8GB) → alloc GEM BO → memcpy 8GB → compute →
> memcpy 8GB back
> With userptr: malloc(8GB) → create userptr BO → compute (zero-copy)
Why don't you alloc GEM BO first and read the file into there?
>
> The explicit flag serves three purposes:
>
> 1. Although both send scatter-gather entries to host. The flag makes the
> intent unambiguous.
Why will the host care?
>
> 2. Ensures consistency between flag and userptr address field.
Addresses are represented with the nr_entries and following struct
virtio_gpu_mem_entry entries, whenever
VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB or
VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING is used. Having a special flag
introduces inconsistency.
>
> 3. Future HMM support: There is a plan to upgrade userptr implementation
> to use Heterogeneous Memory Management for better GPU coherency and
> dynamic page migration. The flag provides a clean path to future upgrade.
How will the upgrade path with the flag and the one without the flag
look like, and in what aspect the upgrade path with the flag is "cleaner"?
>
> I understand the concern about API complexity. I'll defer to the virtio-
> gpu maintainers for the final decision on whether this design is
> acceptable or if they prefer an alternative approach.
It is fine to have API complexity. The problem here is the lack of clear
motivation and documentation.
Another way to put this is: how will you explain the flag in the virtio
specification? It should say "the driver MAY/SHOULD/MUST do something"
and/or "the device MAY/SHOULD/MUST do something", and then Linux and
virglrenderer can implement the flag accordingly.
Regards,
Akihiko Odaki
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
2026-01-16 8:54 ` Akihiko Odaki
@ 2026-01-16 9:39 ` Honglei Huang
2026-01-16 10:01 ` Akihiko Odaki
0 siblings, 1 reply; 15+ messages in thread
From: Honglei Huang @ 2026-01-16 9:39 UTC (permalink / raw)
To: Akihiko Odaki
Cc: Gurchetan Singh, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang, David Airlie, Ray.Huang,
Gerd Hoffmann, Dmitry Osipenko, Thomas Zimmermann, Maxime Ripard,
Maarten Lankhorst, Simona Vetter
On 2026/1/16 16:54, Akihiko Odaki wrote:
> On 2026/01/16 16:20, Honglei Huang wrote:
>>
>>
>> On 2026/1/15 17:20, Akihiko Odaki wrote:
>>> On 2026/01/15 16:58, Honglei Huang wrote:
>>>> From: Honglei Huang <honghuan@amd.com>
>>>>
>>>> Hello,
>>>>
>>>> This series adds virtio-gpu userptr support to enable ROCm native
>>>> context for compute workloads. The userptr feature allows the host to
>>>> directly access guest userspace memory without memcpy overhead,
>>>> which is
>>>> essential for GPU compute performance.
>>>>
>>>> The userptr implementation provides buffer-based zero-copy memory
>>>> access.
>>>> This approach pins guest userspace pages and exposes them to the host
>>>> via scatter-gather tables, enabling efficient compute operations.
>>>
>>> This description looks identical with what
>>> VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST does so there should be some
>>> explanation how it makes difference.
>>>
>>> I have already pointed out this when reviewing the QEMU patches[1],
>>> but I note that here too, since QEMU is just a middleman and this
>>> matter is better discussed by Linux and virglrenderer developers.
>>>
>>> [1] https://lore.kernel.org/qemu-devel/35a8add7-da49-4833-9e69-
>>> d213f52c771a@amd.com/
>>>
>>
>> Thanks for raising this important point about the distinction between
>> VIRTGPU_BLOB_FLAG_USE_USERPTR and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST.
>> I might not have explained it clearly previously.
>>
>> The key difference is memory ownership and lifecycle:
>>
>> BLOB_MEM_HOST3D_GUEST:
>> - Kernel allocates memory (drm_gem_shmem_create)
>> - Userspace accesses via mmap(GEM_BO)
>> - Use case: Graphics resources (Vulkan/OpenGL)
>>
>> BLOB_FLAG_USE_USERPTR:
>> - Userspace pre-allocates memory (malloc/mmap)
>
> "Kernel allocates memory" and "userspace pre-allocates memory" is a bit
> ambiguous phrasing. Either way, the userspace requests the kernel to map
> memory with a system call, brk() or mmap().
They are different:
BLOB_MEM_HOST3D_GUEST (kernel-managed pages):
- Allocated via drm_gem_shmem_create() as GFP_KERNEL pages
- Kernel guarantees pages won't swap or migrate while GEM object exists
- Physical addresses remain stable → safe for DMA
BLOB_FLAG_USE_USERPTR (userspace pages):
- From regular malloc/mmap - subject to MM policies
- Can be swapped, migrated, or compacted by kernel
- Requires FOLL_LONGTERM pinning to make DMA-safe
The device must treat them differently. Kernel-managed pages have stable
physical
addresses. Userspace pages need explicit pinning and the device must be
prepared
for potential invalidation.
This is why all compute drivers (amdgpu, i915, nouveau) implement
userptr - to
make arbitrary userspace allocations DMA-accessible while respecting
their different
page mobility characteristics.
And the drm already has a better frame work for it: SVM, and this
verions is a super simplified verion.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_gpusvm.c#:~:text=*%20GPU%20Shared%20Virtual%20Memory%20(GPU%20SVM)%20layer%20for%20the%20Direct%20Rendering%20Manager%20(DRM)
>
>> - Kernel only get existing pages
>> - Use case: Compute workloads (ROCm/CUDA) with large datasets, like
>> GPU needs load a big model file 10G+, UMD mmap the fd file, then give
>> the mmap ptr into userspace then driver do not need a another copy.
>> But if the shmem is used, the userspace needs copy the file data into
>> a shmem mmap ptr there is a copy overhead.
>>
>> Userptr:
>>
>> file -> open/mmap -> userspace ptr -> driver
>>
>> shmem:
>>
>> user alloc shmem ──→ mmap shmem ──→ shmem userspace ptr -> driver
>> ↑
>> │ copy
>> │
>> file ──→ open/mmap ──→ file userptr ──────────┘
>>
>>
>> For compute workloads, this matters significantly:
>> Without userptr: malloc(8GB) → alloc GEM BO → memcpy 8GB → compute
>> → memcpy 8GB back
>> With userptr: malloc(8GB) → create userptr BO → compute (zero-copy)
>
> Why don't you alloc GEM BO first and read the file into there?
Because that defeats the purpose of zero-copy.
With GEM-BO-first (what you suggest):
void *gembo = virtgpu_gem_create(10GB); // Allocate GEM buffer
void *model = mmap(..., model_file_fd, 0); // Map model file
memcpy(gembo, model, 10GB); // Copy 10GB - NOT zero-copy
munmap(model, 10GB);
gpu_compute(gembo);
Result: 10GB copy overhead + double memory usage during copy.
With userptr (zero-copy):
void *model = mmap(..., model_file_fd, 0); // Map model file
hsa_memory_register(model, 10GB); // Pin pages, create userptr BO
gpu_compute(model); // GPU reads directly from
file pages
>
>>
>> The explicit flag serves three purposes:
>>
>> 1. Although both send scatter-gather entries to host. The flag makes
>> the intent unambiguous.
>
> Why will the host care?
The flag tells host this is a userptr, host side need handle it specially.
>
>>
>> 2. Ensures consistency between flag and userptr address field.
>
> Addresses are represented with the nr_entries and following struct
> virtio_gpu_mem_entry entries, whenever
> VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB or
> VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING is used. Having a special flag
> introduces inconsistency.
For this part I am talking about the virito gpu guest UMD side, in blob
create io ctrl we need this flag to
check the userptr address and is it a read-only attribute:
if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_USERPTR) {
if (!rc_blob->userptr)
return -EINVAL;
} else {
if (rc_blob->userptr)
return -EINVAL;
if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USERPTR_RDONLY)
return -EINVAL;
}
>
>>
>> 3. Future HMM support: There is a plan to upgrade userptr
>> implementation to use Heterogeneous Memory Management for better GPU
>> coherency and dynamic page migration. The flag provides a clean path
>> to future upgrade.
>
> How will the upgrade path with the flag and the one without the flag
> look like, and in what aspect the upgrade path with the flag is "cleaner"?
As I mentioned above the userptr handling is different with shmem/GEM BO.
>
>>
>> I understand the concern about API complexity. I'll defer to the
>> virtio- gpu maintainers for the final decision on whether this design
>> is acceptable or if they prefer an alternative approach.
>
> It is fine to have API complexity. The problem here is the lack of clear
> motivation and documentation.
>
> Another way to put this is: how will you explain the flag in the virtio
> specification? It should say "the driver MAY/SHOULD/MUST do something"
> and/or "the device MAY/SHOULD/MUST do something", and then Linux and
> virglrenderer can implement the flag accordingly.
you're absolutely right that the specification should
be written in proper virtio spec language. The draft should be:
VIRTIO_GPU_BLOB_FLAG_USE_USERPTR:
Linux virtio driver requirements:
- MUST set userptr to valid guest userspace VA in
drm_virtgpu_resource_create_blob
- SHOULD keep VA mapping valid until resource destruction
- MUST pin pages or use HMM at blob creation time
Virglrenderer requirements:
- must use correspoonding API for userptr resource
>
> Regards,
> Akihiko Odaki
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
2026-01-16 9:39 ` Honglei Huang
@ 2026-01-16 10:01 ` Akihiko Odaki
2026-01-16 10:32 ` Honglei Huang
0 siblings, 1 reply; 15+ messages in thread
From: Akihiko Odaki @ 2026-01-16 10:01 UTC (permalink / raw)
To: Honglei Huang
Cc: Gurchetan Singh, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang, David Airlie, Ray.Huang,
Gerd Hoffmann, Dmitry Osipenko, Thomas Zimmermann, Maxime Ripard,
Maarten Lankhorst, Simona Vetter
On 2026/01/16 18:39, Honglei Huang wrote:
>
>
> On 2026/1/16 16:54, Akihiko Odaki wrote:
>> On 2026/01/16 16:20, Honglei Huang wrote:
>>>
>>>
>>> On 2026/1/15 17:20, Akihiko Odaki wrote:
>>>> On 2026/01/15 16:58, Honglei Huang wrote:
>>>>> From: Honglei Huang <honghuan@amd.com>
>>>>>
>>>>> Hello,
>>>>>
>>>>> This series adds virtio-gpu userptr support to enable ROCm native
>>>>> context for compute workloads. The userptr feature allows the host to
>>>>> directly access guest userspace memory without memcpy overhead,
>>>>> which is
>>>>> essential for GPU compute performance.
>>>>>
>>>>> The userptr implementation provides buffer-based zero-copy memory
>>>>> access.
>>>>> This approach pins guest userspace pages and exposes them to the host
>>>>> via scatter-gather tables, enabling efficient compute operations.
>>>>
>>>> This description looks identical with what
>>>> VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST does so there should be some
>>>> explanation how it makes difference.
>>>>
>>>> I have already pointed out this when reviewing the QEMU patches[1],
>>>> but I note that here too, since QEMU is just a middleman and this
>>>> matter is better discussed by Linux and virglrenderer developers.
>>>>
>>>> [1] https://lore.kernel.org/qemu-devel/35a8add7-da49-4833-9e69-
>>>> d213f52c771a@amd.com/
>>>>
>>>
>>> Thanks for raising this important point about the distinction between
>>> VIRTGPU_BLOB_FLAG_USE_USERPTR and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST.
>>> I might not have explained it clearly previously.
>>>
>>> The key difference is memory ownership and lifecycle:
>>>
>>> BLOB_MEM_HOST3D_GUEST:
>>> - Kernel allocates memory (drm_gem_shmem_create)
>>> - Userspace accesses via mmap(GEM_BO)
>>> - Use case: Graphics resources (Vulkan/OpenGL)
>>>
>>> BLOB_FLAG_USE_USERPTR:
>>> - Userspace pre-allocates memory (malloc/mmap)
>>
>> "Kernel allocates memory" and "userspace pre-allocates memory" is a
>> bit ambiguous phrasing. Either way, the userspace requests the kernel
>> to map memory with a system call, brk() or mmap().
>
> They are different:
> BLOB_MEM_HOST3D_GUEST (kernel-managed pages):
> - Allocated via drm_gem_shmem_create() as GFP_KERNEL pages
> - Kernel guarantees pages won't swap or migrate while GEM object exists
> - Physical addresses remain stable → safe for DMA
>
> BLOB_FLAG_USE_USERPTR (userspace pages):
> - From regular malloc/mmap - subject to MM policies
> - Can be swapped, migrated, or compacted by kernel
> - Requires FOLL_LONGTERM pinning to make DMA-safe
>
> The device must treat them differently. Kernel-managed pages have stable
> physical
> addresses. Userspace pages need explicit pinning and the device must be
> prepared
> for potential invalidation.
>
> This is why all compute drivers (amdgpu, i915, nouveau) implement
> userptr - to
> make arbitrary userspace allocations DMA-accessible while respecting
> their different
> page mobility characteristics.
> And the drm already has a better frame work for it: SVM, and this
> verions is a super simplified verion.
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/
> drivers/gpu/drm/
> drm_gpusvm.c#:~:text=*%20GPU%20Shared%20Virtual%20Memory%20(GPU%20SVM)%20layer%20for%20the%20Direct%20Rendering%20Manager%20(DRM)
I referred to phrasing "kernel allocates" vs "userspace allocates".
Using GFP_KERNEL, swapping, migrating, or pinning is all what the kernel
does.
>
>
>>
>>> - Kernel only get existing pages
>>> - Use case: Compute workloads (ROCm/CUDA) with large datasets, like
>>> GPU needs load a big model file 10G+, UMD mmap the fd file, then give
>>> the mmap ptr into userspace then driver do not need a another copy.
>>> But if the shmem is used, the userspace needs copy the file data into
>>> a shmem mmap ptr there is a copy overhead.
>>>
>>> Userptr:
>>>
>>> file -> open/mmap -> userspace ptr -> driver
>>>
>>> shmem:
>>>
>>> user alloc shmem ──→ mmap shmem ──→ shmem userspace ptr -> driver
>>> ↑
>>> │ copy
>>> │
>>> file ──→ open/mmap ──→ file userptr ──────────┘
>>>
>>>
>>> For compute workloads, this matters significantly:
>>> Without userptr: malloc(8GB) → alloc GEM BO → memcpy 8GB → compute
>>> → memcpy 8GB back
>>> With userptr: malloc(8GB) → create userptr BO → compute (zero-
>>> copy)
>>
>> Why don't you alloc GEM BO first and read the file into there?
>
> Because that defeats the purpose of zero-copy.
>
> With GEM-BO-first (what you suggest):
>
> void *gembo = virtgpu_gem_create(10GB); // Allocate GEM buffer
> void *model = mmap(..., model_file_fd, 0); // Map model file
> memcpy(gembo, model, 10GB); // Copy 10GB - NOT zero-copy
> munmap(model, 10GB);
> gpu_compute(gembo);
>
> Result: 10GB copy overhead + double memory usage during copy.
How about:
void *gembo = virtgpu_gem_create(10GB);
read(model_file_fd, gembo, 10GB);
Result: zero-copy + simpler code.
>
> With userptr (zero-copy):
>
> void *model = mmap(..., model_file_fd, 0); // Map model file
> hsa_memory_register(model, 10GB); // Pin pages, create userptr BO
> gpu_compute(model); // GPU reads directly from
> file pages
>
>
>>
>>>
>>> The explicit flag serves three purposes:
>>>
>>> 1. Although both send scatter-gather entries to host. The flag makes
>>> the intent unambiguous.
>>
>> Why will the host care?
>
> The flag tells host this is a userptr, host side need handle it specially.
Please provide the concrete requirement. What is the special handling
the host side needs to perform?
>
>
>>
>>>
>>> 2. Ensures consistency between flag and userptr address field.
>>
>> Addresses are represented with the nr_entries and following struct
>> virtio_gpu_mem_entry entries, whenever
>> VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB or
>> VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING is used. Having a special flag
>> introduces inconsistency.
>
> For this part I am talking about the virito gpu guest UMD side, in blob
> create io ctrl we need this flag to
> check the userptr address and is it a read-only attribute:
> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_USERPTR) {
> if (!rc_blob->userptr)
> return -EINVAL;
> } else {
> if (rc_blob->userptr)
> return -EINVAL;
>
> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USERPTR_RDONLY)
> return -EINVAL;
> }
I see. That shows VIRTGPU_BLOB_FLAG_USE_USERPTR is necessary for the ioctl.
>
>>
>>>
>>> 3. Future HMM support: There is a plan to upgrade userptr
>>> implementation to use Heterogeneous Memory Management for better GPU
>>> coherency and dynamic page migration. The flag provides a clean path
>>> to future upgrade.
>>
>> How will the upgrade path with the flag and the one without the flag
>> look like, and in what aspect the upgrade path with the flag is
>> "cleaner"?
>
> As I mentioned above the userptr handling is different with shmem/GEM BO.
All the above describes the guest-internal behavior. What about the
interaction between the guest and host? How will virtio as a guest-host
interface having VIRTIO_GPU_BLOB_FLAG_USE_USERPTR ease future upgrade?
>
>>
>>>
>>> I understand the concern about API complexity. I'll defer to the
>>> virtio- gpu maintainers for the final decision on whether this design
>>> is acceptable or if they prefer an alternative approach.
>>
>> It is fine to have API complexity. The problem here is the lack of
>> clear motivation and documentation.
>>
>> Another way to put this is: how will you explain the flag in the
>> virtio specification? It should say "the driver MAY/SHOULD/MUST do
>> something" and/or "the device MAY/SHOULD/MUST do something", and then
>> Linux and virglrenderer can implement the flag accordingly.
>
> you're absolutely right that the specification should
> be written in proper virtio spec language. The draft should be:
>
> VIRTIO_GPU_BLOB_FLAG_USE_USERPTR:
>
> Linux virtio driver requirements:
> - MUST set userptr to valid guest userspace VA in
> drm_virtgpu_resource_create_blob
> - SHOULD keep VA mapping valid until resource destruction
> - MUST pin pages or use HMM at blob creation time
These descriptions are not for the virtio specification. The virtio
specification describes the interaction between the driver and device.
These statements describe the interaction between the guest userspace
and the guest kernel.
>
> Virglrenderer requirements:
> - must use correspoonding API for userptr resource
What is the "corresponding API"?
Regards,
Akihiko Odaki
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
2026-01-16 10:01 ` Akihiko Odaki
@ 2026-01-16 10:32 ` Honglei Huang
2026-01-16 11:03 ` Akihiko Odaki
0 siblings, 1 reply; 15+ messages in thread
From: Honglei Huang @ 2026-01-16 10:32 UTC (permalink / raw)
To: Akihiko Odaki
Cc: Gurchetan Singh, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang, David Airlie, Ray.Huang,
Gerd Hoffmann, Dmitry Osipenko, Thomas Zimmermann, Maxime Ripard,
Maarten Lankhorst, Simona Vetter
On 2026/1/16 18:01, Akihiko Odaki wrote:
> On 2026/01/16 18:39, Honglei Huang wrote:
>>
>>
>> On 2026/1/16 16:54, Akihiko Odaki wrote:
>>> On 2026/01/16 16:20, Honglei Huang wrote:
>>>>
>>>>
>>>> On 2026/1/15 17:20, Akihiko Odaki wrote:
>>>>> On 2026/01/15 16:58, Honglei Huang wrote:
>>>>>> From: Honglei Huang <honghuan@amd.com>
>>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> This series adds virtio-gpu userptr support to enable ROCm native
>>>>>> context for compute workloads. The userptr feature allows the host to
>>>>>> directly access guest userspace memory without memcpy overhead,
>>>>>> which is
>>>>>> essential for GPU compute performance.
>>>>>>
>>>>>> The userptr implementation provides buffer-based zero-copy memory
>>>>>> access.
>>>>>> This approach pins guest userspace pages and exposes them to the host
>>>>>> via scatter-gather tables, enabling efficient compute operations.
>>>>>
>>>>> This description looks identical with what
>>>>> VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST does so there should be some
>>>>> explanation how it makes difference.
>>>>>
>>>>> I have already pointed out this when reviewing the QEMU patches[1],
>>>>> but I note that here too, since QEMU is just a middleman and this
>>>>> matter is better discussed by Linux and virglrenderer developers.
>>>>>
>>>>> [1] https://lore.kernel.org/qemu-devel/35a8add7-da49-4833-9e69-
>>>>> d213f52c771a@amd.com/
>>>>>
>>>>
>>>> Thanks for raising this important point about the distinction between
>>>> VIRTGPU_BLOB_FLAG_USE_USERPTR and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST.
>>>> I might not have explained it clearly previously.
>>>>
>>>> The key difference is memory ownership and lifecycle:
>>>>
>>>> BLOB_MEM_HOST3D_GUEST:
>>>> - Kernel allocates memory (drm_gem_shmem_create)
>>>> - Userspace accesses via mmap(GEM_BO)
>>>> - Use case: Graphics resources (Vulkan/OpenGL)
>>>>
>>>> BLOB_FLAG_USE_USERPTR:
>>>> - Userspace pre-allocates memory (malloc/mmap)
>>>
>>> "Kernel allocates memory" and "userspace pre-allocates memory" is a
>>> bit ambiguous phrasing. Either way, the userspace requests the kernel
>>> to map memory with a system call, brk() or mmap().
>>
>> They are different:
>> BLOB_MEM_HOST3D_GUEST (kernel-managed pages):
>> - Allocated via drm_gem_shmem_create() as GFP_KERNEL pages
>> - Kernel guarantees pages won't swap or migrate while GEM object
>> exists
>> - Physical addresses remain stable → safe for DMA
>>
>> BLOB_FLAG_USE_USERPTR (userspace pages):
>> - From regular malloc/mmap - subject to MM policies
>> - Can be swapped, migrated, or compacted by kernel
>> - Requires FOLL_LONGTERM pinning to make DMA-safe
>>
>> The device must treat them differently. Kernel-managed pages have
>> stable physical
>> addresses. Userspace pages need explicit pinning and the device must
>> be prepared
>> for potential invalidation.
>>
>> This is why all compute drivers (amdgpu, i915, nouveau) implement
>> userptr - to
>> make arbitrary userspace allocations DMA-accessible while respecting
>> their different
>> page mobility characteristics.
>> And the drm already has a better frame work for it: SVM, and this
>> verions is a super simplified verion.
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
>> tree/ drivers/gpu/drm/
>> drm_gpusvm.c#:~:text=*%20GPU%20Shared%20Virtual%20Memory%20(GPU%20SVM)%20layer%20for%20the%20Direct%20Rendering%20Manager%20(DRM)
>
> I referred to phrasing "kernel allocates" vs "userspace allocates".
> Using GFP_KERNEL, swapping, migrating, or pinning is all what the kernel
> does.
I am talking about the virtio gpu driver side, the virtio gpu driver
need handle those two type memory differently.
>
>>
>>
>>>
>>>> - Kernel only get existing pages
>>>> - Use case: Compute workloads (ROCm/CUDA) with large datasets, like
>>>> GPU needs load a big model file 10G+, UMD mmap the fd file, then
>>>> give the mmap ptr into userspace then driver do not need a another
>>>> copy.
>>>> But if the shmem is used, the userspace needs copy the file data
>>>> into a shmem mmap ptr there is a copy overhead.
>>>>
>>>> Userptr:
>>>>
>>>> file -> open/mmap -> userspace ptr -> driver
>>>>
>>>> shmem:
>>>>
>>>> user alloc shmem ──→ mmap shmem ──→ shmem userspace ptr -> driver
>>>> ↑
>>>> │ copy
>>>> │
>>>> file ──→ open/mmap ──→ file userptr ──────────┘
>>>>
>>>>
>>>> For compute workloads, this matters significantly:
>>>> Without userptr: malloc(8GB) → alloc GEM BO → memcpy 8GB →
>>>> compute → memcpy 8GB back
>>>> With userptr: malloc(8GB) → create userptr BO → compute (zero-
>>>> copy)
>>>
>>> Why don't you alloc GEM BO first and read the file into there?
>>
>> Because that defeats the purpose of zero-copy.
>>
>> With GEM-BO-first (what you suggest):
>>
>> void *gembo = virtgpu_gem_create(10GB); // Allocate GEM buffer
>> void *model = mmap(..., model_file_fd, 0); // Map model file
>> memcpy(gembo, model, 10GB); // Copy 10GB - NOT zero-copy
>> munmap(model, 10GB);
>> gpu_compute(gembo);
>>
>> Result: 10GB copy overhead + double memory usage during copy.
>
> How about:
>
> void *gembo = virtgpu_gem_create(10GB);
> read(model_file_fd, gembo, 10GB);
I believe there is still memory copy in read operation
model_file_fd -> gembo, they have different physical pages,
but the userptr/SVM feature will access the model_file_fd physical pages
directly.
>
> Result: zero-copy + simpler code.
>
>>
>> With userptr (zero-copy):
>>
>> void *model = mmap(..., model_file_fd, 0); // Map model file
>> hsa_memory_register(model, 10GB); // Pin pages, create
>> userptr BO
>> gpu_compute(model); // GPU reads directly from
>> file pages
>>
>>
>>>
>>>>
>>>> The explicit flag serves three purposes:
>>>>
>>>> 1. Although both send scatter-gather entries to host. The flag makes
>>>> the intent unambiguous.
>>>
>>> Why will the host care?
>>
>> The flag tells host this is a userptr, host side need handle it
>> specially.
>
> Please provide the concrete requirement. What is the special handling
> the host side needs to perform?
Every hardware has it own special API to handle userptr, for amdgpu ROCm
it is hsaKmtRegisterMemoryWithFlags.
>
>>
>>
>>>
>>>>
>>>> 2. Ensures consistency between flag and userptr address field.
>>>
>>> Addresses are represented with the nr_entries and following struct
>>> virtio_gpu_mem_entry entries, whenever
>>> VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB or
>>> VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING is used. Having a special flag
>>> introduces inconsistency.
>>
>> For this part I am talking about the virito gpu guest UMD side, in
>> blob create io ctrl we need this flag to
>> check the userptr address and is it a read-only attribute:
>> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_USERPTR) {
>> if (!rc_blob->userptr)
>> return -EINVAL;
>> } else {
>> if (rc_blob->userptr)
>> return -EINVAL;
>>
>> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USERPTR_RDONLY)
>> return -EINVAL;
>> }
>
> I see. That shows VIRTGPU_BLOB_FLAG_USE_USERPTR is necessary for the ioctl.
>
>>
>>>
>>>>
>>>> 3. Future HMM support: There is a plan to upgrade userptr
>>>> implementation to use Heterogeneous Memory Management for better GPU
>>>> coherency and dynamic page migration. The flag provides a clean path
>>>> to future upgrade.
>>>
>>> How will the upgrade path with the flag and the one without the flag
>>> look like, and in what aspect the upgrade path with the flag is
>>> "cleaner"?
>>
>> As I mentioned above the userptr handling is different with shmem/GEM BO.
>
> All the above describes the guest-internal behavior. What about the
> interaction between the guest and host? How will virtio as a guest-host
> interface having VIRTIO_GPU_BLOB_FLAG_USE_USERPTR ease future upgrade?
It depends on how we implement it, the current version is the simplest
implementation, similar to the implementation in Intel's i915.
If virtio side needs HMM to implement a SVM type userptr feature
I think VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is must needed, stack needs to
know if it is a userptr resource, and to perform advanced operations
such as updating page tables, splitting BOs, etc.
>
>>
>>>
>>>>
>>>> I understand the concern about API complexity. I'll defer to the
>>>> virtio- gpu maintainers for the final decision on whether this
>>>> design is acceptable or if they prefer an alternative approach.
>>>
>>> It is fine to have API complexity. The problem here is the lack of
>>> clear motivation and documentation.
>>>
>>> Another way to put this is: how will you explain the flag in the
>>> virtio specification? It should say "the driver MAY/SHOULD/MUST do
>>> something" and/or "the device MAY/SHOULD/MUST do something", and then
>>> Linux and virglrenderer can implement the flag accordingly.
>>
>> you're absolutely right that the specification should
>> be written in proper virtio spec language. The draft should be:
>>
>> VIRTIO_GPU_BLOB_FLAG_USE_USERPTR:
>>
>> Linux virtio driver requirements:
>> - MUST set userptr to valid guest userspace VA in
>> drm_virtgpu_resource_create_blob
>> - SHOULD keep VA mapping valid until resource destruction
>> - MUST pin pages or use HMM at blob creation time
>
> These descriptions are not for the virtio specification. The virtio
> specification describes the interaction between the driver and device.
> These statements describe the interaction between the guest userspace
> and the guest kernel.
>
>>
>> Virglrenderer requirements:
>> - must use correspoonding API for userptr resource
>
> What is the "corresponding API"?
It may can be:
**VIRTIO_GPU_BLOB_FLAG_USE_USERPTR specification:**
Driver requirements:
- MUST populate mem_entry[] with valid guest physical addresses of
pinned userspace pages
- MUST set blob_mem to VIRTIO_GPU_BLOB_FLAG_USE_USERPTR when using this flag
- SHOULD keep pages pinned until VIRTIO_GPU_CMD_RESOURCE_UNREF
Device requirements:
- MUST establish IOMMU mappings using the provided iovec array with
specific API.(hsaKmtRegisterMemoryWithFlags for ROCm)
Really thanks for your comments, and I believe we need some input of
virito gpu maintainers.
VIRTIO_GPU_BLOB_FLAG_USE_USERPTR flag is a flag for how to use, and it
doen't conflict with VIRTGPU_BLOB_MEM_HOST3D_GUEST. Just like a resource
is used for VIRTGPU_BLOB_FLAG_USE_SHAREABLE but it can be a guest
resource or a host resource.
If we don't have VIRTIO_GPU_BLOB_FLAG_USE_USERPTR flag, we may have some
resource conflict in host side, guest kernel can use 'userptr' param to
identify. But in host side the 'userptr' param is lost, we only know it
is just a guest flag resource.
>
> Regards,
> Akihiko Odaki
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
2026-01-16 10:32 ` Honglei Huang
@ 2026-01-16 11:03 ` Akihiko Odaki
2026-01-16 12:34 ` Honglei Huang
0 siblings, 1 reply; 15+ messages in thread
From: Akihiko Odaki @ 2026-01-16 11:03 UTC (permalink / raw)
To: Honglei Huang
Cc: Gurchetan Singh, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang, David Airlie, Ray.Huang,
Gerd Hoffmann, Dmitry Osipenko, Thomas Zimmermann, Maxime Ripard,
Maarten Lankhorst, Simona Vetter
On 2026/01/16 19:32, Honglei Huang wrote:
>
>
> On 2026/1/16 18:01, Akihiko Odaki wrote:
>> On 2026/01/16 18:39, Honglei Huang wrote:
>>>
>>>
>>> On 2026/1/16 16:54, Akihiko Odaki wrote:
>>>> On 2026/01/16 16:20, Honglei Huang wrote:
>>>>>
>>>>>
>>>>> On 2026/1/15 17:20, Akihiko Odaki wrote:
>>>>>> On 2026/01/15 16:58, Honglei Huang wrote:
>>>>>>> From: Honglei Huang <honghuan@amd.com>
>>>>>>>
>>>>>>> Hello,
>>>>>>>
>>>>>>> This series adds virtio-gpu userptr support to enable ROCm native
>>>>>>> context for compute workloads. The userptr feature allows the
>>>>>>> host to
>>>>>>> directly access guest userspace memory without memcpy overhead,
>>>>>>> which is
>>>>>>> essential for GPU compute performance.
>>>>>>>
>>>>>>> The userptr implementation provides buffer-based zero-copy memory
>>>>>>> access.
>>>>>>> This approach pins guest userspace pages and exposes them to the
>>>>>>> host
>>>>>>> via scatter-gather tables, enabling efficient compute operations.
>>>>>>
>>>>>> This description looks identical with what
>>>>>> VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST does so there should be some
>>>>>> explanation how it makes difference.
>>>>>>
>>>>>> I have already pointed out this when reviewing the QEMU
>>>>>> patches[1], but I note that here too, since QEMU is just a
>>>>>> middleman and this matter is better discussed by Linux and
>>>>>> virglrenderer developers.
>>>>>>
>>>>>> [1] https://lore.kernel.org/qemu-devel/35a8add7-da49-4833-9e69-
>>>>>> d213f52c771a@amd.com/
>>>>>>
>>>>>
>>>>> Thanks for raising this important point about the distinction between
>>>>> VIRTGPU_BLOB_FLAG_USE_USERPTR and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST.
>>>>> I might not have explained it clearly previously.
>>>>>
>>>>> The key difference is memory ownership and lifecycle:
>>>>>
>>>>> BLOB_MEM_HOST3D_GUEST:
>>>>> - Kernel allocates memory (drm_gem_shmem_create)
>>>>> - Userspace accesses via mmap(GEM_BO)
>>>>> - Use case: Graphics resources (Vulkan/OpenGL)
>>>>>
>>>>> BLOB_FLAG_USE_USERPTR:
>>>>> - Userspace pre-allocates memory (malloc/mmap)
>>>>
>>>> "Kernel allocates memory" and "userspace pre-allocates memory" is a
>>>> bit ambiguous phrasing. Either way, the userspace requests the
>>>> kernel to map memory with a system call, brk() or mmap().
>>>
>>> They are different:
>>> BLOB_MEM_HOST3D_GUEST (kernel-managed pages):
>>> - Allocated via drm_gem_shmem_create() as GFP_KERNEL pages
>>> - Kernel guarantees pages won't swap or migrate while GEM object
>>> exists
>>> - Physical addresses remain stable → safe for DMA
>>>
>>> BLOB_FLAG_USE_USERPTR (userspace pages):
>>> - From regular malloc/mmap - subject to MM policies
>>> - Can be swapped, migrated, or compacted by kernel
>>> - Requires FOLL_LONGTERM pinning to make DMA-safe
>>>
>>> The device must treat them differently. Kernel-managed pages have
>>> stable physical
>>> addresses. Userspace pages need explicit pinning and the device must
>>> be prepared
>>> for potential invalidation.
>>>
>>> This is why all compute drivers (amdgpu, i915, nouveau) implement
>>> userptr - to
>>> make arbitrary userspace allocations DMA-accessible while respecting
>>> their different
>>> page mobility characteristics.
>>> And the drm already has a better frame work for it: SVM, and this
>>> verions is a super simplified verion.
>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
>>> tree/ drivers/gpu/drm/
>>> drm_gpusvm.c#:~:text=*%20GPU%20Shared%20Virtual%20Memory%20(GPU%20SVM)%20layer%20for%20the%20Direct%20Rendering%20Manager%20(DRM)
>>
>> I referred to phrasing "kernel allocates" vs "userspace allocates".
>> Using GFP_KERNEL, swapping, migrating, or pinning is all what the
>> kernel does.
>
> I am talking about the virtio gpu driver side, the virtio gpu driver
> need handle those two type memory differently.
>
>>
>>>
>>>
>>>>
>>>>> - Kernel only get existing pages
>>>>> - Use case: Compute workloads (ROCm/CUDA) with large datasets, like
>>>>> GPU needs load a big model file 10G+, UMD mmap the fd file, then
>>>>> give the mmap ptr into userspace then driver do not need a another
>>>>> copy.
>>>>> But if the shmem is used, the userspace needs copy the file data
>>>>> into a shmem mmap ptr there is a copy overhead.
>>>>>
>>>>> Userptr:
>>>>>
>>>>> file -> open/mmap -> userspace ptr -> driver
>>>>>
>>>>> shmem:
>>>>>
>>>>> user alloc shmem ──→ mmap shmem ──→ shmem userspace ptr -> driver
>>>>> ↑
>>>>> │ copy
>>>>> │
>>>>> file ──→ open/mmap ──→ file userptr ──────────┘
>>>>>
>>>>>
>>>>> For compute workloads, this matters significantly:
>>>>> Without userptr: malloc(8GB) → alloc GEM BO → memcpy 8GB →
>>>>> compute → memcpy 8GB back
>>>>> With userptr: malloc(8GB) → create userptr BO → compute
>>>>> (zero- copy)
>>>>
>>>> Why don't you alloc GEM BO first and read the file into there?
>>>
>>> Because that defeats the purpose of zero-copy.
>>>
>>> With GEM-BO-first (what you suggest):
>>>
>>> void *gembo = virtgpu_gem_create(10GB); // Allocate GEM buffer
>>> void *model = mmap(..., model_file_fd, 0); // Map model file
>>> memcpy(gembo, model, 10GB); // Copy 10GB - NOT zero-copy
>>> munmap(model, 10GB);
>>> gpu_compute(gembo);
>>>
>>> Result: 10GB copy overhead + double memory usage during copy.
>>
>> How about:
>>
>> void *gembo = virtgpu_gem_create(10GB);
>> read(model_file_fd, gembo, 10GB);
>
> I believe there is still memory copy in read operation
> model_file_fd -> gembo, they have different physical pages,
> but the userptr/SVM feature will access the model_file_fd physical pages
> directly.
You can use O_DIRECT if you want.
>
>
>>
>> Result: zero-copy + simpler code.
>>
>>>
>>> With userptr (zero-copy):
>>>
>>> void *model = mmap(..., model_file_fd, 0); // Map model file
>>> hsa_memory_register(model, 10GB); // Pin pages, create
>>> userptr BO
>>> gpu_compute(model); // GPU reads directly
>>> from file pages
>>>
>>>
>>>>
>>>>>
>>>>> The explicit flag serves three purposes:
>>>>>
>>>>> 1. Although both send scatter-gather entries to host. The flag
>>>>> makes the intent unambiguous.
>>>>
>>>> Why will the host care?
>>>
>>> The flag tells host this is a userptr, host side need handle it
>>> specially.
>>
>> Please provide the concrete requirement. What is the special handling
>> the host side needs to perform?
>
> Every hardware has it own special API to handle userptr, for amdgpu ROCm
> it is hsaKmtRegisterMemoryWithFlags.
On the host side, BLOB_MEM_HOST3D_GUEST will always result in a
userspace pointer. Below is how the address is translated:
1) (with the ioctl you are adding)
Guest kernel translates guest userspace pointer to guest PA.
2) (with IOMMU)
Guest kernel translates guest PA to device VA
3) The host VMM translates device VA to host userspace pointer
4) virglrenderer passes userspace pointer to the GPU API (ROCm)
BLOB_FLAG_USE_USERPTR tells 1) happened. But the succeeding process is
not affected by that.
>
>>
>>>
>>>
>>>>
>>>>>
>>>>> 2. Ensures consistency between flag and userptr address field.
>>>>
>>>> Addresses are represented with the nr_entries and following struct
>>>> virtio_gpu_mem_entry entries, whenever
>>>> VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB or
>>>> VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING is used. Having a special
>>>> flag introduces inconsistency.
>>>
>>> For this part I am talking about the virito gpu guest UMD side, in
>>> blob create io ctrl we need this flag to
>>> check the userptr address and is it a read-only attribute:
>>> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_USERPTR) {
>>> if (!rc_blob->userptr)
>>> return -EINVAL;
>>> } else {
>>> if (rc_blob->userptr)
>>> return -EINVAL;
>>>
>>> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USERPTR_RDONLY)
>>> return -EINVAL;
>>> }
>>
>> I see. That shows VIRTGPU_BLOB_FLAG_USE_USERPTR is necessary for the
>> ioctl.
>>
>>>
>>>>
>>>>>
>>>>> 3. Future HMM support: There is a plan to upgrade userptr
>>>>> implementation to use Heterogeneous Memory Management for better
>>>>> GPU coherency and dynamic page migration. The flag provides a clean
>>>>> path to future upgrade.
>>>>
>>>> How will the upgrade path with the flag and the one without the flag
>>>> look like, and in what aspect the upgrade path with the flag is
>>>> "cleaner"?
>>>
>>> As I mentioned above the userptr handling is different with shmem/GEM
>>> BO.
>>
>> All the above describes the guest-internal behavior. What about the
>> interaction between the guest and host? How will virtio as a guest-
>> host interface having VIRTIO_GPU_BLOB_FLAG_USE_USERPTR ease future
>> upgrade?
>
> It depends on how we implement it, the current version is the simplest
> implementation, similar to the implementation in Intel's i915.
> If virtio side needs HMM to implement a SVM type userptr feature
> I think VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is must needed, stack needs to
> know if it is a userptr resource, and to perform advanced operations
> such as updating page tables, splitting BOs, etc.
Why do the device need to know if it is a userptr resource to perform
operations when the device always get device VAs?
>
>>
>>>
>>>>
>>>>>
>>>>> I understand the concern about API complexity. I'll defer to the
>>>>> virtio- gpu maintainers for the final decision on whether this
>>>>> design is acceptable or if they prefer an alternative approach.
>>>>
>>>> It is fine to have API complexity. The problem here is the lack of
>>>> clear motivation and documentation.
>>>>
>>>> Another way to put this is: how will you explain the flag in the
>>>> virtio specification? It should say "the driver MAY/SHOULD/MUST do
>>>> something" and/or "the device MAY/SHOULD/MUST do something", and
>>>> then Linux and virglrenderer can implement the flag accordingly.
>>>
>>> you're absolutely right that the specification should
>>> be written in proper virtio spec language. The draft should be:
>>>
>>> VIRTIO_GPU_BLOB_FLAG_USE_USERPTR:
>>>
>>> Linux virtio driver requirements:
>>> - MUST set userptr to valid guest userspace VA in
>>> drm_virtgpu_resource_create_blob
>>> - SHOULD keep VA mapping valid until resource destruction
>>> - MUST pin pages or use HMM at blob creation time
>>
>> These descriptions are not for the virtio specification. The virtio
>> specification describes the interaction between the driver and device.
>> These statements describe the interaction between the guest userspace
>> and the guest kernel.
>>
>>>
>>> Virglrenderer requirements:
>>> - must use correspoonding API for userptr resource
>>
>> What is the "corresponding API"?
>
> It may can be:
> **VIRTIO_GPU_BLOB_FLAG_USE_USERPTR specification:**
>
> Driver requirements:
> - MUST populate mem_entry[] with valid guest physical addresses of
> pinned userspace pages
"Userspace" is a the guest-internal concepts and irrelevant with the
interaction between the driver and device.
> - MUST set blob_mem to VIRTIO_GPU_BLOB_FLAG_USE_USERPTR when using this
> flag
When should the driver use the flag?
> - SHOULD keep pages pinned until VIRTIO_GPU_CMD_RESOURCE_UNREF
It is not a new requirement. The page must stay at the same position
whether VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is used or not.
>
> Device requirements:
> - MUST establish IOMMU mappings using the provided iovec array with
> specific API.(hsaKmtRegisterMemoryWithFlags for ROCm)
This should be also true even when VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is
not set.
>
>
>
> Really thanks for your comments, and I believe we need some input of
> virito gpu maintainers.
>
> VIRTIO_GPU_BLOB_FLAG_USE_USERPTR flag is a flag for how to use, and it
> doen't conflict with VIRTGPU_BLOB_MEM_HOST3D_GUEST. Just like a resource
> is used for VIRTGPU_BLOB_FLAG_USE_SHAREABLE but it can be a guest
> resource or a host resource.
>
> If we don't have VIRTIO_GPU_BLOB_FLAG_USE_USERPTR flag, we may have some
> resource conflict in host side, guest kernel can use 'userptr' param to
> identify. But in host side the 'userptr' param is lost, we only know it
> is just a guest flag resource.
I still don't see why knowing it is a guest resource is insufficient for
the host.
Regards,
AKihiko Odaki
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
2026-01-16 11:03 ` Akihiko Odaki
@ 2026-01-16 12:34 ` Honglei Huang
2026-01-16 13:22 ` Akihiko Odaki
0 siblings, 1 reply; 15+ messages in thread
From: Honglei Huang @ 2026-01-16 12:34 UTC (permalink / raw)
To: Akihiko Odaki
Cc: Gurchetan Singh, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang, David Airlie, Ray.Huang,
Gerd Hoffmann, Dmitry Osipenko, Thomas Zimmermann, Maxime Ripard,
Maarten Lankhorst, Simona Vetter
On 2026/1/16 19:03, Akihiko Odaki wrote:
> On 2026/01/16 19:32, Honglei Huang wrote:
>>
>>
>> On 2026/1/16 18:01, Akihiko Odaki wrote:
>>> On 2026/01/16 18:39, Honglei Huang wrote:
>>>>
>>>>
>>>> On 2026/1/16 16:54, Akihiko Odaki wrote:
>>>>> On 2026/01/16 16:20, Honglei Huang wrote:
>>>>>>
>>>>>>
>>>>>> On 2026/1/15 17:20, Akihiko Odaki wrote:
>>>>>>> On 2026/01/15 16:58, Honglei Huang wrote:
>>>>>>>> From: Honglei Huang <honghuan@amd.com>
>>>>>>>>
>>>>>>>> Hello,
>>>>>>>>
>>>>>>>> This series adds virtio-gpu userptr support to enable ROCm native
>>>>>>>> context for compute workloads. The userptr feature allows the
>>>>>>>> host to
>>>>>>>> directly access guest userspace memory without memcpy overhead,
>>>>>>>> which is
>>>>>>>> essential for GPU compute performance.
>>>>>>>>
>>>>>>>> The userptr implementation provides buffer-based zero-copy
>>>>>>>> memory access.
>>>>>>>> This approach pins guest userspace pages and exposes them to the
>>>>>>>> host
>>>>>>>> via scatter-gather tables, enabling efficient compute operations.
>>>>>>>
>>>>>>> This description looks identical with what
>>>>>>> VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST does so there should be some
>>>>>>> explanation how it makes difference.
>>>>>>>
>>>>>>> I have already pointed out this when reviewing the QEMU
>>>>>>> patches[1], but I note that here too, since QEMU is just a
>>>>>>> middleman and this matter is better discussed by Linux and
>>>>>>> virglrenderer developers.
>>>>>>>
>>>>>>> [1] https://lore.kernel.org/qemu-devel/35a8add7-da49-4833-9e69-
>>>>>>> d213f52c771a@amd.com/
>>>>>>>
>>>>>>
>>>>>> Thanks for raising this important point about the distinction between
>>>>>> VIRTGPU_BLOB_FLAG_USE_USERPTR and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST.
>>>>>> I might not have explained it clearly previously.
>>>>>>
>>>>>> The key difference is memory ownership and lifecycle:
>>>>>>
>>>>>> BLOB_MEM_HOST3D_GUEST:
>>>>>> - Kernel allocates memory (drm_gem_shmem_create)
>>>>>> - Userspace accesses via mmap(GEM_BO)
>>>>>> - Use case: Graphics resources (Vulkan/OpenGL)
>>>>>>
>>>>>> BLOB_FLAG_USE_USERPTR:
>>>>>> - Userspace pre-allocates memory (malloc/mmap)
>>>>>
>>>>> "Kernel allocates memory" and "userspace pre-allocates memory" is a
>>>>> bit ambiguous phrasing. Either way, the userspace requests the
>>>>> kernel to map memory with a system call, brk() or mmap().
>>>>
>>>> They are different:
>>>> BLOB_MEM_HOST3D_GUEST (kernel-managed pages):
>>>> - Allocated via drm_gem_shmem_create() as GFP_KERNEL pages
>>>> - Kernel guarantees pages won't swap or migrate while GEM object
>>>> exists
>>>> - Physical addresses remain stable → safe for DMA
>>>>
>>>> BLOB_FLAG_USE_USERPTR (userspace pages):
>>>> - From regular malloc/mmap - subject to MM policies
>>>> - Can be swapped, migrated, or compacted by kernel
>>>> - Requires FOLL_LONGTERM pinning to make DMA-safe
>>>>
>>>> The device must treat them differently. Kernel-managed pages have
>>>> stable physical
>>>> addresses. Userspace pages need explicit pinning and the device must
>>>> be prepared
>>>> for potential invalidation.
>>>>
>>>> This is why all compute drivers (amdgpu, i915, nouveau) implement
>>>> userptr - to
>>>> make arbitrary userspace allocations DMA-accessible while respecting
>>>> their different
>>>> page mobility characteristics.
>>>> And the drm already has a better frame work for it: SVM, and this
>>>> verions is a super simplified verion.
>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
>>>> tree/ drivers/gpu/drm/
>>>> drm_gpusvm.c#:~:text=*%20GPU%20Shared%20Virtual%20Memory%20(GPU%20SVM)%20layer%20for%20the%20Direct%20Rendering%20Manager%20(DRM)
>>>
>>> I referred to phrasing "kernel allocates" vs "userspace allocates".
>>> Using GFP_KERNEL, swapping, migrating, or pinning is all what the
>>> kernel does.
>>
>> I am talking about the virtio gpu driver side, the virtio gpu driver
>> need handle those two type memory differently.
>>
>>>
>>>>
>>>>
>>>>>
>>>>>> - Kernel only get existing pages
>>>>>> - Use case: Compute workloads (ROCm/CUDA) with large datasets,
>>>>>> like
>>>>>> GPU needs load a big model file 10G+, UMD mmap the fd file, then
>>>>>> give the mmap ptr into userspace then driver do not need a another
>>>>>> copy.
>>>>>> But if the shmem is used, the userspace needs copy the file data
>>>>>> into a shmem mmap ptr there is a copy overhead.
>>>>>>
>>>>>> Userptr:
>>>>>>
>>>>>> file -> open/mmap -> userspace ptr -> driver
>>>>>>
>>>>>> shmem:
>>>>>>
>>>>>> user alloc shmem ──→ mmap shmem ──→ shmem userspace ptr -> driver
>>>>>> ↑
>>>>>> │ copy
>>>>>> │
>>>>>> file ──→ open/mmap ──→ file userptr ──────────┘
>>>>>>
>>>>>>
>>>>>> For compute workloads, this matters significantly:
>>>>>> Without userptr: malloc(8GB) → alloc GEM BO → memcpy 8GB →
>>>>>> compute → memcpy 8GB back
>>>>>> With userptr: malloc(8GB) → create userptr BO → compute
>>>>>> (zero- copy)
>>>>>
>>>>> Why don't you alloc GEM BO first and read the file into there?
>>>>
>>>> Because that defeats the purpose of zero-copy.
>>>>
>>>> With GEM-BO-first (what you suggest):
>>>>
>>>> void *gembo = virtgpu_gem_create(10GB); // Allocate GEM buffer
>>>> void *model = mmap(..., model_file_fd, 0); // Map model file
>>>> memcpy(gembo, model, 10GB); // Copy 10GB - NOT zero-
>>>> copy
>>>> munmap(model, 10GB);
>>>> gpu_compute(gembo);
>>>>
>>>> Result: 10GB copy overhead + double memory usage during copy.
>>>
>>> How about:
>>>
>>> void *gembo = virtgpu_gem_create(10GB);
>>> read(model_file_fd, gembo, 10GB);
>>
>> I believe there is still memory copy in read operation
>> model_file_fd -> gembo, they have different physical pages,
>> but the userptr/SVM feature will access the model_file_fd physical
>> pages directly.
>
> You can use O_DIRECT if you want.
>
>>
>>
>>>
>>> Result: zero-copy + simpler code.
>>>
>>>>
>>>> With userptr (zero-copy):
>>>>
>>>> void *model = mmap(..., model_file_fd, 0); // Map model file
>>>> hsa_memory_register(model, 10GB); // Pin pages, create
>>>> userptr BO
>>>> gpu_compute(model); // GPU reads directly
>>>> from file pages
>>>>
>>>>
>>>>>
>>>>>>
>>>>>> The explicit flag serves three purposes:
>>>>>>
>>>>>> 1. Although both send scatter-gather entries to host. The flag
>>>>>> makes the intent unambiguous.
>>>>>
>>>>> Why will the host care?
>>>>
>>>> The flag tells host this is a userptr, host side need handle it
>>>> specially.
>>>
>>> Please provide the concrete requirement. What is the special handling
>>> the host side needs to perform?
>>
>> Every hardware has it own special API to handle userptr, for amdgpu ROCm
>> it is hsaKmtRegisterMemoryWithFlags.
>
> On the host side, BLOB_MEM_HOST3D_GUEST will always result in a
> userspace pointer. Below is how the address is translated:
>
> 1) (with the ioctl you are adding)
> Guest kernel translates guest userspace pointer to guest PA.
> 2) (with IOMMU)
> Guest kernel translates guest PA to device VA
> 3) The host VMM translates device VA to host userspace pointer
> 4) virglrenderer passes userspace pointer to the GPU API (ROCm)
>
> BLOB_FLAG_USE_USERPTR tells 1) happened. But the succeeding process is
> not affected by that.
>
>>
>>>
>>>>
>>>>
>>>>>
>>>>>>
>>>>>> 2. Ensures consistency between flag and userptr address field.
>>>>>
>>>>> Addresses are represented with the nr_entries and following struct
>>>>> virtio_gpu_mem_entry entries, whenever
>>>>> VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB or
>>>>> VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING is used. Having a special
>>>>> flag introduces inconsistency.
>>>>
>>>> For this part I am talking about the virito gpu guest UMD side, in
>>>> blob create io ctrl we need this flag to
>>>> check the userptr address and is it a read-only attribute:
>>>> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_USERPTR) {
>>>> if (!rc_blob->userptr)
>>>> return -EINVAL;
>>>> } else {
>>>> if (rc_blob->userptr)
>>>> return -EINVAL;
>>>>
>>>> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USERPTR_RDONLY)
>>>> return -EINVAL;
>>>> }
>>>
>>> I see. That shows VIRTGPU_BLOB_FLAG_USE_USERPTR is necessary for the
>>> ioctl.
>>>
>>>>
>>>>>
>>>>>>
>>>>>> 3. Future HMM support: There is a plan to upgrade userptr
>>>>>> implementation to use Heterogeneous Memory Management for better
>>>>>> GPU coherency and dynamic page migration. The flag provides a
>>>>>> clean path to future upgrade.
>>>>>
>>>>> How will the upgrade path with the flag and the one without the
>>>>> flag look like, and in what aspect the upgrade path with the flag
>>>>> is "cleaner"?
>>>>
>>>> As I mentioned above the userptr handling is different with shmem/
>>>> GEM BO.
>>>
>>> All the above describes the guest-internal behavior. What about the
>>> interaction between the guest and host? How will virtio as a guest-
>>> host interface having VIRTIO_GPU_BLOB_FLAG_USE_USERPTR ease future
>>> upgrade?
>>
>> It depends on how we implement it, the current version is the simplest
>> implementation, similar to the implementation in Intel's i915.
>> If virtio side needs HMM to implement a SVM type userptr feature
>> I think VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is must needed, stack needs
>> to know if it is a userptr resource, and to perform advanced
>> operations such as updating page tables, splitting BOs, etc.
>
> Why do the device need to know if it is a userptr resource to perform
> operations when the device always get device VAs?
>
>>
>>>
>>>>
>>>>>
>>>>>>
>>>>>> I understand the concern about API complexity. I'll defer to the
>>>>>> virtio- gpu maintainers for the final decision on whether this
>>>>>> design is acceptable or if they prefer an alternative approach.
>>>>>
>>>>> It is fine to have API complexity. The problem here is the lack of
>>>>> clear motivation and documentation.
>>>>>
>>>>> Another way to put this is: how will you explain the flag in the
>>>>> virtio specification? It should say "the driver MAY/SHOULD/MUST do
>>>>> something" and/or "the device MAY/SHOULD/MUST do something", and
>>>>> then Linux and virglrenderer can implement the flag accordingly.
>>>>
>>>> you're absolutely right that the specification should
>>>> be written in proper virtio spec language. The draft should be:
>>>>
>>>> VIRTIO_GPU_BLOB_FLAG_USE_USERPTR:
>>>>
>>>> Linux virtio driver requirements:
>>>> - MUST set userptr to valid guest userspace VA in
>>>> drm_virtgpu_resource_create_blob
>>>> - SHOULD keep VA mapping valid until resource destruction
>>>> - MUST pin pages or use HMM at blob creation time
>>>
>>> These descriptions are not for the virtio specification. The virtio
>>> specification describes the interaction between the driver and
>>> device. These statements describe the interaction between the guest
>>> userspace and the guest kernel.
>>>
>>>>
>>>> Virglrenderer requirements:
>>>> - must use correspoonding API for userptr resource
>>>
>>> What is the "corresponding API"?
>>
>> It may can be:
>> **VIRTIO_GPU_BLOB_FLAG_USE_USERPTR specification:**
>>
>> Driver requirements:
>> - MUST populate mem_entry[] with valid guest physical addresses of
>> pinned userspace pages
>
> "Userspace" is a the guest-internal concepts and irrelevant with the
> interaction between the driver and device.
>
>> - MUST set blob_mem to VIRTIO_GPU_BLOB_FLAG_USE_USERPTR when using
>> this flag
>
> When should the driver use the flag?
>
>> - SHOULD keep pages pinned until VIRTIO_GPU_CMD_RESOURCE_UNREF
>
> It is not a new requirement. The page must stay at the same position
> whether VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is used or not.
>
>>
>> Device requirements:
>> - MUST establish IOMMU mappings using the provided iovec array with
>> specific API.(hsaKmtRegisterMemoryWithFlags for ROCm)
>
> This should be also true even when VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is
> not set.
>
>>
>>
>>
>> Really thanks for your comments, and I believe we need some input of
>> virito gpu maintainers.
>>
>> VIRTIO_GPU_BLOB_FLAG_USE_USERPTR flag is a flag for how to use, and it
>> doen't conflict with VIRTGPU_BLOB_MEM_HOST3D_GUEST. Just like a
>> resource is used for VIRTGPU_BLOB_FLAG_USE_SHAREABLE but it can be a
>> guest resource or a host resource.
>>
>> If we don't have VIRTIO_GPU_BLOB_FLAG_USE_USERPTR flag, we may have some
>> resource conflict in host side, guest kernel can use 'userptr' param
>> to identify. But in host side the 'userptr' param is lost, we only
>> know it is just a guest flag resource.
>
> I still don't see why knowing it is a guest resource is insufficient for
> the host.
All right, I totally agreed with you.
And let virtio gpu maintainer/drm decide how to design the flag/params
maybe is better.
I believe the core gap between you and me is the concept of userptr/SVM.
What does userptr/SVM used for, it let GPU and CPU share the userspace
virtual address. Perhaps my description is not accurate enough.
>
> Regards,
> AKihiko Odaki
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads
2026-01-16 12:34 ` Honglei Huang
@ 2026-01-16 13:22 ` Akihiko Odaki
0 siblings, 0 replies; 15+ messages in thread
From: Akihiko Odaki @ 2026-01-16 13:22 UTC (permalink / raw)
To: Honglei Huang
Cc: Gurchetan Singh, Chia-I Wu, dri-devel, virtualization,
linux-kernel, Honglei Huang, David Airlie, Ray.Huang,
Gerd Hoffmann, Dmitry Osipenko, Thomas Zimmermann, Maxime Ripard,
Maarten Lankhorst, Simona Vetter
On 2026/01/16 21:34, Honglei Huang wrote:
>
>
> On 2026/1/16 19:03, Akihiko Odaki wrote:
>> On 2026/01/16 19:32, Honglei Huang wrote:
>>>
>>>
>>> On 2026/1/16 18:01, Akihiko Odaki wrote:
>>>> On 2026/01/16 18:39, Honglei Huang wrote:
>>>>>
>>>>>
>>>>> On 2026/1/16 16:54, Akihiko Odaki wrote:
>>>>>> On 2026/01/16 16:20, Honglei Huang wrote:
>>>>>>>
>>>>>>>
>>>>>>> On 2026/1/15 17:20, Akihiko Odaki wrote:
>>>>>>>> On 2026/01/15 16:58, Honglei Huang wrote:
>>>>>>>>> From: Honglei Huang <honghuan@amd.com>
>>>>>>>>>
>>>>>>>>> Hello,
>>>>>>>>>
>>>>>>>>> This series adds virtio-gpu userptr support to enable ROCm native
>>>>>>>>> context for compute workloads. The userptr feature allows the
>>>>>>>>> host to
>>>>>>>>> directly access guest userspace memory without memcpy overhead,
>>>>>>>>> which is
>>>>>>>>> essential for GPU compute performance.
>>>>>>>>>
>>>>>>>>> The userptr implementation provides buffer-based zero-copy
>>>>>>>>> memory access.
>>>>>>>>> This approach pins guest userspace pages and exposes them to
>>>>>>>>> the host
>>>>>>>>> via scatter-gather tables, enabling efficient compute operations.
>>>>>>>>
>>>>>>>> This description looks identical with what
>>>>>>>> VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST does so there should be some
>>>>>>>> explanation how it makes difference.
>>>>>>>>
>>>>>>>> I have already pointed out this when reviewing the QEMU
>>>>>>>> patches[1], but I note that here too, since QEMU is just a
>>>>>>>> middleman and this matter is better discussed by Linux and
>>>>>>>> virglrenderer developers.
>>>>>>>>
>>>>>>>> [1] https://lore.kernel.org/qemu-devel/35a8add7-da49-4833-9e69-
>>>>>>>> d213f52c771a@amd.com/
>>>>>>>>
>>>>>>>
>>>>>>> Thanks for raising this important point about the distinction
>>>>>>> between
>>>>>>> VIRTGPU_BLOB_FLAG_USE_USERPTR and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST.
>>>>>>> I might not have explained it clearly previously.
>>>>>>>
>>>>>>> The key difference is memory ownership and lifecycle:
>>>>>>>
>>>>>>> BLOB_MEM_HOST3D_GUEST:
>>>>>>> - Kernel allocates memory (drm_gem_shmem_create)
>>>>>>> - Userspace accesses via mmap(GEM_BO)
>>>>>>> - Use case: Graphics resources (Vulkan/OpenGL)
>>>>>>>
>>>>>>> BLOB_FLAG_USE_USERPTR:
>>>>>>> - Userspace pre-allocates memory (malloc/mmap)
>>>>>>
>>>>>> "Kernel allocates memory" and "userspace pre-allocates memory" is
>>>>>> a bit ambiguous phrasing. Either way, the userspace requests the
>>>>>> kernel to map memory with a system call, brk() or mmap().
>>>>>
>>>>> They are different:
>>>>> BLOB_MEM_HOST3D_GUEST (kernel-managed pages):
>>>>> - Allocated via drm_gem_shmem_create() as GFP_KERNEL pages
>>>>> - Kernel guarantees pages won't swap or migrate while GEM object
>>>>> exists
>>>>> - Physical addresses remain stable → safe for DMA
>>>>>
>>>>> BLOB_FLAG_USE_USERPTR (userspace pages):
>>>>> - From regular malloc/mmap - subject to MM policies
>>>>> - Can be swapped, migrated, or compacted by kernel
>>>>> - Requires FOLL_LONGTERM pinning to make DMA-safe
>>>>>
>>>>> The device must treat them differently. Kernel-managed pages have
>>>>> stable physical
>>>>> addresses. Userspace pages need explicit pinning and the device
>>>>> must be prepared
>>>>> for potential invalidation.
>>>>>
>>>>> This is why all compute drivers (amdgpu, i915, nouveau) implement
>>>>> userptr - to
>>>>> make arbitrary userspace allocations DMA-accessible while
>>>>> respecting their different
>>>>> page mobility characteristics.
>>>>> And the drm already has a better frame work for it: SVM, and this
>>>>> verions is a super simplified verion.
>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
>>>>> tree/ drivers/gpu/drm/
>>>>> drm_gpusvm.c#:~:text=*%20GPU%20Shared%20Virtual%20Memory%20(GPU%20SVM)%20layer%20for%20the%20Direct%20Rendering%20Manager%20(DRM)
>>>>
>>>> I referred to phrasing "kernel allocates" vs "userspace allocates".
>>>> Using GFP_KERNEL, swapping, migrating, or pinning is all what the
>>>> kernel does.
>>>
>>> I am talking about the virtio gpu driver side, the virtio gpu driver
>>> need handle those two type memory differently.
>>>
>>>>
>>>>>
>>>>>
>>>>>>
>>>>>>> - Kernel only get existing pages
>>>>>>> - Use case: Compute workloads (ROCm/CUDA) with large datasets,
>>>>>>> like
>>>>>>> GPU needs load a big model file 10G+, UMD mmap the fd file, then
>>>>>>> give the mmap ptr into userspace then driver do not need a
>>>>>>> another copy.
>>>>>>> But if the shmem is used, the userspace needs copy the file data
>>>>>>> into a shmem mmap ptr there is a copy overhead.
>>>>>>>
>>>>>>> Userptr:
>>>>>>>
>>>>>>> file -> open/mmap -> userspace ptr -> driver
>>>>>>>
>>>>>>> shmem:
>>>>>>>
>>>>>>> user alloc shmem ──→ mmap shmem ──→ shmem userspace ptr -> driver
>>>>>>> ↑
>>>>>>> │ copy
>>>>>>> │
>>>>>>> file ──→ open/mmap ──→ file userptr ──────────┘
>>>>>>>
>>>>>>>
>>>>>>> For compute workloads, this matters significantly:
>>>>>>> Without userptr: malloc(8GB) → alloc GEM BO → memcpy 8GB →
>>>>>>> compute → memcpy 8GB back
>>>>>>> With userptr: malloc(8GB) → create userptr BO → compute
>>>>>>> (zero- copy)
>>>>>>
>>>>>> Why don't you alloc GEM BO first and read the file into there?
>>>>>
>>>>> Because that defeats the purpose of zero-copy.
>>>>>
>>>>> With GEM-BO-first (what you suggest):
>>>>>
>>>>> void *gembo = virtgpu_gem_create(10GB); // Allocate GEM buffer
>>>>> void *model = mmap(..., model_file_fd, 0); // Map model file
>>>>> memcpy(gembo, model, 10GB); // Copy 10GB - NOT
>>>>> zero- copy
>>>>> munmap(model, 10GB);
>>>>> gpu_compute(gembo);
>>>>>
>>>>> Result: 10GB copy overhead + double memory usage during copy.
>>>>
>>>> How about:
>>>>
>>>> void *gembo = virtgpu_gem_create(10GB);
>>>> read(model_file_fd, gembo, 10GB);
>>>
>>> I believe there is still memory copy in read operation
>>> model_file_fd -> gembo, they have different physical pages,
>>> but the userptr/SVM feature will access the model_file_fd physical
>>> pages directly.
>>
>> You can use O_DIRECT if you want.
>>
>>>
>>>
>>>>
>>>> Result: zero-copy + simpler code.
>>>>
>>>>>
>>>>> With userptr (zero-copy):
>>>>>
>>>>> void *model = mmap(..., model_file_fd, 0); // Map model file
>>>>> hsa_memory_register(model, 10GB); // Pin pages, create
>>>>> userptr BO
>>>>> gpu_compute(model); // GPU reads directly
>>>>> from file pages
>>>>>
>>>>>
>>>>>>
>>>>>>>
>>>>>>> The explicit flag serves three purposes:
>>>>>>>
>>>>>>> 1. Although both send scatter-gather entries to host. The flag
>>>>>>> makes the intent unambiguous.
>>>>>>
>>>>>> Why will the host care?
>>>>>
>>>>> The flag tells host this is a userptr, host side need handle it
>>>>> specially.
>>>>
>>>> Please provide the concrete requirement. What is the special
>>>> handling the host side needs to perform?
>>>
>>> Every hardware has it own special API to handle userptr, for amdgpu ROCm
>>> it is hsaKmtRegisterMemoryWithFlags.
>>
>> On the host side, BLOB_MEM_HOST3D_GUEST will always result in a
>> userspace pointer. Below is how the address is translated:
>>
>> 1) (with the ioctl you are adding)
>> Guest kernel translates guest userspace pointer to guest PA.
>> 2) (with IOMMU)
>> Guest kernel translates guest PA to device VA
>> 3) The host VMM translates device VA to host userspace pointer
>> 4) virglrenderer passes userspace pointer to the GPU API (ROCm)
>>
>> BLOB_FLAG_USE_USERPTR tells 1) happened. But the succeeding process is
>> not affected by that.
>>
>>>
>>>>
>>>>>
>>>>>
>>>>>>
>>>>>>>
>>>>>>> 2. Ensures consistency between flag and userptr address field.
>>>>>>
>>>>>> Addresses are represented with the nr_entries and following struct
>>>>>> virtio_gpu_mem_entry entries, whenever
>>>>>> VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB or
>>>>>> VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING is used. Having a special
>>>>>> flag introduces inconsistency.
>>>>>
>>>>> For this part I am talking about the virito gpu guest UMD side, in
>>>>> blob create io ctrl we need this flag to
>>>>> check the userptr address and is it a read-only attribute:
>>>>> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_USERPTR) {
>>>>> if (!rc_blob->userptr)
>>>>> return -EINVAL;
>>>>> } else {
>>>>> if (rc_blob->userptr)
>>>>> return -EINVAL;
>>>>>
>>>>> if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USERPTR_RDONLY)
>>>>> return -EINVAL;
>>>>> }
>>>>
>>>> I see. That shows VIRTGPU_BLOB_FLAG_USE_USERPTR is necessary for the
>>>> ioctl.
>>>>
>>>>>
>>>>>>
>>>>>>>
>>>>>>> 3. Future HMM support: There is a plan to upgrade userptr
>>>>>>> implementation to use Heterogeneous Memory Management for better
>>>>>>> GPU coherency and dynamic page migration. The flag provides a
>>>>>>> clean path to future upgrade.
>>>>>>
>>>>>> How will the upgrade path with the flag and the one without the
>>>>>> flag look like, and in what aspect the upgrade path with the flag
>>>>>> is "cleaner"?
>>>>>
>>>>> As I mentioned above the userptr handling is different with shmem/
>>>>> GEM BO.
>>>>
>>>> All the above describes the guest-internal behavior. What about the
>>>> interaction between the guest and host? How will virtio as a guest-
>>>> host interface having VIRTIO_GPU_BLOB_FLAG_USE_USERPTR ease future
>>>> upgrade?
>>>
>>> It depends on how we implement it, the current version is the
>>> simplest implementation, similar to the implementation in Intel's i915.
>>> If virtio side needs HMM to implement a SVM type userptr feature
>>> I think VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is must needed, stack needs
>>> to know if it is a userptr resource, and to perform advanced
>>> operations such as updating page tables, splitting BOs, etc.
>>
>> Why do the device need to know if it is a userptr resource to perform
>> operations when the device always get device VAs?
>>
>>>
>>>>
>>>>>
>>>>>>
>>>>>>>
>>>>>>> I understand the concern about API complexity. I'll defer to the
>>>>>>> virtio- gpu maintainers for the final decision on whether this
>>>>>>> design is acceptable or if they prefer an alternative approach.
>>>>>>
>>>>>> It is fine to have API complexity. The problem here is the lack of
>>>>>> clear motivation and documentation.
>>>>>>
>>>>>> Another way to put this is: how will you explain the flag in the
>>>>>> virtio specification? It should say "the driver MAY/SHOULD/MUST do
>>>>>> something" and/or "the device MAY/SHOULD/MUST do something", and
>>>>>> then Linux and virglrenderer can implement the flag accordingly.
>>>>>
>>>>> you're absolutely right that the specification should
>>>>> be written in proper virtio spec language. The draft should be:
>>>>>
>>>>> VIRTIO_GPU_BLOB_FLAG_USE_USERPTR:
>>>>>
>>>>> Linux virtio driver requirements:
>>>>> - MUST set userptr to valid guest userspace VA in
>>>>> drm_virtgpu_resource_create_blob
>>>>> - SHOULD keep VA mapping valid until resource destruction
>>>>> - MUST pin pages or use HMM at blob creation time
>>>>
>>>> These descriptions are not for the virtio specification. The virtio
>>>> specification describes the interaction between the driver and
>>>> device. These statements describe the interaction between the guest
>>>> userspace and the guest kernel.
>>>>
>>>>>
>>>>> Virglrenderer requirements:
>>>>> - must use correspoonding API for userptr resource
>>>>
>>>> What is the "corresponding API"?
>>>
>>> It may can be:
>>> **VIRTIO_GPU_BLOB_FLAG_USE_USERPTR specification:**
>>>
>>> Driver requirements:
>>> - MUST populate mem_entry[] with valid guest physical addresses of
>>> pinned userspace pages
>>
>> "Userspace" is a the guest-internal concepts and irrelevant with the
>> interaction between the driver and device.
>>
>>> - MUST set blob_mem to VIRTIO_GPU_BLOB_FLAG_USE_USERPTR when using
>>> this flag
>>
>> When should the driver use the flag?
>>
>>> - SHOULD keep pages pinned until VIRTIO_GPU_CMD_RESOURCE_UNREF
>>
>> It is not a new requirement. The page must stay at the same position
>> whether VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is used or not.
>>
>>>
>>> Device requirements:
>>> - MUST establish IOMMU mappings using the provided iovec array with
>>> specific API.(hsaKmtRegisterMemoryWithFlags for ROCm)
>>
>> This should be also true even when VIRTIO_GPU_BLOB_FLAG_USE_USERPTR is
>> not set.
>>
>>>
>>>
>>>
>>> Really thanks for your comments, and I believe we need some input of
>>> virito gpu maintainers.
>>>
>>> VIRTIO_GPU_BLOB_FLAG_USE_USERPTR flag is a flag for how to use, and
>>> it doen't conflict with VIRTGPU_BLOB_MEM_HOST3D_GUEST. Just like a
>>> resource is used for VIRTGPU_BLOB_FLAG_USE_SHAREABLE but it can be a
>>> guest resource or a host resource.
>>>
>>> If we don't have VIRTIO_GPU_BLOB_FLAG_USE_USERPTR flag, we may have some
>>> resource conflict in host side, guest kernel can use 'userptr' param
>>> to identify. But in host side the 'userptr' param is lost, we only
>>> know it is just a guest flag resource.
>>
>> I still don't see why knowing it is a guest resource is insufficient
>> for the host.
>
> All right, I totally agreed with you.
>
> And let virtio gpu maintainer/drm decide how to design the flag/params
> maybe is better.
>
>
> I believe the core gap between you and me is the concept of userptr/SVM.
> What does userptr/SVM used for, it let GPU and CPU share the userspace
> virtual address. Perhaps my description is not accurate enough.
That is not what your QEMU patch series does; QEMU sees an address space
bound to the virtio-gpu device which is not the guest userspace virtual
address space.
Below is my points in the discussion:
- Zero copy is not a new thing, but virtio already has features for
that: VIRTIO_GPU_BLOB_MEM_GUEST and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST.
- You *always* need hsaKmtRegisterMemoryWithFlags() or similar when
implementing VIRTIO_GPU_BLOB_MEM_GUEST and/or
VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST, so having another flag does not make
any difference.
- The guest userspace virtual address is never exposed to the host in
your QEMU patch series in contrary to your description.
Regards,
Akihiko Odaki
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-01-16 13:23 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-15 7:58 [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Honglei Huang
2026-01-15 7:58 ` [PATCH v4 1/5] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability Honglei Huang
2026-01-15 7:58 ` [PATCH v4 2/5] virtio-gpu api: add blob userptr resource Honglei Huang
2026-01-15 7:58 ` [PATCH v4 3/5] drm/virtgpu " Honglei Huang
2026-01-15 7:58 ` [PATCH v4 4/5] drm/virtio: implement userptr support for zero-copy memory access Honglei Huang
2026-01-15 7:58 ` [PATCH v4 5/5] drm/virtio: advertise base userptr feature to userspace Honglei Huang
2026-01-15 9:20 ` [PATCH v4 0/5] virtio-gpu: Add userptr support for compute workloads Akihiko Odaki
2026-01-16 7:20 ` Honglei Huang
2026-01-16 8:54 ` Akihiko Odaki
2026-01-16 9:39 ` Honglei Huang
2026-01-16 10:01 ` Akihiko Odaki
2026-01-16 10:32 ` Honglei Huang
2026-01-16 11:03 ` Akihiko Odaki
2026-01-16 12:34 ` Honglei Huang
2026-01-16 13:22 ` Akihiko Odaki
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®