* [PATCH v4 0/4] Panthor BO tagging and GEMS debug display
@ 2025-04-02 11:54 Adrián Larumbe
2025-04-02 11:54 ` [PATCH v4 1/4] drm/panthor: Introduce BO labeling Adrián Larumbe
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Adrián Larumbe @ 2025-04-02 11:54 UTC (permalink / raw)
To: Boris Brezillon, Steven Price, Liviu Dudau, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Sumit Semwal, Christian König
Cc: kernel, Adrián Larumbe, dri-devel, linux-kernel, linux-media,
linaro-mm-sig
This patch series is aimed at providing UM with detailed memory profiling
information in debug builds. It is achieved through a device-wide list of
DRM GEM objects, and also implementing the ability to label BO's from UM
through a new IOCTL.
The new debugfs file shows a list of driver DRM GEM objects in tabular mode.
To visualise it, cat sudo cat /sys/kernel/debug/dri/*.gpu/gems.
To test this functionality from UM, please refer to this Mesa patch series:
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34224
Discussion of previous revision of this patch series can be found at:
https://lore.kernel.org/dri-devel/20250327140845.105962-1-adrian.larumbe@collabora.com/
Changelog:
v4:
- Labelled all kernel BO's, not just heap chunks.
- Refactored DebugGFs GEMs list handling functions
- Added debugfs GEMS node mask to tell different kinds of BO's
Adrián Larumbe (4):
drm/panthor: Introduce BO labeling
drm/panthor: Add driver IOCTL for setting BO labels
drm/panthor: Label all kernel BO's
drm/panthor: show device-wide list of DRM GEM objects over DebugFS
drivers/gpu/drm/panthor/panthor_device.c | 5 +
drivers/gpu/drm/panthor/panthor_device.h | 11 ++
drivers/gpu/drm/panthor/panthor_drv.c | 66 ++++++++
drivers/gpu/drm/panthor/panthor_fw.c | 8 +-
drivers/gpu/drm/panthor/panthor_gem.c | 190 ++++++++++++++++++++++-
drivers/gpu/drm/panthor/panthor_gem.h | 56 ++++++-
drivers/gpu/drm/panthor/panthor_heap.c | 6 +-
drivers/gpu/drm/panthor/panthor_sched.c | 9 +-
include/uapi/drm/panthor_drm.h | 19 +++
9 files changed, 360 insertions(+), 10 deletions(-)
--
2.48.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 1/4] drm/panthor: Introduce BO labeling
2025-04-02 11:54 [PATCH v4 0/4] Panthor BO tagging and GEMS debug display Adrián Larumbe
@ 2025-04-02 11:54 ` Adrián Larumbe
2025-04-02 11:54 ` [PATCH v4 2/4] drm/panthor: Add driver IOCTL for setting BO labels Adrián Larumbe
` (2 subsequent siblings)
3 siblings, 0 replies; 13+ messages in thread
From: Adrián Larumbe @ 2025-04-02 11:54 UTC (permalink / raw)
To: Boris Brezillon, Steven Price, Liviu Dudau, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Sumit Semwal, Christian König
Cc: kernel, Adrián Larumbe, dri-devel, linux-kernel, linux-media,
linaro-mm-sig
Add a new character string Panthor BO field, and a function that allows
setting it from within the driver.
Driver takes care of freeing the string when it's replaced or no longer
needed at object destruction time, but allocating it is the responsibility
of callers.
Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
---
drivers/gpu/drm/panthor/panthor_gem.c | 38 +++++++++++++++++++++++++++
drivers/gpu/drm/panthor/panthor_gem.h | 17 ++++++++++++
2 files changed, 55 insertions(+)
diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
index 8244a4e6c2a2..7d017f9d1d52 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.c
+++ b/drivers/gpu/drm/panthor/panthor_gem.c
@@ -18,6 +18,14 @@ static void panthor_gem_free_object(struct drm_gem_object *obj)
struct panthor_gem_object *bo = to_panthor_bo(obj);
struct drm_gem_object *vm_root_gem = bo->exclusive_vm_root_gem;
+ /*
+ * Label might have been allocated with kstrdup_const(),
+ * we need to take that into account when freeing the memory
+ */
+ kfree_const(bo->label.str);
+
+ mutex_destroy(&bo->label.lock);
+
drm_gem_free_mmap_offset(&bo->base.base);
mutex_destroy(&bo->gpuva_list_lock);
drm_gem_shmem_free(&bo->base);
@@ -196,6 +204,7 @@ struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t
obj->base.map_wc = !ptdev->coherent;
mutex_init(&obj->gpuva_list_lock);
drm_gem_gpuva_set_lock(&obj->base.base, &obj->gpuva_list_lock);
+ mutex_init(&obj->label.lock);
return &obj->base.base;
}
@@ -247,3 +256,32 @@ panthor_gem_create_with_handle(struct drm_file *file,
return ret;
}
+
+void
+panthor_gem_bo_set_label(struct drm_gem_object *obj, const char *label)
+{
+ struct panthor_gem_object *bo = to_panthor_bo(obj);
+ const char *old_label;
+
+ mutex_lock(&bo->label.lock);
+ old_label = bo->label.str;
+ bo->label.str = label;
+ mutex_unlock(&bo->label.lock);
+
+ kfree(old_label);
+}
+
+void
+panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label)
+{
+ const char *str;
+
+ str = kstrdup_const(label, GFP_KERNEL);
+ if (!str) {
+ /* Failing to allocate memory for a label isn't a fatal condition */
+ drm_warn(bo->obj->dev, "Not enough memory to allocate BO label");
+ return;
+ }
+
+ panthor_gem_bo_set_label(bo->obj, kstrdup_const(str, GFP_KERNEL));
+}
diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
index 5749ef2ebe03..0582826b341a 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.h
+++ b/drivers/gpu/drm/panthor/panthor_gem.h
@@ -46,6 +46,20 @@ struct panthor_gem_object {
/** @flags: Combination of drm_panthor_bo_flags flags. */
u32 flags;
+
+ /**
+ * @label: BO tagging fields. The label can be assigned within the
+ * driver itself or through a specific IOCTL.
+ */
+ struct {
+ /**
+ * @label.str: Pointer to NULL-terminated string,
+ */
+ const char *str;
+
+ /** @lock.str: Protects access to the @label.str field. */
+ struct mutex lock;
+ } label;
};
/**
@@ -91,6 +105,9 @@ panthor_gem_create_with_handle(struct drm_file *file,
struct panthor_vm *exclusive_vm,
u64 *size, u32 flags, uint32_t *handle);
+void panthor_gem_bo_set_label(struct drm_gem_object *obj, const char *label);
+void panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label);
+
static inline u64
panthor_kernel_bo_gpuva(struct panthor_kernel_bo *bo)
{
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v4 2/4] drm/panthor: Add driver IOCTL for setting BO labels
2025-04-02 11:54 [PATCH v4 0/4] Panthor BO tagging and GEMS debug display Adrián Larumbe
2025-04-02 11:54 ` [PATCH v4 1/4] drm/panthor: Introduce BO labeling Adrián Larumbe
@ 2025-04-02 11:54 ` Adrián Larumbe
2025-04-07 13:36 ` Liviu Dudau
2025-04-02 11:54 ` [PATCH v4 3/4] drm/panthor: Label all kernel BO's Adrián Larumbe
2025-04-02 11:54 ` [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS Adrián Larumbe
3 siblings, 1 reply; 13+ messages in thread
From: Adrián Larumbe @ 2025-04-02 11:54 UTC (permalink / raw)
To: Boris Brezillon, Steven Price, Liviu Dudau, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Sumit Semwal, Christian König
Cc: kernel, Adrián Larumbe, dri-devel, linux-kernel, linux-media,
linaro-mm-sig
Allow UM to label a BO for which it possesses a DRM handle.
Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
---
drivers/gpu/drm/panthor/panthor_drv.c | 40 +++++++++++++++++++++++++++
drivers/gpu/drm/panthor/panthor_gem.h | 2 ++
include/uapi/drm/panthor_drm.h | 19 +++++++++++++
3 files changed, 61 insertions(+)
diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
index 310bb44abe1a..d5277284fe27 100644
--- a/drivers/gpu/drm/panthor/panthor_drv.c
+++ b/drivers/gpu/drm/panthor/panthor_drv.c
@@ -1330,6 +1330,44 @@ static int panthor_ioctl_vm_get_state(struct drm_device *ddev, void *data,
return 0;
}
+static int panthor_ioctl_bo_set_label(struct drm_device *ddev, void *data,
+ struct drm_file *file)
+{
+ struct drm_panthor_bo_set_label *args = data;
+ struct drm_gem_object *obj;
+ const char *label;
+ int ret = 0;
+
+ obj = drm_gem_object_lookup(file, args->handle);
+ if (!obj)
+ return -ENOENT;
+
+ if (args->size && args->label) {
+ if (args->size > PANTHOR_BO_LABEL_MAXLEN) {
+ ret = -E2BIG;
+ goto err_label;
+ }
+
+ label = strndup_user(u64_to_user_ptr(args->label), args->size);
+ if (IS_ERR(label)) {
+ ret = PTR_ERR(label);
+ goto err_label;
+ }
+ } else if (args->size && !args->label) {
+ ret = -EINVAL;
+ goto err_label;
+ } else {
+ label = NULL;
+ }
+
+ panthor_gem_bo_set_label(obj, label);
+
+err_label:
+ drm_gem_object_put(obj);
+
+ return ret;
+}
+
static int
panthor_open(struct drm_device *ddev, struct drm_file *file)
{
@@ -1399,6 +1437,7 @@ static const struct drm_ioctl_desc panthor_drm_driver_ioctls[] = {
PANTHOR_IOCTL(TILER_HEAP_CREATE, tiler_heap_create, DRM_RENDER_ALLOW),
PANTHOR_IOCTL(TILER_HEAP_DESTROY, tiler_heap_destroy, DRM_RENDER_ALLOW),
PANTHOR_IOCTL(GROUP_SUBMIT, group_submit, DRM_RENDER_ALLOW),
+ PANTHOR_IOCTL(BO_SET_LABEL, bo_set_label, DRM_RENDER_ALLOW),
};
static int panthor_mmap(struct file *filp, struct vm_area_struct *vma)
@@ -1508,6 +1547,7 @@ static void panthor_debugfs_init(struct drm_minor *minor)
* - 1.2 - adds DEV_QUERY_GROUP_PRIORITIES_INFO query
* - adds PANTHOR_GROUP_PRIORITY_REALTIME priority
* - 1.3 - adds DRM_PANTHOR_GROUP_STATE_INNOCENT flag
+ * - 1.4 - adds DRM_IOCTL_PANTHOR_BO_SET_LABEL ioctl
*/
static const struct drm_driver panthor_drm_driver = {
.driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |
diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
index 0582826b341a..e18fbc093abd 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.h
+++ b/drivers/gpu/drm/panthor/panthor_gem.h
@@ -13,6 +13,8 @@
struct panthor_vm;
+#define PANTHOR_BO_LABEL_MAXLEN PAGE_SIZE
+
/**
* struct panthor_gem_object - Driver specific GEM object.
*/
diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h
index 97e2c4510e69..26b52f147360 100644
--- a/include/uapi/drm/panthor_drm.h
+++ b/include/uapi/drm/panthor_drm.h
@@ -127,6 +127,9 @@ enum drm_panthor_ioctl_id {
/** @DRM_PANTHOR_TILER_HEAP_DESTROY: Destroy a tiler heap. */
DRM_PANTHOR_TILER_HEAP_DESTROY,
+
+ /** @DRM_PANTHOR_BO_SET_LABEL: Label a BO. */
+ DRM_PANTHOR_BO_SET_LABEL,
};
/**
@@ -977,6 +980,20 @@ struct drm_panthor_tiler_heap_destroy {
__u32 pad;
};
+/**
+ * struct drm_panthor_bo_set_label - Arguments passed to DRM_IOCTL_PANTHOR_BO_SET_LABEL
+ */
+struct drm_panthor_bo_set_label {
+ /** @handle: Handle of the buffer object to label. */
+ __u32 handle;
+
+ /** @size: Length of the label, including the NULL terminator. */
+ __u32 size;
+
+ /** @label: User pointer to a NULL-terminated string */
+ __u64 label;
+};
+
/**
* DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number
* @__access: Access type. Must be R, W or RW.
@@ -1019,6 +1036,8 @@ enum {
DRM_IOCTL_PANTHOR(WR, TILER_HEAP_CREATE, tiler_heap_create),
DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY =
DRM_IOCTL_PANTHOR(WR, TILER_HEAP_DESTROY, tiler_heap_destroy),
+ DRM_IOCTL_PANTHOR_BO_SET_LABEL =
+ DRM_IOCTL_PANTHOR(WR, BO_SET_LABEL, bo_set_label),
};
#if defined(__cplusplus)
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v4 3/4] drm/panthor: Label all kernel BO's
2025-04-02 11:54 [PATCH v4 0/4] Panthor BO tagging and GEMS debug display Adrián Larumbe
2025-04-02 11:54 ` [PATCH v4 1/4] drm/panthor: Introduce BO labeling Adrián Larumbe
2025-04-02 11:54 ` [PATCH v4 2/4] drm/panthor: Add driver IOCTL for setting BO labels Adrián Larumbe
@ 2025-04-02 11:54 ` Adrián Larumbe
2025-04-02 13:08 ` Boris Brezillon
2025-04-02 11:54 ` [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS Adrián Larumbe
3 siblings, 1 reply; 13+ messages in thread
From: Adrián Larumbe @ 2025-04-02 11:54 UTC (permalink / raw)
To: Boris Brezillon, Steven Price, Liviu Dudau, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Sumit Semwal, Christian König
Cc: kernel, Adrián Larumbe, dri-devel, linux-kernel, linux-media,
linaro-mm-sig
Kernel BO's aren't exposed to UM, so labelling them is the responsibility
of the driver itself. This kind of tagging will prove useful in further
commits when want to expose these objects through DebugFS.
Expand panthor_kernel_bo_create() interface to take a NULL-terminated
string. No bounds checking is done because all label strings are given
as statically-allocated literals, but if a more complex kernel BO naming
scheme with explicit memory allocation and formatting was desired in the
future, this would have to change.
Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
---
drivers/gpu/drm/panthor/panthor_fw.c | 8 +++++---
drivers/gpu/drm/panthor/panthor_gem.c | 3 ++-
drivers/gpu/drm/panthor/panthor_gem.h | 2 +-
drivers/gpu/drm/panthor/panthor_heap.c | 6 ++++--
drivers/gpu/drm/panthor/panthor_sched.c | 9 ++++++---
5 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c
index 4a9c4afa9ad7..36e60bb2dcc5 100644
--- a/drivers/gpu/drm/panthor/panthor_fw.c
+++ b/drivers/gpu/drm/panthor/panthor_fw.c
@@ -449,7 +449,8 @@ panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev,
DRM_PANTHOR_BO_NO_MMAP,
DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
- PANTHOR_VM_KERNEL_AUTO_VA);
+ PANTHOR_VM_KERNEL_AUTO_VA,
+ "Queue FW interface");
if (IS_ERR(mem))
return mem;
@@ -481,7 +482,8 @@ panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size)
return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size,
DRM_PANTHOR_BO_NO_MMAP,
DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
- PANTHOR_VM_KERNEL_AUTO_VA);
+ PANTHOR_VM_KERNEL_AUTO_VA,
+ "FW suspend buffer");
}
static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
@@ -601,7 +603,7 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
section->mem = panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev),
section_size,
DRM_PANTHOR_BO_NO_MMAP,
- vm_map_flags, va);
+ vm_map_flags, va, "FW Section");
if (IS_ERR(section->mem))
return PTR_ERR(section->mem);
diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
index 7d017f9d1d52..44d027e6d664 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.c
+++ b/drivers/gpu/drm/panthor/panthor_gem.c
@@ -81,7 +81,7 @@ void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo)
struct panthor_kernel_bo *
panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
size_t size, u32 bo_flags, u32 vm_map_flags,
- u64 gpu_va)
+ u64 gpu_va, const char *name)
{
struct drm_gem_shmem_object *obj;
struct panthor_kernel_bo *kbo;
@@ -105,6 +105,7 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
kbo->obj = &obj->base;
bo->flags = bo_flags;
+ panthor_gem_kernel_bo_set_label(kbo, name);
/* The system and GPU MMU page size might differ, which becomes a
* problem for FW sections that need to be mapped at explicit address
* since our PAGE_SIZE alignment might cover a VA range that's
diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
index e18fbc093abd..49daa5088a0d 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.h
+++ b/drivers/gpu/drm/panthor/panthor_gem.h
@@ -153,7 +153,7 @@ panthor_kernel_bo_vunmap(struct panthor_kernel_bo *bo)
struct panthor_kernel_bo *
panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
size_t size, u32 bo_flags, u32 vm_map_flags,
- u64 gpu_va);
+ u64 gpu_va, const char *name);
void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo);
diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panthor/panthor_heap.c
index db0285ce5812..ad122bd37ac2 100644
--- a/drivers/gpu/drm/panthor/panthor_heap.c
+++ b/drivers/gpu/drm/panthor/panthor_heap.c
@@ -147,7 +147,8 @@ static int panthor_alloc_heap_chunk(struct panthor_device *ptdev,
chunk->bo = panthor_kernel_bo_create(ptdev, vm, heap->chunk_size,
DRM_PANTHOR_BO_NO_MMAP,
DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
- PANTHOR_VM_KERNEL_AUTO_VA);
+ PANTHOR_VM_KERNEL_AUTO_VA,
+ "Tiler heap chunk");
if (IS_ERR(chunk->bo)) {
ret = PTR_ERR(chunk->bo);
goto err_free_chunk;
@@ -550,7 +551,8 @@ panthor_heap_pool_create(struct panthor_device *ptdev, struct panthor_vm *vm)
pool->gpu_contexts = panthor_kernel_bo_create(ptdev, vm, bosize,
DRM_PANTHOR_BO_NO_MMAP,
DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
- PANTHOR_VM_KERNEL_AUTO_VA);
+ PANTHOR_VM_KERNEL_AUTO_VA,
+ "Heap pool");
if (IS_ERR(pool->gpu_contexts)) {
ret = PTR_ERR(pool->gpu_contexts);
goto err_destroy_pool;
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index 1a276db095ff..a0b8f1ba4ea8 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -3334,7 +3334,8 @@ group_create_queue(struct panthor_group *group,
DRM_PANTHOR_BO_NO_MMAP,
DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
- PANTHOR_VM_KERNEL_AUTO_VA);
+ PANTHOR_VM_KERNEL_AUTO_VA,
+ "Ring buffer");
if (IS_ERR(queue->ringbuf)) {
ret = PTR_ERR(queue->ringbuf);
goto err_free_queue;
@@ -3364,7 +3365,8 @@ group_create_queue(struct panthor_group *group,
DRM_PANTHOR_BO_NO_MMAP,
DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
- PANTHOR_VM_KERNEL_AUTO_VA);
+ PANTHOR_VM_KERNEL_AUTO_VA,
+ "fdinfo slots");
if (IS_ERR(queue->profiling.slots)) {
ret = PTR_ERR(queue->profiling.slots);
@@ -3495,7 +3497,8 @@ int panthor_group_create(struct panthor_file *pfile,
DRM_PANTHOR_BO_NO_MMAP,
DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
- PANTHOR_VM_KERNEL_AUTO_VA);
+ PANTHOR_VM_KERNEL_AUTO_VA,
+ "Group sync objects");
if (IS_ERR(group->syncobjs)) {
ret = PTR_ERR(group->syncobjs);
goto err_put_group;
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS
2025-04-02 11:54 [PATCH v4 0/4] Panthor BO tagging and GEMS debug display Adrián Larumbe
` (2 preceding siblings ...)
2025-04-02 11:54 ` [PATCH v4 3/4] drm/panthor: Label all kernel BO's Adrián Larumbe
@ 2025-04-02 11:54 ` Adrián Larumbe
2025-04-02 12:58 ` Boris Brezillon
2025-04-08 15:26 ` Boris Brezillon
3 siblings, 2 replies; 13+ messages in thread
From: Adrián Larumbe @ 2025-04-02 11:54 UTC (permalink / raw)
To: Boris Brezillon, Steven Price, Liviu Dudau, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Sumit Semwal, Christian König
Cc: kernel, Adrián Larumbe, dri-devel, linux-kernel, linux-media,
linaro-mm-sig
Add a device DebugFS file that displays a complete list of all the DRM
GEM objects that are exposed to UM through a DRM handle.
Since leaking object identifiers that might belong to a different NS is
inadmissible, this functionality is only made available in debug builds
with DEBUGFS support enabled.
File format is that of a table, with each entry displaying a variety of
fields with information about each GEM object.
Each GEM object entry in the file displays the following information
fields: Client PID, BO's global name, reference count, BO virtual size,
BO resize size, VM address in its DRM-managed range, BO label and a flag
bitmask.
There's also a kflags field for the type of BO. Bit 0 tells us whether
it's a kernel BO, and bit 1 means the BO is mapped onto the FW's address
space.
Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
---
drivers/gpu/drm/panthor/panthor_device.c | 5 +
drivers/gpu/drm/panthor/panthor_device.h | 11 ++
drivers/gpu/drm/panthor/panthor_drv.c | 26 ++++
drivers/gpu/drm/panthor/panthor_gem.c | 149 +++++++++++++++++++++++
drivers/gpu/drm/panthor/panthor_gem.h | 35 ++++++
5 files changed, 226 insertions(+)
diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
index a9da1d1eeb70..b776e1a2e4f3 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -184,6 +184,11 @@ int panthor_device_init(struct panthor_device *ptdev)
if (ret)
return ret;
+#ifdef CONFIG_DEBUG_FS
+ drmm_mutex_init(&ptdev->base, &ptdev->gems.lock);
+ INIT_LIST_HEAD(&ptdev->gems.node);
+#endif
+
atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED);
p = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (!p)
diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
index da6574021664..86206a961b38 100644
--- a/drivers/gpu/drm/panthor/panthor_device.h
+++ b/drivers/gpu/drm/panthor/panthor_device.h
@@ -205,6 +205,17 @@ struct panthor_device {
/** @fast_rate: Maximum device clock frequency. Set by DVFS */
unsigned long fast_rate;
+
+#ifdef CONFIG_DEBUG_FS
+ /** @gems: Device-wide list of GEM objects owned by at least one file. */
+ struct {
+ /** @gems.lock: Protects the device-wide list of GEM objects. */
+ struct mutex lock;
+
+ /** @node: Used to keep track of all the device's DRM objects */
+ struct list_head node;
+ } gems;
+#endif
};
struct panthor_gpu_usage {
diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
index d5277284fe27..3e870ed2ad90 100644
--- a/drivers/gpu/drm/panthor/panthor_drv.c
+++ b/drivers/gpu/drm/panthor/panthor_drv.c
@@ -1534,9 +1534,35 @@ static const struct file_operations panthor_drm_driver_fops = {
};
#ifdef CONFIG_DEBUG_FS
+static int panthor_gems_show(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct panthor_device *ptdev = container_of(dev, struct panthor_device, base);
+
+ panthor_gem_debugfs_print_bos(ptdev, m);
+
+ return 0;
+}
+
+
+static struct drm_info_list panthor_debugfs_list[] = {
+ {"gems", panthor_gems_show, 0, NULL},
+};
+
+static int panthor_gems_debugfs_init(struct drm_minor *minor)
+{
+ drm_debugfs_create_files(panthor_debugfs_list,
+ ARRAY_SIZE(panthor_debugfs_list),
+ minor->debugfs_root, minor);
+
+ return 0;
+}
+
static void panthor_debugfs_init(struct drm_minor *minor)
{
panthor_mmu_debugfs_init(minor);
+ panthor_gems_debugfs_init(minor);
}
#endif
diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
index 44d027e6d664..2fc87be9b700 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.c
+++ b/drivers/gpu/drm/panthor/panthor_gem.c
@@ -2,6 +2,7 @@
/* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
/* Copyright 2023 Collabora ltd. */
+#include <linux/cleanup.h>
#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
@@ -10,14 +11,65 @@
#include <drm/panthor_drm.h>
#include "panthor_device.h"
+#include "panthor_fw.h"
#include "panthor_gem.h"
#include "panthor_mmu.h"
+#ifdef CONFIG_DEBUG_FS
+static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo, u32 type_mask)
+{
+ INIT_LIST_HEAD(&bo->debugfs.node);
+
+ if (!(type_mask & PANTHOR_BO_FW_MAPPED)) {
+ bo->debugfs.creator.tgid = current->group_leader->pid;
+ get_task_comm(bo->debugfs.creator.process_name, current->group_leader);
+ } else {
+ bo->debugfs.creator.tgid = 0;
+ snprintf(bo->debugfs.creator.process_name,
+ sizeof(bo->debugfs.creator.process_name),
+ "kernel");
+ }
+
+ bo->debugfs.bo_mask = type_mask;
+}
+
+static void panthor_gem_debugfs_bo_add(struct panthor_gem_object *bo, u32 type_mask)
+{
+ struct panthor_device *ptdev = container_of(bo->base.base.dev,
+ struct panthor_device, base);
+
+ panthor_gem_debugfs_bo_init(bo, type_mask);
+
+ mutex_lock(&ptdev->gems.lock);
+ list_add_tail(&bo->debugfs.node, &ptdev->gems.node);
+ mutex_unlock(&ptdev->gems.lock);
+}
+
+static void panthor_gem_debugfs_bo_rm(struct panthor_gem_object *bo)
+{
+ struct panthor_device *ptdev = container_of(bo->base.base.dev,
+ struct panthor_device, base);
+
+ if (list_empty(&bo->debugfs.node))
+ return;
+
+ mutex_lock(&ptdev->gems.lock);
+ list_del_init(&bo->debugfs.node);
+ mutex_unlock(&ptdev->gems.lock);
+}
+
+#else
+static void panthor_gem_debugfs_bo_add(struct panthor_gem_object *bo, u32 type_mask) {}
+static void panthor_gem_debugfs_bo_rm(struct panthor_gem_object *bo) {}
+#endif
+
static void panthor_gem_free_object(struct drm_gem_object *obj)
{
struct panthor_gem_object *bo = to_panthor_bo(obj);
struct drm_gem_object *vm_root_gem = bo->exclusive_vm_root_gem;
+ panthor_gem_debugfs_bo_rm(bo);
+
/*
* Label might have been allocated with kstrdup_const(),
* we need to take that into account when freeing the memory
@@ -86,6 +138,7 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
struct drm_gem_shmem_object *obj;
struct panthor_kernel_bo *kbo;
struct panthor_gem_object *bo;
+ u32 type_mask = PANTHOR_BO_KERNEL;
int ret;
if (drm_WARN_ON(&ptdev->base, !vm))
@@ -105,7 +158,12 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
kbo->obj = &obj->base;
bo->flags = bo_flags;
+ if (vm == panthor_fw_vm(ptdev))
+ type_mask |= PANTHOR_BO_FW_MAPPED;
+
panthor_gem_kernel_bo_set_label(kbo, name);
+ panthor_gem_debugfs_bo_add(to_panthor_bo(kbo->obj), type_mask);
+
/* The system and GPU MMU page size might differ, which becomes a
* problem for FW sections that need to be mapped at explicit address
* since our PAGE_SIZE alignment might cover a VA range that's
@@ -255,6 +313,8 @@ panthor_gem_create_with_handle(struct drm_file *file,
/* drop reference from allocate - handle holds it now. */
drm_gem_object_put(&shmem->base);
+ panthor_gem_debugfs_bo_add(bo, 0);
+
return ret;
}
@@ -286,3 +346,92 @@ panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label)
panthor_gem_bo_set_label(bo->obj, kstrdup_const(str, GFP_KERNEL));
}
+
+#ifdef CONFIG_DEBUG_FS
+static bool panfrost_gem_print_flag(const char *name,
+ bool is_set,
+ bool other_flags_printed,
+ struct seq_file *m)
+{
+ if (is_set)
+ seq_printf(m, "%s%s", other_flags_printed ? "," : "", name);
+
+ return is_set | other_flags_printed;
+}
+
+struct gem_size_totals {
+ size_t size;
+ size_t resident;
+ size_t reclaimable;
+};
+
+static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo,
+ struct seq_file *m,
+ struct gem_size_totals *totals)
+{
+ unsigned int refcount = kref_read(&bo->base.base.refcount);
+ char creator_info[32] = {};
+ bool has_flags = false;
+ size_t resident_size;
+
+ /* Skip BOs being destroyed. */
+ if (!refcount)
+ return;
+
+ resident_size = bo->base.pages != NULL ? bo->base.base.size : 0;
+
+ snprintf(creator_info, sizeof(creator_info),
+ "%s/%d", bo->debugfs.creator.process_name, bo->debugfs.creator.tgid);
+ seq_printf(m, "%-32s%-16d%-16d%-16zd%-16zd%-16lx",
+ creator_info,
+ bo->base.base.name,
+ refcount,
+ bo->base.base.size,
+ resident_size,
+ drm_vma_node_start(&bo->base.base.vma_node));
+
+ seq_puts(m, "(");
+ has_flags = panfrost_gem_print_flag("imported", bo->base.base.import_attach != NULL,
+ has_flags, m);
+ has_flags = panfrost_gem_print_flag("exported", bo->base.base.dma_buf != NULL,
+ has_flags, m);
+ if (bo->base.madv < 0)
+ has_flags = panfrost_gem_print_flag("purged", true, has_flags, m);
+ else if (bo->base.madv > 0)
+ has_flags = panfrost_gem_print_flag("purgeable", true, has_flags, m);
+ if (!has_flags)
+ seq_puts(m, "none");
+ seq_puts(m, ")");
+
+ seq_printf(m, "%-6s0x%-2x", "", bo->debugfs.bo_mask);
+
+ mutex_lock(&bo->label.lock);
+ seq_printf(m, "%-6s%-60s", "", bo->label.str ? : NULL);
+ mutex_unlock(&bo->label.lock);
+ seq_puts(m, "\n");
+
+ totals->size += bo->base.base.size;
+ totals->resident += resident_size;
+ if (bo->base.madv > 0)
+ totals->reclaimable += resident_size;
+}
+
+void panthor_gem_debugfs_print_bos(struct panthor_device *ptdev,
+ struct seq_file *m)
+{
+ struct gem_size_totals totals = {0};
+ struct panthor_gem_object *bo;
+
+ seq_puts(m, "created-by global-name refcount size resident-size file-offset flags kflags label\n");
+ seq_puts(m, "------------------------------------------------------------------------------------------------------------------------------------------------\n");
+
+ scoped_guard(mutex, &ptdev->gems.lock) {
+ list_for_each_entry(bo, &ptdev->gems.node, debugfs.node)
+ panthor_gem_debugfs_bo_print(bo, m, &totals);
+ }
+
+ seq_puts(m, "==========================================================================================================================================================\n");
+ seq_printf(m, "Total size: %zd, Total resident: %zd, Total reclaimable: %zd\n",
+ totals.size, totals.resident, totals.reclaimable);
+}
+#endif
diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
index 49daa5088a0d..22ecc0d39d5e 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.h
+++ b/drivers/gpu/drm/panthor/panthor_gem.h
@@ -15,6 +15,32 @@ struct panthor_vm;
#define PANTHOR_BO_LABEL_MAXLEN PAGE_SIZE
+#define PANTHOR_BO_KERNEL BIT(0)
+#define PANTHOR_BO_FW_MAPPED BIT(1)
+
+/**
+ * struct panthor_gem_debugfs - GEM object's DebugFS list information
+ */
+struct panthor_gem_debugfs {
+ /**
+ * @node: Node used to insert the object in the device-wide list of
+ * GEM objects, to display information about it through a DebugFS file.
+ */
+ struct list_head node;
+
+ /** @creator: Information about the UM process which created the GEM. */
+ struct {
+ /** @creator.process_name: Group leader name in owning thread's process */
+ char process_name[TASK_COMM_LEN];
+
+ /** @creator.tgid: PID of the thread's group leader within its process */
+ pid_t tgid;
+ } creator;
+
+ /** @bo_mask: Bitmask encoding BO type as {USER, KERNEL} x {GPU, FW} */
+ u32 bo_mask;
+};
+
/**
* struct panthor_gem_object - Driver specific GEM object.
*/
@@ -62,6 +88,10 @@ struct panthor_gem_object {
/** @lock.str: Protects access to the @label.str field. */
struct mutex lock;
} label;
+
+#ifdef CONFIG_DEBUG_FS
+ struct panthor_gem_debugfs debugfs;
+#endif
};
/**
@@ -157,4 +187,9 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo);
+#ifdef CONFIG_DEBUG_FS
+void panthor_gem_debugfs_print_bos(struct panthor_device *pfdev,
+ struct seq_file *m);
+#endif
+
#endif /* __PANTHOR_GEM_H__ */
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS
2025-04-02 11:54 ` [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS Adrián Larumbe
@ 2025-04-02 12:58 ` Boris Brezillon
2025-04-08 13:38 ` Adrián Larumbe
2025-04-08 15:26 ` Boris Brezillon
1 sibling, 1 reply; 13+ messages in thread
From: Boris Brezillon @ 2025-04-02 12:58 UTC (permalink / raw)
To: Adrián Larumbe
Cc: Steven Price, Liviu Dudau, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, kernel, dri-devel, linux-kernel,
linux-media, linaro-mm-sig
On Wed, 2 Apr 2025 12:54:29 +0100
Adrián Larumbe <adrian.larumbe@collabora.com> wrote:
> Add a device DebugFS file that displays a complete list of all the DRM
> GEM objects that are exposed to UM through a DRM handle.
>
> Since leaking object identifiers that might belong to a different NS is
> inadmissible, this functionality is only made available in debug builds
> with DEBUGFS support enabled.
>
> File format is that of a table, with each entry displaying a variety of
> fields with information about each GEM object.
>
> Each GEM object entry in the file displays the following information
> fields: Client PID, BO's global name, reference count, BO virtual size,
> BO resize size, VM address in its DRM-managed range, BO label and a flag
> bitmask.
>
> There's also a kflags field for the type of BO. Bit 0 tells us whether
> it's a kernel BO, and bit 1 means the BO is mapped onto the FW's address
> space.
>
> Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
> ---
> drivers/gpu/drm/panthor/panthor_device.c | 5 +
> drivers/gpu/drm/panthor/panthor_device.h | 11 ++
> drivers/gpu/drm/panthor/panthor_drv.c | 26 ++++
> drivers/gpu/drm/panthor/panthor_gem.c | 149 +++++++++++++++++++++++
> drivers/gpu/drm/panthor/panthor_gem.h | 35 ++++++
> 5 files changed, 226 insertions(+)
>
> diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
> index a9da1d1eeb70..b776e1a2e4f3 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.c
> +++ b/drivers/gpu/drm/panthor/panthor_device.c
> @@ -184,6 +184,11 @@ int panthor_device_init(struct panthor_device *ptdev)
> if (ret)
> return ret;
>
> +#ifdef CONFIG_DEBUG_FS
> + drmm_mutex_init(&ptdev->base, &ptdev->gems.lock);
> + INIT_LIST_HEAD(&ptdev->gems.node);
> +#endif
> +
> atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED);
> p = alloc_page(GFP_KERNEL | __GFP_ZERO);
> if (!p)
> diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
> index da6574021664..86206a961b38 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.h
> +++ b/drivers/gpu/drm/panthor/panthor_device.h
> @@ -205,6 +205,17 @@ struct panthor_device {
>
> /** @fast_rate: Maximum device clock frequency. Set by DVFS */
> unsigned long fast_rate;
> +
> +#ifdef CONFIG_DEBUG_FS
> + /** @gems: Device-wide list of GEM objects owned by at least one file. */
> + struct {
> + /** @gems.lock: Protects the device-wide list of GEM objects. */
> + struct mutex lock;
> +
> + /** @node: Used to keep track of all the device's DRM objects */
> + struct list_head node;
> + } gems;
> +#endif
> };
>
> struct panthor_gpu_usage {
> diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
> index d5277284fe27..3e870ed2ad90 100644
> --- a/drivers/gpu/drm/panthor/panthor_drv.c
> +++ b/drivers/gpu/drm/panthor/panthor_drv.c
> @@ -1534,9 +1534,35 @@ static const struct file_operations panthor_drm_driver_fops = {
> };
>
> #ifdef CONFIG_DEBUG_FS
> +static int panthor_gems_show(struct seq_file *m, void *data)
> +{
> + struct drm_info_node *node = m->private;
> + struct drm_device *dev = node->minor->dev;
> + struct panthor_device *ptdev = container_of(dev, struct panthor_device, base);
> +
> + panthor_gem_debugfs_print_bos(ptdev, m);
> +
> + return 0;
> +}
> +
> +
> +static struct drm_info_list panthor_debugfs_list[] = {
> + {"gems", panthor_gems_show, 0, NULL},
> +};
> +
> +static int panthor_gems_debugfs_init(struct drm_minor *minor)
> +{
> + drm_debugfs_create_files(panthor_debugfs_list,
> + ARRAY_SIZE(panthor_debugfs_list),
> + minor->debugfs_root, minor);
> +
> + return 0;
> +}
> +
> static void panthor_debugfs_init(struct drm_minor *minor)
> {
> panthor_mmu_debugfs_init(minor);
> + panthor_gems_debugfs_init(minor);
> }
> #endif
>
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
> index 44d027e6d664..2fc87be9b700 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.c
> +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> @@ -2,6 +2,7 @@
> /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
> /* Copyright 2023 Collabora ltd. */
>
> +#include <linux/cleanup.h>
> #include <linux/dma-buf.h>
> #include <linux/dma-mapping.h>
> #include <linux/err.h>
> @@ -10,14 +11,65 @@
> #include <drm/panthor_drm.h>
>
> #include "panthor_device.h"
> +#include "panthor_fw.h"
> #include "panthor_gem.h"
> #include "panthor_mmu.h"
>
> +#ifdef CONFIG_DEBUG_FS
> +static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo, u32 type_mask)
> +{
> + INIT_LIST_HEAD(&bo->debugfs.node);
This should be called when the GEM object is created, otherwise the
list_empty() test done in panthor_gem_debugfs_bo_rm() will only work if
panthor_gem_debugfs_bo_add() is called, and depending on when this
happens, or whether it happens at all, the error path will do a NULL
deref.
> +
> + if (!(type_mask & PANTHOR_BO_FW_MAPPED)) {
> + bo->debugfs.creator.tgid = current->group_leader->pid;
> + get_task_comm(bo->debugfs.creator.process_name, current->group_leader);
I don't think that's good to assume that FW-mapped BOs have been
created by the kernel without userspace directly or indirectly asking
for the allocation. For instance, per-group memory allocated for the
USER_CS interfaces are indirectly triggered by a GROUP_CREATE ioctl(),
and should IMO be flagged as being created by the process that
created the group. Don't we have another way to check if we're called
from a kernel thread?
> + } else {
> + bo->debugfs.creator.tgid = 0;
> + snprintf(bo->debugfs.creator.process_name,
> + sizeof(bo->debugfs.creator.process_name),
> + "kernel");
> + }
> +
> + bo->debugfs.bo_mask = type_mask;
Why not do that directly in panthor_gem_debugfs_bo_add()? The only bits
that might be useful to do early is the INIT_LIST_HEAD(), and I think
it can be inlined in panthor_gem_create_object().
> +}
> +
> +static void panthor_gem_debugfs_bo_add(struct panthor_gem_object *bo, u32 type_mask)
> +{
> + struct panthor_device *ptdev = container_of(bo->base.base.dev,
> + struct panthor_device, base);
> +
> + panthor_gem_debugfs_bo_init(bo, type_mask);
> +
> + mutex_lock(&ptdev->gems.lock);
> + list_add_tail(&bo->debugfs.node, &ptdev->gems.node);
> + mutex_unlock(&ptdev->gems.lock);
> +}
> +
> +static void panthor_gem_debugfs_bo_rm(struct panthor_gem_object *bo)
> +{
> + struct panthor_device *ptdev = container_of(bo->base.base.dev,
> + struct panthor_device, base);
> +
> + if (list_empty(&bo->debugfs.node))
> + return;
> +
> + mutex_lock(&ptdev->gems.lock);
> + list_del_init(&bo->debugfs.node);
> + mutex_unlock(&ptdev->gems.lock);
> +}
> +
> +#else
> +static void panthor_gem_debugfs_bo_add(struct panthor_gem_object *bo, u32 type_mask) {}
> +static void panthor_gem_debugfs_bo_rm(struct panthor_gem_object *bo) {}
> +#endif
> +
> static void panthor_gem_free_object(struct drm_gem_object *obj)
> {
> struct panthor_gem_object *bo = to_panthor_bo(obj);
> struct drm_gem_object *vm_root_gem = bo->exclusive_vm_root_gem;
>
> + panthor_gem_debugfs_bo_rm(bo);
> +
> /*
> * Label might have been allocated with kstrdup_const(),
> * we need to take that into account when freeing the memory
> @@ -86,6 +138,7 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> struct drm_gem_shmem_object *obj;
> struct panthor_kernel_bo *kbo;
> struct panthor_gem_object *bo;
> + u32 type_mask = PANTHOR_BO_KERNEL;
> int ret;
>
> if (drm_WARN_ON(&ptdev->base, !vm))
> @@ -105,7 +158,12 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> kbo->obj = &obj->base;
> bo->flags = bo_flags;
>
> + if (vm == panthor_fw_vm(ptdev))
> + type_mask |= PANTHOR_BO_FW_MAPPED;
> +
> panthor_gem_kernel_bo_set_label(kbo, name);
> + panthor_gem_debugfs_bo_add(to_panthor_bo(kbo->obj), type_mask);
> +
> /* The system and GPU MMU page size might differ, which becomes a
> * problem for FW sections that need to be mapped at explicit address
> * since our PAGE_SIZE alignment might cover a VA range that's
> @@ -255,6 +313,8 @@ panthor_gem_create_with_handle(struct drm_file *file,
> /* drop reference from allocate - handle holds it now. */
> drm_gem_object_put(&shmem->base);
>
> + panthor_gem_debugfs_bo_add(bo, 0);
> +
> return ret;
> }
>
> @@ -286,3 +346,92 @@ panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label)
>
> panthor_gem_bo_set_label(bo->obj, kstrdup_const(str, GFP_KERNEL));
> }
> +
> +#ifdef CONFIG_DEBUG_FS
> +static bool panfrost_gem_print_flag(const char *name,
> + bool is_set,
> + bool other_flags_printed,
> + struct seq_file *m)
> +{
> + if (is_set)
> + seq_printf(m, "%s%s", other_flags_printed ? "," : "", name);
> +
> + return is_set | other_flags_printed;
> +}
> +
> +struct gem_size_totals {
> + size_t size;
> + size_t resident;
> + size_t reclaimable;
> +};
> +
> +static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo,
> + struct seq_file *m,
> + struct gem_size_totals *totals)
> +{
> + unsigned int refcount = kref_read(&bo->base.base.refcount);
> + char creator_info[32] = {};
> + bool has_flags = false;
> + size_t resident_size;
> +
> + /* Skip BOs being destroyed. */
> + if (!refcount)
> + return;
> +
> + resident_size = bo->base.pages != NULL ? bo->base.base.size : 0;
> +
> + snprintf(creator_info, sizeof(creator_info),
> + "%s/%d", bo->debugfs.creator.process_name, bo->debugfs.creator.tgid);
> + seq_printf(m, "%-32s%-16d%-16d%-16zd%-16zd%-16lx",
> + creator_info,
> + bo->base.base.name,
> + refcount,
> + bo->base.base.size,
> + resident_size,
> + drm_vma_node_start(&bo->base.base.vma_node));
> +
> + seq_puts(m, "(");
> + has_flags = panfrost_gem_print_flag("imported", bo->base.base.import_attach != NULL,
> + has_flags, m);
> + has_flags = panfrost_gem_print_flag("exported", bo->base.base.dma_buf != NULL,
> + has_flags, m);
> + if (bo->base.madv < 0)
> + has_flags = panfrost_gem_print_flag("purged", true, has_flags, m);
> + else if (bo->base.madv > 0)
> + has_flags = panfrost_gem_print_flag("purgeable", true, has_flags, m);
> + if (!has_flags)
> + seq_puts(m, "none");
> + seq_puts(m, ")");
> +
> + seq_printf(m, "%-6s0x%-2x", "", bo->debugfs.bo_mask);
> +
> + mutex_lock(&bo->label.lock);
> + seq_printf(m, "%-6s%-60s", "", bo->label.str ? : NULL);
> + mutex_unlock(&bo->label.lock);
> + seq_puts(m, "\n");
> +
> + totals->size += bo->base.base.size;
> + totals->resident += resident_size;
> + if (bo->base.madv > 0)
> + totals->reclaimable += resident_size;
> +}
> +
> +void panthor_gem_debugfs_print_bos(struct panthor_device *ptdev,
> + struct seq_file *m)
> +{
> + struct gem_size_totals totals = {0};
> + struct panthor_gem_object *bo;
> +
> + seq_puts(m, "created-by global-name refcount size resident-size file-offset flags kflags label\n");
> + seq_puts(m, "------------------------------------------------------------------------------------------------------------------------------------------------\n");
> +
> + scoped_guard(mutex, &ptdev->gems.lock) {
> + list_for_each_entry(bo, &ptdev->gems.node, debugfs.node)
> + panthor_gem_debugfs_bo_print(bo, m, &totals);
> + }
> +
> + seq_puts(m, "==========================================================================================================================================================\n");
> + seq_printf(m, "Total size: %zd, Total resident: %zd, Total reclaimable: %zd\n",
> + totals.size, totals.resident, totals.reclaimable);
> +}
> +#endif
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
> index 49daa5088a0d..22ecc0d39d5e 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.h
> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
> @@ -15,6 +15,32 @@ struct panthor_vm;
>
> #define PANTHOR_BO_LABEL_MAXLEN PAGE_SIZE
>
> +#define PANTHOR_BO_KERNEL BIT(0)
> +#define PANTHOR_BO_FW_MAPPED BIT(1)
> +
> +/**
> + * struct panthor_gem_debugfs - GEM object's DebugFS list information
> + */
> +struct panthor_gem_debugfs {
> + /**
> + * @node: Node used to insert the object in the device-wide list of
> + * GEM objects, to display information about it through a DebugFS file.
> + */
> + struct list_head node;
> +
> + /** @creator: Information about the UM process which created the GEM. */
> + struct {
> + /** @creator.process_name: Group leader name in owning thread's process */
> + char process_name[TASK_COMM_LEN];
> +
> + /** @creator.tgid: PID of the thread's group leader within its process */
> + pid_t tgid;
> + } creator;
> +
> + /** @bo_mask: Bitmask encoding BO type as {USER, KERNEL} x {GPU, FW} */
> + u32 bo_mask;
> +};
> +
> /**
> * struct panthor_gem_object - Driver specific GEM object.
> */
> @@ -62,6 +88,10 @@ struct panthor_gem_object {
> /** @lock.str: Protects access to the @label.str field. */
> struct mutex lock;
> } label;
> +
> +#ifdef CONFIG_DEBUG_FS
> + struct panthor_gem_debugfs debugfs;
> +#endif
> };
>
> /**
> @@ -157,4 +187,9 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
>
> void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo);
>
> +#ifdef CONFIG_DEBUG_FS
> +void panthor_gem_debugfs_print_bos(struct panthor_device *pfdev,
> + struct seq_file *m);
> +#endif
> +
> #endif /* __PANTHOR_GEM_H__ */
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 3/4] drm/panthor: Label all kernel BO's
2025-04-02 11:54 ` [PATCH v4 3/4] drm/panthor: Label all kernel BO's Adrián Larumbe
@ 2025-04-02 13:08 ` Boris Brezillon
0 siblings, 0 replies; 13+ messages in thread
From: Boris Brezillon @ 2025-04-02 13:08 UTC (permalink / raw)
To: Adrián Larumbe
Cc: Steven Price, Liviu Dudau, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, kernel, dri-devel, linux-kernel,
linux-media, linaro-mm-sig
On Wed, 2 Apr 2025 12:54:28 +0100
Adrián Larumbe <adrian.larumbe@collabora.com> wrote:
> Kernel BO's aren't exposed to UM, so labelling them is the responsibility
> of the driver itself. This kind of tagging will prove useful in further
> commits when want to expose these objects through DebugFS.
>
> Expand panthor_kernel_bo_create() interface to take a NULL-terminated
> string. No bounds checking is done because all label strings are given
> as statically-allocated literals, but if a more complex kernel BO naming
> scheme with explicit memory allocation and formatting was desired in the
> future, this would have to change.
>
> Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
> ---
> drivers/gpu/drm/panthor/panthor_fw.c | 8 +++++---
> drivers/gpu/drm/panthor/panthor_gem.c | 3 ++-
> drivers/gpu/drm/panthor/panthor_gem.h | 2 +-
> drivers/gpu/drm/panthor/panthor_heap.c | 6 ++++--
> drivers/gpu/drm/panthor/panthor_sched.c | 9 ++++++---
> 5 files changed, 18 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c
> index 4a9c4afa9ad7..36e60bb2dcc5 100644
> --- a/drivers/gpu/drm/panthor/panthor_fw.c
> +++ b/drivers/gpu/drm/panthor/panthor_fw.c
> @@ -449,7 +449,8 @@ panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev,
> DRM_PANTHOR_BO_NO_MMAP,
> DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
> DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
> - PANTHOR_VM_KERNEL_AUTO_VA);
> + PANTHOR_VM_KERNEL_AUTO_VA,
> + "Queue FW interface");
> if (IS_ERR(mem))
> return mem;
>
> @@ -481,7 +482,8 @@ panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size)
> return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size,
> DRM_PANTHOR_BO_NO_MMAP,
> DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
> - PANTHOR_VM_KERNEL_AUTO_VA);
> + PANTHOR_VM_KERNEL_AUTO_VA,
> + "FW suspend buffer");
> }
>
> static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
> @@ -601,7 +603,7 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
> section->mem = panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev),
> section_size,
> DRM_PANTHOR_BO_NO_MMAP,
> - vm_map_flags, va);
> + vm_map_flags, va, "FW Section");
nit: Let's try to use the caps consistently in the names we assign to
kernel BOs, like, cap on the first word only, or cap on each word, I
don't mind, but pick one and try to stick to it.
> if (IS_ERR(section->mem))
> return PTR_ERR(section->mem);
>
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
> index 7d017f9d1d52..44d027e6d664 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.c
> +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> @@ -81,7 +81,7 @@ void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo)
> struct panthor_kernel_bo *
> panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> size_t size, u32 bo_flags, u32 vm_map_flags,
> - u64 gpu_va)
> + u64 gpu_va, const char *name)
> {
> struct drm_gem_shmem_object *obj;
> struct panthor_kernel_bo *kbo;
> @@ -105,6 +105,7 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> kbo->obj = &obj->base;
> bo->flags = bo_flags;
>
> + panthor_gem_kernel_bo_set_label(kbo, name);
nit: can we add a blank line here, and remove the one that's after the
bo->flags assignment?
> /* The system and GPU MMU page size might differ, which becomes a
> * problem for FW sections that need to be mapped at explicit address
> * since our PAGE_SIZE alignment might cover a VA range that's
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
> index e18fbc093abd..49daa5088a0d 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.h
> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
> @@ -153,7 +153,7 @@ panthor_kernel_bo_vunmap(struct panthor_kernel_bo *bo)
> struct panthor_kernel_bo *
> panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> size_t size, u32 bo_flags, u32 vm_map_flags,
> - u64 gpu_va);
> + u64 gpu_va, const char *name);
>
> void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo);
>
> diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panthor/panthor_heap.c
> index db0285ce5812..ad122bd37ac2 100644
> --- a/drivers/gpu/drm/panthor/panthor_heap.c
> +++ b/drivers/gpu/drm/panthor/panthor_heap.c
> @@ -147,7 +147,8 @@ static int panthor_alloc_heap_chunk(struct panthor_device *ptdev,
> chunk->bo = panthor_kernel_bo_create(ptdev, vm, heap->chunk_size,
> DRM_PANTHOR_BO_NO_MMAP,
> DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
> - PANTHOR_VM_KERNEL_AUTO_VA);
> + PANTHOR_VM_KERNEL_AUTO_VA,
> + "Tiler heap chunk");
> if (IS_ERR(chunk->bo)) {
> ret = PTR_ERR(chunk->bo);
> goto err_free_chunk;
> @@ -550,7 +551,8 @@ panthor_heap_pool_create(struct panthor_device *ptdev, struct panthor_vm *vm)
> pool->gpu_contexts = panthor_kernel_bo_create(ptdev, vm, bosize,
> DRM_PANTHOR_BO_NO_MMAP,
> DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
> - PANTHOR_VM_KERNEL_AUTO_VA);
> + PANTHOR_VM_KERNEL_AUTO_VA,
> + "Heap pool");
> if (IS_ERR(pool->gpu_contexts)) {
> ret = PTR_ERR(pool->gpu_contexts);
> goto err_destroy_pool;
> diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
> index 1a276db095ff..a0b8f1ba4ea8 100644
> --- a/drivers/gpu/drm/panthor/panthor_sched.c
> +++ b/drivers/gpu/drm/panthor/panthor_sched.c
> @@ -3334,7 +3334,8 @@ group_create_queue(struct panthor_group *group,
> DRM_PANTHOR_BO_NO_MMAP,
> DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
> DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
> - PANTHOR_VM_KERNEL_AUTO_VA);
> + PANTHOR_VM_KERNEL_AUTO_VA,
> + "Ring buffer");
> if (IS_ERR(queue->ringbuf)) {
> ret = PTR_ERR(queue->ringbuf);
> goto err_free_queue;
> @@ -3364,7 +3365,8 @@ group_create_queue(struct panthor_group *group,
> DRM_PANTHOR_BO_NO_MMAP,
> DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
> DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
> - PANTHOR_VM_KERNEL_AUTO_VA);
> + PANTHOR_VM_KERNEL_AUTO_VA,
> + "fdinfo slots");
I think I'd prefer "Group job stats", just in case we end up dumping
other stuff that's not exposed through fdinfo there.
>
> if (IS_ERR(queue->profiling.slots)) {
> ret = PTR_ERR(queue->profiling.slots);
> @@ -3495,7 +3497,8 @@ int panthor_group_create(struct panthor_file *pfile,
> DRM_PANTHOR_BO_NO_MMAP,
> DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
> DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
> - PANTHOR_VM_KERNEL_AUTO_VA);
> + PANTHOR_VM_KERNEL_AUTO_VA,
> + "Group sync objects");
> if (IS_ERR(group->syncobjs)) {
> ret = PTR_ERR(group->syncobjs);
> goto err_put_group;
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/4] drm/panthor: Add driver IOCTL for setting BO labels
2025-04-02 11:54 ` [PATCH v4 2/4] drm/panthor: Add driver IOCTL for setting BO labels Adrián Larumbe
@ 2025-04-07 13:36 ` Liviu Dudau
0 siblings, 0 replies; 13+ messages in thread
From: Liviu Dudau @ 2025-04-07 13:36 UTC (permalink / raw)
To: Adrián Larumbe
Cc: Boris Brezillon, Steven Price, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, kernel, dri-devel, linux-kernel,
linux-media, linaro-mm-sig
On Wed, Apr 02, 2025 at 12:54:27PM +0100, Adrián Larumbe wrote:
> Allow UM to label a BO for which it possesses a DRM handle.
>
> Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
> ---
> drivers/gpu/drm/panthor/panthor_drv.c | 40 +++++++++++++++++++++++++++
> drivers/gpu/drm/panthor/panthor_gem.h | 2 ++
> include/uapi/drm/panthor_drm.h | 19 +++++++++++++
> 3 files changed, 61 insertions(+)
>
> diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
> index 310bb44abe1a..d5277284fe27 100644
> --- a/drivers/gpu/drm/panthor/panthor_drv.c
> +++ b/drivers/gpu/drm/panthor/panthor_drv.c
> @@ -1330,6 +1330,44 @@ static int panthor_ioctl_vm_get_state(struct drm_device *ddev, void *data,
> return 0;
> }
>
> +static int panthor_ioctl_bo_set_label(struct drm_device *ddev, void *data,
> + struct drm_file *file)
> +{
> + struct drm_panthor_bo_set_label *args = data;
> + struct drm_gem_object *obj;
> + const char *label;
> + int ret = 0;
> +
> + obj = drm_gem_object_lookup(file, args->handle);
> + if (!obj)
> + return -ENOENT;
> +
> + if (args->size && args->label) {
> + if (args->size > PANTHOR_BO_LABEL_MAXLEN) {
> + ret = -E2BIG;
> + goto err_label;
> + }
> +
> + label = strndup_user(u64_to_user_ptr(args->label), args->size);
> + if (IS_ERR(label)) {
> + ret = PTR_ERR(label);
> + goto err_label;
> + }
> + } else if (args->size && !args->label) {
> + ret = -EINVAL;
> + goto err_label;
> + } else {
> + label = NULL;
> + }
> +
> + panthor_gem_bo_set_label(obj, label);
> +
> +err_label:
> + drm_gem_object_put(obj);
> +
> + return ret;
> +}
> +
> static int
> panthor_open(struct drm_device *ddev, struct drm_file *file)
> {
> @@ -1399,6 +1437,7 @@ static const struct drm_ioctl_desc panthor_drm_driver_ioctls[] = {
> PANTHOR_IOCTL(TILER_HEAP_CREATE, tiler_heap_create, DRM_RENDER_ALLOW),
> PANTHOR_IOCTL(TILER_HEAP_DESTROY, tiler_heap_destroy, DRM_RENDER_ALLOW),
> PANTHOR_IOCTL(GROUP_SUBMIT, group_submit, DRM_RENDER_ALLOW),
> + PANTHOR_IOCTL(BO_SET_LABEL, bo_set_label, DRM_RENDER_ALLOW),
> };
>
> static int panthor_mmap(struct file *filp, struct vm_area_struct *vma)
> @@ -1508,6 +1547,7 @@ static void panthor_debugfs_init(struct drm_minor *minor)
> * - 1.2 - adds DEV_QUERY_GROUP_PRIORITIES_INFO query
> * - adds PANTHOR_GROUP_PRIORITY_REALTIME priority
> * - 1.3 - adds DRM_PANTHOR_GROUP_STATE_INNOCENT flag
> + * - 1.4 - adds DRM_IOCTL_PANTHOR_BO_SET_LABEL ioctl
Hi Adrián,
You also need to update the .minor value.
With that change,
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Best regards,
Liviu
> */
> static const struct drm_driver panthor_drm_driver = {
> .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
> index 0582826b341a..e18fbc093abd 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.h
> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
> @@ -13,6 +13,8 @@
>
> struct panthor_vm;
>
> +#define PANTHOR_BO_LABEL_MAXLEN PAGE_SIZE
> +
> /**
> * struct panthor_gem_object - Driver specific GEM object.
> */
> diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h
> index 97e2c4510e69..26b52f147360 100644
> --- a/include/uapi/drm/panthor_drm.h
> +++ b/include/uapi/drm/panthor_drm.h
> @@ -127,6 +127,9 @@ enum drm_panthor_ioctl_id {
>
> /** @DRM_PANTHOR_TILER_HEAP_DESTROY: Destroy a tiler heap. */
> DRM_PANTHOR_TILER_HEAP_DESTROY,
> +
> + /** @DRM_PANTHOR_BO_SET_LABEL: Label a BO. */
> + DRM_PANTHOR_BO_SET_LABEL,
> };
>
> /**
> @@ -977,6 +980,20 @@ struct drm_panthor_tiler_heap_destroy {
> __u32 pad;
> };
>
> +/**
> + * struct drm_panthor_bo_set_label - Arguments passed to DRM_IOCTL_PANTHOR_BO_SET_LABEL
> + */
> +struct drm_panthor_bo_set_label {
> + /** @handle: Handle of the buffer object to label. */
> + __u32 handle;
> +
> + /** @size: Length of the label, including the NULL terminator. */
> + __u32 size;
> +
> + /** @label: User pointer to a NULL-terminated string */
> + __u64 label;
> +};
> +
> /**
> * DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number
> * @__access: Access type. Must be R, W or RW.
> @@ -1019,6 +1036,8 @@ enum {
> DRM_IOCTL_PANTHOR(WR, TILER_HEAP_CREATE, tiler_heap_create),
> DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY =
> DRM_IOCTL_PANTHOR(WR, TILER_HEAP_DESTROY, tiler_heap_destroy),
> + DRM_IOCTL_PANTHOR_BO_SET_LABEL =
> + DRM_IOCTL_PANTHOR(WR, BO_SET_LABEL, bo_set_label),
> };
>
> #if defined(__cplusplus)
> --
> 2.48.1
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS
2025-04-02 12:58 ` Boris Brezillon
@ 2025-04-08 13:38 ` Adrián Larumbe
2025-04-08 13:47 ` Boris Brezillon
0 siblings, 1 reply; 13+ messages in thread
From: Adrián Larumbe @ 2025-04-08 13:38 UTC (permalink / raw)
To: Boris Brezillon
Cc: Steven Price, Liviu Dudau, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, kernel, dri-devel, linux-kernel,
linux-media, linaro-mm-sig
On 02.04.2025 14:58, Boris Brezillon wrote:
> On Wed, 2 Apr 2025 12:54:29 +0100
> Adrián Larumbe <adrian.larumbe@collabora.com> wrote:
>
> > Add a device DebugFS file that displays a complete list of all the DRM
> > GEM objects that are exposed to UM through a DRM handle.
> >
> > Since leaking object identifiers that might belong to a different NS is
> > inadmissible, this functionality is only made available in debug builds
> > with DEBUGFS support enabled.
> >
> > File format is that of a table, with each entry displaying a variety of
> > fields with information about each GEM object.
> >
> > Each GEM object entry in the file displays the following information
> > fields: Client PID, BO's global name, reference count, BO virtual size,
> > BO resize size, VM address in its DRM-managed range, BO label and a flag
> > bitmask.
> >
> > There's also a kflags field for the type of BO. Bit 0 tells us whether
> > it's a kernel BO, and bit 1 means the BO is mapped onto the FW's address
> > space.
> >
> > Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
> > ---
> > drivers/gpu/drm/panthor/panthor_device.c | 5 +
> > drivers/gpu/drm/panthor/panthor_device.h | 11 ++
> > drivers/gpu/drm/panthor/panthor_drv.c | 26 ++++
> > drivers/gpu/drm/panthor/panthor_gem.c | 149 +++++++++++++++++++++++
> > drivers/gpu/drm/panthor/panthor_gem.h | 35 ++++++
> > 5 files changed, 226 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
> > index a9da1d1eeb70..b776e1a2e4f3 100644
> > --- a/drivers/gpu/drm/panthor/panthor_device.c
> > +++ b/drivers/gpu/drm/panthor/panthor_device.c
> > @@ -184,6 +184,11 @@ int panthor_device_init(struct panthor_device *ptdev)
> > if (ret)
> > return ret;
> >
> > +#ifdef CONFIG_DEBUG_FS
> > + drmm_mutex_init(&ptdev->base, &ptdev->gems.lock);
> > + INIT_LIST_HEAD(&ptdev->gems.node);
> > +#endif
> > +
> > atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED);
> > p = alloc_page(GFP_KERNEL | __GFP_ZERO);
> > if (!p)
> > diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
> > index da6574021664..86206a961b38 100644
> > --- a/drivers/gpu/drm/panthor/panthor_device.h
> > +++ b/drivers/gpu/drm/panthor/panthor_device.h
> > @@ -205,6 +205,17 @@ struct panthor_device {
> >
> > /** @fast_rate: Maximum device clock frequency. Set by DVFS */
> > unsigned long fast_rate;
> > +
> > +#ifdef CONFIG_DEBUG_FS
> > + /** @gems: Device-wide list of GEM objects owned by at least one file. */
> > + struct {
> > + /** @gems.lock: Protects the device-wide list of GEM objects. */
> > + struct mutex lock;
> > +
> > + /** @node: Used to keep track of all the device's DRM objects */
> > + struct list_head node;
> > + } gems;
> > +#endif
> > };
> >
> > struct panthor_gpu_usage {
> > diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
> > index d5277284fe27..3e870ed2ad90 100644
> > --- a/drivers/gpu/drm/panthor/panthor_drv.c
> > +++ b/drivers/gpu/drm/panthor/panthor_drv.c
> > @@ -1534,9 +1534,35 @@ static const struct file_operations panthor_drm_driver_fops = {
> > };
> >
> > #ifdef CONFIG_DEBUG_FS
> > +static int panthor_gems_show(struct seq_file *m, void *data)
> > +{
> > + struct drm_info_node *node = m->private;
> > + struct drm_device *dev = node->minor->dev;
> > + struct panthor_device *ptdev = container_of(dev, struct panthor_device, base);
> > +
> > + panthor_gem_debugfs_print_bos(ptdev, m);
> > +
> > + return 0;
> > +}
> > +
> > +
> > +static struct drm_info_list panthor_debugfs_list[] = {
> > + {"gems", panthor_gems_show, 0, NULL},
> > +};
> > +
> > +static int panthor_gems_debugfs_init(struct drm_minor *minor)
> > +{
> > + drm_debugfs_create_files(panthor_debugfs_list,
> > + ARRAY_SIZE(panthor_debugfs_list),
> > + minor->debugfs_root, minor);
> > +
> > + return 0;
> > +}
> > +
> > static void panthor_debugfs_init(struct drm_minor *minor)
> > {
> > panthor_mmu_debugfs_init(minor);
> > + panthor_gems_debugfs_init(minor);
> > }
> > #endif
> >
> > diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
> > index 44d027e6d664..2fc87be9b700 100644
> > --- a/drivers/gpu/drm/panthor/panthor_gem.c
> > +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> > @@ -2,6 +2,7 @@
> > /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
> > /* Copyright 2023 Collabora ltd. */
> >
> > +#include <linux/cleanup.h>
> > #include <linux/dma-buf.h>
> > #include <linux/dma-mapping.h>
> > #include <linux/err.h>
> > @@ -10,14 +11,65 @@
> > #include <drm/panthor_drm.h>
> >
> > #include "panthor_device.h"
> > +#include "panthor_fw.h"
> > #include "panthor_gem.h"
> > #include "panthor_mmu.h"
> >
> > +#ifdef CONFIG_DEBUG_FS
> > +static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo, u32 type_mask)
> > +{
> > + INIT_LIST_HEAD(&bo->debugfs.node);
>
> This should be called when the GEM object is created, otherwise the
> list_empty() test done in panthor_gem_debugfs_bo_rm() will only work if
> panthor_gem_debugfs_bo_add() is called, and depending on when this
> happens, or whether it happens at all, the error path will do a NULL
> deref.
I'll be moving panthor_gem_debugfs_bo_add() back into panthor_gem_create_object() and
inline panthor_gem_debugfs_bo_init() into it.
> > +
> > + if (!(type_mask & PANTHOR_BO_FW_MAPPED)) {
> > + bo->debugfs.creator.tgid = current->group_leader->pid;
> > + get_task_comm(bo->debugfs.creator.process_name, current->group_leader);
>
> I don't think that's good to assume that FW-mapped BOs have been
> created by the kernel without userspace directly or indirectly asking
> for the allocation. For instance, per-group memory allocated for the
> USER_CS interfaces are indirectly triggered by a GROUP_CREATE ioctl(),
> and should IMO be flagged as being created by the process that
> created the group. Don't we have another way to check if we're called
> from a kernel thread?
True, I completely missed this. I did some research of the kernel API and apparently
is_kthread() might do the job.
> > + } else {
> > + bo->debugfs.creator.tgid = 0;
> > + snprintf(bo->debugfs.creator.process_name,
> > + sizeof(bo->debugfs.creator.process_name),
> > + "kernel");
> > + }
> > +
> > + bo->debugfs.bo_mask = type_mask;
>
> Why not do that directly in panthor_gem_debugfs_bo_add()? The only bits
> that might be useful to do early is the INIT_LIST_HEAD(), and I think
> it can be inlined in panthor_gem_create_object().
I'll be doing in this in the next revision, but because I've no access to the BO
type mask from inside Panthor's drm_driver::gem_create_object() binding, then
I'll have to assign the mask right after the object has been created.
I think this means there might be a short window after the object's been added to
the DebugFS GEMs list in which it could be shown with the kernel mask field still
set to 0, but I guess that's not too important either.
> > +}
> > +
> > +static void panthor_gem_debugfs_bo_add(struct panthor_gem_object *bo, u32 type_mask)
> > +{
> > + struct panthor_device *ptdev = container_of(bo->base.base.dev,
> > + struct panthor_device, base);
> > +
> > + panthor_gem_debugfs_bo_init(bo, type_mask);
> > +
> > + mutex_lock(&ptdev->gems.lock);
> > + list_add_tail(&bo->debugfs.node, &ptdev->gems.node);
> > + mutex_unlock(&ptdev->gems.lock);
> > +}
> > +
> > +static void panthor_gem_debugfs_bo_rm(struct panthor_gem_object *bo)
> > +{
> > + struct panthor_device *ptdev = container_of(bo->base.base.dev,
> > + struct panthor_device, base);
> > +
> > + if (list_empty(&bo->debugfs.node))
> > + return;
> > +
> > + mutex_lock(&ptdev->gems.lock);
> > + list_del_init(&bo->debugfs.node);
> > + mutex_unlock(&ptdev->gems.lock);
> > +}
> > +
> > +#else
> > +static void panthor_gem_debugfs_bo_add(struct panthor_gem_object *bo, u32 type_mask) {}
> > +static void panthor_gem_debugfs_bo_rm(struct panthor_gem_object *bo) {}
> > +#endif
> > +
> > static void panthor_gem_free_object(struct drm_gem_object *obj)
> > {
> > struct panthor_gem_object *bo = to_panthor_bo(obj);
> > struct drm_gem_object *vm_root_gem = bo->exclusive_vm_root_gem;
> >
> > + panthor_gem_debugfs_bo_rm(bo);
> > +
> > /*
> > * Label might have been allocated with kstrdup_const(),
> > * we need to take that into account when freeing the memory
> > @@ -86,6 +138,7 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> > struct drm_gem_shmem_object *obj;
> > struct panthor_kernel_bo *kbo;
> > struct panthor_gem_object *bo;
> > + u32 type_mask = PANTHOR_BO_KERNEL;
> > int ret;
> >
> > if (drm_WARN_ON(&ptdev->base, !vm))
> > @@ -105,7 +158,12 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> > kbo->obj = &obj->base;
> > bo->flags = bo_flags;
> >
> > + if (vm == panthor_fw_vm(ptdev))
> > + type_mask |= PANTHOR_BO_FW_MAPPED;
> > +
> > panthor_gem_kernel_bo_set_label(kbo, name);
> > + panthor_gem_debugfs_bo_add(to_panthor_bo(kbo->obj), type_mask);
> > +
> > /* The system and GPU MMU page size might differ, which becomes a
> > * problem for FW sections that need to be mapped at explicit address
> > * since our PAGE_SIZE alignment might cover a VA range that's
> > @@ -255,6 +313,8 @@ panthor_gem_create_with_handle(struct drm_file *file,
> > /* drop reference from allocate - handle holds it now. */
> > drm_gem_object_put(&shmem->base);
> >
> > + panthor_gem_debugfs_bo_add(bo, 0);
> > +
> > return ret;
> > }
> >
> > @@ -286,3 +346,92 @@ panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label)
> >
> > panthor_gem_bo_set_label(bo->obj, kstrdup_const(str, GFP_KERNEL));
> > }
> > +
> > +#ifdef CONFIG_DEBUG_FS
> > +static bool panfrost_gem_print_flag(const char *name,
> > + bool is_set,
> > + bool other_flags_printed,
> > + struct seq_file *m)
> > +{
> > + if (is_set)
> > + seq_printf(m, "%s%s", other_flags_printed ? "," : "", name);
> > +
> > + return is_set | other_flags_printed;
> > +}
> > +
> > +struct gem_size_totals {
> > + size_t size;
> > + size_t resident;
> > + size_t reclaimable;
> > +};
> > +
> > +static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo,
> > + struct seq_file *m,
> > + struct gem_size_totals *totals)
> > +{
> > + unsigned int refcount = kref_read(&bo->base.base.refcount);
> > + char creator_info[32] = {};
> > + bool has_flags = false;
> > + size_t resident_size;
> > +
> > + /* Skip BOs being destroyed. */
> > + if (!refcount)
> > + return;
> > +
> > + resident_size = bo->base.pages != NULL ? bo->base.base.size : 0;
> > +
> > + snprintf(creator_info, sizeof(creator_info),
> > + "%s/%d", bo->debugfs.creator.process_name, bo->debugfs.creator.tgid);
> > + seq_printf(m, "%-32s%-16d%-16d%-16zd%-16zd%-16lx",
> > + creator_info,
> > + bo->base.base.name,
> > + refcount,
> > + bo->base.base.size,
> > + resident_size,
> > + drm_vma_node_start(&bo->base.base.vma_node));
> > +
> > + seq_puts(m, "(");
> > + has_flags = panfrost_gem_print_flag("imported", bo->base.base.import_attach != NULL,
> > + has_flags, m);
> > + has_flags = panfrost_gem_print_flag("exported", bo->base.base.dma_buf != NULL,
> > + has_flags, m);
> > + if (bo->base.madv < 0)
> > + has_flags = panfrost_gem_print_flag("purged", true, has_flags, m);
> > + else if (bo->base.madv > 0)
> > + has_flags = panfrost_gem_print_flag("purgeable", true, has_flags, m);
> > + if (!has_flags)
> > + seq_puts(m, "none");
> > + seq_puts(m, ")");
> > +
> > + seq_printf(m, "%-6s0x%-2x", "", bo->debugfs.bo_mask);
> > +
> > + mutex_lock(&bo->label.lock);
> > + seq_printf(m, "%-6s%-60s", "", bo->label.str ? : NULL);
> > + mutex_unlock(&bo->label.lock);
> > + seq_puts(m, "\n");
> > +
> > + totals->size += bo->base.base.size;
> > + totals->resident += resident_size;
> > + if (bo->base.madv > 0)
> > + totals->reclaimable += resident_size;
> > +}
> > +
> > +void panthor_gem_debugfs_print_bos(struct panthor_device *ptdev,
> > + struct seq_file *m)
> > +{
> > + struct gem_size_totals totals = {0};
> > + struct panthor_gem_object *bo;
> > +
> > + seq_puts(m, "created-by global-name refcount size resident-size file-offset flags kflags label\n");
> > + seq_puts(m, "------------------------------------------------------------------------------------------------------------------------------------------------\n");
> > +
> > + scoped_guard(mutex, &ptdev->gems.lock) {
> > + list_for_each_entry(bo, &ptdev->gems.node, debugfs.node)
> > + panthor_gem_debugfs_bo_print(bo, m, &totals);
> > + }
> > +
> > + seq_puts(m, "==========================================================================================================================================================\n");
> > + seq_printf(m, "Total size: %zd, Total resident: %zd, Total reclaimable: %zd\n",
> > + totals.size, totals.resident, totals.reclaimable);
> > +}
> > +#endif
> > diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
> > index 49daa5088a0d..22ecc0d39d5e 100644
> > --- a/drivers/gpu/drm/panthor/panthor_gem.h
> > +++ b/drivers/gpu/drm/panthor/panthor_gem.h
> > @@ -15,6 +15,32 @@ struct panthor_vm;
> >
> > #define PANTHOR_BO_LABEL_MAXLEN PAGE_SIZE
> >
> > +#define PANTHOR_BO_KERNEL BIT(0)
> > +#define PANTHOR_BO_FW_MAPPED BIT(1)
> > +
> > +/**
> > + * struct panthor_gem_debugfs - GEM object's DebugFS list information
> > + */
> > +struct panthor_gem_debugfs {
> > + /**
> > + * @node: Node used to insert the object in the device-wide list of
> > + * GEM objects, to display information about it through a DebugFS file.
> > + */
> > + struct list_head node;
> > +
> > + /** @creator: Information about the UM process which created the GEM. */
> > + struct {
> > + /** @creator.process_name: Group leader name in owning thread's process */
> > + char process_name[TASK_COMM_LEN];
> > +
> > + /** @creator.tgid: PID of the thread's group leader within its process */
> > + pid_t tgid;
> > + } creator;
> > +
> > + /** @bo_mask: Bitmask encoding BO type as {USER, KERNEL} x {GPU, FW} */
> > + u32 bo_mask;
> > +};
> > +
> > /**
> > * struct panthor_gem_object - Driver specific GEM object.
> > */
> > @@ -62,6 +88,10 @@ struct panthor_gem_object {
> > /** @lock.str: Protects access to the @label.str field. */
> > struct mutex lock;
> > } label;
> > +
> > +#ifdef CONFIG_DEBUG_FS
> > + struct panthor_gem_debugfs debugfs;
> > +#endif
> > };
> >
> > /**
> > @@ -157,4 +187,9 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> >
> > void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo);
> >
> > +#ifdef CONFIG_DEBUG_FS
> > +void panthor_gem_debugfs_print_bos(struct panthor_device *pfdev,
> > + struct seq_file *m);
> > +#endif
> > +
> > #endif /* __PANTHOR_GEM_H__ */
Adrian Larumbe
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS
2025-04-08 13:38 ` Adrián Larumbe
@ 2025-04-08 13:47 ` Boris Brezillon
2025-04-08 14:38 ` Adrián Larumbe
0 siblings, 1 reply; 13+ messages in thread
From: Boris Brezillon @ 2025-04-08 13:47 UTC (permalink / raw)
To: Adrián Larumbe
Cc: Steven Price, Liviu Dudau, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, kernel, dri-devel, linux-kernel,
linux-media, linaro-mm-sig
On Tue, 8 Apr 2025 14:38:44 +0100
Adrián Larumbe <adrian.larumbe@collabora.com> wrote:
> > > diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
> > > index 44d027e6d664..2fc87be9b700 100644
> > > --- a/drivers/gpu/drm/panthor/panthor_gem.c
> > > +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> > > @@ -2,6 +2,7 @@
> > > /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
> > > /* Copyright 2023 Collabora ltd. */
> > >
> > > +#include <linux/cleanup.h>
> > > #include <linux/dma-buf.h>
> > > #include <linux/dma-mapping.h>
> > > #include <linux/err.h>
> > > @@ -10,14 +11,65 @@
> > > #include <drm/panthor_drm.h>
> > >
> > > #include "panthor_device.h"
> > > +#include "panthor_fw.h"
> > > #include "panthor_gem.h"
> > > #include "panthor_mmu.h"
> > >
> > > +#ifdef CONFIG_DEBUG_FS
> > > +static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo, u32 type_mask)
> > > +{
> > > + INIT_LIST_HEAD(&bo->debugfs.node);
> >
> > This should be called when the GEM object is created, otherwise the
> > list_empty() test done in panthor_gem_debugfs_bo_rm() will only work if
> > panthor_gem_debugfs_bo_add() is called, and depending on when this
> > happens, or whether it happens at all, the error path will do a NULL
> > deref.
>
> I'll be moving panthor_gem_debugfs_bo_add() back into panthor_gem_create_object() and
> inline panthor_gem_debugfs_bo_init() into it.
You mean moving the panthor_gem_debugfs_bo_add() call to
panthor_gem_create_object(), not inlining its content, right?
> > > + } else {
> > > + bo->debugfs.creator.tgid = 0;
> > > + snprintf(bo->debugfs.creator.process_name,
> > > + sizeof(bo->debugfs.creator.process_name),
> > > + "kernel");
> > > + }
> > > +
> > > + bo->debugfs.bo_mask = type_mask;
> >
> > Why not do that directly in panthor_gem_debugfs_bo_add()? The only bits
> > that might be useful to do early is the INIT_LIST_HEAD(), and I think
> > it can be inlined in panthor_gem_create_object().
>
> I'll be doing in this in the next revision, but because I've no access to the BO
> type mask from inside Panthor's drm_driver::gem_create_object() binding, then
> I'll have to assign the mask right after the object has been created.
>
> I think this means there might be a short window after the object's been added to
> the DebugFS GEMs list in which it could be shown with the kernel mask field still
> set to 0, but I guess that's not too important either.
I think it's okay, as long as you don't crash when printing partially
initialized objects. Another solution would be to have a flag encoding
when the obj is initialized, so you can skip objects that don't have
this flag set yet.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS
2025-04-08 13:47 ` Boris Brezillon
@ 2025-04-08 14:38 ` Adrián Larumbe
2025-04-08 14:46 ` Boris Brezillon
0 siblings, 1 reply; 13+ messages in thread
From: Adrián Larumbe @ 2025-04-08 14:38 UTC (permalink / raw)
To: Boris Brezillon
Cc: Steven Price, Liviu Dudau, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, kernel, dri-devel, linux-kernel,
linux-media, linaro-mm-sig
On 08.04.2025 15:47, Boris Brezillon wrote:
On Tue, 8 Apr 2025 14:38:44 +0100
Adrián Larumbe <adrian.larumbe@collabora.com> wrote:
> > > > diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
> > > > index 44d027e6d664..2fc87be9b700 100644
> > > > --- a/drivers/gpu/drm/panthor/panthor_gem.c
> > > > +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> > > > @@ -2,6 +2,7 @@
> > > > /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
> > > > /* Copyright 2023 Collabora ltd. */
> > > >
> > > > +#include <linux/cleanup.h>
> > > > #include <linux/dma-buf.h>
> > > > #include <linux/dma-mapping.h>
> > > > #include <linux/err.h>
> > > > @@ -10,14 +11,65 @@
> > > > #include <drm/panthor_drm.h>
> > > >
> > > > #include "panthor_device.h"
> > > > +#include "panthor_fw.h"
> > > > #include "panthor_gem.h"
> > > > #include "panthor_mmu.h"
> > > >
> > > > +#ifdef CONFIG_DEBUG_FS
> > > > +static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo, u32 type_mask)
> > > > +{
> > > > + INIT_LIST_HEAD(&bo->debugfs.node);
> > >
> > > This should be called when the GEM object is created, otherwise the
> > > list_empty() test done in panthor_gem_debugfs_bo_rm() will only work if
> > > panthor_gem_debugfs_bo_add() is called, and depending on when this
> > > happens, or whether it happens at all, the error path will do a NULL
> > > deref.
> >
> > I'll be moving panthor_gem_debugfs_bo_add() back into panthor_gem_create_object() and
> > inline panthor_gem_debugfs_bo_init() into it.
>
> You mean moving the panthor_gem_debugfs_bo_add() call to
> panthor_gem_create_object(), not inlining its content, right?
Yes, inlining panthor_gem_debugfs_bo_init() into panthor_gem_debugfs_bo_add() and moving
panthor_gem_debugfs_bo_add() into panthor_gem_create_object().
> > > > + } else {
> > > > + bo->debugfs.creator.tgid = 0;
> > > > + snprintf(bo->debugfs.creator.process_name,
> > > > + sizeof(bo->debugfs.creator.process_name),
> > > > + "kernel");
> > > > + }
> > > > +
> > > > + bo->debugfs.bo_mask = type_mask;
> > >
> > > Why not do that directly in panthor_gem_debugfs_bo_add()? The only bits
> > > that might be useful to do early is the INIT_LIST_HEAD(), and I think
> > > it can be inlined in panthor_gem_create_object().
> >
> > I'll be doing in this in the next revision, but because I've no access to the BO
> > type mask from inside Panthor's drm_driver::gem_create_object() binding, then
> > I'll have to assign the mask right after the object has been created.
> >
> > I think this means there might be a short window after the object's been added to
> > the DebugFS GEMs list in which it could be shown with the kernel mask field still
> > set to 0, but I guess that's not too important either.
>
> I think it's okay, as long as you don't crash when printing partially
> initialized objects. Another solution would be to have a flag encoding
> when the obj is initialized, so you can skip objects that don't have
> this flag set yet.
I think what I'll do is set the mask to a poison value, maybe 0xFF, and only when
it's overwritten with a legitimate value, display the object in the DebugFS GEMS file.
Adrian Larumbe
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS
2025-04-08 14:38 ` Adrián Larumbe
@ 2025-04-08 14:46 ` Boris Brezillon
0 siblings, 0 replies; 13+ messages in thread
From: Boris Brezillon @ 2025-04-08 14:46 UTC (permalink / raw)
To: Adrián Larumbe
Cc: Steven Price, Liviu Dudau, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, kernel, dri-devel, linux-kernel,
linux-media, linaro-mm-sig
On Tue, 8 Apr 2025 15:38:18 +0100
Adrián Larumbe <adrian.larumbe@collabora.com> wrote:
> On 08.04.2025 15:47, Boris Brezillon wrote:
> On Tue, 8 Apr 2025 14:38:44 +0100
> Adrián Larumbe <adrian.larumbe@collabora.com> wrote:
>
> > > > > diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
> > > > > index 44d027e6d664..2fc87be9b700 100644
> > > > > --- a/drivers/gpu/drm/panthor/panthor_gem.c
> > > > > +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> > > > > @@ -2,6 +2,7 @@
> > > > > /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
> > > > > /* Copyright 2023 Collabora ltd. */
> > > > >
> > > > > +#include <linux/cleanup.h>
> > > > > #include <linux/dma-buf.h>
> > > > > #include <linux/dma-mapping.h>
> > > > > #include <linux/err.h>
> > > > > @@ -10,14 +11,65 @@
> > > > > #include <drm/panthor_drm.h>
> > > > >
> > > > > #include "panthor_device.h"
> > > > > +#include "panthor_fw.h"
> > > > > #include "panthor_gem.h"
> > > > > #include "panthor_mmu.h"
> > > > >
> > > > > +#ifdef CONFIG_DEBUG_FS
> > > > > +static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo, u32 type_mask)
> > > > > +{
> > > > > + INIT_LIST_HEAD(&bo->debugfs.node);
> > > >
> > > > This should be called when the GEM object is created, otherwise the
> > > > list_empty() test done in panthor_gem_debugfs_bo_rm() will only work if
> > > > panthor_gem_debugfs_bo_add() is called, and depending on when this
> > > > happens, or whether it happens at all, the error path will do a NULL
> > > > deref.
> > >
> > > I'll be moving panthor_gem_debugfs_bo_add() back into panthor_gem_create_object() and
> > > inline panthor_gem_debugfs_bo_init() into it.
> >
> > You mean moving the panthor_gem_debugfs_bo_add() call to
> > panthor_gem_create_object(), not inlining its content, right?
>
> Yes, inlining panthor_gem_debugfs_bo_init() into panthor_gem_debugfs_bo_add() and moving
> panthor_gem_debugfs_bo_add() into panthor_gem_create_object().
>
> > > > > + } else {
> > > > > + bo->debugfs.creator.tgid = 0;
> > > > > + snprintf(bo->debugfs.creator.process_name,
> > > > > + sizeof(bo->debugfs.creator.process_name),
> > > > > + "kernel");
> > > > > + }
> > > > > +
> > > > > + bo->debugfs.bo_mask = type_mask;
> > > >
> > > > Why not do that directly in panthor_gem_debugfs_bo_add()? The only bits
> > > > that might be useful to do early is the INIT_LIST_HEAD(), and I think
> > > > it can be inlined in panthor_gem_create_object().
> > >
> > > I'll be doing in this in the next revision, but because I've no access to the BO
> > > type mask from inside Panthor's drm_driver::gem_create_object() binding, then
> > > I'll have to assign the mask right after the object has been created.
> > >
> > > I think this means there might be a short window after the object's been added to
> > > the DebugFS GEMs list in which it could be shown with the kernel mask field still
> > > set to 0, but I guess that's not too important either.
> >
> > I think it's okay, as long as you don't crash when printing partially
> > initialized objects. Another solution would be to have a flag encoding
> > when the obj is initialized, so you can skip objects that don't have
> > this flag set yet.
>
> I think what I'll do is set the mask to a poison value, maybe 0xFF, and only when
> it's overwritten with a legitimate value, display the object in the DebugFS GEMS file.
Well, it's just as simple to leave it to zero at bo_add() time, and
have an INITIALIZED flag that you set along the other flags in the
caller of gem_shmem_create(). If you make it a poison value, you'll
need to make sure it never conflicts with a valid flag combination,
which might be annoying.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS
2025-04-02 11:54 ` [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS Adrián Larumbe
2025-04-02 12:58 ` Boris Brezillon
@ 2025-04-08 15:26 ` Boris Brezillon
1 sibling, 0 replies; 13+ messages in thread
From: Boris Brezillon @ 2025-04-08 15:26 UTC (permalink / raw)
To: Adrián Larumbe
Cc: Steven Price, Liviu Dudau, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, kernel, dri-devel, linux-kernel,
linux-media, linaro-mm-sig
On Wed, 2 Apr 2025 12:54:29 +0100
Adrián Larumbe <adrian.larumbe@collabora.com> wrote:
> +static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo,
> + struct seq_file *m,
> + struct gem_size_totals *totals)
> +{
> + unsigned int refcount = kref_read(&bo->base.base.refcount);
> + char creator_info[32] = {};
> + bool has_flags = false;
> + size_t resident_size;
> +
> + /* Skip BOs being destroyed. */
> + if (!refcount)
> + return;
> +
> + resident_size = bo->base.pages != NULL ? bo->base.base.size : 0;
> +
> + snprintf(creator_info, sizeof(creator_info),
> + "%s/%d", bo->debugfs.creator.process_name, bo->debugfs.creator.tgid);
> + seq_printf(m, "%-32s%-16d%-16d%-16zd%-16zd%-16lx",
> + creator_info,
> + bo->base.base.name,
> + refcount,
> + bo->base.base.size,
> + resident_size,
> + drm_vma_node_start(&bo->base.base.vma_node));
> +
> + seq_puts(m, "(");
> + has_flags = panfrost_gem_print_flag("imported", bo->base.base.import_attach != NULL,
> + has_flags, m);
> + has_flags = panfrost_gem_print_flag("exported", bo->base.base.dma_buf != NULL,
> + has_flags, m);
> + if (bo->base.madv < 0)
> + has_flags = panfrost_gem_print_flag("purged", true, has_flags, m);
> + else if (bo->base.madv > 0)
> + has_flags = panfrost_gem_print_flag("purgeable", true, has_flags, m);
I would probably go:
has_flags = panfrost_gem_print_flag("purged", bo->base.madv < 0, has_flags, m);
has_flags = panfrost_gem_print_flag("purgeable", bo->base.madv > 0, has_flags, m);
to keep it one line per flag.
BTW, most of those flags are encoding the GEM state, so maybe the column
should be named state, and the helper panfrost_gem_print_state_flag().
> + if (!has_flags)
> + seq_puts(m, "none");
> + seq_puts(m, ")");
> +
> + seq_printf(m, "%-6s0x%-2x", "", bo->debugfs.bo_mask);
It's probably better if we print the debugfs flags like the GEM flags
(one string per flag, with a ',' separator). We can even make it a
helper function taking a list of flags and their associated strings so
we can use it for both panthor_gem_object::flags and
panthor_gem_object::debugfs::flags.
static void
panthor_gem_debugfs_print_flags(const char *names,
u32 name_count,
u32 flags)
{
bool first = true;
seq_puts(m, "(");
if (!flags)
seq_puts(m, "none");
while (flags) {
u32 bit = fls(flags) - 1;
if (!first)
seq_puts(m, ",");
if (bit >= name_count || !names[bit])
seq_printf(m, "unknown-bit%d", bit);
else
seq_puts(m, name);
first = false;
flags &= ~BIT(bit);
}
seq_puts(m, ")");
}
> +
> + mutex_lock(&bo->label.lock);
> + seq_printf(m, "%-6s%-60s", "", bo->label.str ? : NULL);
> + mutex_unlock(&bo->label.lock);
> + seq_puts(m, "\n");
> +
> + totals->size += bo->base.base.size;
> + totals->resident += resident_size;
> + if (bo->base.madv > 0)
> + totals->reclaimable += resident_size;
> +}
> +
> +void panthor_gem_debugfs_print_bos(struct panthor_device *ptdev,
> + struct seq_file *m)
> +{
> + struct gem_size_totals totals = {0};
> + struct panthor_gem_object *bo;
> +
> + seq_puts(m, "created-by global-name refcount size resident-size file-offset flags kflags label\n");
> + seq_puts(m, "------------------------------------------------------------------------------------------------------------------------------------------------\n");
> +
> + scoped_guard(mutex, &ptdev->gems.lock) {
> + list_for_each_entry(bo, &ptdev->gems.node, debugfs.node)
> + panthor_gem_debugfs_bo_print(bo, m, &totals);
> + }
> +
> + seq_puts(m, "==========================================================================================================================================================\n");
> + seq_printf(m, "Total size: %zd, Total resident: %zd, Total reclaimable: %zd\n",
> + totals.size, totals.resident, totals.reclaimable);
> +}
> +#endif
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
> index 49daa5088a0d..22ecc0d39d5e 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.h
> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
> @@ -15,6 +15,32 @@ struct panthor_vm;
>
> #define PANTHOR_BO_LABEL_MAXLEN PAGE_SIZE
>
> +#define PANTHOR_BO_KERNEL BIT(0)
s/PANTHOR_BO_KERNEL/PANTHOR_DEBUGFS_BO_FLAG_KERNEL/
> +#define PANTHOR_BO_FW_MAPPED BIT(1)
s/PANTHOR_BO_FW_MAPPED/PANTHOR_DEBUGFS_BO_FLAG_FW_MAPPED/
And it'd be better if those flags were documented.
I would also add a
#define PANTHOR_DEBUGFS_BO_FLAG_INITIALIZED BIT(0)
and move the other flags one bit left.
> +
> +/**
> + * struct panthor_gem_debugfs - GEM object's DebugFS list information
> + */
> +struct panthor_gem_debugfs {
> + /**
> + * @node: Node used to insert the object in the device-wide list of
> + * GEM objects, to display information about it through a DebugFS file.
> + */
> + struct list_head node;
> +
> + /** @creator: Information about the UM process which created the GEM. */
> + struct {
> + /** @creator.process_name: Group leader name in owning thread's process */
> + char process_name[TASK_COMM_LEN];
> +
> + /** @creator.tgid: PID of the thread's group leader within its process */
> + pid_t tgid;
> + } creator;
> +
> + /** @bo_mask: Bitmask encoding BO type as {USER, KERNEL} x {GPU, FW} */
> + u32 bo_mask;
s/bo_mask/flags/ and mention that it's a combination of
PANTHOR_DEBUGFS_BO_FLAG_xxx in the doc.
> +};
> +
> /**
> * struct panthor_gem_object - Driver specific GEM object.
> */
> @@ -62,6 +88,10 @@ struct panthor_gem_object {
> /** @lock.str: Protects access to the @label.str field. */
> struct mutex lock;
> } label;
> +
> +#ifdef CONFIG_DEBUG_FS
> + struct panthor_gem_debugfs debugfs;
> +#endif
> };
>
> /**
> @@ -157,4 +187,9 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
>
> void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo);
>
> +#ifdef CONFIG_DEBUG_FS
> +void panthor_gem_debugfs_print_bos(struct panthor_device *pfdev,
> + struct seq_file *m);
> +#endif
> +
> #endif /* __PANTHOR_GEM_H__ */
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-04-08 15:26 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-02 11:54 [PATCH v4 0/4] Panthor BO tagging and GEMS debug display Adrián Larumbe
2025-04-02 11:54 ` [PATCH v4 1/4] drm/panthor: Introduce BO labeling Adrián Larumbe
2025-04-02 11:54 ` [PATCH v4 2/4] drm/panthor: Add driver IOCTL for setting BO labels Adrián Larumbe
2025-04-07 13:36 ` Liviu Dudau
2025-04-02 11:54 ` [PATCH v4 3/4] drm/panthor: Label all kernel BO's Adrián Larumbe
2025-04-02 13:08 ` Boris Brezillon
2025-04-02 11:54 ` [PATCH v4 4/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS Adrián Larumbe
2025-04-02 12:58 ` Boris Brezillon
2025-04-08 13:38 ` Adrián Larumbe
2025-04-08 13:47 ` Boris Brezillon
2025-04-08 14:38 ` Adrián Larumbe
2025-04-08 14:46 ` Boris Brezillon
2025-04-08 15:26 ` Boris Brezillon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox