From: Jonathan Gray Subject: Re: [PATCH 0/4] i915 dg2 patches To: kisekinopureya Cc: tech@openbsd.org Date: Mon, 14 Sep 2026 20:52:15 +1000 On Fri, Sep 11, 2026 at 09:54:43PM +0300, kisekinopureya wrote: > I tested your patches as is on latest codebase, it throws uvm_fault and > system > hard locks: > > i915_tt_get_st: stub > i915_tt_get_st: stub > uvm_fault(0xffffffff82b3a700, 0xffffffffffffffda, 0, 1) -> e I set up my dg2 again: inteldrm0 at pci12 dev 0 function 0 "Intel Arc Pro A40/A50" rev 0x05 drm0 at inteldrm0 inteldrm0: msi, DG2, gen 12 ... intel_slicemask_from_xehp_dssmask: stub intel_slicemask_from_xehp_dssmask: stub i915_resize_lmem_bar: stub intel_slicemask_from_xehp_dssmask: stub drm:pid0:wa_verify *ERROR* [drm] *ERROR* GT0: GT workaround lost on init! (reg[b188]=0x0, relevant bits were 0x0 vs expected 0x8) gsc_init_one: stub gsc_init_one: stub inteldrm0: 1280x1024, 32bpp The problem was with dma_map_sgtable() and another in i915_ttm_purge(). With the below diff X starts and glxinfo/glxgears work. Disabling HuC not required. diff --git sys/dev/pci/drm/drm_linux.c sys/dev/pci/drm/drm_linux.c index 53a6efd90e2..faca11e360d 100644 --- sys/dev/pci/drm/drm_linux.c +++ sys/dev/pci/drm/drm_linux.c @@ -1251,6 +1251,38 @@ sg_free_table(struct sg_table *table) table->sgl = NULL; } +int +sg_alloc_table_from_pages_segment(struct sg_table *table, struct vm_page **pages, + unsigned int npages, unsigned int off, unsigned long size, + unsigned int max_segs, gfp_t gfp_mask) +{ + struct scatterlist *sg; + int r, i; + unsigned int len; + + r = sg_alloc_table(table, npages, gfp_mask); + if (r != 0) + return r; + + sg = table->sgl; + table->nents = 0; + len = PAGE_SIZE - off; + for (i = 0; i < npages; i++) { + if (i) + sg = sg_next(sg); + sg_set_page(sg, pages[i], len, off); + off = 0; + table->nents++; + size -= len; + if (size > PAGE_SIZE) + len = PAGE_SIZE; + else + len = size; + } + + return 0; +} + int i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { @@ -3487,6 +3519,19 @@ dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size, STUB(); } +int +dma_map_sgtable(struct device *dev, struct sg_table *sgt, + enum dma_data_direction dir, unsigned long attrs) +{ + return 0; +} + +void +dma_unmap_sgtable(struct device *dev, struct sg_table *sgt, + enum dma_data_direction dir, unsigned long attrs) +{ +} + #ifdef BUS_DMA_FIXED #include diff --git sys/dev/pci/drm/i915/gem/i915_gem_object.h sys/dev/pci/drm/i915/gem/i915_gem_object.h index b266814d3fb..0fb18d0aa43 100644 --- sys/dev/pci/drm/i915/gem/i915_gem_object.h +++ 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 *); 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 *, size_t); #endif void __shmem_writeback(size_t size, struct address_space *mapping); diff --git sys/dev/pci/drm/i915/gem/i915_gem_shmem.c sys/dev/pci/drm/i915/gem/i915_gem_shmem.c index ee8034c9c63..970b47f8fd6 100644 --- sys/dev/pci/drm/i915/gem/i915_gem_shmem.c +++ sys/dev/pci/drm/i915/gem/i915_gem_shmem.c @@ -34,7 +34,7 @@ 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, size_t uao_size) { struct sgt_iter sgt_iter; struct folio_batch fbatch; @@ -69,7 +69,7 @@ void shmem_sg_free_table(struct sg_table *st, struct address_space *mapping, if (fbatch.nr) check_release_folio_batch(&fbatch); #else - uvm_obj_unwire(obj->base.uao, 0, obj->base.size); + uvm_obj_unwire(uao, 0, uao_size); #endif sg_free_table(st); @@ -79,7 +79,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 +201,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 +225,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, size); } else { mapping_clear_unevictable(mapping); sg_free_table(st); @@ -275,7 +275,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 +291,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, obj->base.size); #endif sg_free_table(st); kfree(st); @@ -320,7 +320,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, obj->base.size); #endif /* * shmemfs first checks if there is enough memory to allocate the page @@ -459,7 +459,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, obj->base.size); #endif kfree(pages); obj->mm.dirty = false; diff --git sys/dev/pci/drm/i915/gem/i915_gem_ttm.c sys/dev/pci/drm/i915/gem/i915_gem_ttm.c index 570d0971fd4..d6676d6d3c3 100644 --- sys/dev/pci/drm/i915/gem/i915_gem_ttm.c +++ sys/dev/pci/drm/i915/gem/i915_gem_ttm.c @@ -53,7 +53,11 @@ struct i915_ttm_tt { struct i915_refct_sgt cached_rsgt; bool is_shmem; +#ifdef __linux__ struct file *filp; +#else + struct uvm_object *filp; +#endif }; static const struct ttm_place sys_placement_flags = { @@ -179,13 +183,11 @@ i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj, placement->placement = places; } +#ifdef __linux__ 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); @@ -239,19 +241,71 @@ err_free_st: shmem_sg_free_table(st, filp->f_mapping, false, false); return err; -#endif } +#else /* !__linux__ */ +static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev, + struct ttm_tt *ttm, + struct ttm_operation_ctx *ctx) +{ + 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; + struct uvm_object *uao = i915_tt->filp; + struct sgt_iter sgt_iter; + struct sg_table *st; + struct vm_page *page; + unsigned long i; + int err; + + if (!uao) { + uao = uao_create(size, 0); + if (uao == NULL) + return -ENOMEM; + + i915_tt->filp = uao; + } + + st = &i915_tt->cached_rsgt.table; + err = shmem_sg_alloc_table(i915, st, size, mr, /*filp->f_mapping*/NULL, + max_segment, uao); + if (err) + return err; + + err = dma_map_sgtable(i915_tt->dev, st, DMA_BIDIRECTIONAL, + DMA_ATTR_SKIP_CPU_SYNC); + if (err) + goto err_free_st; + + i = 0; + for_each_sgt_page(page, sgt_iter, st) + ttm->pages[i++] = page; + + if (ttm->page_flags & TTM_TT_FLAG_SWAPPED) + ttm->page_flags &= ~TTM_TT_FLAG_SWAPPED; + + return 0; + +err_free_st: + shmem_sg_free_table(st, NULL, false, false, uao, size); + + return err; +} +#endif /* !__linux__ */ 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 + const size_t size = (size_t)ttm->num_pages << PAGE_SHIFT; + shmem_sg_free_table(st, NULL, backup, backup, i915_tt->filp, size); #endif } @@ -334,8 +388,6 @@ 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; @@ -348,7 +400,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) @@ -356,7 +407,11 @@ static void i915_ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm); if (i915_tt->filp) +#ifdef __linux__ fput(i915_tt->filp); +#else + uao_detach(i915_tt->filp); +#endif ttm_tt_fini(ttm); i915_refct_sgt_put(&i915_tt->cached_rsgt); @@ -456,13 +511,14 @@ int i915_ttm_purge(struct drm_i915_gem_object *obj) #ifdef __linux__ shmem_truncate_range(file_inode(i915_tt->filp), 0, (loff_t)-1); + fput(fetch_and_zero(&i915_tt->filp)); #else - rw_enter(obj->base.uao->vmobjlock, RW_WRITE); - obj->base.uao->pgops->pgo_flush(obj->base.uao, 0, + rw_enter(i915_tt->filp->vmobjlock, RW_WRITE); + i915_tt->filp->pgops->pgo_flush(i915_tt->filp, 0, obj->base.size, PGO_ALLPAGES | PGO_FREE); - rw_exit(obj->base.uao->vmobjlock); + rw_exit(i915_tt->filp->vmobjlock); + uao_detach(fetch_and_zero(&i915_tt->filp)); #endif - fput(fetch_and_zero(&i915_tt->filp)); } } @@ -544,9 +600,6 @@ 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; @@ -571,7 +624,6 @@ static struct i915_refct_sgt *i915_ttm_tt_get_st(struct ttm_tt *ttm) } return i915_refct_sgt_get(&i915_tt->cached_rsgt); -#endif } /** diff --git sys/dev/pci/drm/i915/i915_pci.c sys/dev/pci/drm/i915/i915_pci.c index 37fe0367e7b..3aea0d1c4b2 100644 --- sys/dev/pci/drm/i915/i915_pci.c +++ sys/dev/pci/drm/i915/i915_pci.c @@ -738,7 +738,6 @@ static const struct intel_device_info adl_p_info = { static const struct intel_device_info dg2_info = { DG2_FEATURES, - .require_force_probe = 1, }; static const struct intel_device_info ats_m_info = { diff --git sys/dev/pci/drm/include/linux/scatterlist.h sys/dev/pci/drm/include/linux/scatterlist.h index fed5b3a399a..d1e02c69791 100644 --- sys/dev/pci/drm/include/linux/scatterlist.h +++ sys/dev/pci/drm/include/linux/scatterlist.h @@ -59,6 +59,9 @@ sg_next(struct scatterlist *sgl) int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); void sg_free_table(struct sg_table *); +int sg_alloc_table_from_pages_segment(struct sg_table *, struct vm_page **, + unsigned int, unsigned int, unsigned long, unsigned int, gfp_t); + static inline void sg_mark_end(struct scatterlist *sgl) {