From: Rob Clark <robdclark@gmail.com>
To: dri-devel@lists.freedesktop.org
Cc: linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org,
"Boris Brezillon" <boris.brezillon@collabora.com>,
"Tvrtko Ursulin" <tvrtko.ursulin@linux.intel.com>,
"Christopher Healy" <healych@amazon.com>,
"Emil Velikov" <emil.l.velikov@gmail.com>,
"Christian König" <christian.koenig@amd.com>,
"Daniel Vetter" <daniel@ffwll.ch>,
"Rob Clark" <robdclark@chromium.org>,
"Daniel Vetter" <daniel.vetter@ffwll.ch>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"David Airlie" <airlied@gmail.com>,
"Jonathan Corbet" <corbet@lwn.net>,
linux-doc@vger.kernel.org (open list:DOCUMENTATION),
linux-kernel@vger.kernel.org (open list)
Subject: [PATCH v4 5/6] drm: Add fdinfo memory stats
Date: Wed, 12 Apr 2023 15:42:57 -0700 [thread overview]
Message-ID: <20230412224311.23511-6-robdclark@gmail.com> (raw)
In-Reply-To: <20230412224311.23511-1-robdclark@gmail.com>
From: Rob Clark <robdclark@chromium.org>
Add support to dump GEM stats to fdinfo.
v2: Fix typos, change size units to match docs, use div_u64
v3: Do it in core
v4: more kerneldoc
Signed-off-by: Rob Clark <robdclark@chromium.org>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
Documentation/gpu/drm-usage-stats.rst | 21 ++++++++
drivers/gpu/drm/drm_file.c | 76 +++++++++++++++++++++++++++
include/drm/drm_file.h | 1 +
include/drm/drm_gem.h | 30 +++++++++++
4 files changed, 128 insertions(+)
diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
index 2ab32c40e93c..80003e27e28e 100644
--- a/Documentation/gpu/drm-usage-stats.rst
+++ b/Documentation/gpu/drm-usage-stats.rst
@@ -105,6 +105,27 @@ object belong to this client, in the respective memory region.
Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB'
indicating kibi- or mebi-bytes.
+- drm-shared-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are shared with another file (ie. have more
+than a single handle).
+
+- drm-private-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are not shared with another file.
+
+- drm-resident-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are resident in system memory.
+
+- drm-purgeable-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are purgeable.
+
+- drm-active-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are active on one or more rings.
+
- drm-cycles-<str> <uint>
Engine identifier string must be the same as the one specified in the
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index 6d5bdd684ae2..04a7ed7eba8e 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -42,6 +42,7 @@
#include <drm/drm_client.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
+#include <drm/drm_gem.h>
#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
@@ -871,6 +872,79 @@ void drm_send_event(struct drm_device *dev, struct drm_pending_event *e)
}
EXPORT_SYMBOL(drm_send_event);
+static void print_size(struct drm_printer *p, const char *stat, size_t sz)
+{
+ const char *units[] = {"", " KiB", " MiB"};
+ unsigned u;
+
+ for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
+ if (sz < SZ_1K)
+ break;
+ sz = div_u64(sz, SZ_1K);
+ }
+
+ drm_printf(p, "%s:\t%zu%s\n", stat, sz, units[u]);
+}
+
+static void print_memory_stats(struct drm_printer *p, struct drm_file *file)
+{
+ struct drm_gem_object *obj;
+ struct {
+ size_t shared;
+ size_t private;
+ size_t resident;
+ size_t purgeable;
+ size_t active;
+ } size = {0};
+ bool has_status = false;
+ int id;
+
+ spin_lock(&file->table_lock);
+ idr_for_each_entry (&file->object_idr, obj, id) {
+ enum drm_gem_object_status s = 0;
+
+ if (obj->funcs && obj->funcs->status) {
+ s = obj->funcs->status(obj);
+ has_status = true;
+ }
+
+ if (obj->handle_count > 1) {
+ size.shared += obj->size;
+ } else {
+ size.private += obj->size;
+ }
+
+ if (s & DRM_GEM_OBJECT_RESIDENT) {
+ size.resident += obj->size;
+ } else {
+ /* If already purged or not yet backed by pages, don't
+ * count it as purgeable:
+ */
+ s &= ~DRM_GEM_OBJECT_PURGEABLE;
+ }
+
+ if (!dma_resv_test_signaled(obj->resv, dma_resv_usage_rw(true))) {
+ size.active += obj->size;
+
+ /* If still active, don't count as purgeable: */
+ s &= ~DRM_GEM_OBJECT_PURGEABLE;
+ }
+
+ if (s & DRM_GEM_OBJECT_PURGEABLE)
+ size.purgeable += obj->size;
+ }
+ spin_unlock(&file->table_lock);
+
+ print_size(p, "drm-shared-memory", size.shared);
+ print_size(p, "drm-private-memory", size.private);
+ print_size(p, "drm-active-memory", size.active);
+
+ if (has_status) {
+ print_size(p, "drm-resident-memory", size.resident);
+ print_size(p, "drm-purgeable-memory", size.purgeable);
+ }
+}
+
/**
* drm_show_fdinfo - helper for drm file fops
* @seq_file: output stream
@@ -900,6 +974,8 @@ void drm_show_fdinfo(struct seq_file *m, struct file *f)
if (dev->driver->show_fdinfo)
dev->driver->show_fdinfo(&p, file);
+
+ print_memory_stats(&p, file);
}
EXPORT_SYMBOL(drm_show_fdinfo);
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index 6de6d0e9c634..919284bb4f1d 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -41,6 +41,7 @@
struct dma_fence;
struct drm_file;
struct drm_device;
+struct drm_printer;
struct device;
struct file;
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 189fd618ca65..9ebd2820ad1f 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -42,6 +42,25 @@
struct iosys_map;
struct drm_gem_object;
+/**
+ * enum drm_gem_object_status - bitmask of object state for fdinfo reporting
+ * @DRM_GEM_OBJECT_RESIDENT: object is resident in memory (ie. not unpinned)
+ * @DRM_GEM_OBJECT_PURGEABLE: object marked as purgeable by userspace
+ *
+ * Bitmask of status used for fdinfo memory stats, see &drm_gem_object_funcs.status
+ * and drm_show_fdinfo(). Note that an object can DRM_GEM_OBJECT_PURGEABLE if
+ * it still active or not resident, in which case drm_show_fdinfo() will not
+ * account for it as purgeable. So drivers do not need to check if the buffer
+ * is idle and resident to return this bit. (Ie. userspace can mark a buffer
+ * as purgeable even while it is still busy on the GPU.. it does not _actually_
+ * become puregeable until it becomes idle. The status gem object func does
+ * not need to consider this.)
+ */
+enum drm_gem_object_status {
+ DRM_GEM_OBJECT_RESIDENT = BIT(0),
+ DRM_GEM_OBJECT_PURGEABLE = BIT(1),
+};
+
/**
* struct drm_gem_object_funcs - GEM object functions
*/
@@ -174,6 +193,17 @@ struct drm_gem_object_funcs {
*/
int (*evict)(struct drm_gem_object *obj);
+ /**
+ * @status:
+ *
+ * The optional status callback can return additional object state
+ * which determines which stats the object is counted against. The
+ * callback is called under table_lock. Racing against object status
+ * change is "harmless", and the callback can expect to not race
+ * against object destruction.
+ */
+ enum drm_gem_object_status (*status)(struct drm_gem_object *obj);
+
/**
* @vm_ops:
*
--
2.39.2
WARNING: multiple messages have this Message-ID (diff)
From: Rob Clark <robdclark@gmail.com>
To: dri-devel@lists.freedesktop.org
Cc: "Rob Clark" <robdclark@chromium.org>,
"Tvrtko Ursulin" <tvrtko.ursulin@linux.intel.com>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"Jonathan Corbet" <corbet@lwn.net>,
linux-arm-msm@vger.kernel.org,
"open list:DOCUMENTATION" <linux-doc@vger.kernel.org>,
"Emil Velikov" <emil.l.velikov@gmail.com>,
"Christopher Healy" <healych@amazon.com>,
"open list" <linux-kernel@vger.kernel.org>,
"Boris Brezillon" <boris.brezillon@collabora.com>,
"Daniel Vetter" <daniel.vetter@ffwll.ch>,
freedreno@lists.freedesktop.org,
"Christian König" <christian.koenig@amd.com>
Subject: [PATCH v4 5/6] drm: Add fdinfo memory stats
Date: Wed, 12 Apr 2023 15:42:57 -0700 [thread overview]
Message-ID: <20230412224311.23511-6-robdclark@gmail.com> (raw)
In-Reply-To: <20230412224311.23511-1-robdclark@gmail.com>
From: Rob Clark <robdclark@chromium.org>
Add support to dump GEM stats to fdinfo.
v2: Fix typos, change size units to match docs, use div_u64
v3: Do it in core
v4: more kerneldoc
Signed-off-by: Rob Clark <robdclark@chromium.org>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
Documentation/gpu/drm-usage-stats.rst | 21 ++++++++
drivers/gpu/drm/drm_file.c | 76 +++++++++++++++++++++++++++
include/drm/drm_file.h | 1 +
include/drm/drm_gem.h | 30 +++++++++++
4 files changed, 128 insertions(+)
diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
index 2ab32c40e93c..80003e27e28e 100644
--- a/Documentation/gpu/drm-usage-stats.rst
+++ b/Documentation/gpu/drm-usage-stats.rst
@@ -105,6 +105,27 @@ object belong to this client, in the respective memory region.
Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB'
indicating kibi- or mebi-bytes.
+- drm-shared-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are shared with another file (ie. have more
+than a single handle).
+
+- drm-private-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are not shared with another file.
+
+- drm-resident-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are resident in system memory.
+
+- drm-purgeable-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are purgeable.
+
+- drm-active-memory: <uint> [KiB|MiB]
+
+The total size of buffers that are active on one or more rings.
+
- drm-cycles-<str> <uint>
Engine identifier string must be the same as the one specified in the
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index 6d5bdd684ae2..04a7ed7eba8e 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -42,6 +42,7 @@
#include <drm/drm_client.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
+#include <drm/drm_gem.h>
#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
@@ -871,6 +872,79 @@ void drm_send_event(struct drm_device *dev, struct drm_pending_event *e)
}
EXPORT_SYMBOL(drm_send_event);
+static void print_size(struct drm_printer *p, const char *stat, size_t sz)
+{
+ const char *units[] = {"", " KiB", " MiB"};
+ unsigned u;
+
+ for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
+ if (sz < SZ_1K)
+ break;
+ sz = div_u64(sz, SZ_1K);
+ }
+
+ drm_printf(p, "%s:\t%zu%s\n", stat, sz, units[u]);
+}
+
+static void print_memory_stats(struct drm_printer *p, struct drm_file *file)
+{
+ struct drm_gem_object *obj;
+ struct {
+ size_t shared;
+ size_t private;
+ size_t resident;
+ size_t purgeable;
+ size_t active;
+ } size = {0};
+ bool has_status = false;
+ int id;
+
+ spin_lock(&file->table_lock);
+ idr_for_each_entry (&file->object_idr, obj, id) {
+ enum drm_gem_object_status s = 0;
+
+ if (obj->funcs && obj->funcs->status) {
+ s = obj->funcs->status(obj);
+ has_status = true;
+ }
+
+ if (obj->handle_count > 1) {
+ size.shared += obj->size;
+ } else {
+ size.private += obj->size;
+ }
+
+ if (s & DRM_GEM_OBJECT_RESIDENT) {
+ size.resident += obj->size;
+ } else {
+ /* If already purged or not yet backed by pages, don't
+ * count it as purgeable:
+ */
+ s &= ~DRM_GEM_OBJECT_PURGEABLE;
+ }
+
+ if (!dma_resv_test_signaled(obj->resv, dma_resv_usage_rw(true))) {
+ size.active += obj->size;
+
+ /* If still active, don't count as purgeable: */
+ s &= ~DRM_GEM_OBJECT_PURGEABLE;
+ }
+
+ if (s & DRM_GEM_OBJECT_PURGEABLE)
+ size.purgeable += obj->size;
+ }
+ spin_unlock(&file->table_lock);
+
+ print_size(p, "drm-shared-memory", size.shared);
+ print_size(p, "drm-private-memory", size.private);
+ print_size(p, "drm-active-memory", size.active);
+
+ if (has_status) {
+ print_size(p, "drm-resident-memory", size.resident);
+ print_size(p, "drm-purgeable-memory", size.purgeable);
+ }
+}
+
/**
* drm_show_fdinfo - helper for drm file fops
* @seq_file: output stream
@@ -900,6 +974,8 @@ void drm_show_fdinfo(struct seq_file *m, struct file *f)
if (dev->driver->show_fdinfo)
dev->driver->show_fdinfo(&p, file);
+
+ print_memory_stats(&p, file);
}
EXPORT_SYMBOL(drm_show_fdinfo);
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index 6de6d0e9c634..919284bb4f1d 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -41,6 +41,7 @@
struct dma_fence;
struct drm_file;
struct drm_device;
+struct drm_printer;
struct device;
struct file;
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 189fd618ca65..9ebd2820ad1f 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -42,6 +42,25 @@
struct iosys_map;
struct drm_gem_object;
+/**
+ * enum drm_gem_object_status - bitmask of object state for fdinfo reporting
+ * @DRM_GEM_OBJECT_RESIDENT: object is resident in memory (ie. not unpinned)
+ * @DRM_GEM_OBJECT_PURGEABLE: object marked as purgeable by userspace
+ *
+ * Bitmask of status used for fdinfo memory stats, see &drm_gem_object_funcs.status
+ * and drm_show_fdinfo(). Note that an object can DRM_GEM_OBJECT_PURGEABLE if
+ * it still active or not resident, in which case drm_show_fdinfo() will not
+ * account for it as purgeable. So drivers do not need to check if the buffer
+ * is idle and resident to return this bit. (Ie. userspace can mark a buffer
+ * as purgeable even while it is still busy on the GPU.. it does not _actually_
+ * become puregeable until it becomes idle. The status gem object func does
+ * not need to consider this.)
+ */
+enum drm_gem_object_status {
+ DRM_GEM_OBJECT_RESIDENT = BIT(0),
+ DRM_GEM_OBJECT_PURGEABLE = BIT(1),
+};
+
/**
* struct drm_gem_object_funcs - GEM object functions
*/
@@ -174,6 +193,17 @@ struct drm_gem_object_funcs {
*/
int (*evict)(struct drm_gem_object *obj);
+ /**
+ * @status:
+ *
+ * The optional status callback can return additional object state
+ * which determines which stats the object is counted against. The
+ * callback is called under table_lock. Racing against object status
+ * change is "harmless", and the callback can expect to not race
+ * against object destruction.
+ */
+ enum drm_gem_object_status (*status)(struct drm_gem_object *obj);
+
/**
* @vm_ops:
*
--
2.39.2
next prev parent reply other threads:[~2023-04-12 22:44 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-12 22:42 [PATCH v4 0/6] drm: fdinfo memory stats Rob Clark
2023-04-12 22:42 ` Rob Clark
2023-04-12 22:42 ` Rob Clark
2023-04-12 22:42 ` [Intel-gfx] " Rob Clark
2023-04-12 22:42 ` [PATCH v4 1/6] drm: Add common fdinfo helper Rob Clark
2023-04-12 22:42 ` Rob Clark
2023-04-13 8:07 ` Christian König
2023-04-13 8:07 ` Christian König
2023-04-13 8:46 ` Daniel Vetter
2023-04-13 8:46 ` Daniel Vetter
2023-04-13 10:34 ` Christian König
2023-04-13 13:03 ` Tvrtko Ursulin
2023-04-12 22:42 ` [PATCH v4 2/6] drm/msm: Switch to " Rob Clark
2023-04-12 22:42 ` Rob Clark
2023-04-20 14:00 ` Dmitry Baryshkov
2023-04-20 14:00 ` Dmitry Baryshkov
2023-04-12 22:42 ` [PATCH v4 3/6] drm/amdgpu: " Rob Clark
2023-04-12 22:42 ` Rob Clark
2023-04-12 22:42 ` Rob Clark
2023-04-13 10:37 ` Christian König
2023-04-13 10:37 ` Christian König
2023-04-13 10:37 ` Christian König
2023-04-12 22:42 ` [Intel-gfx] [PATCH v4 4/6] drm/i915: " Rob Clark
2023-04-12 22:42 ` Rob Clark
2023-04-12 22:42 ` Rob Clark
2023-04-13 13:07 ` [Intel-gfx] " Tvrtko Ursulin
2023-04-13 13:07 ` Tvrtko Ursulin
2023-04-13 13:07 ` Tvrtko Ursulin
2023-04-13 15:42 ` [Intel-gfx] " Rob Clark
2023-04-13 15:42 ` Rob Clark
2023-04-13 15:42 ` Rob Clark
2023-04-12 22:42 ` Rob Clark [this message]
2023-04-12 22:42 ` [PATCH v4 5/6] drm: Add fdinfo memory stats Rob Clark
2023-04-21 10:26 ` Emil Velikov
2023-04-21 10:26 ` Emil Velikov
2023-04-21 11:23 ` Tvrtko Ursulin
2023-04-21 11:23 ` Tvrtko Ursulin
2023-04-21 11:45 ` Emil Velikov
2023-04-21 11:45 ` Emil Velikov
2023-04-21 11:59 ` Tvrtko Ursulin
2023-04-21 11:59 ` Tvrtko Ursulin
2023-04-21 14:50 ` Rob Clark
2023-04-21 14:50 ` Rob Clark
2023-04-12 22:42 ` [PATCH v4 6/6] drm/msm: Add memory stats to fdinfo Rob Clark
2023-04-12 22:42 ` Rob Clark
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=20230412224311.23511-6-robdclark@gmail.com \
--to=robdclark@gmail.com \
--cc=airlied@gmail.com \
--cc=boris.brezillon@collabora.com \
--cc=christian.koenig@amd.com \
--cc=corbet@lwn.net \
--cc=daniel.vetter@ffwll.ch \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=emil.l.velikov@gmail.com \
--cc=freedreno@lists.freedesktop.org \
--cc=healych@amazon.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=robdclark@chromium.org \
--cc=tvrtko.ursulin@linux.intel.com \
--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.