* [PATCH v6 0/2] devcoredump support for Panfrost GPU driver
@ 2022-07-29 14:46 Adrián Larumbe
2022-07-29 14:46 ` [PATCH v6 1/2] drm/panfrost: Add specific register offset macros for JS and MMU AS Adrián Larumbe
2022-07-29 14:46 ` [PATCH v6 2/2] drm/panfrost: Add support for devcoredump Adrián Larumbe
0 siblings, 2 replies; 6+ messages in thread
From: Adrián Larumbe @ 2022-07-29 14:46 UTC (permalink / raw)
To: robh, tomeu.vizoso, steven.price, alyssa.rosenzweig, dri-devel
Cc: adrian.larumbe
This is v6 for a previous patch series being discussed at:
https://lore.kernel.org/dri-devel/20220718172418.584231-1-adrian.larumbe@collabora.com/j
Mesa MR under review can be found at:
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14034
Changes with respect to v5 of the same patch:
- Expressed MMU_AS_STRIDE as a bitshift to avoid yet another magic number and
removed misleading comment on the same line.
Adrián Larumbe (2):
drm/panfrost: Add specific register offset macros for JS and MMU AS
drm/panfrost: Add support for devcoredump
drivers/gpu/drm/panfrost/Kconfig | 1 +
drivers/gpu/drm/panfrost/Makefile | 3 +-
drivers/gpu/drm/panfrost/panfrost_dump.c | 249 +++++++++++++++++++++++
drivers/gpu/drm/panfrost/panfrost_dump.h | 12 ++
drivers/gpu/drm/panfrost/panfrost_job.c | 3 +
drivers/gpu/drm/panfrost/panfrost_regs.h | 42 ++--
include/uapi/drm/panfrost_drm.h | 47 +++++
7 files changed, 338 insertions(+), 19 deletions(-)
create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.c
create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.h
--
2.37.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v6 1/2] drm/panfrost: Add specific register offset macros for JS and MMU AS
2022-07-29 14:46 [PATCH v6 0/2] devcoredump support for Panfrost GPU driver Adrián Larumbe
@ 2022-07-29 14:46 ` Adrián Larumbe
2022-07-29 15:50 ` Alyssa Rosenzweig
2022-08-08 11:28 ` Steven Price
2022-07-29 14:46 ` [PATCH v6 2/2] drm/panfrost: Add support for devcoredump Adrián Larumbe
1 sibling, 2 replies; 6+ messages in thread
From: Adrián Larumbe @ 2022-07-29 14:46 UTC (permalink / raw)
To: robh, tomeu.vizoso, steven.price, alyssa.rosenzweig, dri-devel
Cc: adrian.larumbe
Each Panfrost job has its own job slot and MMU address space set of
registers, which are selected with a job-specific index.
Turn the shift and stride used for selection of the right register set base
into a define rather than using magic numbers.
Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
---
drivers/gpu/drm/panfrost/panfrost_regs.h | 42 ++++++++++++++----------
1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index accb4fa3adb8..919f44ac853d 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -226,23 +226,25 @@
#define JOB_INT_MASK_DONE(j) BIT(j)
#define JS_BASE 0x1800
-#define JS_HEAD_LO(n) (JS_BASE + ((n) * 0x80) + 0x00)
-#define JS_HEAD_HI(n) (JS_BASE + ((n) * 0x80) + 0x04)
-#define JS_TAIL_LO(n) (JS_BASE + ((n) * 0x80) + 0x08)
-#define JS_TAIL_HI(n) (JS_BASE + ((n) * 0x80) + 0x0c)
-#define JS_AFFINITY_LO(n) (JS_BASE + ((n) * 0x80) + 0x10)
-#define JS_AFFINITY_HI(n) (JS_BASE + ((n) * 0x80) + 0x14)
-#define JS_CONFIG(n) (JS_BASE + ((n) * 0x80) + 0x18)
-#define JS_XAFFINITY(n) (JS_BASE + ((n) * 0x80) + 0x1c)
-#define JS_COMMAND(n) (JS_BASE + ((n) * 0x80) + 0x20)
-#define JS_STATUS(n) (JS_BASE + ((n) * 0x80) + 0x24)
-#define JS_HEAD_NEXT_LO(n) (JS_BASE + ((n) * 0x80) + 0x40)
-#define JS_HEAD_NEXT_HI(n) (JS_BASE + ((n) * 0x80) + 0x44)
-#define JS_AFFINITY_NEXT_LO(n) (JS_BASE + ((n) * 0x80) + 0x50)
-#define JS_AFFINITY_NEXT_HI(n) (JS_BASE + ((n) * 0x80) + 0x54)
-#define JS_CONFIG_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x58)
-#define JS_COMMAND_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x60)
-#define JS_FLUSH_ID_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x70)
+#define JS_SLOT_STRIDE 0x80
+
+#define JS_HEAD_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x00)
+#define JS_HEAD_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x04)
+#define JS_TAIL_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x08)
+#define JS_TAIL_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x0c)
+#define JS_AFFINITY_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x10)
+#define JS_AFFINITY_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x14)
+#define JS_CONFIG(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x18)
+#define JS_XAFFINITY(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x1c)
+#define JS_COMMAND(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x20)
+#define JS_STATUS(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x24)
+#define JS_HEAD_NEXT_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x40)
+#define JS_HEAD_NEXT_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x44)
+#define JS_AFFINITY_NEXT_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x50)
+#define JS_AFFINITY_NEXT_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x54)
+#define JS_CONFIG_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x58)
+#define JS_COMMAND_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x60)
+#define JS_FLUSH_ID_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x70)
/* Possible values of JS_CONFIG and JS_CONFIG_NEXT registers */
#define JS_CONFIG_START_FLUSH_CLEAN BIT(8)
@@ -281,7 +283,9 @@
#define AS_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then
flush all L2 caches then issue a flush region command to all MMUs */
-#define MMU_AS(as) (0x2400 + ((as) << 6))
+#define MMU_BASE 0x2400
+#define MMU_AS_SHIFT 0x06
+#define MMU_AS(as) (MMU_BASE + ((as) << MMU_AS_SHIFT))
#define AS_TRANSTAB_LO(as) (MMU_AS(as) + 0x00) /* (RW) Translation Table Base Address for address space n, low word */
#define AS_TRANSTAB_HI(as) (MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
@@ -300,6 +304,8 @@
#define AS_FAULTEXTRA_LO(as) (MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
#define AS_FAULTEXTRA_HI(as) (MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
+#define MMU_AS_STRIDE (1 << MMU_AS_SHIFT)
+
/*
* Begin LPAE MMU TRANSTAB register values
*/
--
2.37.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 2/2] drm/panfrost: Add support for devcoredump
2022-07-29 14:46 [PATCH v6 0/2] devcoredump support for Panfrost GPU driver Adrián Larumbe
2022-07-29 14:46 ` [PATCH v6 1/2] drm/panfrost: Add specific register offset macros for JS and MMU AS Adrián Larumbe
@ 2022-07-29 14:46 ` Adrián Larumbe
2022-08-08 11:28 ` Steven Price
1 sibling, 1 reply; 6+ messages in thread
From: Adrián Larumbe @ 2022-07-29 14:46 UTC (permalink / raw)
To: robh, tomeu.vizoso, steven.price, alyssa.rosenzweig, dri-devel
Cc: adrian.larumbe
In the event of a job timeout, debug dump information will be written into
/sys/class/devcoredump.
Inspired by etnaviv's similar feature.
Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
---
drivers/gpu/drm/panfrost/Kconfig | 1 +
drivers/gpu/drm/panfrost/Makefile | 3 +-
drivers/gpu/drm/panfrost/panfrost_dump.c | 249 +++++++++++++++++++++++
drivers/gpu/drm/panfrost/panfrost_dump.h | 12 ++
drivers/gpu/drm/panfrost/panfrost_job.c | 3 +
include/uapi/drm/panfrost_drm.h | 47 +++++
6 files changed, 314 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.c
create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.h
diff --git a/drivers/gpu/drm/panfrost/Kconfig b/drivers/gpu/drm/panfrost/Kconfig
index 86cdc0ce79e6..079600328be1 100644
--- a/drivers/gpu/drm/panfrost/Kconfig
+++ b/drivers/gpu/drm/panfrost/Kconfig
@@ -11,6 +11,7 @@ config DRM_PANFROST
select DRM_GEM_SHMEM_HELPER
select PM_DEVFREQ
select DEVFREQ_GOV_SIMPLE_ONDEMAND
+ select WANT_DEV_COREDUMP
help
DRM driver for ARM Mali Midgard (T6xx, T7xx, T8xx) and
Bifrost (G3x, G5x, G7x) GPUs.
diff --git a/drivers/gpu/drm/panfrost/Makefile b/drivers/gpu/drm/panfrost/Makefile
index b71935862417..7da2b3f02ed9 100644
--- a/drivers/gpu/drm/panfrost/Makefile
+++ b/drivers/gpu/drm/panfrost/Makefile
@@ -9,6 +9,7 @@ panfrost-y := \
panfrost_gpu.o \
panfrost_job.o \
panfrost_mmu.o \
- panfrost_perfcnt.o
+ panfrost_perfcnt.o \
+ panfrost_dump.o
obj-$(CONFIG_DRM_PANFROST) += panfrost.o
diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.c b/drivers/gpu/drm/panfrost/panfrost_dump.c
new file mode 100644
index 000000000000..72458a6cc197
--- /dev/null
+++ b/drivers/gpu/drm/panfrost/panfrost_dump.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2021 Collabora ltd. */
+
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/devcoredump.h>
+#include <linux/moduleparam.h>
+#include <linux/iosys-map.h>
+#include <drm/panfrost_drm.h>
+#include <drm/drm_device.h>
+
+#include "panfrost_job.h"
+#include "panfrost_gem.h"
+#include "panfrost_regs.h"
+#include "panfrost_dump.h"
+#include "panfrost_device.h"
+
+static bool panfrost_dump_core = true;
+module_param_named(dump_core, panfrost_dump_core, bool, 0600);
+
+struct panfrost_dump_iterator {
+ void *start;
+ struct panfrost_dump_object_header *hdr;
+ void *data;
+};
+
+static const unsigned short panfrost_dump_registers[] = {
+ SHADER_READY_LO,
+ SHADER_READY_HI,
+ TILER_READY_LO,
+ TILER_READY_HI,
+ L2_READY_LO,
+ L2_READY_HI,
+ JOB_INT_MASK,
+ JOB_INT_STAT,
+ JS_HEAD_LO(0),
+ JS_HEAD_HI(0),
+ JS_TAIL_LO(0),
+ JS_TAIL_HI(0),
+ JS_AFFINITY_LO(0),
+ JS_AFFINITY_HI(0),
+ JS_CONFIG(0),
+ JS_STATUS(0),
+ JS_HEAD_NEXT_LO(0),
+ JS_HEAD_NEXT_HI(0),
+ JS_AFFINITY_NEXT_LO(0),
+ JS_AFFINITY_NEXT_HI(0),
+ JS_CONFIG_NEXT(0),
+ MMU_INT_MASK,
+ MMU_INT_STAT,
+ AS_TRANSTAB_LO(0),
+ AS_TRANSTAB_HI(0),
+ AS_MEMATTR_LO(0),
+ AS_MEMATTR_HI(0),
+ AS_FAULTSTATUS(0),
+ AS_FAULTADDRESS_LO(0),
+ AS_FAULTADDRESS_HI(0),
+ AS_STATUS(0),
+};
+
+static void panfrost_core_dump_header(struct panfrost_dump_iterator *iter,
+ u32 type, void *data_end)
+{
+ struct panfrost_dump_object_header *hdr = iter->hdr;
+
+ hdr->magic = cpu_to_le32(PANFROSTDUMP_MAGIC);
+ hdr->type = cpu_to_le32(type);
+ hdr->file_offset = cpu_to_le32(iter->data - iter->start);
+ hdr->file_size = cpu_to_le32(data_end - iter->data);
+
+ iter->hdr++;
+ iter->data += le32_to_cpu(hdr->file_size);
+}
+
+static void
+panfrost_core_dump_registers(struct panfrost_dump_iterator *iter,
+ struct panfrost_device *pfdev,
+ u32 as_nr, int slot)
+{
+ struct panfrost_dump_registers *dumpreg = iter->data;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(panfrost_dump_registers); i++, dumpreg++) {
+ unsigned int js_as_offset = 0;
+ unsigned int reg;
+
+ if (panfrost_dump_registers[i] >= JS_BASE &&
+ panfrost_dump_registers[i] <= JS_BASE + JS_SLOT_STRIDE)
+ js_as_offset = slot * JS_SLOT_STRIDE;
+ else if (panfrost_dump_registers[i] >= MMU_BASE &&
+ panfrost_dump_registers[i] <= MMU_BASE + MMU_AS_STRIDE)
+ js_as_offset = (as_nr << MMU_AS_SHIFT);
+
+ reg = panfrost_dump_registers[i] + js_as_offset;
+
+ dumpreg->reg = cpu_to_le32(reg);
+ dumpreg->value = cpu_to_le32(gpu_read(pfdev, reg));
+ }
+
+ panfrost_core_dump_header(iter, PANFROSTDUMP_BUF_REG, dumpreg);
+}
+
+void panfrost_core_dump(struct panfrost_job *job)
+{
+ struct panfrost_device *pfdev = job->pfdev;
+ struct panfrost_dump_iterator iter;
+ struct drm_gem_object *dbo;
+ unsigned int n_obj, n_bomap_pages;
+ __le64 *bomap, *bomap_start;
+ size_t file_size;
+ u32 as_nr;
+ int slot;
+ int ret, i;
+
+ as_nr = job->mmu->as;
+ slot = panfrost_job_get_slot(job);
+
+ /* Only catch the first event, or when manually re-armed */
+ if (!panfrost_dump_core)
+ return;
+ panfrost_dump_core = false;
+
+ /* At least, we dump registers and end marker */
+ n_obj = 2;
+ n_bomap_pages = 0;
+ file_size = ARRAY_SIZE(panfrost_dump_registers) *
+ sizeof(struct panfrost_dump_registers);
+
+ /* Add in the active buffer objects */
+ for (i = 0; i < job->bo_count; i++) {
+ /*
+ * Even though the CPU could be configured to use 16K or 64K pages, this
+ * is a very unusual situation for most kernel setups on SoCs that have
+ * a Panfrost device. Also many places across the driver make the somewhat
+ * arbitrary assumption that Panfrost's MMU page size is the same as the CPU's,
+ * so let's have a sanity check to ensure that's always the case
+ */
+ dbo = job->bos[i];
+ WARN_ON(!IS_ALIGNED(dbo->size, PAGE_SIZE));
+
+ file_size += dbo->size;
+ n_bomap_pages += dbo->size >> PAGE_SHIFT;
+ n_obj++;
+ }
+
+ /* If we have any buffer objects, add a bomap object */
+ if (n_bomap_pages) {
+ file_size += n_bomap_pages * sizeof(*bomap);
+ n_obj++;
+ }
+
+ /* Add the size of the headers */
+ file_size += sizeof(*iter.hdr) * n_obj;
+
+ /*
+ * Allocate the file in vmalloc memory, it's likely to be big.
+ * The reason behind these GFP flags is that we don't want to trigger the
+ * OOM killer in the event that not enough memory could be found for our
+ * dump file. We also don't want the allocator to do any error reporting,
+ * as the right behaviour is failing gracefully if a big enough buffer
+ * could not be allocated.
+ */
+ iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN |
+ __GFP_NORETRY);
+ if (!iter.start) {
+ dev_warn(pfdev->dev, "failed to allocate devcoredump file\n");
+ return;
+ }
+
+ /* Point the data member after the headers */
+ iter.hdr = iter.start;
+ iter.data = &iter.hdr[n_obj];
+
+ memset(iter.hdr, 0, iter.data - iter.start);
+
+ /*
+ * For now, we write the job identifier in the register dump header,
+ * so that we can decode the entire dump later with pandecode
+ */
+ iter.hdr->reghdr.jc = cpu_to_le64(job->jc);
+ iter.hdr->reghdr.major = cpu_to_le32(PANFROSTDUMP_MAJOR);
+ iter.hdr->reghdr.minor = cpu_to_le32(PANFROSTDUMP_MINOR);
+ iter.hdr->reghdr.gpu_id = cpu_to_le32(pfdev->features.id);
+ iter.hdr->reghdr.nbos = cpu_to_le64(job->bo_count);
+
+ panfrost_core_dump_registers(&iter, pfdev, as_nr, slot);
+
+ /* Reserve space for the bomap */
+ if (job->bo_count) {
+ bomap_start = bomap = iter.data;
+ memset(bomap, 0, sizeof(*bomap) * n_bomap_pages);
+ panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_BOMAP,
+ bomap + n_bomap_pages);
+ }
+
+ for (i = 0; i < job->bo_count; i++) {
+ struct iosys_map map;
+ struct panfrost_gem_mapping *mapping;
+ struct panfrost_gem_object *bo;
+ struct sg_page_iter page_iter;
+ void *vaddr;
+
+ bo = to_panfrost_bo(job->bos[i]);
+ mapping = job->mappings[i];
+
+ if (!bo->base.sgt) {
+ dev_err(pfdev->dev, "Panfrost Dump: BO has no sgt, cannot dump\n");
+ iter.hdr->bomap.valid = 0;
+ goto dump_header;
+ }
+
+ ret = drm_gem_shmem_vmap(&bo->base, &map);
+ if (ret) {
+ dev_err(pfdev->dev, "Panfrost Dump: couldn't map Buffer Object\n");
+ iter.hdr->bomap.valid = 0;
+ goto dump_header;
+ }
+
+ WARN_ON(!mapping->active);
+
+ iter.hdr->bomap.data[0] = cpu_to_le32((bomap - bomap_start));
+
+ for_each_sgtable_page(bo->base.sgt, &page_iter, 0) {
+ struct page *page = sg_page_iter_page(&page_iter);
+
+ if (!IS_ERR(page)) {
+ *bomap++ = cpu_to_le64(page_to_phys(page));
+ } else {
+ dev_err(pfdev->dev, "Panfrost Dump: wrong page\n");
+ *bomap++ = ~cpu_to_le64(0);
+ }
+ }
+
+ iter.hdr->bomap.iova = cpu_to_le64(mapping->mmnode.start << PAGE_SHIFT);
+
+ vaddr = map.vaddr;
+ memcpy(iter.data, vaddr, bo->base.base.size);
+
+ drm_gem_shmem_vunmap(&bo->base, &map);
+
+ iter.hdr->bomap.valid = cpu_to_le32(1);
+
+dump_header: panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_BO, iter.data +
+ bo->base.base.size);
+ }
+ panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_TRAILER, iter.data);
+
+ dev_coredumpv(pfdev->dev, iter.start, iter.data - iter.start, GFP_KERNEL);
+}
diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.h b/drivers/gpu/drm/panfrost/panfrost_dump.h
new file mode 100644
index 000000000000..7d9bcefa5346
--- /dev/null
+++ b/drivers/gpu/drm/panfrost/panfrost_dump.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2021 Collabora ltd.
+ */
+
+#ifndef PANFROST_DUMP_H
+#define PANFROST_DUMP_H
+
+struct panfrost_job;
+void panfrost_core_dump(struct panfrost_job *job);
+
+#endif
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
index 7c4208476fbd..dbc597ab46fb 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.c
+++ b/drivers/gpu/drm/panfrost/panfrost_job.c
@@ -20,6 +20,7 @@
#include "panfrost_regs.h"
#include "panfrost_gpu.h"
#include "panfrost_mmu.h"
+#include "panfrost_dump.h"
#define JOB_TIMEOUT_MS 500
@@ -727,6 +728,8 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
job_read(pfdev, JS_TAIL_LO(js)),
sched_job);
+ panfrost_core_dump(job);
+
atomic_set(&pfdev->reset.pending, 1);
panfrost_reset(pfdev, sched_job);
diff --git a/include/uapi/drm/panfrost_drm.h b/include/uapi/drm/panfrost_drm.h
index 9e40277d8185..eac87310b348 100644
--- a/include/uapi/drm/panfrost_drm.h
+++ b/include/uapi/drm/panfrost_drm.h
@@ -224,6 +224,53 @@ struct drm_panfrost_madvise {
__u32 retained; /* out, whether backing store still exists */
};
+/* Definitions for coredump decoding in user space */
+#define PANFROSTDUMP_MAJOR 1
+#define PANFROSTDUMP_MINOR 0
+
+#define PANFROSTDUMP_MAGIC 0x464E4150 /* PANF */
+
+#define PANFROSTDUMP_BUF_REG 0
+#define PANFROSTDUMP_BUF_BOMAP (PANFROSTDUMP_BUF_REG + 1)
+#define PANFROSTDUMP_BUF_BO (PANFROSTDUMP_BUF_BOMAP + 1)
+#define PANFROSTDUMP_BUF_TRAILER (PANFROSTDUMP_BUF_BO + 1)
+
+struct panfrost_dump_object_header {
+ __le32 magic;
+ __le32 type;
+ __le32 file_size;
+ __le32 file_offset;
+
+ union {
+ struct pan_reg_hdr {
+ __le64 jc;
+ __le32 gpu_id;
+ __le32 major;
+ __le32 minor;
+ __le64 nbos;
+ } reghdr;
+
+ struct pan_bomap_hdr {
+ __le32 valid;
+ __le64 iova;
+ __le32 data[2];
+ } bomap;
+
+ /*
+ * Force same size in case we want to expand the header
+ * with new fields and also keep it 512-byte aligned
+ */
+
+ __le32 sizer[496];
+ };
+};
+
+/* Registers object, an array of these */
+struct panfrost_dump_registers {
+ __le32 reg;
+ __le32 value;
+};
+
#if defined(__cplusplus)
}
#endif
--
2.37.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v6 1/2] drm/panfrost: Add specific register offset macros for JS and MMU AS
2022-07-29 14:46 ` [PATCH v6 1/2] drm/panfrost: Add specific register offset macros for JS and MMU AS Adrián Larumbe
@ 2022-07-29 15:50 ` Alyssa Rosenzweig
2022-08-08 11:28 ` Steven Price
1 sibling, 0 replies; 6+ messages in thread
From: Alyssa Rosenzweig @ 2022-07-29 15:50 UTC (permalink / raw)
To: Adri??n Larumbe; +Cc: dri-devel, alyssa.rosenzweig, tomeu.vizoso, steven.price
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
On Fri, Jul 29, 2022 at 03:46:09PM +0100, Adri??n Larumbe wrote:
> Each Panfrost job has its own job slot and MMU address space set of
> registers, which are selected with a job-specific index.
>
> Turn the shift and stride used for selection of the right register set base
> into a define rather than using magic numbers.
>
> Signed-off-by: Adri??n Larumbe <adrian.larumbe@collabora.com>
> ---
> drivers/gpu/drm/panfrost/panfrost_regs.h | 42 ++++++++++++++----------
> 1 file changed, 24 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
> index accb4fa3adb8..919f44ac853d 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_regs.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
> @@ -226,23 +226,25 @@
> #define JOB_INT_MASK_DONE(j) BIT(j)
>
> #define JS_BASE 0x1800
> -#define JS_HEAD_LO(n) (JS_BASE + ((n) * 0x80) + 0x00)
> -#define JS_HEAD_HI(n) (JS_BASE + ((n) * 0x80) + 0x04)
> -#define JS_TAIL_LO(n) (JS_BASE + ((n) * 0x80) + 0x08)
> -#define JS_TAIL_HI(n) (JS_BASE + ((n) * 0x80) + 0x0c)
> -#define JS_AFFINITY_LO(n) (JS_BASE + ((n) * 0x80) + 0x10)
> -#define JS_AFFINITY_HI(n) (JS_BASE + ((n) * 0x80) + 0x14)
> -#define JS_CONFIG(n) (JS_BASE + ((n) * 0x80) + 0x18)
> -#define JS_XAFFINITY(n) (JS_BASE + ((n) * 0x80) + 0x1c)
> -#define JS_COMMAND(n) (JS_BASE + ((n) * 0x80) + 0x20)
> -#define JS_STATUS(n) (JS_BASE + ((n) * 0x80) + 0x24)
> -#define JS_HEAD_NEXT_LO(n) (JS_BASE + ((n) * 0x80) + 0x40)
> -#define JS_HEAD_NEXT_HI(n) (JS_BASE + ((n) * 0x80) + 0x44)
> -#define JS_AFFINITY_NEXT_LO(n) (JS_BASE + ((n) * 0x80) + 0x50)
> -#define JS_AFFINITY_NEXT_HI(n) (JS_BASE + ((n) * 0x80) + 0x54)
> -#define JS_CONFIG_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x58)
> -#define JS_COMMAND_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x60)
> -#define JS_FLUSH_ID_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x70)
> +#define JS_SLOT_STRIDE 0x80
> +
> +#define JS_HEAD_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x00)
> +#define JS_HEAD_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x04)
> +#define JS_TAIL_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x08)
> +#define JS_TAIL_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x0c)
> +#define JS_AFFINITY_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x10)
> +#define JS_AFFINITY_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x14)
> +#define JS_CONFIG(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x18)
> +#define JS_XAFFINITY(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x1c)
> +#define JS_COMMAND(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x20)
> +#define JS_STATUS(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x24)
> +#define JS_HEAD_NEXT_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x40)
> +#define JS_HEAD_NEXT_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x44)
> +#define JS_AFFINITY_NEXT_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x50)
> +#define JS_AFFINITY_NEXT_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x54)
> +#define JS_CONFIG_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x58)
> +#define JS_COMMAND_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x60)
> +#define JS_FLUSH_ID_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x70)
>
> /* Possible values of JS_CONFIG and JS_CONFIG_NEXT registers */
> #define JS_CONFIG_START_FLUSH_CLEAN BIT(8)
> @@ -281,7 +283,9 @@
> #define AS_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then
> flush all L2 caches then issue a flush region command to all MMUs */
>
> -#define MMU_AS(as) (0x2400 + ((as) << 6))
> +#define MMU_BASE 0x2400
> +#define MMU_AS_SHIFT 0x06
> +#define MMU_AS(as) (MMU_BASE + ((as) << MMU_AS_SHIFT))
>
> #define AS_TRANSTAB_LO(as) (MMU_AS(as) + 0x00) /* (RW) Translation Table Base Address for address space n, low word */
> #define AS_TRANSTAB_HI(as) (MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
> @@ -300,6 +304,8 @@
> #define AS_FAULTEXTRA_LO(as) (MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
> #define AS_FAULTEXTRA_HI(as) (MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
>
> +#define MMU_AS_STRIDE (1 << MMU_AS_SHIFT)
> +
> /*
> * Begin LPAE MMU TRANSTAB register values
> */
> --
> 2.37.0
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v6 1/2] drm/panfrost: Add specific register offset macros for JS and MMU AS
2022-07-29 14:46 ` [PATCH v6 1/2] drm/panfrost: Add specific register offset macros for JS and MMU AS Adrián Larumbe
2022-07-29 15:50 ` Alyssa Rosenzweig
@ 2022-08-08 11:28 ` Steven Price
1 sibling, 0 replies; 6+ messages in thread
From: Steven Price @ 2022-08-08 11:28 UTC (permalink / raw)
To: Adrián Larumbe, robh, tomeu.vizoso, alyssa.rosenzweig, dri-devel
On 29/07/2022 15:46, Adrián Larumbe wrote:
> Each Panfrost job has its own job slot and MMU address space set of
> registers, which are selected with a job-specific index.
>
> Turn the shift and stride used for selection of the right register set base
> into a define rather than using magic numbers.
>
> Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
> ---
> drivers/gpu/drm/panfrost/panfrost_regs.h | 42 ++++++++++++++----------
> 1 file changed, 24 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
> index accb4fa3adb8..919f44ac853d 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_regs.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
> @@ -226,23 +226,25 @@
> #define JOB_INT_MASK_DONE(j) BIT(j)
>
> #define JS_BASE 0x1800
> -#define JS_HEAD_LO(n) (JS_BASE + ((n) * 0x80) + 0x00)
> -#define JS_HEAD_HI(n) (JS_BASE + ((n) * 0x80) + 0x04)
> -#define JS_TAIL_LO(n) (JS_BASE + ((n) * 0x80) + 0x08)
> -#define JS_TAIL_HI(n) (JS_BASE + ((n) * 0x80) + 0x0c)
> -#define JS_AFFINITY_LO(n) (JS_BASE + ((n) * 0x80) + 0x10)
> -#define JS_AFFINITY_HI(n) (JS_BASE + ((n) * 0x80) + 0x14)
> -#define JS_CONFIG(n) (JS_BASE + ((n) * 0x80) + 0x18)
> -#define JS_XAFFINITY(n) (JS_BASE + ((n) * 0x80) + 0x1c)
> -#define JS_COMMAND(n) (JS_BASE + ((n) * 0x80) + 0x20)
> -#define JS_STATUS(n) (JS_BASE + ((n) * 0x80) + 0x24)
> -#define JS_HEAD_NEXT_LO(n) (JS_BASE + ((n) * 0x80) + 0x40)
> -#define JS_HEAD_NEXT_HI(n) (JS_BASE + ((n) * 0x80) + 0x44)
> -#define JS_AFFINITY_NEXT_LO(n) (JS_BASE + ((n) * 0x80) + 0x50)
> -#define JS_AFFINITY_NEXT_HI(n) (JS_BASE + ((n) * 0x80) + 0x54)
> -#define JS_CONFIG_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x58)
> -#define JS_COMMAND_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x60)
> -#define JS_FLUSH_ID_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x70)
> +#define JS_SLOT_STRIDE 0x80
> +
> +#define JS_HEAD_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x00)
> +#define JS_HEAD_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x04)
> +#define JS_TAIL_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x08)
> +#define JS_TAIL_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x0c)
> +#define JS_AFFINITY_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x10)
> +#define JS_AFFINITY_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x14)
> +#define JS_CONFIG(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x18)
> +#define JS_XAFFINITY(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x1c)
> +#define JS_COMMAND(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x20)
> +#define JS_STATUS(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x24)
> +#define JS_HEAD_NEXT_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x40)
> +#define JS_HEAD_NEXT_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x44)
> +#define JS_AFFINITY_NEXT_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x50)
> +#define JS_AFFINITY_NEXT_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x54)
> +#define JS_CONFIG_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x58)
> +#define JS_COMMAND_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x60)
> +#define JS_FLUSH_ID_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x70)
>
> /* Possible values of JS_CONFIG and JS_CONFIG_NEXT registers */
> #define JS_CONFIG_START_FLUSH_CLEAN BIT(8)
> @@ -281,7 +283,9 @@
> #define AS_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then
> flush all L2 caches then issue a flush region command to all MMUs */
>
> -#define MMU_AS(as) (0x2400 + ((as) << 6))
> +#define MMU_BASE 0x2400
> +#define MMU_AS_SHIFT 0x06
> +#define MMU_AS(as) (MMU_BASE + ((as) << MMU_AS_SHIFT))
>
> #define AS_TRANSTAB_LO(as) (MMU_AS(as) + 0x00) /* (RW) Translation Table Base Address for address space n, low word */
> #define AS_TRANSTAB_HI(as) (MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
> @@ -300,6 +304,8 @@
> #define AS_FAULTEXTRA_LO(as) (MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
> #define AS_FAULTEXTRA_HI(as) (MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
>
> +#define MMU_AS_STRIDE (1 << MMU_AS_SHIFT)
> +
> /*
> * Begin LPAE MMU TRANSTAB register values
> */
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v6 2/2] drm/panfrost: Add support for devcoredump
2022-07-29 14:46 ` [PATCH v6 2/2] drm/panfrost: Add support for devcoredump Adrián Larumbe
@ 2022-08-08 11:28 ` Steven Price
0 siblings, 0 replies; 6+ messages in thread
From: Steven Price @ 2022-08-08 11:28 UTC (permalink / raw)
To: Adrián Larumbe, robh, tomeu.vizoso, alyssa.rosenzweig, dri-devel
On 29/07/2022 15:46, Adrián Larumbe wrote:
> In the event of a job timeout, debug dump information will be written into
> /sys/class/devcoredump.
>
> Inspired by etnaviv's similar feature.
>
> Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
I'll push these to drm-misc-next.
Thanks,
Steve
> ---
> drivers/gpu/drm/panfrost/Kconfig | 1 +
> drivers/gpu/drm/panfrost/Makefile | 3 +-
> drivers/gpu/drm/panfrost/panfrost_dump.c | 249 +++++++++++++++++++++++
> drivers/gpu/drm/panfrost/panfrost_dump.h | 12 ++
> drivers/gpu/drm/panfrost/panfrost_job.c | 3 +
> include/uapi/drm/panfrost_drm.h | 47 +++++
> 6 files changed, 314 insertions(+), 1 deletion(-)
> create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.c
> create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.h
>
> diff --git a/drivers/gpu/drm/panfrost/Kconfig b/drivers/gpu/drm/panfrost/Kconfig
> index 86cdc0ce79e6..079600328be1 100644
> --- a/drivers/gpu/drm/panfrost/Kconfig
> +++ b/drivers/gpu/drm/panfrost/Kconfig
> @@ -11,6 +11,7 @@ config DRM_PANFROST
> select DRM_GEM_SHMEM_HELPER
> select PM_DEVFREQ
> select DEVFREQ_GOV_SIMPLE_ONDEMAND
> + select WANT_DEV_COREDUMP
> help
> DRM driver for ARM Mali Midgard (T6xx, T7xx, T8xx) and
> Bifrost (G3x, G5x, G7x) GPUs.
> diff --git a/drivers/gpu/drm/panfrost/Makefile b/drivers/gpu/drm/panfrost/Makefile
> index b71935862417..7da2b3f02ed9 100644
> --- a/drivers/gpu/drm/panfrost/Makefile
> +++ b/drivers/gpu/drm/panfrost/Makefile
> @@ -9,6 +9,7 @@ panfrost-y := \
> panfrost_gpu.o \
> panfrost_job.o \
> panfrost_mmu.o \
> - panfrost_perfcnt.o
> + panfrost_perfcnt.o \
> + panfrost_dump.o
>
> obj-$(CONFIG_DRM_PANFROST) += panfrost.o
> diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.c b/drivers/gpu/drm/panfrost/panfrost_dump.c
> new file mode 100644
> index 000000000000..72458a6cc197
> --- /dev/null
> +++ b/drivers/gpu/drm/panfrost/panfrost_dump.c
> @@ -0,0 +1,249 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright 2021 Collabora ltd. */
> +
> +#include <linux/err.h>
> +#include <linux/device.h>
> +#include <linux/devcoredump.h>
> +#include <linux/moduleparam.h>
> +#include <linux/iosys-map.h>
> +#include <drm/panfrost_drm.h>
> +#include <drm/drm_device.h>
> +
> +#include "panfrost_job.h"
> +#include "panfrost_gem.h"
> +#include "panfrost_regs.h"
> +#include "panfrost_dump.h"
> +#include "panfrost_device.h"
> +
> +static bool panfrost_dump_core = true;
> +module_param_named(dump_core, panfrost_dump_core, bool, 0600);
> +
> +struct panfrost_dump_iterator {
> + void *start;
> + struct panfrost_dump_object_header *hdr;
> + void *data;
> +};
> +
> +static const unsigned short panfrost_dump_registers[] = {
> + SHADER_READY_LO,
> + SHADER_READY_HI,
> + TILER_READY_LO,
> + TILER_READY_HI,
> + L2_READY_LO,
> + L2_READY_HI,
> + JOB_INT_MASK,
> + JOB_INT_STAT,
> + JS_HEAD_LO(0),
> + JS_HEAD_HI(0),
> + JS_TAIL_LO(0),
> + JS_TAIL_HI(0),
> + JS_AFFINITY_LO(0),
> + JS_AFFINITY_HI(0),
> + JS_CONFIG(0),
> + JS_STATUS(0),
> + JS_HEAD_NEXT_LO(0),
> + JS_HEAD_NEXT_HI(0),
> + JS_AFFINITY_NEXT_LO(0),
> + JS_AFFINITY_NEXT_HI(0),
> + JS_CONFIG_NEXT(0),
> + MMU_INT_MASK,
> + MMU_INT_STAT,
> + AS_TRANSTAB_LO(0),
> + AS_TRANSTAB_HI(0),
> + AS_MEMATTR_LO(0),
> + AS_MEMATTR_HI(0),
> + AS_FAULTSTATUS(0),
> + AS_FAULTADDRESS_LO(0),
> + AS_FAULTADDRESS_HI(0),
> + AS_STATUS(0),
> +};
> +
> +static void panfrost_core_dump_header(struct panfrost_dump_iterator *iter,
> + u32 type, void *data_end)
> +{
> + struct panfrost_dump_object_header *hdr = iter->hdr;
> +
> + hdr->magic = cpu_to_le32(PANFROSTDUMP_MAGIC);
> + hdr->type = cpu_to_le32(type);
> + hdr->file_offset = cpu_to_le32(iter->data - iter->start);
> + hdr->file_size = cpu_to_le32(data_end - iter->data);
> +
> + iter->hdr++;
> + iter->data += le32_to_cpu(hdr->file_size);
> +}
> +
> +static void
> +panfrost_core_dump_registers(struct panfrost_dump_iterator *iter,
> + struct panfrost_device *pfdev,
> + u32 as_nr, int slot)
> +{
> + struct panfrost_dump_registers *dumpreg = iter->data;
> + unsigned int i;
> +
> + for (i = 0; i < ARRAY_SIZE(panfrost_dump_registers); i++, dumpreg++) {
> + unsigned int js_as_offset = 0;
> + unsigned int reg;
> +
> + if (panfrost_dump_registers[i] >= JS_BASE &&
> + panfrost_dump_registers[i] <= JS_BASE + JS_SLOT_STRIDE)
> + js_as_offset = slot * JS_SLOT_STRIDE;
> + else if (panfrost_dump_registers[i] >= MMU_BASE &&
> + panfrost_dump_registers[i] <= MMU_BASE + MMU_AS_STRIDE)
> + js_as_offset = (as_nr << MMU_AS_SHIFT);
> +
> + reg = panfrost_dump_registers[i] + js_as_offset;
> +
> + dumpreg->reg = cpu_to_le32(reg);
> + dumpreg->value = cpu_to_le32(gpu_read(pfdev, reg));
> + }
> +
> + panfrost_core_dump_header(iter, PANFROSTDUMP_BUF_REG, dumpreg);
> +}
> +
> +void panfrost_core_dump(struct panfrost_job *job)
> +{
> + struct panfrost_device *pfdev = job->pfdev;
> + struct panfrost_dump_iterator iter;
> + struct drm_gem_object *dbo;
> + unsigned int n_obj, n_bomap_pages;
> + __le64 *bomap, *bomap_start;
> + size_t file_size;
> + u32 as_nr;
> + int slot;
> + int ret, i;
> +
> + as_nr = job->mmu->as;
> + slot = panfrost_job_get_slot(job);
> +
> + /* Only catch the first event, or when manually re-armed */
> + if (!panfrost_dump_core)
> + return;
> + panfrost_dump_core = false;
> +
> + /* At least, we dump registers and end marker */
> + n_obj = 2;
> + n_bomap_pages = 0;
> + file_size = ARRAY_SIZE(panfrost_dump_registers) *
> + sizeof(struct panfrost_dump_registers);
> +
> + /* Add in the active buffer objects */
> + for (i = 0; i < job->bo_count; i++) {
> + /*
> + * Even though the CPU could be configured to use 16K or 64K pages, this
> + * is a very unusual situation for most kernel setups on SoCs that have
> + * a Panfrost device. Also many places across the driver make the somewhat
> + * arbitrary assumption that Panfrost's MMU page size is the same as the CPU's,
> + * so let's have a sanity check to ensure that's always the case
> + */
> + dbo = job->bos[i];
> + WARN_ON(!IS_ALIGNED(dbo->size, PAGE_SIZE));
> +
> + file_size += dbo->size;
> + n_bomap_pages += dbo->size >> PAGE_SHIFT;
> + n_obj++;
> + }
> +
> + /* If we have any buffer objects, add a bomap object */
> + if (n_bomap_pages) {
> + file_size += n_bomap_pages * sizeof(*bomap);
> + n_obj++;
> + }
> +
> + /* Add the size of the headers */
> + file_size += sizeof(*iter.hdr) * n_obj;
> +
> + /*
> + * Allocate the file in vmalloc memory, it's likely to be big.
> + * The reason behind these GFP flags is that we don't want to trigger the
> + * OOM killer in the event that not enough memory could be found for our
> + * dump file. We also don't want the allocator to do any error reporting,
> + * as the right behaviour is failing gracefully if a big enough buffer
> + * could not be allocated.
> + */
> + iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN |
> + __GFP_NORETRY);
> + if (!iter.start) {
> + dev_warn(pfdev->dev, "failed to allocate devcoredump file\n");
> + return;
> + }
> +
> + /* Point the data member after the headers */
> + iter.hdr = iter.start;
> + iter.data = &iter.hdr[n_obj];
> +
> + memset(iter.hdr, 0, iter.data - iter.start);
> +
> + /*
> + * For now, we write the job identifier in the register dump header,
> + * so that we can decode the entire dump later with pandecode
> + */
> + iter.hdr->reghdr.jc = cpu_to_le64(job->jc);
> + iter.hdr->reghdr.major = cpu_to_le32(PANFROSTDUMP_MAJOR);
> + iter.hdr->reghdr.minor = cpu_to_le32(PANFROSTDUMP_MINOR);
> + iter.hdr->reghdr.gpu_id = cpu_to_le32(pfdev->features.id);
> + iter.hdr->reghdr.nbos = cpu_to_le64(job->bo_count);
> +
> + panfrost_core_dump_registers(&iter, pfdev, as_nr, slot);
> +
> + /* Reserve space for the bomap */
> + if (job->bo_count) {
> + bomap_start = bomap = iter.data;
> + memset(bomap, 0, sizeof(*bomap) * n_bomap_pages);
> + panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_BOMAP,
> + bomap + n_bomap_pages);
> + }
> +
> + for (i = 0; i < job->bo_count; i++) {
> + struct iosys_map map;
> + struct panfrost_gem_mapping *mapping;
> + struct panfrost_gem_object *bo;
> + struct sg_page_iter page_iter;
> + void *vaddr;
> +
> + bo = to_panfrost_bo(job->bos[i]);
> + mapping = job->mappings[i];
> +
> + if (!bo->base.sgt) {
> + dev_err(pfdev->dev, "Panfrost Dump: BO has no sgt, cannot dump\n");
> + iter.hdr->bomap.valid = 0;
> + goto dump_header;
> + }
> +
> + ret = drm_gem_shmem_vmap(&bo->base, &map);
> + if (ret) {
> + dev_err(pfdev->dev, "Panfrost Dump: couldn't map Buffer Object\n");
> + iter.hdr->bomap.valid = 0;
> + goto dump_header;
> + }
> +
> + WARN_ON(!mapping->active);
> +
> + iter.hdr->bomap.data[0] = cpu_to_le32((bomap - bomap_start));
> +
> + for_each_sgtable_page(bo->base.sgt, &page_iter, 0) {
> + struct page *page = sg_page_iter_page(&page_iter);
> +
> + if (!IS_ERR(page)) {
> + *bomap++ = cpu_to_le64(page_to_phys(page));
> + } else {
> + dev_err(pfdev->dev, "Panfrost Dump: wrong page\n");
> + *bomap++ = ~cpu_to_le64(0);
> + }
> + }
> +
> + iter.hdr->bomap.iova = cpu_to_le64(mapping->mmnode.start << PAGE_SHIFT);
> +
> + vaddr = map.vaddr;
> + memcpy(iter.data, vaddr, bo->base.base.size);
> +
> + drm_gem_shmem_vunmap(&bo->base, &map);
> +
> + iter.hdr->bomap.valid = cpu_to_le32(1);
> +
> +dump_header: panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_BO, iter.data +
> + bo->base.base.size);
> + }
> + panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_TRAILER, iter.data);
> +
> + dev_coredumpv(pfdev->dev, iter.start, iter.data - iter.start, GFP_KERNEL);
> +}
> diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.h b/drivers/gpu/drm/panfrost/panfrost_dump.h
> new file mode 100644
> index 000000000000..7d9bcefa5346
> --- /dev/null
> +++ b/drivers/gpu/drm/panfrost/panfrost_dump.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2021 Collabora ltd.
> + */
> +
> +#ifndef PANFROST_DUMP_H
> +#define PANFROST_DUMP_H
> +
> +struct panfrost_job;
> +void panfrost_core_dump(struct panfrost_job *job);
> +
> +#endif
> diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
> index 7c4208476fbd..dbc597ab46fb 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_job.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_job.c
> @@ -20,6 +20,7 @@
> #include "panfrost_regs.h"
> #include "panfrost_gpu.h"
> #include "panfrost_mmu.h"
> +#include "panfrost_dump.h"
>
> #define JOB_TIMEOUT_MS 500
>
> @@ -727,6 +728,8 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
> job_read(pfdev, JS_TAIL_LO(js)),
> sched_job);
>
> + panfrost_core_dump(job);
> +
> atomic_set(&pfdev->reset.pending, 1);
> panfrost_reset(pfdev, sched_job);
>
> diff --git a/include/uapi/drm/panfrost_drm.h b/include/uapi/drm/panfrost_drm.h
> index 9e40277d8185..eac87310b348 100644
> --- a/include/uapi/drm/panfrost_drm.h
> +++ b/include/uapi/drm/panfrost_drm.h
> @@ -224,6 +224,53 @@ struct drm_panfrost_madvise {
> __u32 retained; /* out, whether backing store still exists */
> };
>
> +/* Definitions for coredump decoding in user space */
> +#define PANFROSTDUMP_MAJOR 1
> +#define PANFROSTDUMP_MINOR 0
> +
> +#define PANFROSTDUMP_MAGIC 0x464E4150 /* PANF */
> +
> +#define PANFROSTDUMP_BUF_REG 0
> +#define PANFROSTDUMP_BUF_BOMAP (PANFROSTDUMP_BUF_REG + 1)
> +#define PANFROSTDUMP_BUF_BO (PANFROSTDUMP_BUF_BOMAP + 1)
> +#define PANFROSTDUMP_BUF_TRAILER (PANFROSTDUMP_BUF_BO + 1)
> +
> +struct panfrost_dump_object_header {
> + __le32 magic;
> + __le32 type;
> + __le32 file_size;
> + __le32 file_offset;
> +
> + union {
> + struct pan_reg_hdr {
> + __le64 jc;
> + __le32 gpu_id;
> + __le32 major;
> + __le32 minor;
> + __le64 nbos;
> + } reghdr;
> +
> + struct pan_bomap_hdr {
> + __le32 valid;
> + __le64 iova;
> + __le32 data[2];
> + } bomap;
> +
> + /*
> + * Force same size in case we want to expand the header
> + * with new fields and also keep it 512-byte aligned
> + */
> +
> + __le32 sizer[496];
> + };
> +};
> +
> +/* Registers object, an array of these */
> +struct panfrost_dump_registers {
> + __le32 reg;
> + __le32 value;
> +};
> +
> #if defined(__cplusplus)
> }
> #endif
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-08-08 11:38 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-29 14:46 [PATCH v6 0/2] devcoredump support for Panfrost GPU driver Adrián Larumbe
2022-07-29 14:46 ` [PATCH v6 1/2] drm/panfrost: Add specific register offset macros for JS and MMU AS Adrián Larumbe
2022-07-29 15:50 ` Alyssa Rosenzweig
2022-08-08 11:28 ` Steven Price
2022-07-29 14:46 ` [PATCH v6 2/2] drm/panfrost: Add support for devcoredump Adrián Larumbe
2022-08-08 11:28 ` Steven Price
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).