Merge tag 'drm-for-v4.15' of git://people.freedesktop.org/~airlied/linux
[linux-2.6-block.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_cs.c
index cd664832f9e8c7e45895ddeb43bba487f15b4471..6c78623e13863c6773d9dd4f7c4444de045f9f2b 100644 (file)
@@ -25,6 +25,7 @@
  *    Jerome Glisse <glisse@freedesktop.org>
  */
 #include <linux/pagemap.h>
+#include <linux/sync_file.h>
 #include <drm/drmP.h>
 #include <drm/amdgpu_drm.h>
 #include <drm/drm_syncobj.h>
@@ -89,12 +90,14 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
                goto free_chunk;
        }
 
+       mutex_lock(&p->ctx->lock);
+
        /* get chunks */
        chunk_array_user = u64_to_user_ptr(cs->in.chunks);
        if (copy_from_user(chunk_array, chunk_array_user,
                           sizeof(uint64_t)*cs->in.num_chunks)) {
                ret = -EFAULT;
-               goto put_ctx;
+               goto free_chunk;
        }
 
        p->nchunks = cs->in.num_chunks;
@@ -102,7 +105,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
                            GFP_KERNEL);
        if (!p->chunks) {
                ret = -ENOMEM;
-               goto put_ctx;
+               goto free_chunk;
        }
 
        for (i = 0; i < p->nchunks; i++) {
@@ -169,6 +172,11 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
        if (ret)
                goto free_all_kdata;
 
+       if (p->ctx->vram_lost_counter != p->job->vram_lost_counter) {
+               ret = -ECANCELED;
+               goto free_all_kdata;
+       }
+
        if (p->uf_entry.robj)
                p->job->uf_addr = uf_offset;
        kfree(chunk_array);
@@ -182,8 +190,6 @@ free_partial_kdata:
        kfree(p->chunks);
        p->chunks = NULL;
        p->nchunks = 0;
-put_ctx:
-       amdgpu_ctx_put(p->ctx);
 free_chunk:
        kfree(chunk_array);
 
@@ -473,11 +479,16 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
                        return -EPERM;
 
                /* Check if we have user pages and nobody bound the BO already */
-               if (lobj->user_pages && bo->tbo.ttm->state != tt_bound) {
-                       size_t size = sizeof(struct page *);
-
-                       size *= bo->tbo.ttm->num_pages;
-                       memcpy(bo->tbo.ttm->pages, lobj->user_pages, size);
+               if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm) &&
+                   lobj->user_pages) {
+                       amdgpu_ttm_placement_from_domain(bo,
+                                                        AMDGPU_GEM_DOMAIN_CPU);
+                       r = ttm_bo_validate(&bo->tbo, &bo->placement, true,
+                                           false);
+                       if (r)
+                               return r;
+                       amdgpu_ttm_tt_set_user_pages(bo->tbo.ttm,
+                                                    lobj->user_pages);
                        binding_userptr = true;
                }
 
@@ -502,7 +513,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
        struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
        struct amdgpu_bo_list_entry *e;
        struct list_head duplicates;
-       bool need_mmap_lock = false;
        unsigned i, tries = 10;
        int r;
 
@@ -510,9 +520,9 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
 
        p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle);
        if (p->bo_list) {
-               need_mmap_lock = p->bo_list->first_userptr !=
-                       p->bo_list->num_entries;
                amdgpu_bo_list_get_list(p->bo_list, &p->validated);
+               if (p->bo_list->first_userptr != p->bo_list->num_entries)
+                       p->mn = amdgpu_mn_get(p->adev);
        }
 
        INIT_LIST_HEAD(&duplicates);
@@ -521,9 +531,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
        if (p->uf_entry.robj)
                list_add(&p->uf_entry.tv.head, &p->validated);
 
-       if (need_mmap_lock)
-               down_read(&current->mm->mmap_sem);
-
        while (1) {
                struct list_head need_pages;
                unsigned i;
@@ -543,22 +550,24 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
                INIT_LIST_HEAD(&need_pages);
                for (i = p->bo_list->first_userptr;
                     i < p->bo_list->num_entries; ++i) {
+                       struct amdgpu_bo *bo;
 
                        e = &p->bo_list->array[i];
+                       bo = e->robj;
 
-                       if (amdgpu_ttm_tt_userptr_invalidated(e->robj->tbo.ttm,
+                       if (amdgpu_ttm_tt_userptr_invalidated(bo->tbo.ttm,
                                 &e->user_invalidated) && e->user_pages) {
 
                                /* We acquired a page array, but somebody
                                 * invalidated it. Free it and try again
                                 */
                                release_pages(e->user_pages,
-                                             e->robj->tbo.ttm->num_pages);
+                                             bo->tbo.ttm->num_pages);
                                kvfree(e->user_pages);
                                e->user_pages = NULL;
                        }
 
-                       if (e->robj->tbo.ttm->state != tt_bound &&
+                       if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm) &&
                            !e->user_pages) {
                                list_del(&e->tv.head);
                                list_add(&e->tv.head, &need_pages);
@@ -635,9 +644,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
 
        amdgpu_cs_report_moved_bytes(p->adev, p->bytes_moved,
                                     p->bytes_moved_vis);
-       fpriv->vm.last_eviction_counter =
-               atomic64_read(&p->adev->num_evictions);
-
        if (p->bo_list) {
                struct amdgpu_bo *gds = p->bo_list->gds_obj;
                struct amdgpu_bo *gws = p->bo_list->gws_obj;
@@ -678,9 +684,6 @@ error_validate:
 
 error_free_pages:
 
-       if (need_mmap_lock)
-               up_read(&current->mm->mmap_sem);
-
        if (p->bo_list) {
                for (i = p->bo_list->first_userptr;
                     i < p->bo_list->num_entries; ++i) {
@@ -705,7 +708,8 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
 
        list_for_each_entry(e, &p->validated, tv.head) {
                struct reservation_object *resv = e->robj->tbo.resv;
-               r = amdgpu_sync_resv(p->adev, &p->job->sync, resv, p->filp);
+               r = amdgpu_sync_resv(p->adev, &p->job->sync, resv, p->filp,
+                                    amdgpu_bo_explicit_sync(e->robj));
 
                if (r)
                        return r;
@@ -726,11 +730,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error,
 {
        unsigned i;
 
-       if (!error)
-               ttm_eu_fence_buffer_objects(&parser->ticket,
-                                           &parser->validated,
-                                           parser->fence);
-       else if (backoff)
+       if (error && backoff)
                ttm_eu_backoff_reservation(&parser->ticket,
                                           &parser->validated);
 
@@ -740,8 +740,10 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error,
 
        dma_fence_put(parser->fence);
 
-       if (parser->ctx)
+       if (parser->ctx) {
+               mutex_unlock(&parser->ctx->lock);
                amdgpu_ctx_put(parser->ctx);
+       }
        if (parser->bo_list)
                amdgpu_bo_list_put(parser->bo_list);
 
@@ -766,10 +768,6 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p)
        if (r)
                return r;
 
-       r = amdgpu_sync_fence(adev, &p->job->sync, vm->last_dir_update);
-       if (r)
-               return r;
-
        r = amdgpu_vm_clear_freed(adev, vm, NULL);
        if (r)
                return r;
@@ -823,7 +821,13 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p)
 
        }
 
-       r = amdgpu_vm_clear_moved(adev, vm, &p->job->sync);
+       r = amdgpu_vm_handle_moved(adev, vm);
+       if (r)
+               return r;
+
+       r = amdgpu_sync_fence(adev, &p->job->sync, vm->last_update);
+       if (r)
+               return r;
 
        if (amdgpu_vm_debug && p->bo_list) {
                /* Invalidate all BOs to test for userspace bugs */
@@ -833,7 +837,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p)
                        if (!bo)
                                continue;
 
-                       amdgpu_vm_bo_invalidate(adev, bo);
+                       amdgpu_vm_bo_invalidate(adev, bo, false);
                }
        }
 
@@ -846,19 +850,63 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
        struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
        struct amdgpu_vm *vm = &fpriv->vm;
        struct amdgpu_ring *ring = p->job->ring;
-       int i, r;
+       int r;
 
        /* Only for UVD/VCE VM emulation */
-       if (ring->funcs->parse_cs) {
-               for (i = 0; i < p->job->num_ibs; i++) {
-                       r = amdgpu_ring_parse_cs(ring, p, i);
+       if (p->job->ring->funcs->parse_cs) {
+               unsigned i, j;
+
+               for (i = 0, j = 0; i < p->nchunks && j < p->job->num_ibs; i++) {
+                       struct drm_amdgpu_cs_chunk_ib *chunk_ib;
+                       struct amdgpu_bo_va_mapping *m;
+                       struct amdgpu_bo *aobj = NULL;
+                       struct amdgpu_cs_chunk *chunk;
+                       struct amdgpu_ib *ib;
+                       uint64_t offset;
+                       uint8_t *kptr;
+
+                       chunk = &p->chunks[i];
+                       ib = &p->job->ibs[j];
+                       chunk_ib = chunk->kdata;
+
+                       if (chunk->chunk_id != AMDGPU_CHUNK_ID_IB)
+                               continue;
+
+                       r = amdgpu_cs_find_mapping(p, chunk_ib->va_start,
+                                                  &aobj, &m);
+                       if (r) {
+                               DRM_ERROR("IB va_start is invalid\n");
+                               return r;
+                       }
+
+                       if ((chunk_ib->va_start + chunk_ib->ib_bytes) >
+                           (m->last + 1) * AMDGPU_GPU_PAGE_SIZE) {
+                               DRM_ERROR("IB va_start+ib_bytes is invalid\n");
+                               return -EINVAL;
+                       }
+
+                       /* the IB should be reserved at this point */
+                       r = amdgpu_bo_kmap(aobj, (void **)&kptr);
+                       if (r) {
+                               return r;
+                       }
+
+                       offset = m->start * AMDGPU_GPU_PAGE_SIZE;
+                       kptr += chunk_ib->va_start - offset;
+
+                       memcpy(ib->ptr, kptr, chunk_ib->ib_bytes);
+                       amdgpu_bo_kunmap(aobj);
+
+                       r = amdgpu_ring_parse_cs(ring, p, j);
                        if (r)
                                return r;
+
+                       j++;
                }
        }
 
        if (p->job->vm) {
-               p->job->vm_pd_addr = amdgpu_bo_gpu_offset(vm->root.bo);
+               p->job->vm_pd_addr = amdgpu_bo_gpu_offset(vm->root.base.bo);
 
                r = amdgpu_bo_vm_update_pte(p);
                if (r)
@@ -920,54 +968,18 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
 
                parser->job->ring = ring;
 
-               if (ring->funcs->parse_cs) {
-                       struct amdgpu_bo_va_mapping *m;
-                       struct amdgpu_bo *aobj = NULL;
-                       uint64_t offset;
-                       uint8_t *kptr;
-
-                       m = amdgpu_cs_find_mapping(parser, chunk_ib->va_start,
-                                                  &aobj);
-                       if (!aobj) {
-                               DRM_ERROR("IB va_start is invalid\n");
-                               return -EINVAL;
-                       }
-
-                       if ((chunk_ib->va_start + chunk_ib->ib_bytes) >
-                           (m->last + 1) * AMDGPU_GPU_PAGE_SIZE) {
-                               DRM_ERROR("IB va_start+ib_bytes is invalid\n");
-                               return -EINVAL;
-                       }
-
-                       /* the IB should be reserved at this point */
-                       r = amdgpu_bo_kmap(aobj, (void **)&kptr);
-                       if (r) {
-                               return r;
-                       }
-
-                       offset = m->start * AMDGPU_GPU_PAGE_SIZE;
-                       kptr += chunk_ib->va_start - offset;
-
-                       r =  amdgpu_ib_get(adev, vm, chunk_ib->ib_bytes, ib);
-                       if (r) {
-                               DRM_ERROR("Failed to get ib !\n");
-                               return r;
-                       }
-
-                       memcpy(ib->ptr, kptr, chunk_ib->ib_bytes);
-                       amdgpu_bo_kunmap(aobj);
-               } else {
-                       r =  amdgpu_ib_get(adev, vm, 0, ib);
-                       if (r) {
-                               DRM_ERROR("Failed to get ib !\n");
-                               return r;
-                       }
-
+               r =  amdgpu_ib_get(adev, vm,
+                                       ring->funcs->parse_cs ? chunk_ib->ib_bytes : 0,
+                                       ib);
+               if (r) {
+                       DRM_ERROR("Failed to get ib !\n");
+                       return r;
                }
 
                ib->gpu_addr = chunk_ib->va_start;
                ib->length_dw = chunk_ib->ib_bytes / 4;
                ib->flags = chunk_ib->flags;
+
                j++;
        }
 
@@ -977,7 +989,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
            parser->job->ring->funcs->type == AMDGPU_RING_TYPE_VCE))
                return -EINVAL;
 
-       return 0;
+       return amdgpu_ctx_wait_prev_fence(parser->ctx, parser->job->ring->idx);
 }
 
 static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p,
@@ -1131,14 +1143,31 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
        struct amdgpu_ring *ring = p->job->ring;
        struct amd_sched_entity *entity = &p->ctx->rings[ring->idx].entity;
        struct amdgpu_job *job;
+       unsigned i;
+       uint64_t seq;
+
        int r;
 
+       amdgpu_mn_lock(p->mn);
+       if (p->bo_list) {
+               for (i = p->bo_list->first_userptr;
+                    i < p->bo_list->num_entries; ++i) {
+                       struct amdgpu_bo *bo = p->bo_list->array[i].robj;
+
+                       if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm)) {
+                               amdgpu_mn_unlock(p->mn);
+                               return -ERESTARTSYS;
+                       }
+               }
+       }
+
        job = p->job;
        p->job = NULL;
 
        r = amd_sched_job_init(&job->base, &ring->sched, entity, p->filp);
        if (r) {
                amdgpu_job_free(job);
+               amdgpu_mn_unlock(p->mn);
                return r;
        }
 
@@ -1146,21 +1175,36 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
        job->fence_ctx = entity->fence_context;
        p->fence = dma_fence_get(&job->base.s_fence->finished);
 
+       r = amdgpu_ctx_add_fence(p->ctx, ring, p->fence, &seq);
+       if (r) {
+               dma_fence_put(p->fence);
+               dma_fence_put(&job->base.s_fence->finished);
+               amdgpu_job_free(job);
+               amdgpu_mn_unlock(p->mn);
+               return r;
+       }
+
        amdgpu_cs_post_dependencies(p);
 
-       cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring, p->fence);
-       job->uf_sequence = cs->out.handle;
+       cs->out.handle = seq;
+       job->uf_sequence = seq;
+
        amdgpu_job_free_resources(job);
+       amdgpu_ring_priority_get(job->ring,
+                                amd_sched_get_job_priority(&job->base));
 
        trace_amdgpu_cs_ioctl(job);
        amd_sched_entity_push_job(&job->base);
+
+       ttm_eu_fence_buffer_objects(&p->ticket, &p->validated, p->fence);
+       amdgpu_mn_unlock(p->mn);
+
        return 0;
 }
 
 int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
        struct amdgpu_device *adev = dev->dev_private;
-       struct amdgpu_fpriv *fpriv = filp->driver_priv;
        union drm_amdgpu_cs *cs = data;
        struct amdgpu_cs_parser parser = {};
        bool reserved_buffers = false;
@@ -1168,8 +1212,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 
        if (!adev->accel_working)
                return -EBUSY;
-       if (amdgpu_kms_vram_lost(adev, fpriv))
-               return -ENODEV;
 
        parser.adev = adev;
        parser.filp = filp;
@@ -1180,6 +1222,10 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                goto out;
        }
 
+       r = amdgpu_cs_ib_fill(adev, &parser);
+       if (r)
+               goto out;
+
        r = amdgpu_cs_parser_bos(&parser, data);
        if (r) {
                if (r == -ENOMEM)
@@ -1190,9 +1236,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        }
 
        reserved_buffers = true;
-       r = amdgpu_cs_ib_fill(adev, &parser);
-       if (r)
-               goto out;
 
        r = amdgpu_cs_dependencies(adev, &parser);
        if (r) {
@@ -1228,16 +1271,12 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,
 {
        union drm_amdgpu_wait_cs *wait = data;
        struct amdgpu_device *adev = dev->dev_private;
-       struct amdgpu_fpriv *fpriv = filp->driver_priv;
        unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout);
        struct amdgpu_ring *ring = NULL;
        struct amdgpu_ctx *ctx;
        struct dma_fence *fence;
        long r;
 
-       if (amdgpu_kms_vram_lost(adev, fpriv))
-               return -ENODEV;
-
        ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id);
        if (ctx == NULL)
                return -EINVAL;
@@ -1255,6 +1294,8 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,
                r = PTR_ERR(fence);
        else if (fence) {
                r = dma_fence_wait_timeout(fence, true, timeout);
+               if (r > 0 && fence->error)
+                       r = fence->error;
                dma_fence_put(fence);
        } else
                r = 1;
@@ -1302,6 +1343,62 @@ static struct dma_fence *amdgpu_cs_get_fence(struct amdgpu_device *adev,
        return fence;
 }
 
+int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *filp)
+{
+       struct amdgpu_device *adev = dev->dev_private;
+       union drm_amdgpu_fence_to_handle *info = data;
+       struct dma_fence *fence;
+       struct drm_syncobj *syncobj;
+       struct sync_file *sync_file;
+       int fd, r;
+
+       fence = amdgpu_cs_get_fence(adev, filp, &info->in.fence);
+       if (IS_ERR(fence))
+               return PTR_ERR(fence);
+
+       switch (info->in.what) {
+       case AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ:
+               r = drm_syncobj_create(&syncobj, 0, fence);
+               dma_fence_put(fence);
+               if (r)
+                       return r;
+               r = drm_syncobj_get_handle(filp, syncobj, &info->out.handle);
+               drm_syncobj_put(syncobj);
+               return r;
+
+       case AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD:
+               r = drm_syncobj_create(&syncobj, 0, fence);
+               dma_fence_put(fence);
+               if (r)
+                       return r;
+               r = drm_syncobj_get_fd(syncobj, (int*)&info->out.handle);
+               drm_syncobj_put(syncobj);
+               return r;
+
+       case AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD:
+               fd = get_unused_fd_flags(O_CLOEXEC);
+               if (fd < 0) {
+                       dma_fence_put(fence);
+                       return fd;
+               }
+
+               sync_file = sync_file_create(fence);
+               dma_fence_put(fence);
+               if (!sync_file) {
+                       put_unused_fd(fd);
+                       return -ENOMEM;
+               }
+
+               fd_install(fd, sync_file->file);
+               info->out.handle = fd;
+               return 0;
+
+       default:
+               return -EINVAL;
+       }
+}
+
 /**
  * amdgpu_cs_wait_all_fence - wait on all fences to signal
  *
@@ -1336,6 +1433,9 @@ static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev,
 
                if (r == 0)
                        break;
+
+               if (fence->error)
+                       return fence->error;
        }
 
        memset(wait, 0, sizeof(*wait));
@@ -1381,6 +1481,7 @@ static int amdgpu_cs_wait_any_fence(struct amdgpu_device *adev,
                        array[i] = fence;
                } else { /* NULL, the fence has been already signaled */
                        r = 1;
+                       first = i;
                        goto out;
                }
        }
@@ -1395,7 +1496,7 @@ out:
        wait->out.status = (r > 0);
        wait->out.first_signaled = first;
        /* set return value 0 to indicate success */
-       r = 0;
+       r = array[first]->error;
 
 err_free_fence_array:
        for (i = 0; i < fence_count; i++)
@@ -1416,15 +1517,12 @@ int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *filp)
 {
        struct amdgpu_device *adev = dev->dev_private;
-       struct amdgpu_fpriv *fpriv = filp->driver_priv;
        union drm_amdgpu_wait_fences *wait = data;
        uint32_t fence_count = wait->in.fence_count;
        struct drm_amdgpu_fence *fences_user;
        struct drm_amdgpu_fence *fences;
        int r;
 
-       if (amdgpu_kms_vram_lost(adev, fpriv))
-               return -ENODEV;
        /* Get the fences from userspace */
        fences = kmalloc_array(fence_count, sizeof(struct drm_amdgpu_fence),
                        GFP_KERNEL);
@@ -1460,78 +1558,36 @@ err_free_fences:
  * virtual memory address. Returns allocation structure when found, NULL
  * otherwise.
  */
-struct amdgpu_bo_va_mapping *
-amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
-                      uint64_t addr, struct amdgpu_bo **bo)
+int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
+                          uint64_t addr, struct amdgpu_bo **bo,
+                          struct amdgpu_bo_va_mapping **map)
 {
+       struct amdgpu_fpriv *fpriv = parser->filp->driver_priv;
+       struct amdgpu_vm *vm = &fpriv->vm;
        struct amdgpu_bo_va_mapping *mapping;
-       unsigned i;
-
-       if (!parser->bo_list)
-               return NULL;
-
-       addr /= AMDGPU_GPU_PAGE_SIZE;
-
-       for (i = 0; i < parser->bo_list->num_entries; i++) {
-               struct amdgpu_bo_list_entry *lobj;
-
-               lobj = &parser->bo_list->array[i];
-               if (!lobj->bo_va)
-                       continue;
-
-               list_for_each_entry(mapping, &lobj->bo_va->valids, list) {
-                       if (mapping->start > addr ||
-                           addr > mapping->last)
-                               continue;
-
-                       *bo = lobj->bo_va->base.bo;
-                       return mapping;
-               }
-
-               list_for_each_entry(mapping, &lobj->bo_va->invalids, list) {
-                       if (mapping->start > addr ||
-                           addr > mapping->last)
-                               continue;
-
-                       *bo = lobj->bo_va->base.bo;
-                       return mapping;
-               }
-       }
-
-       return NULL;
-}
-
-/**
- * amdgpu_cs_sysvm_access_required - make BOs accessible by the system VM
- *
- * @parser: command submission parser context
- *
- * Helper for UVD/VCE VM emulation, make sure BOs are accessible by the system VM.
- */
-int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser)
-{
-       unsigned i;
        int r;
 
-       if (!parser->bo_list)
-               return 0;
+       addr /= AMDGPU_GPU_PAGE_SIZE;
 
-       for (i = 0; i < parser->bo_list->num_entries; i++) {
-               struct amdgpu_bo *bo = parser->bo_list->array[i].robj;
+       mapping = amdgpu_vm_bo_lookup_mapping(vm, addr);
+       if (!mapping || !mapping->bo_va || !mapping->bo_va->base.bo)
+               return -EINVAL;
 
-               r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem);
-               if (unlikely(r))
-                       return r;
+       *bo = mapping->bo_va->base.bo;
+       *map = mapping;
 
-               if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
-                       continue;
+       /* Double check that the BO is reserved by this CS */
+       if (READ_ONCE((*bo)->tbo.resv->lock.ctx) != &parser->ticket)
+               return -EINVAL;
 
-               bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
-               amdgpu_ttm_placement_from_domain(bo, bo->allowed_domains);
-               r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
-               if (unlikely(r))
+       if (!((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)) {
+               (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
+               amdgpu_ttm_placement_from_domain(*bo, (*bo)->allowed_domains);
+               r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, false,
+                                   false);
+               if (r)
                        return r;
        }
 
-       return 0;
+       return amdgpu_ttm_bind(&(*bo)->tbo, &(*bo)->tbo.mem);
 }