summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-06-03 16:28:42 +1000
committerDave Airlie <airlied@redhat.com>2026-06-03 16:28:43 +1000
commitfe017012c5825f22bd856249e4f3cf57e31027b8 (patch)
tree59f05ec5cc216f7c58c1a3126a5e688c53011fb6 /drivers/gpu
parent61cd9291cab2fe34b6260d092d633f891c32bf9c (diff)
parent6c064db893f548d57036fce17c6493808396e620 (diff)
Merge tag 'drm-intel-gt-next-2026-05-29' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next
Cross-subsystem Changes: - Backmerge of drm-next to pull in a commit to revert Driver Changes: - Avoid skipping already signaled fence after reset (Sebastian) - Fix potential UAF in TTM object purge (Janusz) - Fix refcount underflow in intel_engine_park_heartbeat (Sebastian) - Drop check for changed VM in EXECBUF (Joonas) - Revert the "else vma = NULL" patch for being superseded (Joonas) - Selfest improvements (Janusz, Krzysztof) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patch.msgid.link/ahlc1R5bzJvmBLlZ@jlahtine-mobl
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm.c28
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c16
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_workarounds.c3
-rw-r--r--drivers/gpu/drm/i915/i915_selftest.h1
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_selftest.c74
6 files changed, 101 insertions, 23 deletions
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 05997e8bbb29..1f303d4eaa4d 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -898,8 +898,6 @@ static struct i915_vma *eb_lookup_vma(struct i915_execbuffer *eb, u32 handle)
vma = radix_tree_lookup(&eb->gem_context->handles_vma, handle);
if (likely(vma))
vma = i915_vma_tryget(vma);
- else
- vma = NULL;
rcu_read_unlock();
if (likely(vma))
return vma;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index de70517b4ef2..df3fcc2b1248 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -419,8 +419,6 @@ void i915_ttm_free_cached_io_rsgt(struct drm_i915_gem_object *obj)
int i915_ttm_purge(struct drm_i915_gem_object *obj)
{
struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
- struct i915_ttm_tt *i915_tt =
- container_of(bo->ttm, typeof(*i915_tt), ttm);
struct ttm_operation_ctx ctx = {
.interruptible = true,
.no_wait_gpu = false,
@@ -435,16 +433,22 @@ int i915_ttm_purge(struct drm_i915_gem_object *obj)
if (ret)
return ret;
- if (bo->ttm && i915_tt->filp) {
- /*
- * The below fput(which eventually calls shmem_truncate) might
- * be delayed by worker, so when directly called to purge the
- * pages(like by the shrinker) we should try to be more
- * aggressive and release the pages immediately.
- */
- shmem_truncate_range(file_inode(i915_tt->filp),
- 0, (loff_t)-1);
- fput(fetch_and_zero(&i915_tt->filp));
+ if (bo->ttm) {
+ struct i915_ttm_tt *i915_tt =
+ container_of(bo->ttm, typeof(*i915_tt), ttm);
+
+ if (i915_tt->filp) {
+ /*
+ * The below fput(which eventually calls shmem_truncate)
+ * might be delayed by worker, so when directly called
+ * to purge the pages(like by the shrinker) we should
+ * try to be more aggressive and release the pages
+ * immediately.
+ */
+ shmem_truncate_range(file_inode(i915_tt->filp),
+ 0, (loff_t)-1);
+ fput(fetch_and_zero(&i915_tt->filp));
+ }
}
obj->write_domain = 0;
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 9d454d0b46f2..d01acfb7d93d 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -1847,11 +1847,12 @@ static int igt_mmap_revoke(void *arg)
int i915_gem_mman_live_selftests(struct drm_i915_private *i915)
{
int ret;
- bool unuse_mm = false;
static const struct i915_subtest tests[] = {
SUBTEST(igt_partial_tiling),
SUBTEST(igt_smoke_tiling),
SUBTEST(igt_mmap_offset_exhaustion),
+ };
+ static const struct i915_subtest vma_tests[] = {
SUBTEST(igt_mmap),
SUBTEST(igt_mmap_migrate),
SUBTEST(igt_mmap_access),
@@ -1859,15 +1860,14 @@ int i915_gem_mman_live_selftests(struct drm_i915_private *i915)
SUBTEST(igt_mmap_gpu),
};
- if (!current->mm) {
- kthread_use_mm(current->active_mm);
- unuse_mm = true;
- }
-
ret = i915_live_subtests(tests, i915);
+ if (ret)
+ return ret;
- if (unuse_mm)
- kthread_unuse_mm(current->active_mm);
+ if (current->mm)
+ ret = i915_live_subtests(vma_tests, i915);
+ else
+ pr_warn("No current->mm to safely borrow userspace memory from. Skipping VMA tests.\n");
return ret;
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
index 81cdecd38346..4e4c420ae67f 100644
--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
@@ -1064,6 +1064,9 @@ static int live_isolated_whitelist(void *arg)
enum intel_engine_id id;
int i, err = 0;
+ if (IS_DG2(gt->i915) || IS_METEORLAKE(gt->i915))
+ return 0;
+
/*
* Check that a write into a whitelist register works, but
* invisible to a second context.
diff --git a/drivers/gpu/drm/i915/i915_selftest.h b/drivers/gpu/drm/i915/i915_selftest.h
index 72922028f4ba..e29ca298e7eb 100644
--- a/drivers/gpu/drm/i915/i915_selftest.h
+++ b/drivers/gpu/drm/i915/i915_selftest.h
@@ -35,6 +35,7 @@ struct i915_selftest {
unsigned long timeout_jiffies;
unsigned int timeout_ms;
unsigned int random_seed;
+ unsigned int userspace_pid;
char *filter;
int mock;
int live;
diff --git a/drivers/gpu/drm/i915/selftests/i915_selftest.c b/drivers/gpu/drm/i915/selftests/i915_selftest.c
index 8460f0a70d04..3adcfdab75ae 100644
--- a/drivers/gpu/drm/i915/selftests/i915_selftest.c
+++ b/drivers/gpu/drm/i915/selftests/i915_selftest.c
@@ -181,13 +181,56 @@ __wait_gsc_huc_load_completed(struct drm_i915_private *i915)
pr_warn(DRIVER_NAME "Timed out waiting for huc load via GSC!\n");
}
+static struct mm_struct *get_selftest_mm(int u_pid_nr)
+{
+ struct task_struct *task = NULL;
+ struct mm_struct *mm = NULL;
+ struct pid *u_pid = NULL;
+
+ if (u_pid_nr < 1)
+ return NULL;
+
+ u_pid = find_get_pid(u_pid_nr);
+ if (!u_pid) {
+ pr_warn("Could not find PID: %d\n", u_pid_nr);
+ return NULL;
+ }
+
+ task = get_pid_task(u_pid, PIDTYPE_PID);
+ put_pid(u_pid);
+ if (!task) {
+ pr_warn("Could not find task for PID: %d\n", u_pid_nr);
+ return NULL;
+ }
+
+ if (task->flags & PF_KTHREAD) {
+ pr_warn("Task not in userspace: %d\n", u_pid_nr);
+ put_task_struct(task);
+ return NULL;
+ }
+
+ mm = get_task_mm(task);
+ put_task_struct(task);
+ if (!mm) {
+ pr_warn("Could not find address space of task with PID: %d\n", u_pid_nr);
+ return NULL;
+ }
+
+ return mm;
+}
+
static int __run_selftests(const char *name,
struct selftest *st,
unsigned int count,
void *data)
{
+ struct mm_struct *mm = NULL;
+ int u_pid_nr = -1;
int err = 0;
+ if (i915_selftest.userspace_pid)
+ u_pid_nr = i915_selftest.userspace_pid;
+
while (!i915_selftest.random_seed)
i915_selftest.random_seed = get_random_u32();
@@ -201,14 +244,36 @@ static int __run_selftests(const char *name,
pr_info(DRIVER_NAME ": Performing %s selftests with st_random_seed=0x%x st_timeout=%u\n",
name, i915_selftest.random_seed, i915_selftest.timeout_ms);
+ /*
+ * If we are running in a kthread on a multi NUMA system and the user passed
+ * a valid PID of a userspace task, then we may borrow its address space
+ * to prepare a safe environment for the mmap selftests.
+ */
+ if (!current->mm && u_pid_nr > 0) {
+ mm = get_selftest_mm(u_pid_nr);
+ if (mm) {
+ kthread_use_mm(mm);
+ if (unlikely(!current->mm)) {
+ mmput(mm);
+ mm = NULL;
+ pr_warn("Could not set mm as current->mm\n");
+ }
+ }
+ }
+
/* Tests are listed in order in i915_*_selftests.h */
for (; count--; st++) {
if (!st->enabled)
continue;
cond_resched();
- if (signal_pending(current))
+ if (signal_pending(current)) {
+ if (mm) {
+ kthread_unuse_mm(mm);
+ mmput_async(mm);
+ }
return -EINTR;
+ }
pr_info(DRIVER_NAME ": Running %s\n", st->name);
if (data)
@@ -226,6 +291,11 @@ static int __run_selftests(const char *name,
st->name, err))
err = -1;
+ if (mm) {
+ kthread_unuse_mm(mm);
+ mmput_async(mm);
+ }
+
return err;
}
@@ -507,6 +577,8 @@ void igt_hexdump(const void *buf, size_t len)
module_param_named(st_random_seed, i915_selftest.random_seed, uint, 0400);
module_param_named(st_timeout, i915_selftest.timeout_ms, uint, 0400);
module_param_named(st_filter, i915_selftest.filter, charp, 0400);
+module_param_named(st_userspace_pid, i915_selftest.userspace_pid, uint, 0400);
+MODULE_PARM_DESC(st_userspace_pid, "For usage in tests that map userspace memory and require address space with controllable lifetime.");
module_param_named_unsafe(mock_selftests, i915_selftest.mock, int, 0400);
MODULE_PARM_DESC(mock_selftests, "Run selftests before loading, using mock hardware (0:disabled [default], 1:run tests then load driver, -1:run tests then leave dummy module)");