Since the gem pagefault handler relocks the vm object lock, other

thread might fault on the same GTT offset meantime and instantiate the
mapping.  Recheck that the mgt device object still does not have a
page at the current offset after relocking, and return a possibly
installed page.

Reported by:	Oleg Sidorkin <osidorkin@gmail.com>
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2013-06-18 20:02:52 +00:00
parent 8b73dbd71f
commit aec577b8d1

View File

@ -1371,6 +1371,23 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot,
} else
DRM_LOCK(dev);
/*
* Since the object lock was dropped, other thread might have
* faulted on the same GTT address and instantiated the
* mapping for the page. Recheck.
*/
VM_OBJECT_WLOCK(vm_obj);
m = vm_page_lookup(vm_obj, OFF_TO_IDX(offset));
if (m != NULL) {
if ((m->flags & VPO_BUSY) != 0) {
DRM_UNLOCK(dev);
vm_page_sleep(m, "915pee");
goto retry;
}
goto have_page;
} else
VM_OBJECT_WUNLOCK(vm_obj);
/* Now bind it into the GTT if needed */
if (!obj->map_and_fenceable) {
ret = i915_gem_object_unbind(obj);
@ -1424,8 +1441,9 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot,
goto retry;
}
m->valid = VM_PAGE_BITS_ALL;
*mres = m;
vm_page_insert(m, vm_obj, OFF_TO_IDX(offset));
have_page:
*mres = m;
vm_page_busy(m);
CTR4(KTR_DRM, "fault %p %jx %x phys %x", gem_obj, offset, prot,