diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-03-20 17:09:12 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-03-23 05:17:03 -0400 |
commit | f6e47884e7f588094bf7b824c839a9ee33f2aa55 (patch) | |
tree | 81e9f8e5b5c14d4ce98f4dfdcdffcd6e14f6463c | |
parent | 26e12f894317bf0221fed40bef6f937538a78c0b (diff) |
drm/i915: Avoid unmapping pages from a NULL address space
Found by gem_stress.
As we perform retirement from a workqueue, it is possible for us to free
and unbind objects after the last close on the device, and so after the
address space has been torn down and reset to NULL:
BUG: unable to handle kernel NULL pointer dereference at 00000054
IP: [<c1295a20>] mutex_lock+0xf/0x27
*pde = 00000000
Oops: 0002 [#1] SMP
last sysfs file: /sys/module/vt/parameters/default_utf8
Pid: 5, comm: kworker/u:0 Not tainted 2.6.38+ #214
EIP: 0060:[<c1295a20>] EFLAGS: 00010206 CPU: 1
EIP is at mutex_lock+0xf/0x27
EAX: 00000054 EBX: 00000054 ECX: 00000000 EDX: 00012fff
ESI: 00000028 EDI: 00000000 EBP: f706fe20 ESP: f706fe18
DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
Process kworker/u:0 (pid: 5, ti=f706e000 task=f7060d00 task.ti=f706e000)
Stack:
f5aa3c60 00000000 f706fe74 c107e7df 00000246 dea55380 00000054 f5aa3c60
f706fe44 00000061 f70b4000 c13fff84 00000008 f706fe54 00000000 00000000
00012f00 00012fff 00000028 c109e575 f6b36700 00100000 00000000 f706fe90
Call Trace:
[<c107e7df>] unmap_mapping_range+0x7d/0x1e6
[<c109e575>] ? mntput_no_expire+0x52/0xb6
[<c11c12f6>] i915_gem_release_mmap+0x49/0x58
[<c11c3449>] i915_gem_object_unbind+0x4c/0x125
[<c11c353f>] i915_gem_free_object_tail+0x1d/0xdb
[<c11c55a2>] i915_gem_free_object+0x3d/0x41
[<c11a6be2>] ? drm_gem_object_free+0x0/0x27
[<c11a6c07>] drm_gem_object_free+0x25/0x27
[<c113c3ca>] kref_put+0x39/0x42
[<c11c0a59>] drm_gem_object_unreference+0x16/0x18
[<c11c0b15>] i915_gem_object_move_to_inactive+0xba/0xbe
[<c11c0c87>] i915_gem_retire_requests_ring+0x16e/0x1a5
[<c11c3645>] i915_gem_retire_requests+0x48/0x63
[<c11c36ac>] i915_gem_retire_work_handler+0x4c/0x117
[<c10385d1>] process_one_work+0x140/0x21b
[<c103734c>] ? __need_more_worker+0x13/0x2a
[<c10373b1>] ? need_to_create_worker+0x1c/0x35
[<c11c3660>] ? i915_gem_retire_work_handler+0x0/0x117
[<c1038faf>] worker_thread+0xd4/0x14b
[<c1038edb>] ? worker_thread+0x0/0x14b
[<c103be1b>] kthread+0x68/0x6d
[<c103bdb3>] ? kthread+0x0/0x6d
[<c12970f6>] kernel_thread_helper+0x6/0x10
Code: 00 e8 98 fe ff ff 5d c3 55 89 e5 3e 8d 74 26 00 ba 01 00 00 00 e8
84 fe ff ff 5d c3 55 89 e5 53 8d 64 24 fc 3e 8d 74 26 00 89 c3 <f0> ff
08 79 05 e8 ab ff ff ff 89 e0 25 00 e0 ff ff 89 43 10 58
EIP: [<c1295a20>] mutex_lock+0xf/0x27 SS:ESP 0068:f706fe18
CR2: 0000000000000054
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Keith Packard <keithp@keithp.com>
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c9bdaf208a91..7ce3f353af33 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1356,9 +1356,10 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj) | |||
1356 | if (!obj->fault_mappable) | 1356 | if (!obj->fault_mappable) |
1357 | return; | 1357 | return; |
1358 | 1358 | ||
1359 | unmap_mapping_range(obj->base.dev->dev_mapping, | 1359 | if (obj->base.dev->dev_mapping) |
1360 | (loff_t)obj->base.map_list.hash.key<<PAGE_SHIFT, | 1360 | unmap_mapping_range(obj->base.dev->dev_mapping, |
1361 | obj->base.size, 1); | 1361 | (loff_t)obj->base.map_list.hash.key<<PAGE_SHIFT, |
1362 | obj->base.size, 1); | ||
1362 | 1363 | ||
1363 | obj->fault_mappable = false; | 1364 | obj->fault_mappable = false; |
1364 | } | 1365 | } |