From: kisekinopureya Subject: [PATCH 4/4] port gem and ttm memory management to uvm To: tech@openbsd.org Date: Thu, 10 Sep 2026 22:13:52 +0300 sys/dev/pci/drm/i915/gem/i915_gem_object.h | 4 +- sys/dev/pci/drm/i915/gem/i915_gem_shmem.c | 23 ++++--- sys/dev/pci/drm/i915/gem/i915_gem_ttm.c | 72 ++++++++++++++++++---- 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/sys/dev/pci/drm/i915/gem/i915_gem_object.h b/sys/dev/pci/drm/i915/gem/i915_gem_object.h index b266814d3fb..5ac665209ec 100644 --- a/sys/dev/pci/drm/i915/gem/i915_gem_object.h +++ b/sys/dev/pci/drm/i915/gem/i915_gem_object.h @@ -855,10 +855,10 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, size_t size, struct intel_memory_region *mr, struct address_space *mapping, unsigned int max_segment, - struct drm_i915_gem_object *obj); + struct uvm_object *uao); void shmem_sg_free_table(struct sg_table *st, struct address_space *mapping, bool dirty, bool backup, - struct drm_i915_gem_object *obj); + struct uvm_object *uao); #endif void __shmem_writeback(size_t size, struct address_space *mapping); diff --git a/sys/dev/pci/drm/i915/gem/i915_gem_shmem.c b/sys/dev/pci/drm/i915/gem/i915_gem_shmem.c index ee8034c9c63..c2e5a09fa09 100644 --- a/sys/dev/pci/drm/i915/gem/i915_gem_shmem.c +++ b/sys/dev/pci/drm/i915/gem/i915_gem_shmem.c @@ -34,12 +34,15 @@ static void check_release_folio_batch(struct folio_batch *fbatch) void shmem_sg_free_table(struct sg_table *st, struct address_space *mapping, bool dirty, bool backup, - struct drm_i915_gem_object *obj) + struct uvm_object *uao) { struct sgt_iter sgt_iter; struct folio_batch fbatch; struct folio *last = NULL; struct vm_page *page; +#ifdef __OpenBSD__ + size_t size = 0; +#endif #ifdef __linux__ mapping_clear_unevictable(mapping); @@ -63,13 +66,14 @@ void shmem_sg_free_table(struct sg_table *st, struct address_space *mapping, #else if (dirty) set_page_dirty(page); + size += PAGE_SIZE; #endif } #ifdef __linux__ if (fbatch.nr) check_release_folio_batch(&fbatch); #else - uvm_obj_unwire(obj->base.uao, 0, obj->base.size); + uvm_obj_unwire(uao, 0, size); #endif sg_free_table(st); @@ -79,7 +83,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, size_t size, struct intel_memory_region *mr, struct address_space *mapping, unsigned int max_segment, - struct drm_i915_gem_object *obj) + struct uvm_object *uao) { unsigned int page_count; /* restricted by sg_alloc_table */ unsigned long i; @@ -201,7 +205,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, st->nents = 0; TAILQ_INIT(&plist); - if (uvm_obj_wire(obj->base.uao, 0, obj->base.size, &plist)) { + if (uvm_obj_wire(uao, 0, size, &plist)) { ret = -ENOMEM; goto err_sg; } @@ -225,7 +229,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, err_sg: sg_mark_end(sg); if (sg != st->sgl) { - shmem_sg_free_table(st, mapping, false, false, obj); + shmem_sg_free_table(st, mapping, false, false, uao); } else { mapping_clear_unevictable(mapping); sg_free_table(st); @@ -275,7 +279,7 @@ rebuild_st: max_segment); #else ret = shmem_sg_alloc_table(i915, st, obj->base.size, mem, NULL, - max_segment, obj); + max_segment, obj->base.uao); #endif if (ret) goto err_st; @@ -291,7 +295,7 @@ rebuild_st: #ifdef __linux__ shmem_sg_free_table(st, mapping, false, false); #else - shmem_sg_free_table(st, NULL, false, false, obj); + shmem_sg_free_table(st, NULL, false, false, obj->base.uao); #endif sg_free_table(st); kfree(st); @@ -320,7 +324,7 @@ err_pages: #ifdef __linux__ shmem_sg_free_table(st, mapping, false, false); #else - shmem_sg_free_table(st, NULL, false, false, obj); + shmem_sg_free_table(st, NULL, false, false, obj->base.uao); #endif /* * shmemfs first checks if there is enough memory to allocate the page @@ -459,7 +463,8 @@ void i915_gem_object_put_pages_shmem(struct drm_i915_gem_object *obj, struct sg_ obj->mm.dirty, obj->mm.madv == I915_MADV_WILLNEED); #else shmem_sg_free_table(pages, NULL, - obj->mm.dirty, obj->mm.madv == I915_MADV_WILLNEED, obj); + obj->mm.dirty, obj->mm.madv == I915_MADV_WILLNEED, + obj->base.uao); #endif kfree(pages); obj->mm.dirty = false; diff --git a/sys/dev/pci/drm/i915/gem/i915_gem_ttm.c b/sys/dev/pci/drm/i915/gem/i915_gem_ttm.c index 570d0971fd4..340ede9e68d 100644 --- a/sys/dev/pci/drm/i915/gem/i915_gem_ttm.c +++ b/sys/dev/pci/drm/i915/gem/i915_gem_ttm.c @@ -54,6 +54,9 @@ struct i915_ttm_tt { bool is_shmem; struct file *filp; +#ifdef __OpenBSD__ + struct uvm_object *uao; +#endif }; static const struct ttm_place sys_placement_flags = { @@ -183,21 +186,24 @@ static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) { - STUB(); - return -ENOSYS; -#ifdef notyet struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev); struct intel_memory_region *mr = i915->mm.regions[INTEL_MEMORY_SYSTEM]; struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm); const unsigned int max_segment = i915_sg_segment_size(i915->drm.dev); const size_t size = (size_t)ttm->num_pages << PAGE_SHIFT; +#ifdef __linux__ struct file *filp = i915_tt->filp; +#else + struct uvm_object *uao = i915_tt->uao; +#endif + struct sgt_iter sgt_iter; struct sg_table *st; struct vm_page *page; unsigned long i; int err; +#ifdef __linux__ if (!filp) { struct address_space *mapping; gfp_t mask; @@ -214,17 +220,33 @@ static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev, i915_tt->filp = filp; } +#else + if (!uao) { + uao = uao_create(size, 0); + if (uao == NULL) + return -ENOMEM; + + i915_tt->uao = uao; + } +#endif st = &i915_tt->cached_rsgt.table; +#ifdef __linux__ err = shmem_sg_alloc_table(i915, st, size, mr, filp->f_mapping, max_segment); +#else + err = shmem_sg_alloc_table(i915, st, size, mr, NULL, + max_segment, uao); +#endif if (err) return err; +#ifdef __linux__ err = dma_map_sgtable(i915_tt->dev, st, DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC); if (err) goto err_free_st; +#endif i = 0; for_each_sgt_page(page, sgt_iter, st) @@ -235,23 +257,25 @@ static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev, return 0; +#ifdef __linux__ err_free_st: shmem_sg_free_table(st, filp->f_mapping, false, false); +#endif return err; -#endif } static void i915_ttm_tt_shmem_unpopulate(struct ttm_tt *ttm) { - STUB(); -#ifdef notyet struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm); bool backup = ttm->page_flags & TTM_TT_FLAG_SWAPPED; struct sg_table *st = &i915_tt->cached_rsgt.table; +#ifdef __linux__ shmem_sg_free_table(st, file_inode(i915_tt->filp)->i_mapping, backup, backup); +#else + shmem_sg_free_table(st, NULL, backup, backup, i915_tt->uao); #endif } @@ -334,13 +358,13 @@ static int i915_ttm_tt_populate(struct ttm_device *bdev, static void i915_ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm) { - STUB(); -#ifdef notyet struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm); struct sg_table *st = &i915_tt->cached_rsgt.table; +#ifdef __linux__ if (st->sgl) dma_unmap_sgtable(i915_tt->dev, st, DMA_BIDIRECTIONAL, 0); +#endif if (i915_tt->is_shmem) { i915_ttm_tt_shmem_unpopulate(ttm); @@ -348,7 +372,6 @@ static void i915_ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm) sg_free_table(st); ttm_pool_free(&bdev->pool, ttm); } -#endif } static void i915_ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) @@ -357,6 +380,10 @@ static void i915_ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) if (i915_tt->filp) fput(i915_tt->filp); +#ifdef __OpenBSD__ + if (i915_tt->uao) + uao_detach(i915_tt->uao); +#endif ttm_tt_fini(ttm); i915_refct_sgt_put(&i915_tt->cached_rsgt); @@ -544,17 +571,19 @@ static void i915_ttm_delete_mem_notify(struct ttm_buffer_object *bo) static struct i915_refct_sgt *i915_ttm_tt_get_st(struct ttm_tt *ttm) { - STUB(); - return ERR_PTR(-ENOSYS); -#ifdef notyet struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm); struct sg_table *st; int ret; +#ifdef __OpenBSD__ + struct scatterlist *sg; + unsigned long i; +#endif if (i915_tt->cached_rsgt.table.sgl) return i915_refct_sgt_get(&i915_tt->cached_rsgt); st = &i915_tt->cached_rsgt.table; +#ifdef __linux__ ret = sg_alloc_table_from_pages_segment(st, ttm->pages, ttm->num_pages, 0, (unsigned long)ttm->num_pages << PAGE_SHIFT, @@ -563,15 +592,32 @@ static struct i915_refct_sgt *i915_ttm_tt_get_st(struct ttm_tt *ttm) st->sgl = NULL; return ERR_PTR(ret); } +#else + ret = sg_alloc_table(st, ttm->num_pages, GFP_KERNEL); + if (ret) { + st->sgl = NULL; + return ERR_PTR(ret); + } + sg = st->sgl; + st->nents = 0; + for (i = 0; i < ttm->num_pages; i++) { + if (i) + sg = sg_next(sg); + st->nents++; + sg_set_page(sg, ttm->pages[i], PAGE_SIZE, 0); + } +#endif + +#ifdef __linux__ ret = dma_map_sgtable(i915_tt->dev, st, DMA_BIDIRECTIONAL, 0); if (ret) { sg_free_table(st); return ERR_PTR(ret); } +#endif return i915_refct_sgt_get(&i915_tt->cached_rsgt); -#endif } /**