--- a/sys/dev/drm/ttm/ttm_bo_vm.c +++ b/sys/dev/drm/ttm/ttm_bo_vm.c @@ -826,6 +826,15 @@ if (vm_obj == NULL) return; + /* + * DF-4587: cdev_pager_lookup() does NOT take a reference. The + * pager object's only references are the per-mmap references owned + * by the user's vm_map entries, so hold the object across the + * revocation to keep a concurrent last-unmap from terminating it + * while we operate on it. + */ + vm_object_hold(vm_obj); + VM_OBJECT_LOCK(vm_obj); #if 1 vm_object_page_remove(vm_obj, 0, 0, false); @@ -847,8 +856,18 @@ } #endif VM_OBJECT_UNLOCK(vm_obj); + vm_object_drop(vm_obj); - vm_object_deallocate(vm_obj); + /* + * DF-4587: DO NOT vm_object_deallocate() here. This function runs + * on every BO revocation (ttm_bo_handle_move_mem, ttm_bo_swapout, + * radeon_pm), and we hold no reference: each call would drop a + * reference owned by a live mapping, terminate the object while + * mappings are still attached (freed vm_object under live map + * entries) and fire ttm_bo_vm_dtor -> premature ttm_bo_unref(). + * The object must die when its last mapping goes away; the dtor + * then releases the mmap's BO reference. + */ } #endif