Skip to content

Commit 4ca1fd4

Browse files
committed
drm/xe: Fix fault on fd close after unbind
If userspace holds an fd open, unbinds the device and then closes it, the driver shouldn't try to access the hardware. Protect it by using drm_dev_enter()/drm_dev_exit(). This fixes the following page fault: <6> [IGT] xe_wedged: exiting, ret=98 <1> BUG: unable to handle page fault for address: ffffc901bc5e508c <1> #PF: supervisor read access in kernel mode <1> #PF: error_code(0x0000) - not-present page ... <4> xe_lrc_update_timestamp+0x1c/0xd0 [xe] <4> xe_exec_queue_update_run_ticks+0x50/0xb0 [xe] <4> xe_exec_queue_fini+0x16/0xb0 [xe] <4> __guc_exec_queue_fini_async+0xc4/0x190 [xe] <4> guc_exec_queue_fini_async+0xa0/0xe0 [xe] <4> guc_exec_queue_fini+0x23/0x40 [xe] <4> xe_exec_queue_destroy+0xb3/0xf0 [xe] <4> xe_file_close+0xd4/0x1a0 [xe] <4> drm_file_free+0x210/0x280 [drm] <4> drm_close_helper.isra.0+0x6d/0x80 [drm] <4> drm_release_noglobal+0x20/0x90 [drm] Fixes: 83db047 ("drm/xe: Stop accumulating LRC timestamp on job_free") Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/3421 Reviewed-by: Umesh Nerlige Ramappa <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Signed-off-by: Lucas De Marchi <[email protected]>
1 parent 2f12e9c commit 4ca1fd4

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

drivers/gpu/drm/xe/xe_exec_queue.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/nospec.h>
99

1010
#include <drm/drm_device.h>
11+
#include <drm/drm_drv.h>
1112
#include <drm/drm_file.h>
1213
#include <uapi/drm/xe_drm.h>
1314

@@ -768,9 +769,11 @@ bool xe_exec_queue_is_idle(struct xe_exec_queue *q)
768769
*/
769770
void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q)
770771
{
772+
struct xe_device *xe = gt_to_xe(q->gt);
771773
struct xe_file *xef;
772774
struct xe_lrc *lrc;
773775
u32 old_ts, new_ts;
776+
int idx;
774777

775778
/*
776779
* Jobs that are run during driver load may use an exec_queue, but are
@@ -780,6 +783,10 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q)
780783
if (!q->vm || !q->vm->xef)
781784
return;
782785

786+
/* Synchronize with unbind while holding the xe file open */
787+
if (!drm_dev_enter(&xe->drm, &idx))
788+
return;
789+
783790
xef = q->vm->xef;
784791

785792
/*
@@ -793,6 +800,8 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q)
793800
lrc = q->lrc[0];
794801
new_ts = xe_lrc_update_timestamp(lrc, &old_ts);
795802
xef->run_ticks[q->class] += (new_ts - old_ts) * q->width;
803+
804+
drm_dev_exit(idx);
796805
}
797806

798807
/**

0 commit comments

Comments
 (0)