From: Jiwoo Kim <arpe1618@gmail.com>
To: Rob Clark <robin.clark@oss.qualcomm.com>,
Dmitry Baryshkov <lumag@kernel.org>
Cc: Akhil P Oommen <akhilpo@oss.qualcomm.com>,
Konrad Dybcio <konradybcio@kernel.org>,
Antonino Maniscalco <antomani103@gmail.com>,
Abhinav Kumar <abhinav.kumar@linux.dev>,
Jessica Zhang <jesszhan0024@gmail.com>,
Sean Paul <sean@poorly.run>,
Marijn Suijten <marijn.suijten@somainline.org>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org,
freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: [PATCH v2 1/3] drm/msm: Release the pins and ops of a VM_BIND job that never ran
Date: Sat, 14 Nov 2026 17:19:00 +0900 [thread overview]
Message-ID: <20261114081902.1669-2-arpe1618@gmail.com> (raw)
In-Reply-To: <20261114081902.1669-1-arpe1618@gmail.com>
msm_vma_job_run() applies the pgtable updates that vm_bind_job_prepare()
queued for a VM_BIND job, drops the GEM object references that
vm_op_enqueue() took for them, and unpins the BOs of the job. A job can
also be freed without having run: when its entity is killed, e.g. on
SIGKILL while the process exits, and when msm_ioctl_vm_bind() fails
part-way through vm_bind_job_prepare() or after it. msm_vma_job_free()
then frees the queued ops without applying them and without dropping
their references, and a killed job also keeps its BOs pinned. Besides
the leaks, the VM no longer matches its pgtables: for example, the
pages of a VMA that was unmapped from the VM are still mapped.
In msm_vma_job_free(), apply the queued updates the way
msm_vma_job_run() does on error: skip the maps, but apply the unmaps,
so that their references can be dropped without freeing pages that are
still mapped, and mark the VM unusable. Move that part of
msm_vma_job_run() into a helper for this. Also clear bos_pinned once
msm_vma_job_run() has unpinned the BOs, as msm_job_run() does for
submits, and unpin the BOs of a job that still has them pinned. The
job's fence does not keep them busy anymore at that point, so take the
object lock to unpin them.
This also marks the VM unusable when msm_ioctl_vm_bind() fails after
vm_bind_job_prepare() has queued updates, i.e. when the first op fails
part-way or when sync_file_create() fails. The VM is then left
partially updated, as when a later op fails.
The patch and its changelog were drafted with an AI coding assistant.
The issue has not been reproduced, and the change has only been
compile-tested.
Fixes: 2e6a8a1fe2b2 ("drm/msm: Add VM_BIND ioctl")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/r/sashiko-outbox-214234@kernel.org
Signed-off-by: Jiwoo Kim <arpe1618@gmail.com>
---
At commit 2e6a8a1fe2b2, msm_vma_job_run() still unpinned the BOs under
the object lock, and msm_gem_vm_unusable() did not exist yet, so older
stable trees need an adapted backport.
drivers/gpu/drm/msm/msm_gem_vma.c | 65 +++++++++++++++++++++++--------
1 file changed, 49 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
index 8b702422030a..a6f106d0cdef 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -700,16 +700,16 @@ static const struct drm_gpuvm_ops msm_gpuvm_ops = {
.sm_step_unmap = msm_gem_vm_sm_step_unmap,
};
-static struct dma_fence *
-msm_vma_job_run(struct drm_sched_job *_job)
+/*
+ * Apply the pgtable updates queued for a job, and drop the references that
+ * the ops hold. If ret is an error, or one occurs, the remaining maps are
+ * skipped, but the unmaps are still applied, as the pages they unmap must
+ * not be freed while they are still mapped.
+ */
+static int
+vm_bind_job_apply_ops(struct msm_vm_bind_job *job, int ret)
{
- struct msm_vm_bind_job *job = to_msm_vm_bind_job(_job);
- struct drm_device *dev = job->vm->drm;
struct msm_gem_vm *vm = to_msm_vm(job->vm);
- struct drm_gem_object *obj;
- int ret = vm->unusable ? -EINVAL : 0;
-
- vm_dbg("");
mutex_lock(&vm->mmu_lock);
vm->mmu->prealloc = &job->prealloc;
@@ -740,6 +740,22 @@ msm_vma_job_run(struct drm_sched_job *_job)
vm->mmu->prealloc = NULL;
mutex_unlock(&vm->mmu_lock);
+ return ret;
+}
+
+static struct dma_fence *
+msm_vma_job_run(struct drm_sched_job *_job)
+{
+ struct msm_vm_bind_job *job = to_msm_vm_bind_job(_job);
+ struct drm_device *dev = job->vm->drm;
+ struct msm_gem_vm *vm = to_msm_vm(job->vm);
+ struct drm_gem_object *obj;
+ int ret;
+
+ vm_dbg("");
+
+ ret = vm_bind_job_apply_ops(job, vm->unusable ? -EINVAL : 0);
+
/*
* We failed to perform at least _some_ of the pgtable updates, so
* now the VM is in an undefined state. Game over!
@@ -753,6 +769,8 @@ msm_vma_job_run(struct drm_sched_job *_job)
msm_gem_unpin_active(obj);
}
+ job->bos_pinned = false;
+
mutex_unlock(&dev->gem_lru_mutex);
/* VM_BIND ops are synchronous, so no fence to wait on: */
@@ -766,26 +784,41 @@ msm_vma_job_free(struct drm_sched_job *_job)
struct msm_gem_vm *vm = to_msm_vm(job->vm);
struct drm_gem_object *obj;
+ /*
+ * In error paths, and if the job was killed before it ran, we could
+ * have unexecuted ops. Their changes were already made to the VM, so
+ * apply the unmaps, and give up on the VM.
+ */
+ if (!list_empty(&job->vm_ops)) {
+ vm_bind_job_apply_ops(job, -ECANCELED);
+ msm_gem_vm_unusable(job->vm);
+ }
+
vm->mmu->funcs->prealloc_cleanup(vm->mmu, &job->prealloc);
atomic_sub(job->prealloc.count, &vm->prealloc_throttle.in_flight);
drm_sched_job_cleanup(_job);
+ /*
+ * A job that was killed before it ran still has its BOs pinned. The
+ * job's fence does not keep them busy anymore, so take the object lock
+ * to unpin them.
+ */
+ if (job->bos_pinned) {
+ job_foreach_bo(obj, job) {
+ msm_gem_lock(obj);
+ msm_gem_unpin_locked(obj);
+ msm_gem_unlock(obj);
+ }
+ }
+
job_foreach_bo (obj, job)
drm_gem_object_put(obj);
msm_submitqueue_put(job->queue);
dma_fence_put(job->fence);
- /* In error paths, we could have unexecuted ops: */
- while (!list_empty(&job->vm_ops)) {
- struct msm_vm_op *op =
- list_first_entry(&job->vm_ops, struct msm_vm_op, node);
- list_del(&op->node);
- kfree(op);
- }
-
wake_up(&vm->prealloc_throttle.wait);
kfree(job);
--
2.43.0
next prev parent reply other threads:[~2026-11-14 8:19 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-14 8:18 [PATCH v2 0/3] drm/msm: Fix VM_BIND job, queue and entity lifetimes Jiwoo Kim
2026-11-14 8:19 ` Jiwoo Kim [this message]
2026-11-14 8:19 ` [PATCH v2 2/3] drm/msm: Destroy the VM_BIND entity when its queue is closed Jiwoo Kim
2026-11-14 8:19 ` [PATCH v2 3/3] drm/msm: Put the VM_BIND queue last in msm_vma_job_free() Jiwoo Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261114081902.1669-2-arpe1618@gmail.com \
--to=arpe1618@gmail.com \
--cc=abhinav.kumar@linux.dev \
--cc=airlied@gmail.com \
--cc=akhilpo@oss.qualcomm.com \
--cc=antomani103@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=freedreno@lists.freedesktop.org \
--cc=jesszhan0024@gmail.com \
--cc=konradybcio@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lumag@kernel.org \
--cc=marijn.suijten@somainline.org \
--cc=robin.clark@oss.qualcomm.com \
--cc=sean@poorly.run \
--cc=simona@ffwll.ch \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®