--- i915_gem_gtt_419.c 2026-09-16 03:44:03.908154110 +0000 +++ /home/maxx/dfbsd/dfbsd/sys/dev/drm/i915/i915_gem_gtt.c 2026-06-29 12:51:18.000000000 +0000 @@ -173,19 +173,11 @@ return 0; } - /* Early VLV doesn't have this */ - if (IS_VALLEYVIEW(dev_priv) && dev_priv->drm.pdev->revision < 0xb) { - DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n"); - return 0; - } - - if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { if (has_full_48bit_ppgtt) return 3; if (has_full_ppgtt) return 2; - } return 1; } @@ -381,17 +373,17 @@ static void stash_init(struct pagestash *stash) { pagevec_init(&stash->pvec); - spin_lock_init(&stash->lock); + lockinit(&stash->lock, "i915stl", 0, LK_CANRECURSE); } static struct page *stash_pop_page(struct pagestash *stash) { struct page *page = NULL; - spin_lock(&stash->lock); + lockmgr(&stash->lock, LK_EXCLUSIVE); if (likely(stash->pvec.nr)) page = stash->pvec.pages[--stash->pvec.nr]; - spin_unlock(&stash->lock); + lockmgr(&stash->lock, LK_RELEASE); return page; } @@ -400,7 +392,10 @@ { int nr; +#if 0 spin_lock_nested(&stash->lock, SINGLE_DEPTH_NESTING); +#endif + lockmgr(&stash->lock, LK_EXCLUSIVE); nr = min_t(int, pvec->nr, pagevec_space(&stash->pvec)); memcpy(stash->pvec.pages + stash->pvec.nr, @@ -408,7 +403,7 @@ sizeof(pvec->pages[0]) * nr); stash->pvec.nr += nr; - spin_unlock(&stash->lock); + lockmgr(&stash->lock, LK_RELEASE); pvec->nr -= nr; } @@ -504,12 +499,12 @@ */ stack = *pvec; pagevec_reinit(pvec); - spin_unlock(&vm->free_pages.lock); + lockmgr(&vm->free_pages.lock, LK_RELEASE); pvec = &stack; set_pages_array_wb(pvec->pages, pvec->nr); - spin_lock(&vm->free_pages.lock); + lockmgr(&vm->free_pages.lock, LK_EXCLUSIVE); } __pagevec_release(pvec); @@ -525,10 +520,10 @@ * unconditional might_sleep() for everybody. */ might_sleep(); - spin_lock(&vm->free_pages.lock); + lockmgr(&vm->free_pages.lock, LK_EXCLUSIVE); if (!pagevec_add(&vm->free_pages.pvec, page)) vm_free_pages_release(vm, false); - spin_unlock(&vm->free_pages.lock); + lockmgr(&vm->free_pages.lock, LK_RELEASE); } static void i915_address_space_init(struct i915_address_space *vm, @@ -539,7 +534,7 @@ * Do a dummy acquire now under fs_reclaim so that any allocation * attempt holding the lock is immediately reported by lockdep. */ - mutex_init(&vm->mutex); + lockinit(&vm->mutex, "i915vmm", 0, LK_CANRECURSE); i915_gem_shrinker_taints_mutex(&vm->mutex); GEM_BUG_ON(!vm->total); @@ -555,11 +550,11 @@ static void i915_address_space_fini(struct i915_address_space *vm) { - spin_lock(&vm->free_pages.lock); + lockmgr(&vm->free_pages.lock, LK_EXCLUSIVE); if (pagevec_count(&vm->free_pages.pvec)) vm_free_pages_release(vm, true); GEM_BUG_ON(pagevec_count(&vm->free_pages.pvec)); - spin_unlock(&vm->free_pages.lock); + lockmgr(&vm->free_pages.lock, LK_RELEASE); drm_mm_takedown(&vm->mm); @@ -701,7 +696,7 @@ { struct i915_page_table *pt; - pt = kmalloc(sizeof(*pt), I915_GFP_ALLOW_FAIL); + pt = kmalloc(sizeof(*pt), M_DRM, I915_GFP_ALLOW_FAIL); if (unlikely(!pt)) return ERR_PTR(-ENOMEM); @@ -1058,7 +1053,7 @@ do { vaddr[idx->pte] = pte_encode | iter->dma; - iter->dma += PAGE_SIZE; + iter->dma += I915_GTT_PAGE_SIZE; if (iter->dma >= iter->max) { iter->sg = __sg_next(iter->sg); if (!iter->sg) { @@ -1152,7 +1147,7 @@ vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K && IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) && (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) || - rem >= (max - index) << PAGE_SHIFT)) + rem >= (max - index) * I915_GTT_PAGE_SIZE)) maybe_64K = true; vaddr = kmap_atomic_px(pt); @@ -1177,7 +1172,7 @@ if (maybe_64K && index < max && !(IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) && (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) || - rem >= (max - index) << PAGE_SHIFT))) + rem >= (max - index) * I915_GTT_PAGE_SIZE))) maybe_64K = false; if (unlikely(!IS_ALIGNED(iter->dma, page_size))) @@ -1259,9 +1254,6 @@ { int i; - if (!px_page(pd)) - return; - for (i = 0; i < I915_PDES; i++) { if (pd->page_table[i] != vm->scratch_pt) free_pt(vm, pd->page_table[i]); @@ -1768,9 +1760,9 @@ if (i == 4) continue; - seq_printf(m, "\t\t(%03d, %04d) %08lx: ", + seq_printf(m, "\t\t(%03d, %04d) %08llx: ", pde, pte, - (pde * GEN6_PTES + pte) * PAGE_SIZE); + (pde * GEN6_PTES + pte) * I915_GTT_PAGE_SIZE); for (i = 0; i < 4; i++) { if (vaddr[pte + i] != scratch_pte) seq_printf(m, " %08x", vaddr[pte + i]); @@ -1853,10 +1845,10 @@ u64 start, u64 length) { struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm)); - unsigned int first_entry = start >> PAGE_SHIFT; + unsigned int first_entry = start / I915_GTT_PAGE_SIZE; unsigned int pde = first_entry / GEN6_PTES; unsigned int pte = first_entry % GEN6_PTES; - unsigned int num_entries = length >> PAGE_SHIFT; + unsigned int num_entries = length / I915_GTT_PAGE_SIZE; const gen6_pte_t scratch_pte = ppgtt->scratch_pte; while (num_entries) { @@ -1897,7 +1889,7 @@ u32 flags) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); - unsigned first_entry = vma->node.start >> PAGE_SHIFT; + unsigned first_entry = vma->node.start / I915_GTT_PAGE_SIZE; unsigned act_pt = first_entry / GEN6_PTES; unsigned act_pte = first_entry % GEN6_PTES; const u32 pte_encode = vm->pte_encode(0, cache_level, flags); @@ -1910,7 +1902,7 @@ do { vaddr[act_pte] = pte_encode | GEN6_PTE_ADDR_ENCODE(iter.dma); - iter.dma += PAGE_SIZE; + iter.dma += I915_GTT_PAGE_SIZE; if (iter.dma == iter.max) { iter.sg = __sg_next(iter.sg); if (!iter.sg) @@ -2048,7 +2040,7 @@ { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vma->vm); struct gen6_hw_ppgtt *ppgtt = vma->private; - u32 ggtt_offset = i915_ggtt_offset(vma) / PAGE_SIZE; + u32 ggtt_offset = i915_ggtt_offset(vma) / I915_GTT_PAGE_SIZE; struct i915_page_table *pt; unsigned int pde; @@ -2112,7 +2104,7 @@ vma->ops = &pd_vma_ops; vma->private = ppgtt; - vma->active = RB_ROOT; + vma->active = LINUX_RB_ROOT; vma->size = size; vma->fence_size = size; @@ -2128,6 +2120,7 @@ int gen6_ppgtt_pin(struct i915_hw_ppgtt *base) { struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base); + int err; /* * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt @@ -2143,9 +2136,17 @@ * allocator works in address space sizes, so it's multiplied by page * size. We allocate at the top of the GTT to avoid fragmentation. */ - return i915_vma_pin(ppgtt->vma, + err = i915_vma_pin(ppgtt->vma, 0, GEN6_PD_ALIGN, PIN_GLOBAL | PIN_HIGH); + if (err) + goto unpin; + + return 0; + +unpin: + ppgtt->pin_count = 0; + return err; } void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base) @@ -2174,7 +2175,7 @@ ppgtt->base.vm.i915 = i915; ppgtt->base.vm.dma = &i915->drm.pdev->dev; - ppgtt->base.vm.total = I915_PDES * GEN6_PTES * PAGE_SIZE; + ppgtt->base.vm.total = I915_PDES * GEN6_PTES * I915_GTT_PAGE_SIZE; i915_address_space_init(&ppgtt->base.vm, i915); @@ -2348,7 +2349,7 @@ return IS_GEN5(dev_priv) && IS_MOBILE(dev_priv) && intel_vtd_active(); } -static void gen6_check_and_clear_faults(struct drm_i915_private *dev_priv) +static void gen6_check_faults(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -2358,23 +2359,19 @@ fault = I915_READ(RING_FAULT_REG(engine)); if (fault & RING_FAULT_VALID) { DRM_DEBUG_DRIVER("Unexpected fault\n" - "\tAddr: 0x%08lx\n" + "\tAddr: 0x%08x\n" "\tAddress space: %s\n" "\tSource ID: %d\n" "\tType: %d\n", - fault & PAGE_MASK, + fault & LINUX_PAGE_MASK, fault & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT", RING_FAULT_SRCID(fault), RING_FAULT_FAULT_TYPE(fault)); - I915_WRITE(RING_FAULT_REG(engine), - fault & ~RING_FAULT_VALID); } } - - POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS])); } -static void gen8_check_and_clear_faults(struct drm_i915_private *dev_priv) +static void gen8_check_faults(struct drm_i915_private *dev_priv) { u32 fault = I915_READ(GEN8_RING_FAULT_REG); @@ -2399,22 +2396,20 @@ GEN8_RING_FAULT_ENGINE_ID(fault), RING_FAULT_SRCID(fault), RING_FAULT_FAULT_TYPE(fault)); - I915_WRITE(GEN8_RING_FAULT_REG, - fault & ~RING_FAULT_VALID); } - - POSTING_READ(GEN8_RING_FAULT_REG); } void i915_check_and_clear_faults(struct drm_i915_private *dev_priv) { /* From GEN8 onwards we only have one 'All Engine Fault Register' */ if (INTEL_GEN(dev_priv) >= 8) - gen8_check_and_clear_faults(dev_priv); + gen8_check_faults(dev_priv); else if (INTEL_GEN(dev_priv) >= 6) - gen6_check_and_clear_faults(dev_priv); + gen6_check_faults(dev_priv); else return; + + i915_clear_error_registers(dev_priv); } void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv) @@ -2473,7 +2468,7 @@ { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); gen8_pte_t __iomem *pte = - (gen8_pte_t __iomem *)ggtt->gsm + (offset >> PAGE_SHIFT); + (gen8_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE; gen8_set_pte(pte, gen8_pte_encode(addr, level, 0)); @@ -2497,7 +2492,7 @@ */ gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm; - gtt_entries += vma->node.start >> PAGE_SHIFT; + gtt_entries += vma->node.start / I915_GTT_PAGE_SIZE; for_each_sgt_dma(addr, sgt_iter, vma->pages) gen8_set_pte(gtt_entries++, pte_encode | addr); @@ -2516,7 +2511,7 @@ { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); gen6_pte_t __iomem *pte = - (gen6_pte_t __iomem *)ggtt->gsm + (offset >> PAGE_SHIFT); + (gen6_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE; iowrite32(vm->pte_encode(addr, level, flags), pte); @@ -2536,7 +2531,7 @@ { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); gen6_pte_t __iomem *entries = (gen6_pte_t __iomem *)ggtt->gsm; - unsigned int i = vma->node.start >> PAGE_SHIFT; + unsigned int i = vma->node.start / I915_GTT_PAGE_SIZE; struct sgt_iter iter; dma_addr_t addr; for_each_sgt_dma(addr, iter, vma->pages) @@ -2558,8 +2553,8 @@ u64 start, u64 length) { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); - unsigned first_entry = start >> PAGE_SHIFT; - unsigned num_entries = length >> PAGE_SHIFT; + unsigned first_entry = start / I915_GTT_PAGE_SIZE; + unsigned num_entries = length / I915_GTT_PAGE_SIZE; const gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, 0); gen8_pte_t __iomem *gtt_base = @@ -2674,8 +2669,8 @@ u64 start, u64 length) { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); - unsigned first_entry = start >> PAGE_SHIFT; - unsigned num_entries = length >> PAGE_SHIFT; + unsigned first_entry = start / I915_GTT_PAGE_SIZE; + unsigned num_entries = length / I915_GTT_PAGE_SIZE; gen6_pte_t scratch_pte, __iomem *gtt_base = (gen6_pte_t __iomem *)ggtt->gsm + first_entry; const int max_entries = ggtt_total_entries(ggtt) - first_entry; @@ -2936,6 +2931,16 @@ unsigned long hole_start, hole_end; struct drm_mm_node *entry; int ret; + unsigned long mappable = min(ggtt->vm.total, ggtt->mappable_end); + + /* + * GuC requires all resources that we're sharing with it to be placed in + * non-WOPCM memory. If GuC is not present or not in use we still need a + * small bias as ring wraparound at offset 0 sometimes hangs. No idea + * why. + */ + ggtt->pin_bias = max_t(u32, I915_GTT_PAGE_SIZE, + intel_guc_reserved_gtt_size(&dev_priv->guc)); ret = intel_vgt_balloon(dev_priv); if (ret) @@ -2957,6 +2962,13 @@ hole_end - hole_start); } +#ifdef __DragonFly__ + DRM_INFO("taking over the fictitious range 0x%lx-0x%lx\n", + dev_priv->ggtt.gmadr.start, dev_priv->ggtt.mappable_end); + vm_phys_fictitious_reg_range(dev_priv->ggtt.gmadr.start, + dev_priv->ggtt.gmadr.start + mappable, VM_MEMATTR_WRITE_COMBINING); +#endif + /* And finally clear the reserved guard page */ ggtt->vm.clear_range(&ggtt->vm, ggtt->vm.total - PAGE_SIZE, PAGE_SIZE); @@ -3013,7 +3025,7 @@ arch_phys_wc_del(ggtt->mtrr); io_mapping_fini(&ggtt->iomap); - i915_gem_cleanup_stolen(&dev_priv->drm); + i915_gem_cleanup_stolen(dev_priv); } static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) @@ -3031,7 +3043,7 @@ bdw_gmch_ctl = 1 << bdw_gmch_ctl; #ifdef CONFIG_X86_32 - /* Limit 32b platforms to a 2GB GGTT: 4 << 20 / pte size * PAGE_SIZE */ + /* Limit 32b platforms to a 2GB GGTT: 4 << 20 / pte size * I915_GTT_PAGE_SIZE */ if (bdw_gmch_ctl > 4) bdw_gmch_ctl = 4; #endif @@ -3390,7 +3402,7 @@ /* TODO: We're not aware of mappable constraints on gen8 yet */ ggtt->gmadr = - (struct resource) DEFINE_RES_MEM(pci_resource_start(pdev, 2), + (struct linux_resource) DEFINE_RES_MEM(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); ggtt->mappable_end = resource_size(&ggtt->gmadr); @@ -3406,7 +3418,7 @@ else size = gen8_get_total_gtt_size(snb_gmch_ctl); - ggtt->vm.total = (size / sizeof(gen8_pte_t)) << PAGE_SHIFT; + ggtt->vm.total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE; ggtt->vm.cleanup = gen6_gmch_remove; ggtt->vm.insert_page = gen8_ggtt_insert_page; ggtt->vm.clear_range = nop_clear_range; @@ -3421,6 +3433,11 @@ ggtt->vm.insert_page = bxt_vtd_ggtt_insert_page__BKL; if (ggtt->vm.clear_range != nop_clear_range) ggtt->vm.clear_range = bxt_vtd_ggtt_clear_range__BKL; + + /* Prevent recursively calling stop_machine() and deadlocks. */ + dev_info(dev_priv->drm.dev, + "Disabling error capture for VT-d workaround\n"); + i915_disable_error_state(dev_priv, -ENODEV); } ggtt->invalidate = gen6_ggtt_invalidate; @@ -3444,7 +3461,7 @@ int err; ggtt->gmadr = - (struct resource) DEFINE_RES_MEM(pci_resource_start(pdev, 2), + (struct linux_resource) DEFINE_RES_MEM(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); ggtt->mappable_end = resource_size(&ggtt->gmadr); @@ -3464,7 +3481,7 @@ pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); size = gen6_get_total_gtt_size(snb_gmch_ctl); - ggtt->vm.total = (size / sizeof(gen6_pte_t)) << PAGE_SHIFT; + ggtt->vm.total = (size / sizeof(gen6_pte_t)) * I915_GTT_PAGE_SIZE; ggtt->vm.clear_range = gen6_ggtt_clear_range; ggtt->vm.insert_page = gen6_ggtt_insert_page; @@ -3501,6 +3518,7 @@ { struct drm_i915_private *dev_priv = ggtt->vm.i915; phys_addr_t gmadr_base; +#if 0 int ret; ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->drm.pdev, NULL); @@ -3508,11 +3526,12 @@ DRM_ERROR("failed to set up gmch\n"); return -EIO; } +#endif intel_gtt_get(&ggtt->vm.total, &gmadr_base, &ggtt->mappable_end); ggtt->gmadr = - (struct resource) DEFINE_RES_MEM(gmadr_base, + (struct linux_resource) DEFINE_RES_MEM(gmadr_base, ggtt->mappable_end); ggtt->do_idle_maps = needs_idle_maps(dev_priv); @@ -3612,6 +3631,8 @@ mutex_lock(&dev_priv->drm.struct_mutex); i915_address_space_init(&ggtt->vm, dev_priv); + ggtt->vm.is_ggtt = true; + /* Only VLV supports read-only GGTT mappings */ ggtt->vm.has_read_only = IS_VALLEYVIEW(dev_priv); @@ -3662,6 +3683,10 @@ void i915_ggtt_disable_guc(struct drm_i915_private *i915) { + /* XXX Temporary pardon for error unload */ + if (i915->ggtt.invalidate == gen6_ggtt_invalidate) + return; + /* We should only be called after i915_ggtt_enable_guc() */ GEM_BUG_ON(i915->ggtt.invalidate != guc_ggtt_invalidate); @@ -3729,9 +3754,9 @@ * the entries so the sg list can be happily traversed. * The only thing we need are DMA addresses. */ - sg_set_page(sg, NULL, PAGE_SIZE, 0); + sg_set_page(sg, NULL, I915_GTT_PAGE_SIZE, 0); sg_dma_address(sg) = in[offset + src_idx]; - sg_dma_len(sg) = PAGE_SIZE; + sg_dma_len(sg) = I915_GTT_PAGE_SIZE; sg = sg_next(sg); src_idx -= stride; } @@ -3744,7 +3769,7 @@ intel_rotate_pages(struct intel_rotation_info *rot_info, struct drm_i915_gem_object *obj) { - const unsigned long n_pages = obj->base.size / PAGE_SIZE; + const unsigned long n_pages = obj->base.size / I915_GTT_PAGE_SIZE; unsigned int size = intel_rotation_info_size(rot_info); struct sgt_iter sgt_iter; dma_addr_t dma_addr; @@ -3762,7 +3787,7 @@ return ERR_PTR(ret); /* Allocate target SG list. */ - st = kmalloc(sizeof(*st), GFP_KERNEL); + st = kmalloc(sizeof(*st), M_DRM, GFP_KERNEL); if (!st) goto err_st_alloc; @@ -3810,7 +3835,7 @@ unsigned int offset; int ret = -ENOMEM; - st = kmalloc(sizeof(*st), GFP_KERNEL); + st = kmalloc(sizeof(*st), M_DRM, GFP_KERNEL); if (!st) goto err_st_alloc;