* [RFC 1/2] drm: Add fdinfo memory stats
@ 2023-04-06 21:59 ` Rob Clark
0 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2023-04-06 21:59 UTC (permalink / raw)
To: dri-devel
Cc: Rob Clark, Tvrtko Ursulin, Jonathan Corbet, linux-arm-msm,
open list:DOCUMENTATION, Christopher Healy, open list,
Boris Brezillon, Thomas Zimmermann, freedreno
From: Rob Clark <robdclark@chromium.org>
Add a helper to dump memory stats to fdinfo. For the things the drm
core isn't aware of, use a callback.
Signed-off-by: Rob Clark <robdclark@chromium.org>
---
Documentation/gpu/drm-usage-stats.rst | 21 +++++++
drivers/gpu/drm/drm_file.c | 79 +++++++++++++++++++++++++++
include/drm/drm_file.h | 10 ++++
3 files changed, 110 insertions(+)
diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
index b46327356e80..56e3c95b6e0a 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 purgable.
+
+- 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 a51ff8cee049..21911d6ff38d 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"
@@ -868,6 +869,84 @@ 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[] = {"B", "KiB", "MiB", "GiB"};
+ unsigned u;
+
+ for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
+ if (sz < SZ_1K)
+ break;
+ sz /= SZ_1K;
+ }
+
+ drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
+}
+
+/**
+ * drm_print_memory_stats - Helper to print standard fdinfo memory stats
+ * @file: the DRM file
+ * @p: the printer to print output to
+ * @status: callback to get driver tracked object status
+ *
+ * Helper to iterate over GEM objects with a handle allocated in the specified
+ * file. 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 destroy.
+ */
+void drm_print_memory_stats(struct drm_file *file, struct drm_printer *p,
+ enum drm_gem_object_status (*status)(struct drm_gem_object *))
+{
+ struct drm_gem_object *obj;
+ struct {
+ size_t shared;
+ size_t private;
+ size_t resident;
+ size_t purgeable;
+ size_t active;
+ } size = {0};
+ int id;
+
+ spin_lock(&file->table_lock);
+ idr_for_each_entry (&file->object_idr, obj, id) {
+ enum drm_gem_object_status s = 0;
+
+ if (status)
+ s = status(obj);
+
+ if (obj->handle_count > 1) {
+ size.shared += obj->size;
+ } else {
+ size.private += obj->size;
+ }
+
+ if (s & DRM_GEM_OBJECT_RESIDENT) {
+ size.resident += obj->size;
+ s &= ~DRM_GEM_OBJECT_PURGEABLE;
+ }
+
+ if (s & DRM_GEM_OBJECT_ACTIVE) {
+ size.active += obj->size;
+ 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);
+
+ if (status) {
+ print_size(p, "drm-resident-memory", size.resident);
+ print_size(p, "drm-purgeable-memory", size.purgeable);
+ print_size(p, "drm-active-memory", size.active);
+ }
+}
+EXPORT_SYMBOL(drm_print_memory_stats);
+
/**
* mock_drm_getfile - Create a new struct file for the drm device
* @minor: drm minor to wrap (e.g. #drm_device.primary)
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index 0d1f853092ab..7bd8a1374f39 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;
@@ -438,6 +439,15 @@ void drm_send_event_timestamp_locked(struct drm_device *dev,
struct drm_pending_event *e,
ktime_t timestamp);
+enum drm_gem_object_status {
+ DRM_GEM_OBJECT_RESIDENT = BIT(0),
+ DRM_GEM_OBJECT_PURGEABLE = BIT(1),
+ DRM_GEM_OBJECT_ACTIVE = BIT(2),
+};
+
+void drm_print_memory_stats(struct drm_file *file, struct drm_printer *p,
+ enum drm_gem_object_status (*status)(struct drm_gem_object *));
+
struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags);
#endif /* _DRM_FILE_H_ */
--
2.39.2
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [RFC 1/2] drm: Add fdinfo memory stats
2023-04-06 21:59 ` Rob Clark
(?)
@ 2023-04-07 0:21 ` kernel test robot
-1 siblings, 0 replies; 18+ messages in thread
From: kernel test robot @ 2023-04-07 0:21 UTC (permalink / raw)
To: Rob Clark; +Cc: oe-kbuild-all
Hi Rob,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build warnings:
[auto build test WARNING on drm-misc/drm-misc-next]
[also build test WARNING on drm/drm-next drm-exynos/exynos-drm-next drm-intel/for-linux-next drm-intel/for-linux-next-fixes drm-tip/drm-tip linus/master v6.3-rc5 next-20230406]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Rob-Clark/drm-Add-fdinfo-memory-stats/20230407-060118
base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next
patch link: https://lore.kernel.org/r/20230406215917.1475704-2-robdclark%40gmail.com
patch subject: [RFC 1/2] drm: Add fdinfo memory stats
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20230407/202304070855.Cl06hUYU-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/eebbb3ec0a196240e1084554563ac4ae7e85dbb3
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Rob-Clark/drm-Add-fdinfo-memory-stats/20230407-060118
git checkout eebbb3ec0a196240e1084554563ac4ae7e85dbb3
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/gpu/drm/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304070855.Cl06hUYU-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/gpu/drm/drm_file.c: In function 'print_size':
>> drivers/gpu/drm/drm_file.c:883:31: warning: format '%lu' expects argument of type 'long unsigned int', but argument 4 has type 'size_t' {aka 'unsigned int'} [-Wformat=]
883 | drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
| ~~^ ~~
| | |
| | size_t {aka unsigned int}
| long unsigned int
| %u
vim +883 drivers/gpu/drm/drm_file.c
871
872 static void print_size(struct drm_printer *p, const char *stat, size_t sz)
873 {
874 const char *units[] = {"B", "KiB", "MiB", "GiB"};
875 unsigned u;
876
877 for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
878 if (sz < SZ_1K)
879 break;
880 sz /= SZ_1K;
881 }
882
> 883 drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
884 }
885
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFC 1/2] drm: Add fdinfo memory stats
2023-04-06 21:59 ` Rob Clark
(?)
(?)
@ 2023-04-07 4:17 ` kernel test robot
-1 siblings, 0 replies; 18+ messages in thread
From: kernel test robot @ 2023-04-07 4:17 UTC (permalink / raw)
To: Rob Clark; +Cc: llvm, oe-kbuild-all
Hi Rob,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build warnings:
[auto build test WARNING on drm-misc/drm-misc-next]
[also build test WARNING on drm/drm-next drm-exynos/exynos-drm-next drm-intel/for-linux-next drm-intel/for-linux-next-fixes drm-tip/drm-tip linus/master v6.3-rc5 next-20230406]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Rob-Clark/drm-Add-fdinfo-memory-stats/20230407-060118
base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next
patch link: https://lore.kernel.org/r/20230406215917.1475704-2-robdclark%40gmail.com
patch subject: [RFC 1/2] drm: Add fdinfo memory stats
config: i386-randconfig-a002-20230403 (https://download.01.org/0day-ci/archive/20230407/202304071241.sHlGa8UH-lkp@intel.com/config)
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/eebbb3ec0a196240e1084554563ac4ae7e85dbb3
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Rob-Clark/drm-Add-fdinfo-memory-stats/20230407-060118
git checkout eebbb3ec0a196240e1084554563ac4ae7e85dbb3
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/gpu/drm/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304071241.sHlGa8UH-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/gpu/drm/drm_file.c:883:39: warning: format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat]
drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
~~~ ^~
%zu
1 warning generated.
vim +883 drivers/gpu/drm/drm_file.c
871
872 static void print_size(struct drm_printer *p, const char *stat, size_t sz)
873 {
874 const char *units[] = {"B", "KiB", "MiB", "GiB"};
875 unsigned u;
876
877 for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
878 if (sz < SZ_1K)
879 break;
880 sz /= SZ_1K;
881 }
882
> 883 drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
884 }
885
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFC 1/2] drm: Add fdinfo memory stats
2023-04-06 21:59 ` Rob Clark
@ 2023-04-08 12:20 ` Emil Velikov
-1 siblings, 0 replies; 18+ messages in thread
From: Emil Velikov @ 2023-04-08 12:20 UTC (permalink / raw)
To: Rob Clark
Cc: dri-devel, Rob Clark, Tvrtko Ursulin, Jonathan Corbet,
linux-arm-msm, open list:DOCUMENTATION, Christopher Healy,
open list, Boris Brezillon, Thomas Zimmermann, freedreno
Hey Rob,
On Thu, 6 Apr 2023 at 22:59, Rob Clark <robdclark@gmail.com> wrote:
> +- drm-purgeable-memory: <uint> [KiB|MiB]
> +
> +The total size of buffers that are purgable.
s/purgable/purgeable/
> +static void print_size(struct drm_printer *p, const char *stat, size_t sz)
> +{
> + const char *units[] = {"B", "KiB", "MiB", "GiB"};
The documentation says:
> Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB'
> indicating kibi- or mebi-bytes.
So I would drop the B and/or update the documentation to mention B && GiB.
> + unsigned u;
> +
> + for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
> + if (sz < SZ_1K)
> + break;
> + sz /= SZ_1K;
IIRC size_t can be 64bit, so we should probably use do_div() here.
> + }
> +
> + drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
> +}
> +
> +/**
> + * drm_print_memory_stats - Helper to print standard fdinfo memory stats
> + * @file: the DRM file
> + * @p: the printer to print output to
> + * @status: callback to get driver tracked object status
> + *
> + * Helper to iterate over GEM objects with a handle allocated in the specified
> + * file. The optional status callback can return additional object state which
s/return additional/return an additional/
> + * 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 destroy.
s/destroy/destruction/
> + */
> +void drm_print_memory_stats(struct drm_file *file, struct drm_printer *p,
> + enum drm_gem_object_status (*status)(struct drm_gem_object *))
> +{
> + if (s & DRM_GEM_OBJECT_RESIDENT) {
> + size.resident += obj->size;
> + s &= ~DRM_GEM_OBJECT_PURGEABLE;
Is MSM capable of marking the object as both purgeable and resident or
is this to catch other drivers? Should we add a note to the
documentation above - resident memory cannot be purgeable
> + }
> +
> + if (s & DRM_GEM_OBJECT_ACTIVE) {
> + size.active += obj->size;
> + s &= ~DRM_GEM_OBJECT_PURGEABLE;
Ditto.
With the above nits, the patch is:
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
HTH
Emil
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFC 1/2] drm: Add fdinfo memory stats
@ 2023-04-08 12:20 ` Emil Velikov
0 siblings, 0 replies; 18+ messages in thread
From: Emil Velikov @ 2023-04-08 12:20 UTC (permalink / raw)
To: Rob Clark
Cc: Rob Clark, Tvrtko Ursulin, open list:DOCUMENTATION, linux-arm-msm,
Jonathan Corbet, Christopher Healy, dri-devel, open list,
Boris Brezillon, Thomas Zimmermann, freedreno
Hey Rob,
On Thu, 6 Apr 2023 at 22:59, Rob Clark <robdclark@gmail.com> wrote:
> +- drm-purgeable-memory: <uint> [KiB|MiB]
> +
> +The total size of buffers that are purgable.
s/purgable/purgeable/
> +static void print_size(struct drm_printer *p, const char *stat, size_t sz)
> +{
> + const char *units[] = {"B", "KiB", "MiB", "GiB"};
The documentation says:
> Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB'
> indicating kibi- or mebi-bytes.
So I would drop the B and/or update the documentation to mention B && GiB.
> + unsigned u;
> +
> + for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
> + if (sz < SZ_1K)
> + break;
> + sz /= SZ_1K;
IIRC size_t can be 64bit, so we should probably use do_div() here.
> + }
> +
> + drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
> +}
> +
> +/**
> + * drm_print_memory_stats - Helper to print standard fdinfo memory stats
> + * @file: the DRM file
> + * @p: the printer to print output to
> + * @status: callback to get driver tracked object status
> + *
> + * Helper to iterate over GEM objects with a handle allocated in the specified
> + * file. The optional status callback can return additional object state which
s/return additional/return an additional/
> + * 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 destroy.
s/destroy/destruction/
> + */
> +void drm_print_memory_stats(struct drm_file *file, struct drm_printer *p,
> + enum drm_gem_object_status (*status)(struct drm_gem_object *))
> +{
> + if (s & DRM_GEM_OBJECT_RESIDENT) {
> + size.resident += obj->size;
> + s &= ~DRM_GEM_OBJECT_PURGEABLE;
Is MSM capable of marking the object as both purgeable and resident or
is this to catch other drivers? Should we add a note to the
documentation above - resident memory cannot be purgeable
> + }
> +
> + if (s & DRM_GEM_OBJECT_ACTIVE) {
> + size.active += obj->size;
> + s &= ~DRM_GEM_OBJECT_PURGEABLE;
Ditto.
With the above nits, the patch is:
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
HTH
Emil
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFC 1/2] drm: Add fdinfo memory stats
2023-04-08 12:20 ` Emil Velikov
@ 2023-04-10 19:01 ` Rob Clark
-1 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2023-04-10 19:01 UTC (permalink / raw)
To: Emil Velikov
Cc: dri-devel, Rob Clark, Tvrtko Ursulin, Jonathan Corbet,
linux-arm-msm, open list:DOCUMENTATION, Christopher Healy,
open list, Boris Brezillon, Thomas Zimmermann, freedreno
On Sat, Apr 8, 2023 at 5:20 AM Emil Velikov <emil.l.velikov@gmail.com> wrote:
>
> Hey Rob,
>
> On Thu, 6 Apr 2023 at 22:59, Rob Clark <robdclark@gmail.com> wrote:
>
> > +- drm-purgeable-memory: <uint> [KiB|MiB]
> > +
> > +The total size of buffers that are purgable.
>
> s/purgable/purgeable/
>
>
> > +static void print_size(struct drm_printer *p, const char *stat, size_t sz)
> > +{
> > + const char *units[] = {"B", "KiB", "MiB", "GiB"};
>
> The documentation says:
>
> > Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB'
> > indicating kibi- or mebi-bytes.
>
> So I would drop the B and/or update the documentation to mention B && GiB.
>
> > + unsigned u;
> > +
> > + for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
> > + if (sz < SZ_1K)
> > + break;
> > + sz /= SZ_1K;
>
> IIRC size_t can be 64bit, so we should probably use do_div() here.
>
> > + }
> > +
> > + drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
> > +}
> > +
> > +/**
> > + * drm_print_memory_stats - Helper to print standard fdinfo memory stats
> > + * @file: the DRM file
> > + * @p: the printer to print output to
> > + * @status: callback to get driver tracked object status
> > + *
> > + * Helper to iterate over GEM objects with a handle allocated in the specified
> > + * file. The optional status callback can return additional object state which
>
> s/return additional/return an additional/
"an" reads funny to me, as the state is plural (bitmask).. but agreed
on the other things
> > + * 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 destroy.
>
> s/destroy/destruction/
>
> > + */
> > +void drm_print_memory_stats(struct drm_file *file, struct drm_printer *p,
> > + enum drm_gem_object_status (*status)(struct drm_gem_object *))
> > +{
>
> > + if (s & DRM_GEM_OBJECT_RESIDENT) {
> > + size.resident += obj->size;
> > + s &= ~DRM_GEM_OBJECT_PURGEABLE;
>
> Is MSM capable of marking the object as both purgeable and resident or
> is this to catch other drivers? Should we add a note to the
> documentation above - resident memory cannot be purgeable
It is just to simplify drivers so they don't have to repeat this
logic. Ie. an object can be marked purgeable while it is still active
(so it will be eventually purgeable when it becomes idle). Likewise
it doesn't make sense to count an object that has already been purged
(is no longer resident) as purgeable.
BR,
-R
> > + }
> > +
> > + if (s & DRM_GEM_OBJECT_ACTIVE) {
> > + size.active += obj->size;
> > + s &= ~DRM_GEM_OBJECT_PURGEABLE;
>
> Ditto.
>
> With the above nits, the patch is:
> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
>
> HTH
> Emil
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFC 1/2] drm: Add fdinfo memory stats
@ 2023-04-10 19:01 ` Rob Clark
0 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2023-04-10 19:01 UTC (permalink / raw)
To: Emil Velikov
Cc: Rob Clark, Tvrtko Ursulin, open list:DOCUMENTATION, linux-arm-msm,
Jonathan Corbet, Christopher Healy, dri-devel, open list,
Boris Brezillon, Thomas Zimmermann, freedreno
On Sat, Apr 8, 2023 at 5:20 AM Emil Velikov <emil.l.velikov@gmail.com> wrote:
>
> Hey Rob,
>
> On Thu, 6 Apr 2023 at 22:59, Rob Clark <robdclark@gmail.com> wrote:
>
> > +- drm-purgeable-memory: <uint> [KiB|MiB]
> > +
> > +The total size of buffers that are purgable.
>
> s/purgable/purgeable/
>
>
> > +static void print_size(struct drm_printer *p, const char *stat, size_t sz)
> > +{
> > + const char *units[] = {"B", "KiB", "MiB", "GiB"};
>
> The documentation says:
>
> > Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB'
> > indicating kibi- or mebi-bytes.
>
> So I would drop the B and/or update the documentation to mention B && GiB.
>
> > + unsigned u;
> > +
> > + for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
> > + if (sz < SZ_1K)
> > + break;
> > + sz /= SZ_1K;
>
> IIRC size_t can be 64bit, so we should probably use do_div() here.
>
> > + }
> > +
> > + drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
> > +}
> > +
> > +/**
> > + * drm_print_memory_stats - Helper to print standard fdinfo memory stats
> > + * @file: the DRM file
> > + * @p: the printer to print output to
> > + * @status: callback to get driver tracked object status
> > + *
> > + * Helper to iterate over GEM objects with a handle allocated in the specified
> > + * file. The optional status callback can return additional object state which
>
> s/return additional/return an additional/
"an" reads funny to me, as the state is plural (bitmask).. but agreed
on the other things
> > + * 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 destroy.
>
> s/destroy/destruction/
>
> > + */
> > +void drm_print_memory_stats(struct drm_file *file, struct drm_printer *p,
> > + enum drm_gem_object_status (*status)(struct drm_gem_object *))
> > +{
>
> > + if (s & DRM_GEM_OBJECT_RESIDENT) {
> > + size.resident += obj->size;
> > + s &= ~DRM_GEM_OBJECT_PURGEABLE;
>
> Is MSM capable of marking the object as both purgeable and resident or
> is this to catch other drivers? Should we add a note to the
> documentation above - resident memory cannot be purgeable
It is just to simplify drivers so they don't have to repeat this
logic. Ie. an object can be marked purgeable while it is still active
(so it will be eventually purgeable when it becomes idle). Likewise
it doesn't make sense to count an object that has already been purged
(is no longer resident) as purgeable.
BR,
-R
> > + }
> > +
> > + if (s & DRM_GEM_OBJECT_ACTIVE) {
> > + size.active += obj->size;
> > + s &= ~DRM_GEM_OBJECT_PURGEABLE;
>
> Ditto.
>
> With the above nits, the patch is:
> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
>
> HTH
> Emil
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC 1/2] drm: Add fdinfo memory stats
2023-04-06 21:59 ` Rob Clark
@ 2023-04-11 7:54 ` Boris Brezillon
-1 siblings, 0 replies; 18+ messages in thread
From: Boris Brezillon @ 2023-04-11 7:54 UTC (permalink / raw)
To: Rob Clark
Cc: dri-devel, linux-arm-msm, freedreno, Tvrtko Ursulin,
Christopher Healy, Rob Clark, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Daniel Vetter, Jonathan Corbet,
open list:DOCUMENTATION, open list
Hi Rob,
On Thu, 6 Apr 2023 14:59:16 -0700
Rob Clark <robdclark@gmail.com> wrote:
> From: Rob Clark <robdclark@chromium.org>
>
> Add a helper to dump memory stats to fdinfo. For the things the drm
> core isn't aware of, use a callback.
>
> Signed-off-by: Rob Clark <robdclark@chromium.org>
> ---
> Documentation/gpu/drm-usage-stats.rst | 21 +++++++
> drivers/gpu/drm/drm_file.c | 79 +++++++++++++++++++++++++++
> include/drm/drm_file.h | 10 ++++
> 3 files changed, 110 insertions(+)
>
> diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
> index b46327356e80..56e3c95b6e0a 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 purgable.
> +
> +- 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 a51ff8cee049..21911d6ff38d 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"
> @@ -868,6 +869,84 @@ 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[] = {"B", "KiB", "MiB", "GiB"};
> + unsigned u;
> +
> + for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
> + if (sz < SZ_1K)
> + break;
> + sz /= SZ_1K;
> + }
> +
> + drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
> +}
> +
> +/**
> + * drm_print_memory_stats - Helper to print standard fdinfo memory stats
> + * @file: the DRM file
> + * @p: the printer to print output to
> + * @status: callback to get driver tracked object status
> + *
> + * Helper to iterate over GEM objects with a handle allocated in the specified
> + * file. 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 destroy.
> + */
> +void drm_print_memory_stats(struct drm_file *file, struct drm_printer *p,
> + enum drm_gem_object_status (*status)(struct drm_gem_object *))
Nit: status() returning an 'enum drm_gem_object_status' makes it look
like it can only return one of the DRM_GEM_OBJECT_* flag, when it can
actually be a combination of flags. Should we make it return an u32
instead? At the very least this should be clarified in the function doc.
> +{
> + struct drm_gem_object *obj;
> + struct {
> + size_t shared;
> + size_t private;
> + size_t resident;
> + size_t purgeable;
> + size_t active;
> + } size = {0};
> + int id;
> +
> + spin_lock(&file->table_lock);
> + idr_for_each_entry (&file->object_idr, obj, id) {
> + enum drm_gem_object_status s = 0;
> +
> + if (status)
> + s = status(obj);
> +
> + if (obj->handle_count > 1) {
> + size.shared += obj->size;
> + } else {
> + size.private += obj->size;
> + }
> +
> + if (s & DRM_GEM_OBJECT_RESIDENT) {
> + size.resident += obj->size;
> + s &= ~DRM_GEM_OBJECT_PURGEABLE;
> + }
> +
> + if (s & DRM_GEM_OBJECT_ACTIVE) {
> + size.active += obj->size;
> + 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);
> +
> + if (status) {
> + print_size(p, "drm-resident-memory", size.resident);
> + print_size(p, "drm-purgeable-memory", size.purgeable);
> + print_size(p, "drm-active-memory", size.active);
> + }
Should we assume that all users of this drm_print_memory_stats() helper
support tracking all these non-standard stats as soon as they provide a
status callback? If not, we should probably not print the
`drm-xxx-memory` line when the driver is not tracking this state (can
be done with a 'supported_status' mask passed to
drm_print_memory_stats()).
Other than these 2 minor things, I think it's a perfect match for
panfrost mem-tracking, and I certainly intend to use this helper in
panfrost.
Thanks,
Boris
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFC 1/2] drm: Add fdinfo memory stats
@ 2023-04-11 7:54 ` Boris Brezillon
0 siblings, 0 replies; 18+ messages in thread
From: Boris Brezillon @ 2023-04-11 7:54 UTC (permalink / raw)
To: Rob Clark
Cc: Rob Clark, Tvrtko Ursulin, Jonathan Corbet, linux-arm-msm,
open list:DOCUMENTATION, Christopher Healy, dri-devel, open list,
Thomas Zimmermann, freedreno
Hi Rob,
On Thu, 6 Apr 2023 14:59:16 -0700
Rob Clark <robdclark@gmail.com> wrote:
> From: Rob Clark <robdclark@chromium.org>
>
> Add a helper to dump memory stats to fdinfo. For the things the drm
> core isn't aware of, use a callback.
>
> Signed-off-by: Rob Clark <robdclark@chromium.org>
> ---
> Documentation/gpu/drm-usage-stats.rst | 21 +++++++
> drivers/gpu/drm/drm_file.c | 79 +++++++++++++++++++++++++++
> include/drm/drm_file.h | 10 ++++
> 3 files changed, 110 insertions(+)
>
> diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
> index b46327356e80..56e3c95b6e0a 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 purgable.
> +
> +- 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 a51ff8cee049..21911d6ff38d 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"
> @@ -868,6 +869,84 @@ 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[] = {"B", "KiB", "MiB", "GiB"};
> + unsigned u;
> +
> + for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
> + if (sz < SZ_1K)
> + break;
> + sz /= SZ_1K;
> + }
> +
> + drm_printf(p, "%s:\t%lu %s\n", stat, sz, units[u]);
> +}
> +
> +/**
> + * drm_print_memory_stats - Helper to print standard fdinfo memory stats
> + * @file: the DRM file
> + * @p: the printer to print output to
> + * @status: callback to get driver tracked object status
> + *
> + * Helper to iterate over GEM objects with a handle allocated in the specified
> + * file. 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 destroy.
> + */
> +void drm_print_memory_stats(struct drm_file *file, struct drm_printer *p,
> + enum drm_gem_object_status (*status)(struct drm_gem_object *))
Nit: status() returning an 'enum drm_gem_object_status' makes it look
like it can only return one of the DRM_GEM_OBJECT_* flag, when it can
actually be a combination of flags. Should we make it return an u32
instead? At the very least this should be clarified in the function doc.
> +{
> + struct drm_gem_object *obj;
> + struct {
> + size_t shared;
> + size_t private;
> + size_t resident;
> + size_t purgeable;
> + size_t active;
> + } size = {0};
> + int id;
> +
> + spin_lock(&file->table_lock);
> + idr_for_each_entry (&file->object_idr, obj, id) {
> + enum drm_gem_object_status s = 0;
> +
> + if (status)
> + s = status(obj);
> +
> + if (obj->handle_count > 1) {
> + size.shared += obj->size;
> + } else {
> + size.private += obj->size;
> + }
> +
> + if (s & DRM_GEM_OBJECT_RESIDENT) {
> + size.resident += obj->size;
> + s &= ~DRM_GEM_OBJECT_PURGEABLE;
> + }
> +
> + if (s & DRM_GEM_OBJECT_ACTIVE) {
> + size.active += obj->size;
> + 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);
> +
> + if (status) {
> + print_size(p, "drm-resident-memory", size.resident);
> + print_size(p, "drm-purgeable-memory", size.purgeable);
> + print_size(p, "drm-active-memory", size.active);
> + }
Should we assume that all users of this drm_print_memory_stats() helper
support tracking all these non-standard stats as soon as they provide a
status callback? If not, we should probably not print the
`drm-xxx-memory` line when the driver is not tracking this state (can
be done with a 'supported_status' mask passed to
drm_print_memory_stats()).
Other than these 2 minor things, I think it's a perfect match for
panfrost mem-tracking, and I certainly intend to use this helper in
panfrost.
Thanks,
Boris
^ permalink raw reply [flat|nested] 18+ messages in thread