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>,
Anna Maniscalco <anna.maniscalco2000@gmail.com>,
Julius Bairaktaris <julius@bairaktaris.de>,
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 v3 1/3] drm/msm: Release the pins and ops of a killed VM_BIND job
Date: Sat, 14 Nov 2026 23:18:49 +0900 [thread overview]
Message-ID: <20261114141851.134290-2-arpe1618@gmail.com> (raw)
In-Reply-To: <20261114141851.134290-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. When the
entity of a job is killed, e.g. on SIGKILL while the process exits, the
scheduler frees the job without running it. msm_vma_job_free() then
frees the queued ops without applying them and without dropping their
references, and leaves the 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.
The scheduler only frees a killed job once its dependencies have
signalled and the job queued before it on the same entity has run or
been killed, so the updates of the jobs that ran before it have all been
applied by then. 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. Killed jobs can be freed
concurrently, but as they only unmap, their order does not matter. 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,
taking the object lock, as the job's fence does not keep them busy
anymore.
msm_ioctl_vm_bind() frees a job that fails right away, before its
dependencies and the previous jobs of its queue have completed, so the
queued updates of such a job must not be applied. Move the freeing
itself into vm_bind_job_free(), and call that directly from there.
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.
Julius Bairaktaris' "drm/msm: Keep objects of queued VM_BIND unmaps
busy" keeps the objects of queued unmaps busy with the job's fence:
https://lore.kernel.org/r/20261111080619.244138-1-julius@bairaktaris.de
For a killed job, the scheduler signals that fence before it calls
free_job(), so with both patches, these objects are no longer busy for
the short time until this patch applies the unmaps. Without this patch,
the unmaps of a killed job are never applied. Closing that window would
need the objects to stay pinned until their unmaps are applied. The two
patches apply in either order.
Not addressed here, as before this patch:
- The error path of msm_ioctl_vm_bind() still frees the queued ops of a
failed job without applying them or dropping their references. Their
unmaps could only be applied after the job's dependencies and the
previous jobs of its queue, i.e. by queuing the job anyway.
- The issues in the error handling of vm_bind_job_prepare() that
Sashiko listed for v2: a VMA left in the VM when vm_op_enqueue()
fails, which a later remap of a MAP_NULL area turns into a NULL
dereference, and the vm_bo reference in msm_gem_vm_sm_step_remap().
drivers/gpu/drm/msm/msm_gem_vma.c | 87 ++++++++++++++++++++++++++-----
1 file changed, 75 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
index 8b702422030a..0b9f2e8916b7 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,16 +769,22 @@ 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: */
return NULL;
}
+/*
+ * Free a job, whether it ran or not. Ops that are still queued are freed
+ * without being applied, and without dropping their object references, as
+ * the pages of their unmaps may still be mapped.
+ */
static void
-msm_vma_job_free(struct drm_sched_job *_job)
+vm_bind_job_free(struct msm_vm_bind_job *job)
{
- struct msm_vm_bind_job *job = to_msm_vm_bind_job(_job);
struct msm_gem_vm *vm = to_msm_vm(job->vm);
struct drm_gem_object *obj;
@@ -770,7 +792,20 @@ msm_vma_job_free(struct drm_sched_job *_job)
atomic_sub(job->prealloc.count, &vm->prealloc_throttle.in_flight);
- drm_sched_job_cleanup(_job);
+ drm_sched_job_cleanup(&job->base);
+
+ /*
+ * 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);
@@ -791,6 +826,29 @@ msm_vma_job_free(struct drm_sched_job *_job)
kfree(job);
}
+static void
+msm_vma_job_free(struct drm_sched_job *_job)
+{
+ struct msm_vm_bind_job *job = to_msm_vm_bind_job(_job);
+
+ /*
+ * A job that the scheduler frees without having run it was killed,
+ * e.g. because its entity was destroyed. Its queued updates were
+ * already applied to the VM's address space, but not to its pgtables.
+ * The scheduler has waited for the job's dependencies, and for the job
+ * before it on the entity to run or be killed, so apply its unmaps now,
+ * before the references to the unmapped objects are dropped, and give
+ * up on the VM, as its maps are skipped. Killed jobs only unmap, so
+ * the order in which they are freed does not matter.
+ */
+ if (!list_empty(&job->vm_ops)) {
+ vm_bind_job_apply_ops(job, -ECANCELED);
+ msm_gem_vm_unusable(job->vm);
+ }
+
+ vm_bind_job_free(job);
+}
+
static const struct drm_sched_backend_ops msm_vm_bind_ops = {
.run_job = msm_vma_job_run,
.free_job = msm_vma_job_free
@@ -1607,8 +1665,13 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file)
}
if (!IS_ERR_OR_NULL(job)) {
+ /*
+ * Not msm_vma_job_free(): the job's dependencies and the
+ * previous jobs of the queue may not have completed, so its
+ * queued updates must not be applied here.
+ */
if (ret)
- msm_vma_job_free(&job->base);
+ vm_bind_job_free(job);
} else {
/*
* If the submit hasn't yet taken ownership of the queue
--
2.43.0
next prev parent reply other threads:[~2026-11-14 14:19 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-14 14:18 [PATCH v3 0/3] drm/msm: Fix VM_BIND job, queue and entity lifetimes Jiwoo Kim
2026-11-14 14:18 ` Jiwoo Kim [this message]
2026-11-14 14:18 ` [PATCH v3 2/3] drm/msm: Destroy the VM_BIND entity when its queue is closed Jiwoo Kim
2026-11-14 14:18 ` [PATCH v3 3/3] drm/msm: Put the VM_BIND queue last when freeing a VM_BIND job 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=20261114141851.134290-2-arpe1618@gmail.com \
--to=arpe1618@gmail.com \
--cc=abhinav.kumar@linux.dev \
--cc=airlied@gmail.com \
--cc=akhilpo@oss.qualcomm.com \
--cc=anna.maniscalco2000@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=freedreno@lists.freedesktop.org \
--cc=jesszhan0024@gmail.com \
--cc=julius@bairaktaris.de \
--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®