Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/drm2/dist/drm Implement drm userptr with uv...



details:   https://anonhg.NetBSD.org/src/rev/5ccee9dedd49
branches:  trunk
changeset: 744844:5ccee9dedd49
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Fri Feb 14 04:38:23 2020 +0000

description:
Implement drm userptr with uvm_vslock & bus_dmamap_load_uio.

diffstat:

 sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_cs.c  |   16 +-
 sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_gem.c |   26 ++-
 sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_ttm.c |  110 ++++++++++++++-
 sys/external/bsd/drm2/dist/drm/radeon/radeon_cs.c      |   16 +-
 sys/external/bsd/drm2/dist/drm/radeon/radeon_gem.c     |   26 ++-
 sys/external/bsd/drm2/dist/drm/radeon/radeon_ttm.c     |  115 ++++++++++++++--
 6 files changed, 241 insertions(+), 68 deletions(-)

diffs (truncated from 647 to 300 lines):

diff -r b07dcaf85d1a -r 5ccee9dedd49 sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_cs.c
--- a/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_cs.c     Fri Feb 14 04:38:13 2020 +0000
+++ b/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_cs.c     Fri Feb 14 04:38:23 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: amdgpu_cs.c,v 1.3 2018/08/27 14:04:50 riastradh Exp $  */
+/*     $NetBSD: amdgpu_cs.c,v 1.4 2020/02/14 04:38:23 riastradh Exp $  */
 
 /*
  * Copyright 2008 Jerome Glisse.
@@ -27,7 +27,7 @@
  *    Jerome Glisse <glisse%freedesktop.org@localhost>
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amdgpu_cs.c,v 1.3 2018/08/27 14:04:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amdgpu_cs.c,v 1.4 2020/02/14 04:38:23 riastradh Exp $");
 
 #include <linux/list_sort.h>
 #include <drm/drmP.h>
@@ -406,7 +406,7 @@
        struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
        struct amdgpu_cs_buckets buckets;
        struct list_head duplicates;
-       bool need_mmap_lock __diagused = false;
+       bool need_mmap_lock = false;
        int i, r;
 
        if (p->bo_list) {
@@ -426,9 +426,8 @@
                list_add(&p->uf_entry.tv.head, &p->validated);
 
 #ifdef __NetBSD__
-       KASSERTMSG(!need_mmap_lock,
-           "someone didn't finish adding support for userptr"
-           " and it wasn't me");
+       if (need_mmap_lock)
+               vm_map_lock_read(&curproc->p_vmspace->vm_map);
 #else
        if (need_mmap_lock)
                down_read(&current->mm->mmap_sem);
@@ -450,7 +449,10 @@
                ttm_eu_backoff_reservation(&p->ticket, &p->validated);
 
 error_reserve:
-#ifndef __NetBSD__
+#ifdef __NetBSD__
+       if (need_mmap_lock)
+               vm_map_unlock_read(&curproc->p_vmspace->vm_map);
+#else
        if (need_mmap_lock)
                up_read(&current->mm->mmap_sem);
 #endif
diff -r b07dcaf85d1a -r 5ccee9dedd49 sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_gem.c
--- a/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_gem.c    Fri Feb 14 04:38:13 2020 +0000
+++ b/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_gem.c    Fri Feb 14 04:38:23 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: amdgpu_gem.c,v 1.5 2020/02/14 04:35:19 riastradh Exp $ */
+/*     $NetBSD: amdgpu_gem.c,v 1.6 2020/02/14 04:38:23 riastradh Exp $ */
 
 /*
  * Copyright 2008 Advanced Micro Devices, Inc.
@@ -28,7 +28,7 @@
  *          Jerome Glisse
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amdgpu_gem.c,v 1.5 2020/02/14 04:35:19 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amdgpu_gem.c,v 1.6 2020/02/14 04:38:23 riastradh Exp $");
 
 #include <linux/ktime.h>
 #include <drm/drmP.h>
@@ -228,15 +228,6 @@
 int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
                             struct drm_file *filp)
 {
-#ifdef __NetBSD__
-       /*
-        * XXX Too painful to contemplate for now.  If you add this,
-        * make sure to update amdgpu_cs.c amdgpu_cs_parser_relocs
-        * (need_mmap_lock), and anything else using
-        * amdgpu_ttm_tt_has_userptr.
-        */
-       return -ENODEV;
-#else
        struct amdgpu_device *adev = dev->dev_private;
        struct drm_amdgpu_gem_userptr *args = data;
        struct drm_gem_object *gobj;
@@ -281,17 +272,29 @@
        }
 
        if (args->flags & AMDGPU_GEM_USERPTR_VALIDATE) {
+#ifdef __NetBSD__
+               vm_map_lock_read(&curproc->p_vmspace->vm_map);
+#else
                down_read(&current->mm->mmap_sem);
+#endif
                r = amdgpu_bo_reserve(bo, true);
                if (r) {
+#ifdef __NetBSD__
+                       vm_map_unlock_read(&curproc->p_vmspace->vm_map);
+#else
                        up_read(&current->mm->mmap_sem);
+#endif
                        goto release_object;
                }
 
                amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT);
                r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
                amdgpu_bo_unreserve(bo);
+#ifdef __NetBSD__
+               vm_map_unlock_read(&curproc->p_vmspace->vm_map);
+#else
                up_read(&current->mm->mmap_sem);
+#endif
                if (r)
                        goto release_object;
        }
@@ -312,7 +315,6 @@
        r = amdgpu_gem_handle_lockup(adev, r);
 
        return r;
-#endif
 }
 
 int amdgpu_mode_dumb_mmap(struct drm_file *filp,
diff -r b07dcaf85d1a -r 5ccee9dedd49 sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_ttm.c
--- a/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_ttm.c    Fri Feb 14 04:38:13 2020 +0000
+++ b/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_ttm.c    Fri Feb 14 04:38:23 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: amdgpu_ttm.c,v 1.4 2018/08/27 15:22:54 riastradh Exp $ */
+/*     $NetBSD: amdgpu_ttm.c,v 1.5 2020/02/14 04:38:23 riastradh Exp $ */
 
 /*
  * Copyright 2009 Jerome Glisse.
@@ -32,7 +32,7 @@
  *    Dave Airlie
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amdgpu_ttm.c,v 1.4 2018/08/27 15:22:54 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amdgpu_ttm.c,v 1.5 2020/02/14 04:38:23 riastradh Exp $");
 
 #include <ttm/ttm_bo_api.h>
 #include <ttm/ttm_bo_driver.h>
@@ -488,39 +488,119 @@
        struct amdgpu_device            *adev;
        u64                             offset;
        uint64_t                        userptr;
+#ifdef __NetBSD__
+       struct vmspace                  *usermm;
+#else
        struct mm_struct                *usermm;
+#endif
        uint32_t                        userflags;
 };
 
 /* prepare the sg table with the user pages */
 static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
 {
-#ifdef __NetBSD__
-       panic("we don't handle user pointers round these parts");
-#else
        struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev);
        struct amdgpu_ttm_tt *gtt = (void *)ttm;
+#ifndef __NetBSD__
        unsigned pinned = 0, nents;
+#endif
        int r;
 
        int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
+#ifndef __NetBSD__
        enum dma_data_direction direction = write ?
                DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
+#endif
 
+#ifdef __NetBSD__
+       if (curproc->p_vmspace != gtt->usermm)
+               return -EPERM;
+#else
        if (current->mm != gtt->usermm)
                return -EPERM;
+#endif
 
        if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) {
                /* check that we only pin down anonymous memory
                   to prevent problems with writeback */
                unsigned long end = gtt->userptr + ttm->num_pages * PAGE_SIZE;
+#ifdef __NetBSD__
+               /* XXX ???  TOCTOU, anyone?  */
+               /* XXX should do range_test */
+               struct vm_map_entry *entry;
+               bool ok;
+               vm_map_lock_read(&gtt->usermm->vm_map);
+               ok = uvm_map_lookup_entry(&gtt->usermm->vm_map,
+                   (vaddr_t)gtt->userptr, &entry);
+               if (ok)
+                       ok = !UVM_ET_ISOBJ(entry) && end <= entry->end;
+               vm_map_unlock_read(&gtt->usermm->vm_map);
+               if (!ok)
+                       return -EPERM;
+#else
                struct vm_area_struct *vma;
 
                vma = find_vma(gtt->usermm, gtt->userptr);
                if (!vma || vma->vm_file || vma->vm_end < end)
                        return -EPERM;
+#endif
        }
 
+#ifdef __NetBSD__
+       struct iovec iov = {
+               .iov_base = (void *)(vaddr_t)gtt->userptr,
+               .iov_len = ttm->num_pages << PAGE_SHIFT,
+       };
+       struct uio uio = {
+               .uio_iov = &iov,
+               .uio_iovcnt = 1,
+               .uio_offset = 0,
+               .uio_resid = ttm->num_pages << PAGE_SHIFT,
+               .uio_rw = (write ? UIO_READ : UIO_WRITE), /* XXX ??? */
+               .uio_vmspace = gtt->usermm,
+       };
+       unsigned long i;
+
+       /* Wire the relevant part of the user's address space.  */
+       /* XXX What happens if user does munmap?  */
+       /* XXX errno NetBSD->Linux */
+       r = -uvm_vslock(gtt->usermm, (void *)(vaddr_t)gtt->userptr,
+           ttm->num_pages << PAGE_SHIFT,
+           (write ? VM_PROT_WRITE : VM_PROT_READ)); /* XXX ??? */
+       if (r)
+               goto fail0;
+
+       /* Load it up for DMA.  */
+       /* XXX errno NetBSD->Linux */
+       r = -bus_dmamap_load_uio(adev->ddev->dmat, gtt->ttm.dma_address, &uio,
+           BUS_DMA_WAITOK);
+       if (r)
+               goto fail1;
+
+       /* Get each of the pages as ttm requests.  */
+       for (i = 0; i < ttm->num_pages; i++) {
+               vaddr_t va = (vaddr_t)gtt->userptr + (i << PAGE_SHIFT);
+               paddr_t pa;
+               struct vm_page *vmp;
+
+               if (!pmap_extract(gtt->usermm->vm_map.pmap, va, &pa)) {
+                       r = -EFAULT;
+                       goto fail2;
+               }
+               vmp = PHYS_TO_VM_PAGE(pa);
+               ttm->pages[i] = container_of(vmp, struct page, p_vmp);
+       }
+
+       /* Success!  */
+       return 0;
+
+fail2: while (i --> 0)
+               ttm->pages[i] = NULL; /* paranoia */
+       bus_dmamap_unload(adev->ddev->dmat, gtt->ttm.dma_address);
+fail1: uvm_vsunlock(gtt->usermm, (void *)(vaddr_t)gtt->userptr,
+           ttm->num_pages << PAGE_SHIFT);
+fail0: return r;
+#else
        do {
                unsigned num_pages = ttm->num_pages - pinned;
                uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE;
@@ -563,7 +643,13 @@
 static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm)
 {
 #ifdef __NetBSD__
-       panic("some varmint pinned a userptr to my hat");
+       struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev);
+       struct amdgpu_ttm_tt *gtt = container_of(ttm, struct amdgpu_ttm_tt,
+           ttm.ttm);
+
+       bus_dmamap_unload(adev->ddev->dmat, gtt->ttm.dma_address);
+       uvm_vsunlock(gtt->usermm, (void *)(vaddr_t)gtt->userptr,
+           ttm->num_pages << PAGE_SHIFT);
 #else
        struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev);
        struct amdgpu_ttm_tt *gtt = (void *)ttm;
@@ -696,16 +782,16 @@
 
        if (gtt && gtt->userptr) {
 #ifdef __NetBSD__
-               panic("don't point at users, it's not polite");
+               ttm->sg = NULL;
 #else
                ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
                if (!ttm->sg)
                        return -ENOMEM;
+#endif
 
                ttm->page_flags |= TTM_PAGE_FLAG_SG;
                ttm->state = tt_unbound;
                return 0;
-#endif
        }
 
        if (slave && ttm->sg) {
@@ -823,19 +909,19 @@
 int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr,



Home | Main Index | Thread Index | Old Index