mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Huang, Honglei" <honghuan@amd.com>
To: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Cc: Gurchetan Singh <gurchetansingh@chromium.org>,
	Chia-I Wu <olvaffe@gmail.com>, Ray Huang <Ray.Huang@amd.com>,
	dri-devel@lists.freedesktop.org, virtualization@lists.linux.dev,
	linux-kernel@vger.kernel.org,
	Dmitry Osipenko <dmitry.osipenko@collabora.com>,
	David Airlie <airlied@redhat.com>,
	Gerd Hoffmann <kraxel@redhat.com>
Subject: Re: [PATCH v8 3/4] drm/virtio: implement userptr support for zero-copy memory access
Date: Thu, 24 Sep 2026 17:25:13 +0800	[thread overview]
Message-ID: <4813f53c-d6f4-4e2b-a92d-2218b6e49951@amd.com> (raw)
In-Reply-To: <30ce57b1-21ab-4fb3-9e6c-75d061807b17@rsg.ci.i.u-tokyo.ac.jp>



On 9/19/2026 4:59 PM, Akihiko Odaki wrote:
> On 2026/09/18 18:59, Honglei Huang wrote:
>> Add userptr blob objects so the guest kernel can pin an existing
>> userspace mapping and advertise it as CREATE_BLOB backing entries.
>>
>> - New virtio_gpu_object_userptr type for userptr resources
>> - Pin pages with pin_user_pages_fast() and FOLL_LONGTERM
>> - Omit FOLL_WRITE when VIRTGPU_BLOB_FLAG_USE_READONLY is set
>> - Charge FOLL_LONGTERM pins against RLIMIT_MEMLOCK
>> - DMA-map the scatterlist only when virtio_gpu_use_dma_api() is
>>    required; use DMA_TO_DEVICE for USE_READONLY blobs
>> - Sync userptr SG for the device on TRANSFER_TO_HOST
>> - Mark writable pages dirty when unpinning
>> - Keep pages pinned until RESOURCE_UNREF is queued; drop them from
>>    cleanup_object() on the unref response or on create failure
>> - Clear userptr->pages on pin failure to avoid double-free on cleanup
>> - Reject unaligned or overflowing userptr ranges at create time
>> - Disallow PRIME export of userptr objects
>> - Save CREATE_BLOB params and restore userptr resources after
>>    hibernation without using the shmem restore path
>>
>> Signed-off-by: Honglei Huang <honghuan@amd.com>
>> ---
>>   drivers/gpu/drm/virtio/Makefile          |   3 +-
>>   drivers/gpu/drm/virtio/virtgpu_drv.h     |  43 +++
>>   drivers/gpu/drm/virtio/virtgpu_object.c  |  22 ++
>>   drivers/gpu/drm/virtio/virtgpu_userptr.c | 365 +++++++++++++++++++++++
>>   drivers/gpu/drm/virtio/virtgpu_vq.c      |  33 +-
>>   5 files changed, 456 insertions(+), 10 deletions(-)
>>   create mode 100644 drivers/gpu/drm/virtio/virtgpu_userptr.c
>>
>> diff --git a/drivers/gpu/drm/virtio/Makefile b/drivers/gpu/drm/virtio/ 
>> Makefile
>> index d2e1788a82..fe7332a621 100644
>> --- a/drivers/gpu/drm/virtio/Makefile
>> +++ b/drivers/gpu/drm/virtio/Makefile
>> @@ -6,6 +6,7 @@
>>   virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o 
>> virtgpu_vram.o \
>>       virtgpu_display.o virtgpu_vq.o \
>>       virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o 
>> virtgpu_plane.o \
>> -    virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o 
>> virtgpu_submit.o
>> +    virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o 
>> virtgpu_submit.o \
>> +    virtgpu_userptr.o
>>   obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/ 
>> virtio/virtgpu_drv.h
>> index 9df4c71173..e0941cc187 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
>> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
>> @@ -105,6 +105,7 @@ struct virtio_gpu_object_params {
>>       uint32_t blob_flags;
>>       uint64_t blob_id;
>>       uint32_t blob_hints;
>> +    uint64_t userptr;
>>   };
>>   struct virtio_gpu_object {
>> @@ -138,12 +139,42 @@ struct virtio_gpu_object_vram {
>>       struct drm_mm_node vram_node;
>>   };
>> +struct virtio_gpu_object_userptr;
>> +
>> +struct virtio_gpu_object_userptr_ops {
>> +    int (*get_pages)(struct virtio_gpu_object_userptr *userptr);
>> +    void (*put_pages)(struct virtio_gpu_object_userptr *userptr);
>> +};
>> +
>> +struct virtio_gpu_object_userptr {
>> +    struct virtio_gpu_object base;
>> +    const struct virtio_gpu_object_userptr_ops *ops;
>> +    /* Protects pages and sgt. */
>> +    struct mutex lock;
>> +
>> +    uint64_t start;
>> +    uint32_t npages;
>> +    uint32_t bo_handle;
>> +    uint32_t flags;
>> +
>> +    struct virtio_gpu_device *vgdev;
>> +    struct drm_file *file;
>> +    struct page **pages;
>> +    struct sg_table *sgt;
>> +    bool dma_mapped;
>> +    enum dma_data_direction dma_dir;
>> +    struct mm_struct *mm;
>> +};
>> +
>>   #define to_virtio_gpu_shmem(virtio_gpu_object) \
>>       container_of((virtio_gpu_object), struct 
>> virtio_gpu_object_shmem, base)
>>   #define to_virtio_gpu_vram(virtio_gpu_object) \
>>       container_of((virtio_gpu_object), struct virtio_gpu_object_vram, 
>> base)
>> +#define to_virtio_gpu_userptr(virtio_gpu_object) \
>> +    container_of((virtio_gpu_object), struct 
>> virtio_gpu_object_userptr, base)
>> +
>>   struct virtio_gpu_object_array {
>>       struct ww_acquire_ctx ticket;
>>       struct list_head next;
>> @@ -284,6 +315,7 @@ struct virtio_gpu_device {
>>       bool has_host_visible;
>>       bool has_context_init;
>>       bool has_blob_alignment;
>> +    bool has_blob_readonly;
>>       bool hibernated;
>>       struct virtio_shm_region host_visible_region;
>>       struct drm_mm host_visible_mm;
>> @@ -562,4 +594,15 @@ void virtio_gpu_vram_map_deferred(struct 
>> virtio_gpu_object_vram *vram);
>>   int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
>>                   struct drm_file *file);
>> +/* virtgpu_userptr.c */
>> +int virtio_gpu_userptr_create(struct virtio_gpu_device *vgdev,
>> +                  struct drm_file *file,
>> +                  struct virtio_gpu_object_params *params,
>> +                  struct virtio_gpu_object **bo_ptr);
>> +bool virtio_gpu_is_userptr(struct virtio_gpu_object *bo);
>> +void virtio_gpu_userptr_dma_sync_for_device(struct virtio_gpu_object 
>> *bo);
>> +int virtio_gpu_userptr_restore(struct virtio_gpu_device *vgdev,
>> +                   struct virtio_gpu_object *bo,
>> +                   struct virtio_gpu_mem_entry **ents,
>> +                   unsigned int *nents);
>>   #endif
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/ 
>> drm/virtio/virtgpu_object.c
>> index 49899485be..ab21494b1c 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_object.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_object.c
>> @@ -91,6 +91,16 @@ void virtio_gpu_cleanup_object(struct 
>> virtio_gpu_object *bo)
>>           drm_gem_free_mmap_offset(&vram->base.base.base);
>>           drm_gem_object_release(&vram->base.base.base);
>>           kfree(vram);
>> +    } else if (virtio_gpu_is_userptr(bo)) {
>> +        struct virtio_gpu_object_userptr *userptr =
>> +            to_virtio_gpu_userptr(bo);
>> +
>> +        mutex_lock(&userptr->lock);
>> +        userptr->ops->put_pages(userptr);
>> +        mutex_unlock(&userptr->lock);
>> +        mutex_destroy(&userptr->lock);
>> +        drm_gem_object_release(&userptr->base.base.base);
>> +        kfree(userptr);
>>       } else {
>>           drm_gem_object_release(&bo->base.base);
>>           kfree(bo);
>> @@ -316,6 +326,18 @@ int virtio_gpu_object_restore_all(struct 
>> virtio_gpu_device *vgdev)
>>               continue;
>>           }
>> +        if (virtio_gpu_is_userptr(bo)) {
>> +            ret = virtio_gpu_userptr_restore(vgdev, bo, &ents,
>> +                             &nents);
>> +            if (ret)
>> +                break;
>> +
>> +            virtio_gpu_cmd_resource_create_blob(vgdev, bo,
>> +                                &bo->params,
>> +                                ents, nents);
>> +            continue;
>> +        }
>> +
>>           if (bo->params.blob || bo->attached) {
>>               ret = virtio_gpu_object_shmem_init(vgdev, bo, &ents,
>>                                  &nents);
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_userptr.c b/drivers/gpu/ 
>> drm/virtio/virtgpu_userptr.c
>> new file mode 100644
>> index 0000000000..ccfd96844e
>> --- /dev/null
>> +++ b/drivers/gpu/drm/virtio/virtgpu_userptr.c
>> @@ -0,0 +1,365 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +#include <linux/dma-mapping.h>
>> +#include <linux/limits.h>
>> +#include <linux/mm.h>
>> +#include <linux/overflow.h>
>> +#include <linux/pid.h>
>> +#include <linux/sched/mm.h>
>> +#include <linux/sched/signal.h>
>> +#include <linux/vmalloc.h>
>> +
>> +#include "virtgpu_drv.h"
>> +#include <drm/drm_gem.h>
>> +
>> +static void virtio_gpu_userptr_free(struct drm_gem_object *obj)
>> +{
>> +    struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
>> +    struct virtio_gpu_device *vgdev = obj->dev->dev_private;
>> +
>> +    /*
>> +     * Keep pages pinned until RESOURCE_UNREF completes. The response
>> +     * callback calls virtio_gpu_cleanup_object(), which drops them.
>> +     */
>> +    if (bo->created) {
>> +        virtio_gpu_remove_from_restore_list(bo);
>> +        virtio_gpu_cmd_unref_resource(vgdev, bo, false);
>> +        virtio_gpu_notify(vgdev);
>> +        return;
>> +    }
>> +
>> +    virtio_gpu_cleanup_object(bo);
>> +}
>> +
>> +static struct dma_buf *
>> +virtio_gpu_userptr_prime_export(struct drm_gem_object *obj, int flags)
>> +{
>> +    return ERR_PTR(-EINVAL);
>> +}
>> +
>> +static const struct drm_gem_object_funcs virtio_gpu_userptr_funcs = {
>> +    .open = virtio_gpu_gem_object_open,
>> +    .close = virtio_gpu_gem_object_close,
>> +    .free = virtio_gpu_userptr_free,
>> +    .export = virtio_gpu_userptr_prime_export,
>> +};
>> +
>> +bool virtio_gpu_is_userptr(struct virtio_gpu_object *bo)
>> +{
>> +    return bo->base.base.funcs == &virtio_gpu_userptr_funcs;
>> +}
>> +
>> +void virtio_gpu_userptr_dma_sync_for_device(struct virtio_gpu_object 
>> *bo)
>> +{
>> +    struct virtio_gpu_object_userptr *userptr = 
>> to_virtio_gpu_userptr(bo);
>> +    struct device *dev;
>> +
>> +    if (!userptr->dma_mapped)
>> +        return;
>> +
>> +    dev = drm_dev_dma_dev(userptr->base.base.base.dev);
>> +    dma_sync_sgtable_for_device(dev, userptr->sgt, DMA_TO_DEVICE);
>> +}
>> +
>> +static int
>> +virtio_gpu_userptr_get_pages(struct virtio_gpu_object_userptr *userptr)
>> +{
>> +    unsigned int flag = FOLL_LONGTERM;
>> +    unsigned int num_pages, pinned = 0;
>> +    int ret = 0;
>> +
>> +    if (userptr->pages)
>> +        return 0;
>> +
>> +    userptr->pages = kvmalloc_array(userptr->npages, sizeof(struct 
>> page *),
>> +                    GFP_KERNEL);
>> +    if (!userptr->pages)
>> +        return -ENOMEM;
>> +
>> +    if (!(userptr->flags & VIRTGPU_BLOB_FLAG_USE_READONLY))
>> +        flag |= FOLL_WRITE;
>> +
>> +    do {
>> +        num_pages = userptr->npages - pinned;
>> +
>> +        ret = pin_user_pages_fast(userptr->start + pinned * PAGE_SIZE,
>> +                      num_pages, flag,
>> +                      userptr->pages + pinned);
>> +
>> +        if (ret < 0) {
>> +            if (pinned)
>> +                unpin_user_pages(userptr->pages, pinned);
>> +            kvfree(userptr->pages);
>> +            userptr->pages = NULL;
>> +            return ret;
>> +        }
>> +
>> +        pinned += ret;
>> +
>> +    } while (pinned < userptr->npages);
>> +
>> +    return 0;
>> +}
>> +
>> +static void
>> +virtio_gpu_userptr_unaccount(struct virtio_gpu_object_userptr *userptr)
>> +{
>> +    if (!userptr->mm)
>> +        return;
>> +
>> +    atomic64_sub(userptr->npages, &userptr->mm->pinned_vm);
>> +    mmdrop(userptr->mm);
>> +    userptr->mm = NULL;
>> +}
>> +
>> +static void
>> +virtio_gpu_userptr_put_pages(struct virtio_gpu_object_userptr *userptr)
>> +{
>> +    struct drm_device *dev = userptr->base.base.base.dev;
>> +
>> +    if (userptr->sgt) {
>> +        if (userptr->dma_mapped)
>> +            dma_unmap_sgtable(drm_dev_dma_dev(dev), userptr->sgt,
>> +                      userptr->dma_dir, 0);
>> +        userptr->dma_mapped = false;
>> +        sg_free_table(userptr->sgt);
>> +        kfree(userptr->sgt);
>> +        userptr->sgt = NULL;
>> +    }
>> +
>> +    if (userptr->pages) {
>> +        bool dirty = !(userptr->flags & VIRTGPU_BLOB_FLAG_USE_READONLY);
>> +
>> +        unpin_user_pages_dirty_lock(userptr->pages, userptr->npages,
>> +                        dirty);
>> +        kvfree(userptr->pages);
>> +        userptr->pages = NULL;
>> +    }
>> +
>> +    virtio_gpu_userptr_unaccount(userptr);
>> +}
>> +
>> +static int
>> +virtio_gpu_userptr_get_entries(struct virtio_gpu_device *vgdev,
>> +                   struct virtio_gpu_object_userptr *userptr,
>> +                   struct virtio_gpu_mem_entry **ents,
>> +                   unsigned int *nents)
>> +{
>> +    bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
>> +    struct scatterlist *sg;
>> +    unsigned int count;
>> +    int si;
>> +
>> +    count = use_dma_api ? userptr->sgt->nents : userptr->sgt- 
>> >orig_nents;
>> +    if (!count)
>> +        return -EINVAL;
>> +
>> +    *ents = kvmalloc_array(count, sizeof(**ents), GFP_KERNEL);
>> +    if (!*ents)
>> +        return -ENOMEM;
>> +
>> +    if (use_dma_api) {
>> +        for_each_sgtable_dma_sg(userptr->sgt, sg, si) {
>> +            (*ents)[si].addr = cpu_to_le64(sg_dma_address(sg));
>> +            (*ents)[si].length = cpu_to_le32(sg_dma_len(sg));
>> +            (*ents)[si].padding = 0;
>> +        }
>> +    } else {
>> +        for_each_sgtable_sg(userptr->sgt, sg, si) {
>> +            (*ents)[si].addr = cpu_to_le64(sg_phys(sg));
>> +            (*ents)[si].length = cpu_to_le32(sg->length);
>> +            (*ents)[si].padding = 0;
>> +        }
>> +    }
>> +
>> +    *nents = count;
>> +    return 0;
>> +}
>> +
>> +int virtio_gpu_userptr_restore(struct virtio_gpu_device *vgdev,
>> +                   struct virtio_gpu_object *bo,
>> +                   struct virtio_gpu_mem_entry **ents,
>> +                   unsigned int *nents)
>> +{
>> +    struct virtio_gpu_object_userptr *userptr = 
>> to_virtio_gpu_userptr(bo);
>> +    int ret;
>> +
>> +    mutex_lock(&userptr->lock);
>> +    if (!userptr->sgt || !userptr->pages) {
>> +        mutex_unlock(&userptr->lock);
>> +        return -EINVAL;
>> +    }
>> +
>> +    if (userptr->dma_mapped) {
>> +        struct device *dev = drm_dev_dma_dev(vgdev->ddev);
>> +
>> +        dma_unmap_sgtable(dev, userptr->sgt, userptr->dma_dir, 0);
>> +        userptr->dma_mapped = false;
>> +        ret = dma_map_sgtable(dev, userptr->sgt, userptr->dma_dir, 0);
> 
> This maps with attributes 0, allowing bounce buffers instead of
> "zero-copy memory access". It is also unclear what coherence guarantee 
> the UAPI is intended to provide.


This is a good point, will modify the commit and patch tittle to remove
ero-copy memory access.
And in virtio_gpu_object_shmem_init it also uses dma_map_sgtable(..., 
0), so keep 0 here.

Regards,
Honglei

> 
>> +        if (ret) {
>> +            mutex_unlock(&userptr->lock);
>> +            return ret;
>> +        }
>> +        userptr->dma_mapped = true;
>> +    }
>> +
>> +    ret = virtio_gpu_userptr_get_entries(vgdev, userptr, ents, nents);
>> +    mutex_unlock(&userptr->lock);
>> +    return ret;
>> +}
>> +
>> +static int
>> +virtio_gpu_userptr_init(struct drm_device *dev, struct drm_file *file,
>> +            struct virtio_gpu_object_userptr *userptr,
>> +            struct virtio_gpu_object_params *params,
>> +            const struct virtio_gpu_object_userptr_ops *ops)
>> +{
>> +    struct drm_gem_object *obj;
>> +    int ret;
>> +
>> +    userptr->start = params->userptr;
>> +    userptr->npages = params->size >> PAGE_SHIFT;
>> +    userptr->flags = params->blob_flags;
>> +
>> +    mutex_init(&userptr->lock);
>> +    userptr->vgdev = dev->dev_private;
>> +    userptr->file = file;
>> +    userptr->ops = ops;
>> +
>> +    /*
>> +     * Allocate the resource id before GEM init so a failure here can
>> +     * unwind with a plain kfree and does not need a special id=0 guard
>> +     * in the shared resource_id_put helper.
>> +     */
>> +    ret = virtio_gpu_resource_id_get(userptr->vgdev,
>> +                     &userptr->base.hw_res_handle);
>> +    if (ret) {
>> +        mutex_destroy(&userptr->lock);
>> +        return ret;
>> +    }
>> +
>> +    obj = &userptr->base.base.base;
>> +    obj->funcs = &virtio_gpu_userptr_funcs;
>> +
>> +    drm_gem_private_object_init(dev, obj, params->size);
>> +    INIT_LIST_HEAD(&userptr->base.restore_node);
>> +
>> +    return 0;
>> +}
>> +
>> +static const struct virtio_gpu_object_userptr_ops 
>> virtio_gpu_userptr_ops = {
>> +    .get_pages = virtio_gpu_userptr_get_pages,
>> +    .put_pages = virtio_gpu_userptr_put_pages,
>> +};
>> +
>> +int virtio_gpu_userptr_create(struct virtio_gpu_device *vgdev,
>> +                  struct drm_file *file,
>> +                  struct virtio_gpu_object_params *params,
>> +                  struct virtio_gpu_object **bo_ptr)
>> +{
>> +    struct virtio_gpu_object_userptr *userptr;
>> +    struct virtio_gpu_mem_entry *ents = NULL;
>> +    struct sg_table *sgt;
>> +    struct mm_struct *mm;
>> +    unsigned long lock_limit;
>> +    unsigned long start;
>> +    unsigned long end;
>> +    s64 new_pinned;
>> +    unsigned int nents;
>> +    int ret;
>> +
>> +    *bo_ptr = NULL;
>> +
>> +    if (!params->size || !IS_ALIGNED(params->size, PAGE_SIZE) ||
>> +        params->userptr != (unsigned long)params->userptr)
>> +        return -EINVAL;
>> +
>> +    start = params->userptr;
>> +    if (!IS_ALIGNED(start, PAGE_SIZE) ||
>> +        check_add_overflow(start, (unsigned long)params->size, &end))
>> +        return -EINVAL;
>> +
>> +    if (!can_do_mlock())
>> +        return -EPERM;
>> +
>> +    if (params->size >> PAGE_SHIFT > INT_MAX)
>> +        return -E2BIG;
>> +
>> +    if (!access_ok((void __user *)start, params->size))
>> +        return -EFAULT;
>> +
>> +    userptr = kzalloc_obj(*userptr);
>> +    if (!userptr)
>> +        return -ENOMEM;
>> +
>> +    ret = virtio_gpu_userptr_init(vgdev->ddev, file, userptr, params,
>> +                      &virtio_gpu_userptr_ops);
>> +    if (ret) {
>> +        kfree(userptr);
>> +        return ret;
>> +    }
>> +
>> +    mm = current->mm;
>> +    mmgrab(mm);
>> +    lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
>> +    new_pinned = atomic64_add_return(userptr->npages, &mm->pinned_vm);
>> +    if (new_pinned < 0 ||
>> +        (new_pinned > lock_limit && !capable(CAP_IPC_LOCK))) {
>> +        atomic64_sub(userptr->npages, &mm->pinned_vm);
>> +        mmdrop(mm);
>> +        ret = new_pinned < 0 ? -EOVERFLOW : -ENOMEM;
>> +        goto err_cleanup;
>> +    }
>> +    userptr->mm = mm;
>> +
>> +    mutex_lock(&userptr->lock);
>> +    ret = userptr->ops->get_pages(userptr);
>> +    mutex_unlock(&userptr->lock);
>> +    if (ret)
>> +        goto err_cleanup;
>> +
>> +    sgt = drm_prime_pages_to_sg(vgdev->ddev, userptr->pages,
>> +                    userptr->npages);
>> +    if (IS_ERR(sgt)) {
>> +        ret = PTR_ERR(sgt);
>> +        goto err_cleanup;
>> +    }
>> +
>> +    userptr->sgt = sgt;
>> +
>> +    /*
>> +     * Match shmem blobs: only DMA-map when the virtio DMA API is in
>> +     * use. Mapping unconditionally can create SWIOTLB bounce buffers
>> +     * that get copied back over guest pages on unmap even though the
>> +     * host was given sg_phys() addresses.
>> +     */
>> +    if (virtio_gpu_use_dma_api(vgdev->vdev)) {
>> +        enum dma_data_direction dir =
>> +            (userptr->flags & VIRTGPU_BLOB_FLAG_USE_READONLY) ?
>> +            DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
>> +
>> +        ret = dma_map_sgtable(drm_dev_dma_dev(vgdev->ddev), sgt,
>> +                      dir, 0);
>> +        if (ret)
>> +            goto err_cleanup;
>> +
>> +        userptr->dma_dir = dir;
>> +        userptr->dma_mapped = true;
>> +    }
>> +
>> +    ret = virtio_gpu_userptr_get_entries(vgdev, userptr, &ents, &nents);
>> +    if (ret)
>> +        goto err_cleanup;
>> +
>> +    virtio_gpu_cmd_resource_create_blob(vgdev, &userptr->base, 
>> params, ents,
>> +                        nents);
>> +
>> +    userptr->base.params = *params;
>> +    virtio_gpu_add_object_to_restore_list(vgdev, &userptr->base);
>> +
>> +    *bo_ptr = &userptr->base;
>> +    return 0;
>> +
>> +err_cleanup:
>> +    virtio_gpu_cleanup_object(&userptr->base);
>> +    return ret;
>> +}
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/ 
>> virtio/virtgpu_vq.c
>> index c02c03c10d..dcbd7bb7a6 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_vq.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
>> @@ -781,9 +781,14 @@ int 
>> virtio_gpu_panic_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
>>       struct virtio_gpu_vbuffer *vbuf;
>>       bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
>> -    if (virtio_gpu_is_shmem(bo) && use_dma_api)
>> -        dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
>> -                        bo->base.sgt, DMA_TO_DEVICE);
>> +    if (use_dma_api) {
>> +        if (virtio_gpu_is_shmem(bo))
>> +            dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
>> +                            bo->base.sgt,
>> +                            DMA_TO_DEVICE);
>> +        else if (virtio_gpu_is_userptr(bo))
>> +            virtio_gpu_userptr_dma_sync_for_device(bo);
>> +    }
>>       cmd_p = virtio_gpu_panic_alloc_cmd_resp(vgdev, &vbuf, 
>> sizeof(*cmd_p));
>>       memset(cmd_p, 0, sizeof(*cmd_p));
>> @@ -812,9 +817,14 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct 
>> virtio_gpu_device *vgdev,
>>       struct virtio_gpu_vbuffer *vbuf;
>>       bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
>> -    if (virtio_gpu_is_shmem(bo) && use_dma_api)
>> -        dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
>> -                        bo->base.sgt, DMA_TO_DEVICE);
>> +    if (use_dma_api) {
>> +        if (virtio_gpu_is_shmem(bo))
>> +            dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
>> +                            bo->base.sgt,
>> +                            DMA_TO_DEVICE);
>> +        else if (virtio_gpu_is_userptr(bo))
>> +            virtio_gpu_userptr_dma_sync_for_device(bo);
>> +    }
>>       cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
>>       memset(cmd_p, 0, sizeof(*cmd_p));
>> @@ -1245,9 +1255,14 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct 
>> virtio_gpu_device *vgdev,
>>       struct virtio_gpu_vbuffer *vbuf;
>>       bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
>> -    if (virtio_gpu_is_shmem(bo) && use_dma_api)
>> -        dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
>> -                        bo->base.sgt, DMA_TO_DEVICE);
>> +    if (use_dma_api) {
>> +        if (virtio_gpu_is_shmem(bo))
>> +            dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
>> +                            bo->base.sgt,
>> +                            DMA_TO_DEVICE);
>> +        else if (virtio_gpu_is_userptr(bo))
>> +            virtio_gpu_userptr_dma_sync_for_device(bo);
> 
> This code is ineffective since the transfer ioctl rejects 
> VIRTGPU_BLOB_MEM_GUEST.
> 
> Regards,
> Akihiko Odaki


  reply	other threads:[~2026-09-24  9:25 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-18  9:59 [PATCH v8 0/4] virtio-gpu: Add userptr support for compute workloads Honglei Huang
2026-09-18  9:59 ` [PATCH v8 1/4] drm/virtio-gpu: Add VIRTIO_GPU_CAPSET_ROCM capability Honglei Huang
2026-09-18  9:59 ` [PATCH v8 2/4] drm/virtgpu api: add blob userptr resource Honglei Huang
2026-09-18 12:12   ` Akihiko Odaki
2026-09-18 15:48     ` Huang, Honglei
2026-09-18  9:59 ` [PATCH v8 3/4] drm/virtio: implement userptr support for zero-copy memory access Honglei Huang
2026-09-19  8:59   ` Akihiko Odaki
2026-09-24  9:25     ` Huang, Honglei [this message]
2026-09-18  9:59 ` [PATCH v8 4/4] drm/virtio: wire blob ioctl creation to userptr objects Honglei Huang
2026-09-19 14:28   ` Akihiko Odaki
2026-09-24  9:33     ` Huang, Honglei

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4813f53c-d6f4-4e2b-a92d-2218b6e49951@amd.com \
    --to=honghuan@amd.com \
    --cc=Ray.Huang@amd.com \
    --cc=airlied@redhat.com \
    --cc=dmitry.osipenko@collabora.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gurchetansingh@chromium.org \
    --cc=kraxel@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=odaki@rsg.ci.i.u-tokyo.ac.jp \
    --cc=olvaffe@gmail.com \
    --cc=virtualization@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®