From: Boris Brezillon <boris.brezillon@collabora.com>
To: "Adrián Larumbe" <adrian.larumbe@collabora.com>
Cc: "Steven Price" <steven.price@arm.com>,
"Liviu Dudau" <liviu.dudau@arm.com>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Sumit Semwal" <sumit.semwal@linaro.org>,
"Christian König" <christian.koenig@amd.com>,
kernel@collabora.com, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org, linux-media@vger.kernel.org,
linaro-mm-sig@lists.linaro.org
Subject: Re: [PATCH 3/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS
Date: Mon, 17 Mar 2025 09:26:14 +0100 [thread overview]
Message-ID: <20250317092614.55b3c4e9@collabora.com> (raw)
In-Reply-To: <20250316215139.3940623-4-adrian.larumbe@collabora.com>
On Sun, 16 Mar 2025 21:51:34 +0000
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.
>
> 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 | 8 ++
> drivers/gpu/drm/panthor/panthor_drv.c | 26 ++++++
> drivers/gpu/drm/panthor/panthor_gem.c | 101 +++++++++++++++++++++++
> drivers/gpu/drm/panthor/panthor_gem.h | 22 +++++
> 5 files changed, 162 insertions(+)
>
> diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
> index a9da1d1eeb70..7df12eefc39f 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.c
> +++ b/drivers/gpu/drm/panthor/panthor_device.c
> @@ -263,6 +263,11 @@ int panthor_device_init(struct panthor_device *ptdev)
> pm_runtime_set_autosuspend_delay(ptdev->base.dev, 50);
> pm_runtime_use_autosuspend(ptdev->base.dev);
>
> +#ifdef CONFIG_DEBUG_FS
> + drmm_mutex_init(&ptdev->base, &ptdev->gems_lock);
> + INIT_LIST_HEAD(&ptdev->gems);
> +#endif
> +
> ret = drm_dev_register(&ptdev->base, 0);
> if (ret)
> goto err_disable_autosuspend;
> diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
> index da6574021664..6c030978cdc3 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.h
> +++ b/drivers/gpu/drm/panthor/panthor_device.h
> @@ -205,6 +205,14 @@ struct panthor_device {
>
> /** @fast_rate: Maximum device clock frequency. Set by DVFS */
> unsigned long fast_rate;
> +
> +#ifdef CONFIG_DEBUG_FS
> + /** @gems_lock: Protects the device-wide list of GEM objects. */
> + struct mutex gems_lock;
> +
> + /** @gems: Device-wide list of GEM objects owned by at least one file. */
> + struct list_head gems;
struct {
struct mutex lock;
struct list_head list;
} 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 f41b8946258f..6663eff44bdc 100644
> --- a/drivers/gpu/drm/panthor/panthor_drv.c
> +++ b/drivers/gpu/drm/panthor/panthor_drv.c
> @@ -1525,9 +1525,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_print_objects(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 3c58bb2965ea..8cea6caf3143 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.c
> +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> @@ -17,6 +17,16 @@ 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;
> +#ifdef CONFIG_DEBUG_FS
> + struct drm_device *dev = bo->base.base.dev;
> + struct panthor_device *ptdev = container_of(dev, struct panthor_device, base);
> +
> + if (!list_empty(&bo->gems_node)) {
> + mutex_lock(&ptdev->gems_lock);
> + list_del_init(&bo->gems_node);
> + mutex_unlock(&ptdev->gems_lock);
> + }
> +#endif
Can we add helpers to add/remove a GEM to the list and define dummy
implementations for the !CONFIG_DEBUG_FS case?
#ifdef CONFIG_DEBUG_FS
static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo)
{
INIT_LIST_HEAD(&obj->gems_node);
obj->creator.tgid = current->group_leader->pid;
get_task_comm(obj->creator.process_name, current->group_leader);
}
static void panthor_gem_debugfs_bo_add(struct panthor_gem_object *bo)
{
struct panthor_device *ptdev = container_of(bo->base.base.dev,
struct panthor_device, base);
mutex_lock(&ptdev->gems_lock);
list_add_tail(&bo->gems_node, &ptdev->gems);
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->gems_node))
return;
mutex_lock(&ptdev->gems_lock);
list_del_init(&bo->gems_node);
mutex_unlock(&ptdev->gems_lock);
}
#else
static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo) {}
static void panthor_gem_debugfs_bo_add(struct panthor_gem_object *bo) {}
static void panthor_gem_debugfs_bo_rm(struct panthor_gem_object *bo) {}
#endif
>
> kfree(bo->label);
> mutex_destroy(&bo->label_lock);
> @@ -201,6 +211,12 @@ struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t
> drm_gem_gpuva_set_lock(&obj->base.base, &obj->gpuva_list_lock);
> mutex_init(&obj->label_lock);
>
> +#ifdef CONFIG_DEBUG_FS
> + INIT_LIST_HEAD(&obj->gems_node);
> + obj->creator.tgid = current->group_leader->pid;
> + get_task_comm(obj->creator.process_name, current->group_leader);
> +#endif
panthor_gem_debugfs_bo_init(obj);
> +
> return &obj->base.base;
> }
>
> @@ -224,6 +240,10 @@ panthor_gem_create_with_handle(struct drm_file *file,
> int ret;
> struct drm_gem_shmem_object *shmem;
> struct panthor_gem_object *bo;
> +#ifdef CONFIG_DEBUG_FS
> + struct panthor_device *ptdev =
> + container_of(ddev, struct panthor_device, base);
> +#endif
>
> shmem = drm_gem_shmem_create(ddev, *size);
> if (IS_ERR(shmem))
> @@ -249,6 +269,12 @@ panthor_gem_create_with_handle(struct drm_file *file,
> /* drop reference from allocate - handle holds it now. */
> drm_gem_object_put(&shmem->base);
>
> +#ifdef CONFIG_DEBUG_FS
> + mutex_lock(&ptdev->gems_lock);
> + list_add_tail(&bo->gems_node, &ptdev->gems);
> + mutex_unlock(&ptdev->gems_lock);
> +#endif
panthor_gem_debugfs_bo_rm(bo);
> +
> return ret;
> }
>
> @@ -265,3 +291,78 @@ panthor_gem_label_bo(struct drm_gem_object *obj, const char *label)
>
> kfree(old_label);
> }
> +
> +#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;
> +}
> +
> +void panthor_gem_print_objects(struct panthor_device *ptdev,
> + struct seq_file *m)
> +{
> + size_t total = 0, total_resident = 0, total_reclaimable = 0;
> + struct panthor_gem_object *bo;
> +
> + seq_puts(m, "created-by global-name refcount size resident-size file-offset flags label\n");
> + seq_puts(m, "------------------------------------------------------------------------------------------------------------------------------------------------\n");
> +
> + mutex_lock(&ptdev->gems_lock);
> + list_for_each_entry(bo, &ptdev->gems, gems_node) {
> + 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)
> + continue;
> +
> + resident_size = bo->base.pages != NULL ? bo->base.base.size : 0;
> +
> + snprintf(creator_info, sizeof(creator_info),
> + "%s/%d", bo->creator.process_name, bo->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, ")");
> +
> + mutex_lock(&bo->label_lock);
> + seq_printf(m, "%-16s%-60s", "", bo->label ? : NULL);
> + mutex_unlock(&bo->label_lock);
> + seq_puts(m, "\n");
Let's have a panthor_gem_debugfs_bo_print() helper to print a single BO.
> +
> + total += bo->base.base.size;
> + total_resident += resident_size;
> + if (bo->base.madv > 0)
> + total_reclaimable += resident_size;
> + }
> + mutex_unlock(&ptdev->gems_lock);
> +
> + seq_puts(m, "================================================================================================================================================\n");
> + seq_printf(m, "Total size: %zd, Total resident: %zd, Total reclaimable: %zd\n",
> + total, total_resident, total_reclaimable);
> +}
> +#endif
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
> index da9268d24566..c0be30434b34 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.h
> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
> @@ -55,6 +55,23 @@ struct panthor_gem_object {
>
> /** @label_lock: Lock that protects access to the @label field. */
> struct mutex label_lock;
> +
> +#ifdef CONFIG_DEBUG_FS
> + /**
> + * @gems_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 gems_node;
> +
> + /** @creator: Information about the UM process which created the GEM. */
> + struct {
> + /** @process_name: Group leader name in owning thread's process */
> + char process_name[TASK_COMM_LEN];
> +
> + /** @tgid: PID of the thread's group leader within its process */
> + pid_t tgid;
> + } creator;
Can we put all these fields under a debugfs struct?
struct panthor_gem_debugfs {
/**
* @gems_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 gems_node;
/** @creator: Information about the UM process which created the GEM. */
struct {
/** @process_name: Group leader name in owning thread's process */
char process_name[TASK_COMM_LEN];
/** @tgid: PID of the thread's group leader within its process */
pid_t tgid;
} creator;
};
...
struct panthor_gem_object {
...
#ifdef CONFIG_DEBUG_FS
struct panthor_gem_debugfs debugfs;
#endif
...
};
> +#endif
> };
>
> /**
> @@ -150,4 +167,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_print_objects(struct panthor_device *pfdev,
> + struct seq_file *m);
s/panthor_gem_print_objects/panthor_gem_debugfs_print_bos/
> +#endif
> +
> #endif /* __PANTHOR_GEM_H__ */
next prev parent reply other threads:[~2025-03-17 8:26 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-16 21:51 [PATCH 0/4] Panthor BO tagging and GEMS debug display Adrián Larumbe
2025-03-16 21:51 ` [PATCH 1/4] drm/panthor: Introduce BO labeling Adrián Larumbe
2025-03-17 7:45 ` Boris Brezillon
2025-03-16 21:51 ` [PATCH 2/4] drm/panthor: Add driver IOCTL for setting BO labels Adrián Larumbe
2025-03-17 7:50 ` Boris Brezillon
2025-03-19 13:49 ` Adrián Larumbe
2025-03-19 16:28 ` Boris Brezillon
2025-03-17 7:54 ` Boris Brezillon
2025-03-16 21:51 ` [PATCH 3/4] drm/panthor: show device-wide list of DRM GEM objects over DebugFS Adrián Larumbe
2025-03-17 8:26 ` Boris Brezillon [this message]
2025-03-16 21:51 ` [PATCH 4/4] drm/panthor: Display heap chunk entries in DebugFS GEMS file Adrián Larumbe
2025-03-17 8:31 ` Boris Brezillon
2025-03-19 13:18 ` Adrián Larumbe
2025-03-19 16:39 ` Boris Brezillon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250317092614.55b3c4e9@collabora.com \
--to=boris.brezillon@collabora.com \
--cc=adrian.larumbe@collabora.com \
--cc=airlied@gmail.com \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=kernel@collabora.com \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=liviu.dudau@arm.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=simona@ffwll.ch \
--cc=steven.price@arm.com \
--cc=sumit.semwal@linaro.org \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.