⬢ DragonFlyBSD Kernel Audit
DF-3768 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/i915/i915_gem_gtt.c b/sys/dev/drm/i915/i915_gem_gtt.c
--- a/sys/dev/drm/i915/i915_gem_gtt.c
+++ b/sys/dev/drm/i915/i915_gem_gtt.c
@@ -2962,6 +2962,13 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv)
 	}
 
 #ifdef __DragonFly__
+	/*
+	 * Remember the fictitious range we register below so that
+	 * i915_ggtt_cleanup_hw() can hand it back (mirrors the radeon
+	 * lifecycle, radeon_device.c:1493/1566).  Without this, every
+	 * driver re-attach leaks the fake vm_page array and burns one of
+	 * the 8 global slots in drm_vm.c, until attach fails with EBUSY.
+	 */
+	dev_priv->ggtt.fictitious_registered = true;
 	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,
@@ -3013,6 +3020,15 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv)
 	arch_phys_wc_del(ggtt->mtrr);
 	io_mapping_fini(&ggtt->iomap);
 
+#ifdef __DragonFly__
+	/*
+	 * All GGTT vmas have been unbound and the iomap is gone: hand the
+	 * aperture's fictitious range back so a later re-attach (module
+	 * reload or re-probe) gets a clean table and no leak.
+	 */
+	if (ggtt->fictitious_registered)
+		vm_phys_fictitious_unreg_range(ggtt->gmadr.start,
+		    ggtt->gmadr.start +
+		    min(ggtt->vm.total, ggtt->mappable_end));
+#endif
 	i915_gem_cleanup_stolen(dev_priv);
 }
diff --git a/sys/dev/drm/i915/i915_gem_gtt.h b/sys/dev/drm/i915/i915_gem_gtt.h
--- a/sys/dev/drm/i915/i915_gem_gtt.h
+++ b/sys/dev/drm/i915/i915_gem_gtt.h
@@ -398,6 +398,10 @@ struct i915_ggtt {
 
 	bool do_idle_maps;
 
+#ifdef __DragonFly__
+	bool fictitious_registered;
+#endif
+
 	int mtrr;
 
 	u32 pin_bias;