Skip to content

Commit

Permalink
drm/i915: Handle ERESTARTSYS during page fault
Browse files Browse the repository at this point in the history
During a page fault and rebinding the buffer there exists a window for a
signal to arrive during the i915_wait_request() and trigger a
ERESTARTSYS. This used to be handled by returning SIGBUS and thereby
killing the application. Try 'cairo-perf-trace & cairo-test-suite' and
watch X go boom!

The solution as suggested by H. Peter Anvin is to simply return NOPAGE and
leave the higher layers to spot we did not fill the page and resubmit
the page fault.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: stable@kernel.org
[anholt: Mostly squash it with another commit]
  • Loading branch information
Chris Wilson authored and Eric Anholt committed Sep 23, 2009
1 parent ab18282 commit c715089
Showing 1 changed file with 12 additions and 17 deletions.
29 changes: 12 additions & 17 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1200,45 +1200,40 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
mutex_lock(&dev->struct_mutex);
if (!obj_priv->gtt_space) {
ret = i915_gem_object_bind_to_gtt(obj, 0);
if (ret) {
mutex_unlock(&dev->struct_mutex);
return VM_FAULT_SIGBUS;
}
if (ret)
goto unlock;

list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);

ret = i915_gem_object_set_to_gtt_domain(obj, write);
if (ret) {
mutex_unlock(&dev->struct_mutex);
return VM_FAULT_SIGBUS;
}
if (ret)
goto unlock;
}

/* Need a new fence register? */
if (obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj);
if (ret) {
mutex_unlock(&dev->struct_mutex);
return VM_FAULT_SIGBUS;
}
if (ret)
goto unlock;
}

pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
page_offset;

/* Finally, remap it using the new GTT offset */
ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);

unlock:
mutex_unlock(&dev->struct_mutex);

switch (ret) {
case 0:
case -ERESTARTSYS:
return VM_FAULT_NOPAGE;
case -ENOMEM:
case -EAGAIN:
return VM_FAULT_OOM;
case -EFAULT:
case -EINVAL:
return VM_FAULT_SIGBUS;
default:
return VM_FAULT_NOPAGE;
return VM_FAULT_SIGBUS;
}
}

Expand Down

0 comments on commit c715089

Please sign in to comment.