Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amdgpu: dump job ibs in the devcoredump

Now that we have a worker thread, we can try to access the
IBs of the job. The process is:
* get the VM from the PASID
* get the BO from its VA and the VM
* map the BO for CPU access
* copy everything, then add it to the dump
Each step can fail so we have to be cautious.
These operations can be slow so when amdgpu_devcoredump_format
is called only to determine the size of the buffer we skip all
of them and assume they will succeed.

---
v3: use kvfree
---

Signed-off-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Pierre-Eric Pelloux-Prayer and committed by
Alex Deucher
7b15fc2d 32ab301b

+92 -1
+92 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
··· 210 210 static ssize_t 211 211 amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_info *coredump) 212 212 { 213 + struct amdgpu_device *adev = coredump->adev; 213 214 struct drm_printer p; 214 215 struct drm_print_iterator iter; 215 216 struct amdgpu_vm_fault_info *fault_info; 217 + struct amdgpu_bo_va_mapping *mapping; 216 218 struct amdgpu_ip_block *ip_block; 219 + struct amdgpu_res_cursor cursor; 220 + struct amdgpu_bo *abo, *root; 221 + uint64_t va_start, offset; 217 222 struct amdgpu_ring *ring; 218 - int ver, i, j; 223 + struct amdgpu_vm *vm; 224 + u32 *ib_content; 225 + uint8_t *kptr; 226 + int ver, i, j, r; 219 227 u32 ring_idx, off; 228 + bool sizing_pass; 220 229 230 + sizing_pass = buffer == NULL; 221 231 iter.data = buffer; 222 232 iter.offset = 0; 223 233 iter.remain = count; ··· 341 331 drm_printf(&p, "VRAM lost check is skipped!\n"); 342 332 else if (coredump->reset_vram_lost) 343 333 drm_printf(&p, "VRAM is lost due to GPU reset!\n"); 334 + 335 + if (coredump->num_ibs) { 336 + /* Don't try to lookup the VM or map the BOs when calculating the 337 + * size required to store the devcoredump. 338 + */ 339 + if (sizing_pass) 340 + vm = NULL; 341 + else 342 + vm = amdgpu_vm_lock_by_pasid(adev, &root, coredump->pasid); 343 + 344 + for (int i = 0; i < coredump->num_ibs && (sizing_pass || vm); i++) { 345 + ib_content = kvmalloc_array(coredump->ibs[i].ib_size_dw, 4, 346 + GFP_KERNEL); 347 + if (!ib_content) 348 + continue; 349 + 350 + /* vm=NULL can only happen when 'sizing_pass' is true. Skip to the 351 + * drm_printf() calls (ib_content doesn't need to be initialized 352 + * as its content won't be written anywhere). 353 + */ 354 + if (!vm) 355 + goto output_ib_content; 356 + 357 + va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK; 358 + mapping = amdgpu_vm_bo_lookup_mapping(vm, va_start / AMDGPU_GPU_PAGE_SIZE); 359 + if (!mapping) 360 + goto free_ib_content; 361 + 362 + offset = va_start - (mapping->start * AMDGPU_GPU_PAGE_SIZE); 363 + abo = amdgpu_bo_ref(mapping->bo_va->base.bo); 364 + r = amdgpu_bo_reserve(abo, false); 365 + if (r) 366 + goto free_ib_content; 367 + 368 + if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) { 369 + off = 0; 370 + 371 + if (abo->tbo.resource->mem_type != TTM_PL_VRAM) 372 + goto unreserve_abo; 373 + 374 + amdgpu_res_first(abo->tbo.resource, offset, 375 + coredump->ibs[i].ib_size_dw * 4, 376 + &cursor); 377 + while (cursor.remaining) { 378 + amdgpu_device_mm_access(adev, cursor.start / 4, 379 + &ib_content[off], cursor.size / 4, 380 + false); 381 + off += cursor.size; 382 + amdgpu_res_next(&cursor, cursor.size); 383 + } 384 + } else { 385 + r = ttm_bo_kmap(&abo->tbo, 0, 386 + PFN_UP(abo->tbo.base.size), 387 + &abo->kmap); 388 + if (r) 389 + goto unreserve_abo; 390 + 391 + kptr = amdgpu_bo_kptr(abo); 392 + kptr += offset; 393 + memcpy(ib_content, kptr, 394 + coredump->ibs[i].ib_size_dw * 4); 395 + 396 + amdgpu_bo_kunmap(abo); 397 + } 398 + 399 + output_ib_content: 400 + drm_printf(&p, "\nIB #%d 0x%llx %d dw\n", 401 + i, coredump->ibs[i].gpu_addr, coredump->ibs[i].ib_size_dw); 402 + for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++) 403 + drm_printf(&p, "0x%08x\n", ib_content[j]); 404 + unreserve_abo: 405 + if (vm) 406 + amdgpu_bo_unreserve(abo); 407 + free_ib_content: 408 + kvfree(ib_content); 409 + } 410 + if (vm) { 411 + amdgpu_bo_unreserve(root); 412 + amdgpu_bo_unref(&root); 413 + } 414 + } 344 415 345 416 return count - iter.remain; 346 417 }