diff --git a/sys/external/bsd/drm2/dist/drm/radeon/radeon_cs.c b/sys/external/bsd/drm2/dist/drm/radeon/radeon_cs.c index 8f98b18070ec..edf946d7bebb 100644 --- a/sys/external/bsd/drm2/dist/drm/radeon/radeon_cs.c +++ b/sys/external/bsd/drm2/dist/drm/radeon/radeon_cs.c @@ -83,7 +83,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) struct radeon_cs_chunk *chunk; struct radeon_cs_buckets buckets; unsigned i; - bool need_mmap_lock __diagused = false; + bool need_mmap_lock = false; int r; if (p->chunk_relocs == NULL) { @@ -182,9 +182,16 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) p->vm_bos = radeon_vm_get_bos(p->rdev, p->ib.vm, &p->validated); #ifdef __NetBSD__ - KASSERTMSG(!need_mmap_lock, - "someone didn't finish adding support for userptr" - " and it wasn't me"); + /* + * XXX Use read lock instead of busy? Not sure exactly what + * needs to be serialized here -- do we just need to lock out + * changes to the VM map? + */ + if (need_mmap_lock) { + vm_map_lock(&curproc->p_vmspace->vm_map); + vm_map_busy(&curproc->p_vmspace->vm_map); + vm_map_unlock(&curproc->p_vmspace->vm_map); + } #else if (need_mmap_lock) down_read(¤t->mm->mmap_sem); @@ -192,7 +199,13 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) r = radeon_bo_list_validate(p->rdev, &p->ticket, &p->validated, p->ring); -#ifndef __NetBSD__ +#ifdef __NetBSD__ + if (need_mmap_lock) { + vm_map_lock_read(&curproc->p_vmspace->vm_map); + vm_map_unbusy(&curproc->p_vmspace->vm_map); + vm_map_unlock(&curproc->p_vmspace->vm_map); + } +#else if (need_mmap_lock) up_read(¤t->mm->mmap_sem); #endif diff --git a/sys/external/bsd/drm2/dist/drm/radeon/radeon_gem.c b/sys/external/bsd/drm2/dist/drm/radeon/radeon_gem.c index fcdd98388ddc..04fc037c2e5e 100644 --- a/sys/external/bsd/drm2/dist/drm/radeon/radeon_gem.c +++ b/sys/external/bsd/drm2/dist/drm/radeon/radeon_gem.c @@ -288,15 +288,6 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, int radeon_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 radeon_cs.c radeon_cs_parser_relocs - * (need_mmap_lock), and anything else using - * radeon_ttm_tt_has_userptr. - */ - return -ENODEV; -#else struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_userptr *args = data; struct drm_gem_object *gobj; @@ -341,23 +332,45 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, void *data, goto release_object; if (args->flags & RADEON_GEM_USERPTR_REGISTER) { +#ifdef __NetBSD__ + r = -ENODEV; +#else r = radeon_mn_register(bo, args->addr); +#endif if (r) goto release_object; } if (args->flags & RADEON_GEM_USERPTR_VALIDATE) { +#ifdef __NetBSD__ + vm_map_lock(&curproc->p_vmspace->vm_map); + vm_map_busy(&curproc->p_vmspace->vm_map); + vm_map_unlock(&curproc->p_vmspace->vm_map); +#else down_read(¤t->mm->mmap_sem); +#endif r = radeon_bo_reserve(bo, true); if (r) { +#ifdef __NetBSD__ + vm_map_lock_read(&curproc->p_vmspace->vm_map); + vm_map_unbusy(&curproc->p_vmspace->vm_map); + vm_map_unlock(&curproc->p_vmspace->vm_map); +#else up_read(¤t->mm->mmap_sem); +#endif goto release_object; } radeon_ttm_placement_from_domain(bo, RADEON_GEM_DOMAIN_GTT); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); radeon_bo_unreserve(bo); +#ifdef __NetBSD__ + vm_map_lock_read(&curproc->p_vmspace->vm_map); + vm_map_unbusy(&curproc->p_vmspace->vm_map); + vm_map_unlock(&curproc->p_vmspace->vm_map); +#else up_read(¤t->mm->mmap_sem); +#endif if (r) goto release_object; } @@ -380,7 +393,6 @@ handle_lockup: r = radeon_gem_handle_lockup(rdev, r); return r; -#endif } int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, diff --git a/sys/external/bsd/drm2/dist/drm/radeon/radeon_ttm.c b/sys/external/bsd/drm2/dist/drm/radeon/radeon_ttm.c index 2d18eefb2cd9..bdd5c97453c6 100644 --- a/sys/external/bsd/drm2/dist/drm/radeon/radeon_ttm.c +++ b/sys/external/bsd/drm2/dist/drm/radeon/radeon_ttm.c @@ -546,38 +546,116 @@ struct radeon_ttm_tt { 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 radeon_ttm_tt_pin_userptr(struct ttm_tt *ttm) { -#ifdef __NetBSD__ - panic("we don't handle user pointers round these parts"); -#else struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); struct radeon_ttm_tt *gtt = (void *)ttm; +#ifndef __NetBSD__ unsigned pinned = 0, nents; +#endif int r; int write = !(gtt->userflags & RADEON_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 & RADEON_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(>t->usermm->vm_map); + ok = uvm_map_lookup_entry(>t->usermm->vm_map, + (vaddr_t)gtt->userptr, &entry); + if (ok) + ok = !UVM_ET_ISOBJ(entry) && end <= entry->end; + vm_map_unlock_read(>t->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(rdev->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)) + 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(ttm->bdev->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; @@ -903,25 +981,19 @@ static const struct uvm_pagerops radeon_uvm_ops = { int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, uint32_t flags) { -#ifdef __NetBSD__ - /* - * XXX Too painful to contemplate for now. If you add this, - * make sure to update radeon_cs.c radeon_cs_parser_relocs - * (need_mmap_lock), and anything else using - * radeon_ttm_tt_has_userptr. - */ - return -ENODEV; -#else struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); if (gtt == NULL) return -EINVAL; gtt->userptr = addr; +#ifdef __NetBSD__ + gtt->usermm = curproc->p_vmspace; +#else gtt->usermm = current->mm; +#endif gtt->userflags = flags; return 0; -#endif } bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm) diff --git a/sys/external/bsd/drm2/radeon/files.radeon b/sys/external/bsd/drm2/radeon/files.radeon index 84727d964c61..0949d2d8b8c9 100644 --- a/sys/external/bsd/drm2/radeon/files.radeon +++ b/sys/external/bsd/drm2/radeon/files.radeon @@ -88,6 +88,7 @@ file external/bsd/drm2/dist/drm/radeon/radeon_kv_smc.c radeon file external/bsd/drm2/dist/drm/radeon/radeon_legacy_crtc.c radeon file external/bsd/drm2/dist/drm/radeon/radeon_legacy_encoders.c radeon file external/bsd/drm2/dist/drm/radeon/radeon_legacy_tv.c radeon +#file external/bsd/drm2/dist/drm/radeon/radeon_mn.c radeon file external/bsd/drm2/dist/drm/radeon/radeon_ni.c radeon file external/bsd/drm2/dist/drm/radeon/radeon_ni_dma.c radeon file external/bsd/drm2/dist/drm/radeon/radeon_ni_dpm.c radeon