drm/xe: Implement capture of HWSP and HWCTX
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Tue, 27 Feb 2024 13:12:47 +0000 (14:12 +0100)
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Mon, 4 Mar 2024 11:24:39 +0000 (12:24 +0100)
Dump the HWCTX and HWSP as part of LRC capture.

Changes since v1:
- Use same layout for HWSP and HWCTX as VM bo's, to simplify dumping.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240227131248.92910-3-maarten.lankhorst@linux.intel.com
drivers/gpu/drm/xe/xe_lrc.c

index 3f32b1bd7e910026a880d4f7a31ae4ba1436f154..ff639fe9a181ac41026fb88d058a4e4a1f8b96de 100644 (file)
@@ -5,6 +5,8 @@
 
 #include "xe_lrc.h"
 
+#include <linux/ascii85.h>
+
 #include "instructions/xe_mi_commands.h"
 #include "instructions/xe_gfxpipe_commands.h"
 #include "instructions/xe_gfx_state_commands.h"
 #define ENGINE_INSTANCE_SHIFT                  48
 
 struct xe_lrc_snapshot {
+       struct xe_bo *lrc_bo;
+       void *lrc_snapshot;
+       unsigned long lrc_size, lrc_offset;
+
        u32 context_desc;
        u32 head;
        struct {
@@ -1356,19 +1362,47 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc)
        snapshot->tail.memory = xe_lrc_read_ctx_reg(lrc, CTX_RING_TAIL);
        snapshot->start_seqno = xe_lrc_start_seqno(lrc);
        snapshot->seqno = xe_lrc_seqno(lrc);
+       snapshot->lrc_bo = xe_bo_get(lrc->bo);
+       snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc);
+       snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset;
+       snapshot->lrc_snapshot = NULL;
        return snapshot;
 }
 
 void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot)
 {
+       struct xe_bo *bo;
+       struct iosys_map src;
+
        if (!snapshot)
                return;
 
-       /* TODO: Copy status page */
+       bo = snapshot->lrc_bo;
+       snapshot->lrc_bo = NULL;
+
+       snapshot->lrc_snapshot = kvmalloc(snapshot->lrc_size, GFP_KERNEL);
+       if (!snapshot->lrc_snapshot)
+               goto put_bo;
+
+       dma_resv_lock(bo->ttm.base.resv, NULL);
+       if (!ttm_bo_vmap(&bo->ttm, &src)) {
+               xe_map_memcpy_from(xe_bo_device(bo),
+                                  snapshot->lrc_snapshot, &src, snapshot->lrc_offset,
+                                  snapshot->lrc_size);
+               ttm_bo_vunmap(&bo->ttm, &src);
+       } else {
+               kvfree(snapshot->lrc_snapshot);
+               snapshot->lrc_snapshot = NULL;
+       }
+       dma_resv_unlock(bo->ttm.base.resv);
+put_bo:
+       xe_bo_put(bo);
 }
 
 void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer *p)
 {
+       unsigned long i;
+
        if (!snapshot)
                return;
 
@@ -1378,9 +1412,37 @@ void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer
                   snapshot->tail.internal, snapshot->tail.memory);
        drm_printf(p, "\tStart seqno: (memory) %d\n", snapshot->start_seqno);
        drm_printf(p, "\tSeqno: (memory) %d\n", snapshot->seqno);
+
+       if (!snapshot->lrc_snapshot)
+               return;
+
+       drm_printf(p, "\t[HWSP].length: 0x%x\n", LRC_PPHWSP_SIZE);
+       drm_puts(p, "\t[HWSP].data: ");
+       for (i = 0; i < LRC_PPHWSP_SIZE; i += sizeof(u32)) {
+               u32 *val = snapshot->lrc_snapshot + i;
+               char dumped[ASCII85_BUFSZ];
+
+               drm_puts(p, ascii85_encode(*val, dumped));
+       }
+
+       drm_printf(p, "\n\t[HWCTX].length: 0x%lx\n", snapshot->lrc_size - LRC_PPHWSP_SIZE);
+       drm_puts(p, "\t[HWCTX].data: ");
+       for (; i < snapshot->lrc_size; i += sizeof(u32)) {
+               u32 *val = snapshot->lrc_snapshot + i;
+               char dumped[ASCII85_BUFSZ];
+
+               drm_puts(p, ascii85_encode(*val, dumped));
+       }
+       drm_puts(p, "\n");
 }
 
 void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot)
 {
+       if (!snapshot)
+               return;
+
+       kvfree(snapshot->lrc_snapshot);
+       if (snapshot->lrc_bo)
+               xe_bo_put(snapshot->lrc_bo);
        kfree(snapshot);
 }