Commit 1934acbe authored by Chris Wilson's avatar Chris Wilson Committed by Greg Kroah-Hartman

drm/i915: Handle ERESTARTSYS during page fault

commit c715089f upstream.

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
[anholt: Mostly squash it with another commit]
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 03429ffa
...@@ -1151,26 +1151,21 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -1151,26 +1151,21 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
if (!obj_priv->gtt_space) { if (!obj_priv->gtt_space) {
ret = i915_gem_object_bind_to_gtt(obj, obj_priv->gtt_alignment); ret = i915_gem_object_bind_to_gtt(obj, obj_priv->gtt_alignment);
if (ret) { if (ret)
mutex_unlock(&dev->struct_mutex); goto unlock;
return VM_FAULT_SIGBUS;
}
list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
ret = i915_gem_object_set_to_gtt_domain(obj, write); ret = i915_gem_object_set_to_gtt_domain(obj, write);
if (ret) { if (ret)
mutex_unlock(&dev->struct_mutex); goto unlock;
return VM_FAULT_SIGBUS;
}
} }
/* Need a new fence register? */ /* Need a new fence register? */
if (obj_priv->tiling_mode != I915_TILING_NONE) { if (obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj); ret = i915_gem_object_get_fence_reg(obj);
if (ret) { if (ret)
mutex_unlock(&dev->struct_mutex); goto unlock;
return VM_FAULT_SIGBUS;
}
} }
pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
...@@ -1178,18 +1173,18 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -1178,18 +1173,18 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
/* Finally, remap it using the new GTT offset */ /* Finally, remap it using the new GTT offset */
ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
unlock:
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
switch (ret) { switch (ret) {
case 0:
case -ERESTARTSYS:
return VM_FAULT_NOPAGE;
case -ENOMEM: case -ENOMEM:
case -EAGAIN: case -EAGAIN:
return VM_FAULT_OOM; return VM_FAULT_OOM;
case -EFAULT:
case -EINVAL:
return VM_FAULT_SIGBUS;
default: default:
return VM_FAULT_NOPAGE; return VM_FAULT_SIGBUS;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment