diff --git a/sys/dev/drm/i915/i915_vma.c b/sys/dev/drm/i915/i915_vma.c index 1111111..2222222 100644 --- a/sys/dev/drm/i915/i915_vma.c +++ b/sys/dev/drm/i915/i915_vma.c @@ -25,6 +25,9 @@ #include "i915_drv.h" #include "intel_ringbuffer.h" #include "intel_frontbuffer.h" +#ifdef __DragonFly__ +#include /* pmap_page_protect, vm_phys_fictitious_to_vm_page */ +#endif #include @@ -854,46 +857,42 @@ static void __i915_vma_iounmap(struct i915_vma *vma) vma->iomap = NULL; } #ifdef __DragonFly__ /* - * XXX: this is a bit of a hammer approach - * On DragonFly, we invalidate the entire set of gem object pages - * and not just the ones belonging to a particular VMA + * Revoke user CPU mappings of this VMA's GGTT aperture window. + * + * OBJT_MGTDEVICE pages are never inserted into the device vm_object + * (i915_gem_fault() hands fictitious aperture pages straight to the + * pmap), so vm_object_page_remove()/vm_page_lookup() on the object + * cannot see them and the previous implementation removed nothing: + * user PTEs into the aperture survived VMA unbind and kept pointing + * into whatever object later reused the aperture range. + * + * The correct zap is at the pmap level: the fictitious pages covering + * [gmadr + node.start, gmadr + node.start + node.size) are exactly the + * physical pages those PTEs map, and pmap_page_protect(VM_PROT_NONE) + * removes every PV entry for them (the same idiom cdev_pager_free_page() + * uses in sys/vm/device_pager.c). */ -static inline void drm_vma_node_unmap(struct drm_vma_offset_node *node, - struct address_space *file_mapping) +static void drm_vma_node_unmap(struct i915_vma *vma) { - struct drm_i915_gem_object *obj = container_of( - node,struct drm_i915_gem_object, base.vma_node); - vm_object_t devobj; + struct i915_ggtt *ggtt = i915_vm_to_ggtt(vma->vm); vm_page_t m; - int i, page_count; + u64 start, len, off; - devobj = cdev_pager_lookup(obj); - if (devobj != NULL) { - page_count = OFF_TO_IDX(obj->base.size); + if (!drm_mm_node_allocated(&vma->node)) + return; - VM_OBJECT_LOCK(devobj); - vm_object_page_remove(devobj, 0, 0, false); -#if 1 - for (i = 0; i < page_count; i++) { - m = vm_page_lookup_busy_wait(devobj, i, TRUE, "915unm"); - if (m == NULL) - continue; - cdev_pager_free_page(devobj, m); - } -#endif - VM_OBJECT_UNLOCK(devobj); - vm_object_deallocate(devobj); + start = vma->node.start; + if (start >= ggtt->mappable_end) + return; + len = min(vma->node.size, ggtt->mappable_end - start); + + for (off = 0; off < len; off += PAGE_SIZE) { + m = vm_phys_fictitious_to_vm_page(ggtt->gmadr.start + + start + off); + if (m == NULL) + continue; + pmap_page_protect(m, VM_PROT_NONE); } } #endif void i915_vma_revoke_mmap(struct i915_vma *vma) { - struct drm_vma_offset_node *node = &vma->obj->base.vma_node; - u64 vma_offset; - lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); if (!i915_vma_has_userfault(vma)) @@ -902,16 +901,7 @@ void i915_vma_revoke_mmap(struct i915_vma *vma) GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma)); GEM_BUG_ON(!vma->obj->userfault_count); - vma_offset = vma->ggtt_view.partial.offset << PAGE_SHIFT; #ifdef __DragonFly__ - drm_vma_node_unmap(node, NULL); -#else - unmap_mapping_range(vma->vm->i915->drm.anon_inode->i_mapping, - drm_vma_node_offset_addr(node) + vma_offset, - vma->size, - 1); + drm_vma_node_unmap(vma); #endif i915_vma_unset_userfault(vma);