@@ -210,12 +210,24 @@ static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
210210static ssize_t
211211amdgpu_devcoredump_format (char * buffer , size_t count , struct amdgpu_coredump_info * coredump )
212212{
213+ struct amdgpu_device * adev = coredump -> adev ;
213214 struct drm_printer p ;
214215 struct drm_print_iterator iter ;
215216 struct amdgpu_vm_fault_info * fault_info ;
217+ struct amdgpu_bo_va_mapping * mapping ;
216218 struct amdgpu_ip_block * ip_block ;
217- int ver ;
218-
219+ struct amdgpu_res_cursor cursor ;
220+ struct amdgpu_bo * abo , * root ;
221+ uint64_t va_start , offset ;
222+ struct amdgpu_ring * ring ;
223+ struct amdgpu_vm * vm ;
224+ u32 * ib_content ;
225+ uint8_t * kptr ;
226+ int ver , i , j , r ;
227+ u32 ring_idx , off ;
228+ bool sizing_pass ;
229+
230+ sizing_pass = buffer == NULL ;
219231 iter .data = buffer ;
220232 iter .offset = 0 ;
221233 iter .remain = count ;
@@ -303,23 +315,25 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
303315
304316 /* Add ring buffer information */
305317 drm_printf (& p , "Ring buffer information\n" );
306- for (int i = 0 ; i < coredump -> adev -> num_rings ; i ++ ) {
307- int j = 0 ;
308- struct amdgpu_ring * ring = coredump -> adev -> rings [i ];
309-
310- drm_printf (& p , "ring name: %s\n" , ring -> name );
311- drm_printf (& p , "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n" ,
312- amdgpu_ring_get_rptr (ring ),
313- amdgpu_ring_get_wptr (ring ),
314- ring -> buf_mask );
315- drm_printf (& p , "Ring size in dwords: %d\n" ,
316- ring -> ring_size / 4 );
317- drm_printf (& p , "Ring contents\n" );
318- drm_printf (& p , "Offset \t Value\n" );
319-
320- while (j < ring -> ring_size ) {
321- drm_printf (& p , "0x%x \t 0x%x\n" , j , ring -> ring [j / 4 ]);
322- j += 4 ;
318+ if (coredump -> num_rings ) {
319+ for (i = 0 ; i < coredump -> num_rings ; i ++ ) {
320+ ring_idx = coredump -> rings [i ].ring_index ;
321+ ring = coredump -> adev -> rings [ring_idx ];
322+ off = coredump -> rings [i ].offset ;
323+
324+ drm_printf (& p , "ring name: %s\n" , ring -> name );
325+ drm_printf (& p , "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n" ,
326+ coredump -> rings [i ].rptr ,
327+ coredump -> rings [i ].wptr ,
328+ ring -> buf_mask );
329+ drm_printf (& p , "Ring size in dwords: %d\n" ,
330+ ring -> ring_size / 4 );
331+ drm_printf (& p , "Ring contents\n" );
332+ drm_printf (& p , "Offset \t Value\n" );
333+
334+ for (j = 0 ; j < ring -> ring_size ; j += 4 )
335+ drm_printf (& p , "0x%x \t 0x%x\n" , j ,
336+ coredump -> rings_dw [off + j / 4 ]);
323337 }
324338 }
325339
@@ -328,6 +342,87 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
328342 else if (coredump -> reset_vram_lost )
329343 drm_printf (& p , "VRAM is lost due to GPU reset!\n" );
330344
345+ if (coredump -> num_ibs ) {
346+ /* Don't try to lookup the VM or map the BOs when calculating the
347+ * size required to store the devcoredump.
348+ */
349+ if (sizing_pass )
350+ vm = NULL ;
351+ else
352+ vm = amdgpu_vm_lock_by_pasid (adev , & root , coredump -> pasid );
353+
354+ for (int i = 0 ; i < coredump -> num_ibs && (sizing_pass || vm ); i ++ ) {
355+ ib_content = kvmalloc_array (coredump -> ibs [i ].ib_size_dw , 4 ,
356+ GFP_KERNEL );
357+ if (!ib_content )
358+ continue ;
359+
360+ /* vm=NULL can only happen when 'sizing_pass' is true. Skip to the
361+ * drm_printf() calls (ib_content doesn't need to be initialized
362+ * as its content won't be written anywhere).
363+ */
364+ if (!vm )
365+ goto output_ib_content ;
366+
367+ va_start = coredump -> ibs [i ].gpu_addr & AMDGPU_GMC_HOLE_MASK ;
368+ mapping = amdgpu_vm_bo_lookup_mapping (vm , va_start / AMDGPU_GPU_PAGE_SIZE );
369+ if (!mapping )
370+ goto free_ib_content ;
371+
372+ offset = va_start - (mapping -> start * AMDGPU_GPU_PAGE_SIZE );
373+ abo = amdgpu_bo_ref (mapping -> bo_va -> base .bo );
374+ r = amdgpu_bo_reserve (abo , false);
375+ if (r )
376+ goto free_ib_content ;
377+
378+ if (abo -> flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS ) {
379+ off = 0 ;
380+
381+ if (abo -> tbo .resource -> mem_type != TTM_PL_VRAM )
382+ goto unreserve_abo ;
383+
384+ amdgpu_res_first (abo -> tbo .resource , offset ,
385+ coredump -> ibs [i ].ib_size_dw * 4 ,
386+ & cursor );
387+ while (cursor .remaining ) {
388+ amdgpu_device_mm_access (adev , cursor .start / 4 ,
389+ & ib_content [off ], cursor .size / 4 ,
390+ false);
391+ off += cursor .size ;
392+ amdgpu_res_next (& cursor , cursor .size );
393+ }
394+ } else {
395+ r = ttm_bo_kmap (& abo -> tbo , 0 ,
396+ PFN_UP (abo -> tbo .base .size ),
397+ & abo -> kmap );
398+ if (r )
399+ goto unreserve_abo ;
400+
401+ kptr = amdgpu_bo_kptr (abo );
402+ kptr += offset ;
403+ memcpy (ib_content , kptr ,
404+ coredump -> ibs [i ].ib_size_dw * 4 );
405+
406+ amdgpu_bo_kunmap (abo );
407+ }
408+
409+ output_ib_content :
410+ drm_printf (& p , "\nIB #%d 0x%llx %d dw\n" ,
411+ i , coredump -> ibs [i ].gpu_addr , coredump -> ibs [i ].ib_size_dw );
412+ for (int j = 0 ; j < coredump -> ibs [i ].ib_size_dw ; j ++ )
413+ drm_printf (& p , "0x%08x\n" , ib_content [j ]);
414+ unreserve_abo :
415+ if (vm )
416+ amdgpu_bo_unreserve (abo );
417+ free_ib_content :
418+ kvfree (ib_content );
419+ }
420+ if (vm ) {
421+ amdgpu_bo_unreserve (root );
422+ amdgpu_bo_unref (& root );
423+ }
424+ }
425+
331426 return count - iter .remain ;
332427}
333428
@@ -359,6 +454,8 @@ static void amdgpu_devcoredump_free(void *data)
359454 struct amdgpu_coredump_info * coredump = data ;
360455
361456 kvfree (coredump -> formatted );
457+ kvfree (coredump -> rings );
458+ kvfree (coredump -> rings_dw );
362459 kvfree (data );
363460}
364461
@@ -395,18 +492,26 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
395492{
396493 struct drm_device * dev = adev_to_drm (adev );
397494 struct amdgpu_coredump_info * coredump ;
495+ size_t size = sizeof (* coredump );
398496 struct drm_sched_job * s_job ;
497+ u64 total_ring_size , ring_count ;
498+ struct amdgpu_ring * ring ;
499+ int i , off , idx ;
399500
400501 /* No need to generate a new coredump if there's one in progress already. */
401502 if (work_pending (& adev -> coredump_work ))
402503 return ;
403504
404- coredump = kzalloc_obj (* coredump , GFP_NOWAIT );
505+ if (job && job -> pasid )
506+ size += sizeof (struct amdgpu_coredump_ib_info ) * job -> num_ibs ;
507+
508+ coredump = kzalloc (size , GFP_NOWAIT );
405509 if (!coredump )
406510 return ;
407511
408512 coredump -> skip_vram_check = skip_vram_check ;
409513 coredump -> reset_vram_lost = vram_lost ;
514+ coredump -> pasid = job -> pasid ;
410515
411516 if (job && job -> pasid ) {
412517 struct amdgpu_task_info * ti ;
@@ -416,13 +521,59 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
416521 coredump -> reset_task_info = * ti ;
417522 amdgpu_vm_put_task_info (ti );
418523 }
524+ coredump -> num_ibs = job -> num_ibs ;
525+ for (i = 0 ; i < job -> num_ibs ; ++ i ) {
526+ coredump -> ibs [i ].gpu_addr = job -> ibs [i ].gpu_addr ;
527+ coredump -> ibs [i ].ib_size_dw = job -> ibs [i ].length_dw ;
528+ }
419529 }
420530
421531 if (job ) {
422532 s_job = & job -> base ;
423533 coredump -> ring = to_amdgpu_ring (s_job -> sched );
424534 }
425535
536+ /* Dump ring content if memory allocation succeeds. */
537+ ring_count = 0 ;
538+ total_ring_size = 0 ;
539+ for (i = 0 ; i < adev -> num_rings ; i ++ ) {
540+ ring = adev -> rings [i ];
541+
542+ /* Only dump rings with unsignalled fences. */
543+ if (atomic_read (& ring -> fence_drv .last_seq ) == ring -> fence_drv .sync_seq &&
544+ coredump -> ring != ring )
545+ continue ;
546+
547+ total_ring_size += ring -> ring_size ;
548+ ring_count ++ ;
549+ }
550+ coredump -> rings_dw = kzalloc (total_ring_size , GFP_NOWAIT );
551+ coredump -> rings = kcalloc (ring_count , sizeof (struct amdgpu_coredump_ring ), GFP_NOWAIT );
552+ if (coredump -> rings && coredump -> rings_dw ) {
553+ for (i = 0 , off = 0 , idx = 0 ; i < adev -> num_rings ; i ++ ) {
554+ ring = adev -> rings [i ];
555+
556+ if (atomic_read (& ring -> fence_drv .last_seq ) == ring -> fence_drv .sync_seq &&
557+ coredump -> ring != ring )
558+ continue ;
559+
560+ coredump -> rings [idx ].ring_index = ring -> idx ;
561+ coredump -> rings [idx ].rptr = amdgpu_ring_get_rptr (ring );
562+ coredump -> rings [idx ].wptr = amdgpu_ring_get_wptr (ring );
563+ coredump -> rings [idx ].offset = off ;
564+
565+ memcpy (& coredump -> rings_dw [off ], ring -> ring , ring -> ring_size );
566+ off += ring -> ring_size ;
567+ idx ++ ;
568+ }
569+ coredump -> num_rings = idx ;
570+ } else {
571+ kvfree (coredump -> rings_dw );
572+ kvfree (coredump -> rings );
573+ coredump -> rings_dw = NULL ;
574+ coredump -> rings = NULL ;
575+ }
576+
426577 coredump -> adev = adev ;
427578
428579 ktime_get_ts64 (& coredump -> reset_time );
0 commit comments