summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/msm_gpu.c
diff options
context:
space:
mode:
authorRob Clark <robdclark@chromium.org>2025-06-29 13:13:19 -0700
committerRob Clark <robin.clark@oss.qualcomm.com>2025-07-04 17:48:38 -0700
commit9edc52967cc7fcd430749cdd8866aa68f25422bf (patch)
tree16bef168717a46a1cd3366404d435cd18ea4c6e5 /drivers/gpu/drm/msm/msm_gpu.c
parent2e6a8a1fe2b262a6dfd0a65041fcd830ee1e7143 (diff)
drm/msm: Add VM logging for VM_BIND updates
When userspace opts in to VM_BIND, the submit no longer holds references keeping the VMA alive. This makes it difficult to distinguish between UMD/KMD/app bugs. So add a debug option for logging the most recent VM updates and capturing these in GPU devcoredumps. The submitqueue id is also captured, a value of zero means the operation did not go via a submitqueue (ie. comes from msm_gem_vm_close() tearing down the remaining mappings when the device file is closed. Signed-off-by: Rob Clark <robdclark@chromium.org> Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com> Tested-by: Antonino Maniscalco <antomani103@gmail.com> Reviewed-by: Antonino Maniscalco <antomani103@gmail.com> Patchwork: https://patchwork.freedesktop.org/patch/661518/
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gpu.c')
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index ccd9ebfc5c7c..c317b25a8162 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -259,9 +259,6 @@ static void crashstate_get_bos(struct msm_gpu_state *state, struct msm_gem_submi
{
extern bool rd_full;
- if (!submit)
- return;
-
if (msm_context_is_vmbind(submit->queue->ctx)) {
struct drm_exec exec;
struct drm_gpuva *vma;
@@ -318,6 +315,48 @@ static void crashstate_get_bos(struct msm_gpu_state *state, struct msm_gem_submi
}
}
+static void crashstate_get_vm_logs(struct msm_gpu_state *state, struct msm_gem_vm *vm)
+{
+ uint32_t vm_log_len = (1 << vm->log_shift);
+ uint32_t vm_log_mask = vm_log_len - 1;
+ int first;
+
+ /* Bail if no log, or empty log: */
+ if (!vm->log || !vm->log[0].op)
+ return;
+
+ mutex_lock(&vm->mmu_lock);
+
+ /*
+ * log_idx is the next entry to overwrite, meaning it is the oldest, or
+ * first, entry (other than the special case handled below where the
+ * log hasn't wrapped around yet)
+ */
+ first = vm->log_idx;
+
+ if (!vm->log[first].op) {
+ /*
+ * If the next log entry has not been written yet, then only
+ * entries 0 to idx-1 are valid (ie. we haven't wrapped around
+ * yet)
+ */
+ state->nr_vm_logs = MAX(0, first - 1);
+ first = 0;
+ } else {
+ state->nr_vm_logs = vm_log_len;
+ }
+
+ state->vm_logs = kmalloc_array(
+ state->nr_vm_logs, sizeof(vm->log[0]), GFP_KERNEL);
+ for (int i = 0; i < state->nr_vm_logs; i++) {
+ int idx = (i + first) & vm_log_mask;
+
+ state->vm_logs[i] = vm->log[idx];
+ }
+
+ mutex_unlock(&vm->mmu_lock);
+}
+
static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
struct msm_gem_submit *submit, struct msm_gpu_fault_info *fault_info,
char *comm, char *cmd)
@@ -351,7 +390,10 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
msm_iommu_pagetable_walk(mmu, info->iova, info->ptes);
}
- crashstate_get_bos(state, submit);
+ if (submit) {
+ crashstate_get_vm_logs(state, to_msm_vm(submit->vm));
+ crashstate_get_bos(state, submit);
+ }
/* Set the active crash state to be dumped on failure */
gpu->crashstate = state;
@@ -452,7 +494,7 @@ static void recover_worker(struct kthread_work *work)
* VM_BIND)
*/
if (!vm->managed)
- vm->unusable = true;
+ msm_gem_vm_unusable(submit->vm);
}
get_comm_cmdline(submit, &comm, &cmd);