drm/msm: Crashdump support for sparse

In this case, we need to iterate the VMAs looking for ones with
MSM_VMA_DUMP flag.

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/661504/
This commit is contained in:
Rob Clark
2025-06-29 13:13:10 -07:00
committed by Rob Clark
parent 4570dbb8a6
commit af9aa6f316

View File

@@ -241,9 +241,7 @@ static void msm_gpu_crashstate_get_bo(struct msm_gpu_state *state,
if (!state_bo->data)
goto out;
msm_gem_lock(obj);
ptr = msm_gem_get_vaddr_active(obj);
msm_gem_unlock(obj);
if (IS_ERR(ptr)) {
kvfree(state_bo->data);
state_bo->data = NULL;
@@ -251,12 +249,75 @@ static void msm_gpu_crashstate_get_bo(struct msm_gpu_state *state,
}
memcpy(state_bo->data, ptr + offset, size);
msm_gem_put_vaddr(obj);
msm_gem_put_vaddr_locked(obj);
}
out:
state->nr_bos++;
}
static void crashstate_get_bos(struct msm_gpu_state *state, struct msm_gem_submit *submit)
{
extern bool rd_full;
if (!submit)
return;
if (msm_context_is_vmbind(submit->queue->ctx)) {
struct drm_exec exec;
struct drm_gpuva *vma;
unsigned cnt = 0;
drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
drm_exec_until_all_locked(&exec) {
cnt = 0;
drm_exec_lock_obj(&exec, drm_gpuvm_resv_obj(submit->vm));
drm_exec_retry_on_contention(&exec);
drm_gpuvm_for_each_va (vma, submit->vm) {
if (!vma->gem.obj)
continue;
cnt++;
drm_exec_lock_obj(&exec, vma->gem.obj);
drm_exec_retry_on_contention(&exec);
}
}
drm_gpuvm_for_each_va (vma, submit->vm)
cnt++;
state->bos = kcalloc(cnt, sizeof(struct msm_gpu_state_bo), GFP_KERNEL);
drm_gpuvm_for_each_va (vma, submit->vm) {
bool dump = rd_full || (vma->flags & MSM_VMA_DUMP);
/* Skip MAP_NULL/PRR VMAs: */
if (!vma->gem.obj)
continue;
msm_gpu_crashstate_get_bo(state, vma->gem.obj, vma->va.addr,
dump, vma->gem.offset, vma->va.range);
}
drm_exec_fini(&exec);
} else {
state->bos = kcalloc(submit->nr_bos,
sizeof(struct msm_gpu_state_bo), GFP_KERNEL);
for (int i = 0; state->bos && i < submit->nr_bos; i++) {
struct drm_gem_object *obj = submit->bos[i].obj;;
bool dump = rd_full || (submit->bos[i].flags & MSM_SUBMIT_BO_DUMP);
msm_gem_lock(obj);
msm_gpu_crashstate_get_bo(state, obj, submit->bos[i].iova,
dump, 0, obj->size);
msm_gem_unlock(obj);
}
}
}
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)
@@ -281,30 +342,17 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
if (fault_info)
state->fault_info = *fault_info;
if (submit) {
extern bool rd_full;
int i;
if (submit && state->fault_info.ttbr0) {
struct msm_gpu_fault_info *info = &state->fault_info;
struct msm_mmu *mmu = to_msm_vm(submit->vm)->mmu;
if (state->fault_info.ttbr0) {
struct msm_gpu_fault_info *info = &state->fault_info;
struct msm_mmu *mmu = to_msm_vm(submit->vm)->mmu;
msm_iommu_pagetable_params(mmu, &info->pgtbl_ttbr0,
&info->asid);
msm_iommu_pagetable_walk(mmu, info->iova, info->ptes);
}
state->bos = kcalloc(submit->nr_bos,
sizeof(struct msm_gpu_state_bo), GFP_KERNEL);
for (i = 0; state->bos && i < submit->nr_bos; i++) {
struct drm_gem_object *obj = submit->bos[i].obj;
bool dump = rd_full || (submit->bos[i].flags & MSM_SUBMIT_BO_DUMP);
msm_gpu_crashstate_get_bo(state, obj, submit->bos[i].iova,
dump, 0, obj->size);
}
msm_iommu_pagetable_params(mmu, &info->pgtbl_ttbr0,
&info->asid);
msm_iommu_pagetable_walk(mmu, info->iova, info->ptes);
}
crashstate_get_bos(state, submit);
/* Set the active crash state to be dumped on failure */
gpu->crashstate = state;