* [PATCH 0/2] Let userspace know about swapped out panthor GEM objects
@ 2026-04-20 15:46 Nicolas Frattaroli
2026-04-20 15:46 ` [PATCH 1/2] drm/fdinfo: Add "evicted" memory accounting Nicolas Frattaroli
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Nicolas Frattaroli @ 2026-04-20 15:46 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Boris Brezillon, Steven Price, Liviu Dudau
Cc: dri-devel, linux-kernel, kernel, Nicolas Frattaroli
Panthor has recently gained a GEM shrinker. It allows evicting memory
that backs unused GEM objects to swap.
In this series, both fdinfo and Panthor's gems debugfs are extended so
that information on evicted pages can be gathered by users through these
two methods.
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
Nicolas Frattaroli (2):
drm/fdinfo: Add "evicted" memory accounting
drm/panthor: Implement evicted status for GEM objects
drivers/gpu/drm/drm_file.c | 8 ++++++++
drivers/gpu/drm/panthor/panthor_gem.c | 10 ++++++++++
drivers/gpu/drm/panthor/panthor_gem.h | 11 +++++++++++
include/drm/drm_file.h | 2 ++
include/drm/drm_gem.h | 2 ++
5 files changed, 33 insertions(+)
---
base-commit: 3f9357c30a44734d45e3093c521d52b2aefb09f5
change-id: 20260420-panthor-bo-reclaim-observability-970679c9533c
Best regards,
--
Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 1/2] drm/fdinfo: Add "evicted" memory accounting 2026-04-20 15:46 [PATCH 0/2] Let userspace know about swapped out panthor GEM objects Nicolas Frattaroli @ 2026-04-20 15:46 ` Nicolas Frattaroli 2026-04-22 23:29 ` Claude review: " Claude Code Review Bot 2026-04-20 15:47 ` [PATCH 2/2] drm/panthor: Implement evicted status for GEM objects Nicolas Frattaroli 2026-04-22 23:29 ` Claude review: Let userspace know about swapped out panthor " Claude Code Review Bot 2 siblings, 1 reply; 10+ messages in thread From: Nicolas Frattaroli @ 2026-04-20 15:46 UTC (permalink / raw) To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Boris Brezillon, Steven Price, Liviu Dudau Cc: dri-devel, linux-kernel, kernel, Nicolas Frattaroli Currently, there's no way to know for certain how much GPU memory was swapped out. The difference between total and resident memory would include newly allocated pages, which are not resident, but also aren't swapped out. Add a new drm_gem_object_status so drivers can signal when an object has been evicted to swap, and add a new "evicted" counter to drm_memory_stats. Due to how the supported_flags bitmask is determined, the "evicted" count won't be printed to fdinfo if there's no swapped out pages. Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> --- drivers/gpu/drm/drm_file.c | 8 ++++++++ include/drm/drm_file.h | 2 ++ include/drm/drm_gem.h | 2 ++ 3 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index ec820686b302..5078172976c0 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -868,6 +868,7 @@ int drm_memory_stats_is_zero(const struct drm_memory_stats *stats) stats->private == 0 && stats->resident == 0 && stats->purgeable == 0 && + stats->evicted == 0 && stats->active == 0); } EXPORT_SYMBOL(drm_memory_stats_is_zero); @@ -901,6 +902,10 @@ void drm_print_memory_stats(struct drm_printer *p, if (supported_status & DRM_GEM_OBJECT_PURGEABLE) drm_fdinfo_print_size(p, prefix, "purgeable", region, stats->purgeable); + + if (supported_status & DRM_GEM_OBJECT_EVICTED) + drm_fdinfo_print_size(p, prefix, "evicted", region, + stats->evicted); } EXPORT_SYMBOL(drm_print_memory_stats); @@ -954,6 +959,9 @@ void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file) if (s & DRM_GEM_OBJECT_PURGEABLE) status.purgeable += add_size; + + if (s & DRM_GEM_OBJECT_EVICTED) + status.evicted += add_size; } spin_unlock(&file->table_lock); diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 6ee70ad65e1f..213dfecac342 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -500,6 +500,7 @@ void drm_send_event_timestamp_locked(struct drm_device *dev, * @resident: Total size of GEM objects backing pages * @purgeable: Total size of GEM objects that can be purged (resident and not active) * @active: Total size of GEM objects active on one or more engines + * @evicted: Total size of GEM objects that have been evicted to swap * * Used by drm_print_memory_stats() */ @@ -509,6 +510,7 @@ struct drm_memory_stats { u64 resident; u64 purgeable; u64 active; + u64 evicted; }; enum drm_gem_object_status; diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index 86f5846154f7..b42ea2e582cf 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -53,6 +53,7 @@ struct drm_gem_object; * @DRM_GEM_OBJECT_RESIDENT: object is resident in memory (ie. not unpinned) * @DRM_GEM_OBJECT_PURGEABLE: object marked as purgeable by userspace * @DRM_GEM_OBJECT_ACTIVE: object is currently used by an active submission + * @DRM_GEM_OBJECT_EVICTED: object is evicted to swap * * Bitmask of status used for fdinfo memory stats, see &drm_gem_object_funcs.status * and drm_show_fdinfo(). Note that an object can report DRM_GEM_OBJECT_PURGEABLE @@ -67,6 +68,7 @@ enum drm_gem_object_status { DRM_GEM_OBJECT_RESIDENT = BIT(0), DRM_GEM_OBJECT_PURGEABLE = BIT(1), DRM_GEM_OBJECT_ACTIVE = BIT(2), + DRM_GEM_OBJECT_EVICTED = BIT(3), }; /** -- 2.53.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Claude review: drm/fdinfo: Add "evicted" memory accounting 2026-04-20 15:46 ` [PATCH 1/2] drm/fdinfo: Add "evicted" memory accounting Nicolas Frattaroli @ 2026-04-22 23:29 ` Claude Code Review Bot 0 siblings, 0 replies; 10+ messages in thread From: Claude Code Review Bot @ 2026-04-22 23:29 UTC (permalink / raw) To: dri-devel-reviews Patch Review **Summary:** Adds `DRM_GEM_OBJECT_EVICTED` (BIT(3)) to `enum drm_gem_object_status`, adds `u64 evicted` to `struct drm_memory_stats`, and wires both into the fdinfo printing and accumulation paths. **Review:** The changes correctly follow the established pattern used by `RESIDENT`, `PURGEABLE`, and `ACTIVE`. The new enum value is properly documented with a kdoc comment. **Issue 1 (minor): The "evicted" accumulation in `drm_show_memory_stats` uses `add_size` unconditionally.** ```c if (s & DRM_GEM_OBJECT_EVICTED) status.evicted += add_size; ``` This uses `add_size`, which is the RSS size (from `obj->funcs->rss()` if available, otherwise `obj->size`). For an evicted object, `rss()` would typically return 0 since the pages are gone. In the panthor driver (patch 2), evicted objects won't have `DRM_GEM_OBJECT_RESIDENT` set, so they won't have backing pages — meaning `rss()` would return 0 (or not be meaningful). For evicted objects, the interesting number is the *total* size of the object (how much was evicted to swap), not the RSS. Consider using `obj->size` instead of `add_size`, or document why `add_size` is correct here. **Issue 2 (minor/doc): The `@DRM_GEM_OBJECT_EVICTED` doc says "object is evicted to swap".** ```c * @DRM_GEM_OBJECT_EVICTED: object is evicted to swap ``` The commit message mentions this is about pages being swapped out, but "evicted" in the GPU driver world often means "evicted from VRAM to system memory" (e.g., in TTM-based drivers). The doc comment and the enum value name could potentially be confused with VRAM eviction. Consider whether the description should be more specific, e.g. "object's backing pages have been reclaimed by the shrinker." This is a naming/documentation concern rather than a correctness issue. **Issue 3 (question): Interaction with existing `RESIDENT`/`PURGEABLE` filtering logic.** In `drm_show_memory_stats`, when an object is not `RESIDENT`, the code clears `PURGEABLE`: ```c if (s & DRM_GEM_OBJECT_RESIDENT) { status.resident += add_size; } else { s &= ~DRM_GEM_OBJECT_PURGEABLE; } ``` The new `EVICTED` status is accumulated *after* this block (based on the patch context), which is correct since evicted objects should be non-resident by definition. But there's no explicit mutual exclusivity check — a driver could theoretically return both `RESIDENT` and `EVICTED`, which would be nonsensical. This is not a bug (drivers shouldn't do this), but a comment noting that `EVICTED` is expected to be mutually exclusive with `RESIDENT` would be helpful in the enum documentation. **Issue 4 (nit): Missing documentation update.** The `drm_gem_object_status` enum doc block has a long comment about the interaction between `PURGEABLE`, `RESIDENT`, and `ACTIVE`. It would be good to add a similar note about `EVICTED` — specifically that it should only be set for non-resident objects whose pages were previously allocated and then reclaimed, and that it is mutually exclusive with `RESIDENT`. **Positive:** The `drm_memory_stats_is_zero` check is correctly updated, and the printing order (after purgeable) is reasonable. --- --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/2] drm/panthor: Implement evicted status for GEM objects 2026-04-20 15:46 [PATCH 0/2] Let userspace know about swapped out panthor GEM objects Nicolas Frattaroli 2026-04-20 15:46 ` [PATCH 1/2] drm/fdinfo: Add "evicted" memory accounting Nicolas Frattaroli @ 2026-04-20 15:47 ` Nicolas Frattaroli 2026-04-20 16:17 ` Boris Brezillon 2026-04-22 23:29 ` Claude review: " Claude Code Review Bot 2026-04-22 23:29 ` Claude review: Let userspace know about swapped out panthor " Claude Code Review Bot 2 siblings, 2 replies; 10+ messages in thread From: Nicolas Frattaroli @ 2026-04-20 15:47 UTC (permalink / raw) To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Boris Brezillon, Steven Price, Liviu Dudau Cc: dri-devel, linux-kernel, kernel, Nicolas Frattaroli For fdinfo to be able to fill its evicted counter with data, panthor needs to keep track of whether a GEM object has ever been reclaimed. Just checking whether the pages are resident isn't enough, as newly allocated objects also won't be resident. Do this with a new atomic_t member on panthor_gem_object. It's increased when an object gets evicted by the shrinker. While it's allowed to wrap around to below zero and assume a value less than a previous observed value, the reclaim counter will never return to 0 for any particular object once it's been reclaimed at least once. Use this new member to then set the appropriate DRM_GEM_OBJECT_EVICTED status flag for fdinfo, and use it in the gems debugfs. It's possible to distinguish evicted non-resident pages from newly allocated non-resident pages by checking whether reclaimed_count is != 0. Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> --- drivers/gpu/drm/panthor/panthor_gem.c | 10 ++++++++++ drivers/gpu/drm/panthor/panthor_gem.h | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c index 69cef05b6ef7..4b761b39565d 100644 --- a/drivers/gpu/drm/panthor/panthor_gem.c +++ b/drivers/gpu/drm/panthor/panthor_gem.c @@ -687,6 +687,10 @@ static void panthor_gem_evict_locked(struct panthor_gem_object *bo) if (drm_WARN_ON_ONCE(bo->base.dev, !bo->backing.pages)) return; + /* Don't ever wrap around as far as 0, jump from INT_MIN to 1 */ + if (!atomic_inc_unless_negative(&bo->reclaimed_count)) + atomic_set(&bo->reclaimed_count, 1); + panthor_gem_dev_map_cleanup_locked(bo); panthor_gem_backing_cleanup_locked(bo); panthor_gem_update_reclaim_state_locked(bo, NULL); @@ -788,6 +792,8 @@ static enum drm_gem_object_status panthor_gem_status(struct drm_gem_object *obj) if (drm_gem_is_imported(&bo->base) || bo->backing.pages) res |= DRM_GEM_OBJECT_RESIDENT; + else if (atomic_read(&bo->reclaimed_count)) + res |= DRM_GEM_OBJECT_EVICTED; return res; } @@ -1595,6 +1601,7 @@ static void panthor_gem_debugfs_print_flag_names(struct seq_file *m) static const char * const gem_state_flags_names[] = { [PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT] = "imported", [PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT] = "exported", + [PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT] = "evicted", }; static const char * const gem_usage_flags_names[] = { @@ -1648,6 +1655,9 @@ static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo, if (drm_gem_is_imported(&bo->base)) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED; + else if (!resident_size && atomic_read(&bo->reclaimed_count)) + gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED; + if (bo->base.dma_buf) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED; diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h index ae0491d0b121..1ab573f03330 100644 --- a/drivers/gpu/drm/panthor/panthor_gem.h +++ b/drivers/gpu/drm/panthor/panthor_gem.h @@ -19,12 +19,16 @@ struct panthor_vm; enum panthor_debugfs_gem_state_flags { PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT = 0, PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT = 1, + PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT = 2, /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED: GEM BO is PRIME imported. */ PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT), /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED: GEM BO is PRIME exported. */ PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT), + + /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED: GEM BO is evicted to swap. */ + PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT), }; enum panthor_debugfs_gem_usage_flags { @@ -172,6 +176,13 @@ struct panthor_gem_object { /** @reclaim_state: Cached reclaim state */ enum panthor_gem_reclaim_state reclaim_state; + /** + * @reclaimed_count: How many times object has been evicted to swap. + * Never returns to 0 once incremented even on wrap-around, but may + * become < 0 and < the previous value if wrap-around occurs. + */ + atomic_t reclaimed_count; + /** * @exclusive_vm_root_gem: Root GEM of the exclusive VM this GEM object * is attached to. -- 2.53.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] drm/panthor: Implement evicted status for GEM objects 2026-04-20 15:47 ` [PATCH 2/2] drm/panthor: Implement evicted status for GEM objects Nicolas Frattaroli @ 2026-04-20 16:17 ` Boris Brezillon 2026-04-20 17:46 ` Nicolas Frattaroli 2026-04-22 23:29 ` Claude review: " Claude Code Review Bot 1 sibling, 1 reply; 10+ messages in thread From: Boris Brezillon @ 2026-04-20 16:17 UTC (permalink / raw) To: Nicolas Frattaroli Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Steven Price, Liviu Dudau, dri-devel, linux-kernel, kernel On Mon, 20 Apr 2026 17:47:00 +0200 Nicolas Frattaroli <nicolas.frattaroli@collabora.com> wrote: > For fdinfo to be able to fill its evicted counter with data, panthor > needs to keep track of whether a GEM object has ever been reclaimed. > Just checking whether the pages are resident isn't enough, as newly > allocated objects also won't be resident. > > Do this with a new atomic_t member on panthor_gem_object. It's increased > when an object gets evicted by the shrinker. While it's allowed to wrap > around to below zero and assume a value less than a previous observed > value, the reclaim counter will never return to 0 for any particular > object once it's been reclaimed at least once. > > Use this new member to then set the appropriate DRM_GEM_OBJECT_EVICTED > status flag for fdinfo, and use it in the gems debugfs. It's possible to > distinguish evicted non-resident pages from newly allocated non-resident > pages by checking whether reclaimed_count is != 0. > > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> > --- > drivers/gpu/drm/panthor/panthor_gem.c | 10 ++++++++++ > drivers/gpu/drm/panthor/panthor_gem.h | 11 +++++++++++ > 2 files changed, 21 insertions(+) > > diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c > index 69cef05b6ef7..4b761b39565d 100644 > --- a/drivers/gpu/drm/panthor/panthor_gem.c > +++ b/drivers/gpu/drm/panthor/panthor_gem.c > @@ -687,6 +687,10 @@ static void panthor_gem_evict_locked(struct panthor_gem_object *bo) > if (drm_WARN_ON_ONCE(bo->base.dev, !bo->backing.pages)) > return; > > + /* Don't ever wrap around as far as 0, jump from INT_MIN to 1 */ > + if (!atomic_inc_unless_negative(&bo->reclaimed_count)) > + atomic_set(&bo->reclaimed_count, 1); Can't we just go atomic_add_unless(&bo->reclaimed_count, 1, INT_MAX); here, to handle the INT_MAX saturation? > + > panthor_gem_dev_map_cleanup_locked(bo); > panthor_gem_backing_cleanup_locked(bo); > panthor_gem_update_reclaim_state_locked(bo, NULL); > @@ -788,6 +792,8 @@ static enum drm_gem_object_status panthor_gem_status(struct drm_gem_object *obj) > > if (drm_gem_is_imported(&bo->base) || bo->backing.pages) > res |= DRM_GEM_OBJECT_RESIDENT; > + else if (atomic_read(&bo->reclaimed_count)) > + res |= DRM_GEM_OBJECT_EVICTED; > > return res; > } > @@ -1595,6 +1601,7 @@ static void panthor_gem_debugfs_print_flag_names(struct seq_file *m) > static const char * const gem_state_flags_names[] = { > [PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT] = "imported", > [PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT] = "exported", > + [PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT] = "evicted", > }; > > static const char * const gem_usage_flags_names[] = { > @@ -1648,6 +1655,9 @@ static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo, > > if (drm_gem_is_imported(&bo->base)) > gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED; > + else if (!resident_size && atomic_read(&bo->reclaimed_count)) > + gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED; I think it'd be interesting to know the number of times a BO got evicted. > + > if (bo->base.dma_buf) > gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED; > > diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h > index ae0491d0b121..1ab573f03330 100644 > --- a/drivers/gpu/drm/panthor/panthor_gem.h > +++ b/drivers/gpu/drm/panthor/panthor_gem.h > @@ -19,12 +19,16 @@ struct panthor_vm; > enum panthor_debugfs_gem_state_flags { > PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT = 0, > PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT = 1, > + PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT = 2, > > /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED: GEM BO is PRIME imported. */ > PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT), > > /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED: GEM BO is PRIME exported. */ > PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT), > + > + /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED: GEM BO is evicted to swap. */ > + PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT), > }; > > enum panthor_debugfs_gem_usage_flags { > @@ -172,6 +176,13 @@ struct panthor_gem_object { > /** @reclaim_state: Cached reclaim state */ > enum panthor_gem_reclaim_state reclaim_state; > > + /** > + * @reclaimed_count: How many times object has been evicted to swap. * > + * Never returns to 0 once incremented even on wrap-around, but may > + * become < 0 and < the previous value if wrap-around occurs. With the saturation I suggested, I'd just add that when INT_MAX is reached, it will stay there. > + */ > + atomic_t reclaimed_count; > + > /** > * @exclusive_vm_root_gem: Root GEM of the exclusive VM this GEM object > * is attached to. > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] drm/panthor: Implement evicted status for GEM objects 2026-04-20 16:17 ` Boris Brezillon @ 2026-04-20 17:46 ` Nicolas Frattaroli 2026-04-21 7:22 ` Boris Brezillon 0 siblings, 1 reply; 10+ messages in thread From: Nicolas Frattaroli @ 2026-04-20 17:46 UTC (permalink / raw) To: Boris Brezillon Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Steven Price, Liviu Dudau, dri-devel, linux-kernel, kernel On Monday, 20 April 2026 18:17:35 Central European Summer Time Boris Brezillon wrote: > On Mon, 20 Apr 2026 17:47:00 +0200 > Nicolas Frattaroli <nicolas.frattaroli@collabora.com> wrote: > > > For fdinfo to be able to fill its evicted counter with data, panthor > > needs to keep track of whether a GEM object has ever been reclaimed. > > Just checking whether the pages are resident isn't enough, as newly > > allocated objects also won't be resident. > > > > Do this with a new atomic_t member on panthor_gem_object. It's increased > > when an object gets evicted by the shrinker. While it's allowed to wrap > > around to below zero and assume a value less than a previous observed > > value, the reclaim counter will never return to 0 for any particular > > object once it's been reclaimed at least once. > > > > Use this new member to then set the appropriate DRM_GEM_OBJECT_EVICTED > > status flag for fdinfo, and use it in the gems debugfs. It's possible to > > distinguish evicted non-resident pages from newly allocated non-resident > > pages by checking whether reclaimed_count is != 0. > > > > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> > > --- > > drivers/gpu/drm/panthor/panthor_gem.c | 10 ++++++++++ > > drivers/gpu/drm/panthor/panthor_gem.h | 11 +++++++++++ > > 2 files changed, 21 insertions(+) > > > > diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c > > index 69cef05b6ef7..4b761b39565d 100644 > > --- a/drivers/gpu/drm/panthor/panthor_gem.c > > +++ b/drivers/gpu/drm/panthor/panthor_gem.c > > @@ -687,6 +687,10 @@ static void panthor_gem_evict_locked(struct panthor_gem_object *bo) > > if (drm_WARN_ON_ONCE(bo->base.dev, !bo->backing.pages)) > > return; > > > > + /* Don't ever wrap around as far as 0, jump from INT_MIN to 1 */ > > + if (!atomic_inc_unless_negative(&bo->reclaimed_count)) > > + atomic_set(&bo->reclaimed_count, 1); > > Can't we just go > > atomic_add_unless(&bo->reclaimed_count, 1, INT_MAX); > > here, to handle the INT_MAX saturation? Yeah, I was torn between the two. My way does keep a somewhat cyclical nature, so once it wraps, things could still detect that it's increasing from one observance to the next. But now that I think about it again, it's not a property of this count that's worth keeping, I think. Nothing relies on this behaviour currently, and at best it'll trip up any code that uses it for a < comparison later down the road. > > + > > panthor_gem_dev_map_cleanup_locked(bo); > > panthor_gem_backing_cleanup_locked(bo); > > panthor_gem_update_reclaim_state_locked(bo, NULL); > > @@ -788,6 +792,8 @@ static enum drm_gem_object_status panthor_gem_status(struct drm_gem_object *obj) > > > > if (drm_gem_is_imported(&bo->base) || bo->backing.pages) > > res |= DRM_GEM_OBJECT_RESIDENT; > > + else if (atomic_read(&bo->reclaimed_count)) > > + res |= DRM_GEM_OBJECT_EVICTED; > > > > return res; > > } > > @@ -1595,6 +1601,7 @@ static void panthor_gem_debugfs_print_flag_names(struct seq_file *m) > > static const char * const gem_state_flags_names[] = { > > [PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT] = "imported", > > [PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT] = "exported", > > + [PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT] = "evicted", > > }; > > > > static const char * const gem_usage_flags_names[] = { > > @@ -1648,6 +1655,9 @@ static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo, > > > > if (drm_gem_is_imported(&bo->base)) > > gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED; > > + else if (!resident_size && atomic_read(&bo->reclaimed_count)) > > + gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED; > > I think it'd be interesting to know the number of times a BO got > evicted. Agreed. Should I add that as a separate column? I think I'll keep the state flag even if I add a column, because even if it's technically redundant, it'll still be useful to see without having to compare three different columns. > > + > > if (bo->base.dma_buf) > > gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED; > > > > diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h > > index ae0491d0b121..1ab573f03330 100644 > > --- a/drivers/gpu/drm/panthor/panthor_gem.h > > +++ b/drivers/gpu/drm/panthor/panthor_gem.h > > @@ -19,12 +19,16 @@ struct panthor_vm; > > enum panthor_debugfs_gem_state_flags { > > PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT = 0, > > PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT = 1, > > + PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT = 2, > > > > /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED: GEM BO is PRIME imported. */ > > PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT), > > > > /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED: GEM BO is PRIME exported. */ > > PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT), > > + > > + /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED: GEM BO is evicted to swap. */ > > + PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT), > > }; > > > > enum panthor_debugfs_gem_usage_flags { > > @@ -172,6 +176,13 @@ struct panthor_gem_object { > > /** @reclaim_state: Cached reclaim state */ > > enum panthor_gem_reclaim_state reclaim_state; > > > > + /** > > + * @reclaimed_count: How many times object has been evicted to swap. > > * > > > + * Never returns to 0 once incremented even on wrap-around, but may > > + * become < 0 and < the previous value if wrap-around occurs. > > With the saturation I suggested, I'd just add that when INT_MAX is > reached, it will stay there. > > > + */ > > + atomic_t reclaimed_count; > > + > > /** > > * @exclusive_vm_root_gem: Root GEM of the exclusive VM this GEM object > > * is attached to. > > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] drm/panthor: Implement evicted status for GEM objects 2026-04-20 17:46 ` Nicolas Frattaroli @ 2026-04-21 7:22 ` Boris Brezillon 0 siblings, 0 replies; 10+ messages in thread From: Boris Brezillon @ 2026-04-21 7:22 UTC (permalink / raw) To: Nicolas Frattaroli Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Steven Price, Liviu Dudau, dri-devel, linux-kernel, kernel On Mon, 20 Apr 2026 19:46:52 +0200 Nicolas Frattaroli <nicolas.frattaroli@collabora.com> wrote: > > > + > > > panthor_gem_dev_map_cleanup_locked(bo); > > > panthor_gem_backing_cleanup_locked(bo); > > > panthor_gem_update_reclaim_state_locked(bo, NULL); > > > @@ -788,6 +792,8 @@ static enum drm_gem_object_status panthor_gem_status(struct drm_gem_object *obj) > > > > > > if (drm_gem_is_imported(&bo->base) || bo->backing.pages) > > > res |= DRM_GEM_OBJECT_RESIDENT; > > > + else if (atomic_read(&bo->reclaimed_count)) > > > + res |= DRM_GEM_OBJECT_EVICTED; > > > > > > return res; > > > } > > > @@ -1595,6 +1601,7 @@ static void panthor_gem_debugfs_print_flag_names(struct seq_file *m) > > > static const char * const gem_state_flags_names[] = { > > > [PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT] = "imported", > > > [PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT] = "exported", > > > + [PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT] = "evicted", > > > }; > > > > > > static const char * const gem_usage_flags_names[] = { > > > @@ -1648,6 +1655,9 @@ static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo, > > > > > > if (drm_gem_is_imported(&bo->base)) > > > gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED; > > > + else if (!resident_size && atomic_read(&bo->reclaimed_count)) > > > + gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED; > > > > I think it'd be interesting to know the number of times a BO got > > evicted. > > Agreed. Should I add that as a separate column? Yes > I think I'll keep the > state flag even if I add a column, because even if it's technically > redundant, it'll still be useful to see without having to compare > three different columns. Sure, keeping the "evicted" flag is fine. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Claude review: drm/panthor: Implement evicted status for GEM objects 2026-04-20 15:47 ` [PATCH 2/2] drm/panthor: Implement evicted status for GEM objects Nicolas Frattaroli 2026-04-20 16:17 ` Boris Brezillon @ 2026-04-22 23:29 ` Claude Code Review Bot 1 sibling, 0 replies; 10+ messages in thread From: Claude Code Review Bot @ 2026-04-22 23:29 UTC (permalink / raw) To: dri-devel-reviews Patch Review **Summary:** Adds an `atomic_t reclaimed_count` field to `panthor_gem_object`, increments it in the evict path, and uses it to report `DRM_GEM_OBJECT_EVICTED` via the `.status` callback and the debugfs gems interface. **Review:** **Issue 1 (design): The wrap-around avoidance is over-engineered for a boolean need.** ```c /* Don't ever wrap around as far as 0, jump from INT_MIN to 1 */ if (!atomic_inc_unless_negative(&bo->reclaimed_count)) atomic_set(&bo->reclaimed_count, 1); ``` The only consumer of `reclaimed_count` checks `!= 0`: ```c else if (atomic_read(&bo->reclaimed_count)) res |= DRM_GEM_OBJECT_EVICTED; ``` If the sole purpose is "has this BO ever been evicted", a simple `bool` or even a flag bit would suffice. The commit message justifies the counter by saying "It's possible to distinguish evicted non-resident pages from newly allocated non-resident pages by checking whether reclaimed_count is != 0" — but that's the same as a boolean. If there's a genuine use case for knowing *how many times* a BO was evicted (e.g., for future debugfs stats), the counter makes sense. But in that case, the wrap-around logic is wrong — after wrap-around, the count is no longer meaningful. And `atomic_inc_unless_negative` is not a cheap operation (it's a cmpxchg loop), unlike a simple `atomic_inc` or `atomic_set`. Suggestion: Either use a simpler `bool evicted` (or a flag bit) if you only need the boolean, or use a plain `atomic_inc` if you want a counter (wrap-around after 2^31 evictions is not a real-world concern, and the count being "wrong" after wrap is no worse than clamping at 1). **Issue 2 (atomics concern): `atomic_set` after failed `atomic_inc_unless_negative` is not atomic with respect to concurrent reads.** ```c if (!atomic_inc_unless_negative(&bo->reclaimed_count)) atomic_set(&bo->reclaimed_count, 1); ``` If two threads hit this simultaneously when `reclaimed_count` is `INT_MIN`, both could see `atomic_inc_unless_negative` fail (since `INT_MIN` is negative), and both call `atomic_set(&bo->reclaimed_count, 1)`. That's fine — the result is still 1. But there's a window where a concurrent `atomic_read` from `panthor_gem_status` could observe 0 if the set hasn't completed. In practice, this is harmless since: - Eviction holds a lock (`panthor_gem_evict_locked`) - The status read is racy by design (documented in `drm_gem_object_funcs.status`) But it would be cleaner to just use `atomic_inc` and accept that the counter can wrap, or use a simple flag. **Issue 3 (logic): The `else if` chain in `panthor_gem_status` means imported objects can never be reported as evicted.** ```c if (drm_gem_is_imported(&bo->base) || bo->backing.pages) res |= DRM_GEM_OBJECT_RESIDENT; else if (atomic_read(&bo->reclaimed_count)) res |= DRM_GEM_OBJECT_EVICTED; ``` Since imported objects always get `RESIDENT`, they can never get `EVICTED`. This is probably correct (imported objects shouldn't be evicted by the panthor shrinker), but worth confirming — does the panthor shrinker skip imported BOs? If an imported BO were somehow evicted, the status would incorrectly show it as `RESIDENT`. **Issue 4 (debugfs): Same `else if` pattern with different condition for debugfs.** ```c if (drm_gem_is_imported(&bo->base)) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED; else if (!resident_size && atomic_read(&bo->reclaimed_count)) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED; if (bo->base.dma_buf) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED; ``` Note the `else if` means an imported BO will never show as evicted in debugfs either. An exported BO *can* show as evicted (since the exported check uses a separate `if`), which is inconsistent with the imported BO treatment. If an exported BO is evicted, it will show both "exported" and "evicted" flags in debugfs, which seems correct. But an imported+evicted BO (if possible) would only show "imported". This is a minor consistency concern. **Issue 5 (missing initialization): `reclaimed_count` is not explicitly initialized.** The new `atomic_t reclaimed_count` field in `panthor_gem_object` is not explicitly initialized to 0 in any allocation path. This relies on the GEM object being allocated with `kzalloc` (via shmem helpers), which zero-initializes the entire struct. This works correctly for `atomic_t` since `ATOMIC_INIT(0)` is just `{ 0 }`, but it's worth noting that this is an implicit dependency on zero-initialization. **Issue 6 (nit): Comment style.** ```c /* Don't ever wrap around as far as 0, jump from INT_MIN to 1 */ ``` This is a reasonable comment given the non-obvious wrap-around handling, though it could be simplified if the approach itself is simplified. **Positive aspects:** - The debugfs flag naming table is correctly extended - The `else if` logic in `panthor_gem_status` correctly makes `EVICTED` mutually exclusive with `RESIDENT` - The commit message is well-written and clearly explains the rationale --- **Summary:** The series is architecturally sound and fills a real observability gap. The main feedback is: (1) consider whether `obj->size` is more appropriate than `add_size` for the evicted counter in patch 1, (2) simplify the `reclaimed_count` to either a plain boolean flag or a simple `atomic_inc` counter in patch 2, and (3) add documentation about `EVICTED`/`RESIDENT` mutual exclusivity to the enum comments. --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 10+ messages in thread
* Claude review: Let userspace know about swapped out panthor GEM objects 2026-04-20 15:46 [PATCH 0/2] Let userspace know about swapped out panthor GEM objects Nicolas Frattaroli 2026-04-20 15:46 ` [PATCH 1/2] drm/fdinfo: Add "evicted" memory accounting Nicolas Frattaroli 2026-04-20 15:47 ` [PATCH 2/2] drm/panthor: Implement evicted status for GEM objects Nicolas Frattaroli @ 2026-04-22 23:29 ` Claude Code Review Bot 2 siblings, 0 replies; 10+ messages in thread From: Claude Code Review Bot @ 2026-04-22 23:29 UTC (permalink / raw) To: dri-devel-reviews Overall Series Review Subject: Let userspace know about swapped out panthor GEM objects Author: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> Patches: 6 Reviewed: 2026-04-23T09:29:11.567506 --- This is a clean, small, 2-patch series that adds "evicted" (swapped-out) memory tracking to the DRM fdinfo infrastructure and wires it up in the panthor driver. The motivation is sound: without this, userspace cannot distinguish between a BO that was never backed by pages and one that was backed but later evicted to swap. The implementation is straightforward and follows the established patterns for `RESIDENT`, `PURGEABLE`, and `ACTIVE` statuses. **Key observations:** 1. The series depends on a not-yet-landed panthor GEM shrinker series (the patches reference `bo->backing.pages` while the current drm-next tree uses `bo->base.pages`, and `panthor_gem_evict_locked` doesn't exist yet). This is fine as a dependency chain, but should be noted. 2. The `atomic_t reclaimed_count` wrap-around-avoidance logic is clever but over-engineered for what is effectively a boolean "has ever been evicted" flag. The counter approach tries to serve dual duty — providing the count for potential future use while also acting as a boolean — and the wrap-around handling adds complexity for a scenario that is practically impossible (2^31 evictions of a single BO). 3. The fdinfo integration in patch 1 is clean and follows established patterns correctly. The `supported_status` bitmask mechanism means the "evicted" line only appears in fdinfo output when at least one object has actually been evicted, which is the right behavior. **Overall: Series looks good. A few minor issues and design questions below.** --- --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 0/3] Let userspace know about swapped out panthor GEM objects
@ 2026-04-21 10:45 Nicolas Frattaroli
2026-04-21 10:45 ` [PATCH v2 2/3] drm/panthor: Implement evicted status for " Nicolas Frattaroli
0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Frattaroli @ 2026-04-21 10:45 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Boris Brezillon, Steven Price, Liviu Dudau
Cc: dri-devel, linux-kernel, kernel, Nicolas Frattaroli
Panthor has recently gained a GEM shrinker. It allows evicting memory
that backs unused GEM objects to swap.
In this series, both fdinfo and Panthor's gems debugfs are extended so
that information on evicted pages can be gathered by users through these
two methods.
---
Changes in v2:
- Change reclaimed_count to saturate at INT_MAX
- Add "evictions" column to panthor gems debugfs which prints
reclaimed_count
- Add a patch to reduce the padding of one panthor gems debugfs column a
bit
- Link to v1: https://patch.msgid.link/20260420-panthor-bo-reclaim-observability-v1-0-a4d1a36ee84f@collabora.com
To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
To: Maxime Ripard <mripard@kernel.org>
To: Thomas Zimmermann <tzimmermann@suse.de>
To: David Airlie <airlied@gmail.com>
To: Simona Vetter <simona@ffwll.ch>
To: Boris Brezillon <boris.brezillon@collabora.com>
To: Steven Price <steven.price@arm.com>
To: Liviu Dudau <liviu.dudau@arm.com>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Cc: kernel@collabora.com
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
Nicolas Frattaroli (3):
drm/fdinfo: Add "evicted" memory accounting
drm/panthor: Implement evicted status for GEM objects
drm/panthor: Reduce padding in gems debugfs for refcount
drivers/gpu/drm/drm_file.c | 8 ++++++++
drivers/gpu/drm/panthor/panthor_gem.c | 18 ++++++++++++++----
drivers/gpu/drm/panthor/panthor_gem.h | 10 ++++++++++
include/drm/drm_file.h | 2 ++
include/drm/drm_gem.h | 2 ++
5 files changed, 36 insertions(+), 4 deletions(-)
---
base-commit: 3f9357c30a44734d45e3093c521d52b2aefb09f5
change-id: 20260420-panthor-bo-reclaim-observability-970679c9533c
Best regards,
--
Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v2 2/3] drm/panthor: Implement evicted status for GEM objects 2026-04-21 10:45 [PATCH v2 0/3] " Nicolas Frattaroli @ 2026-04-21 10:45 ` Nicolas Frattaroli 2026-04-22 22:36 ` Claude review: " Claude Code Review Bot 0 siblings, 1 reply; 10+ messages in thread From: Nicolas Frattaroli @ 2026-04-21 10:45 UTC (permalink / raw) To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Boris Brezillon, Steven Price, Liviu Dudau Cc: dri-devel, linux-kernel, kernel, Nicolas Frattaroli For fdinfo to be able to fill its evicted counter with data, panthor needs to keep track of whether a GEM object has ever been reclaimed. Just checking whether the pages are resident isn't enough, as newly allocated objects also won't be resident. Do this with a new atomic_t member on panthor_gem_object. It's increased when an object gets evicted by the shrinker, and saturates at INT_MAX. This means that once an object has been evicted at least once, its reclaim counter will never return to 0. Due to this, it's possible to distinguish evicted non-resident pages from newly allocated non-resident pages by checking whether reclaimed_count is != 0 Use this new member to then set the appropriate DRM_GEM_OBJECT_EVICTED status flag for fdinfo. Also add a new column and status flag to the panthor gems debugfs: the column is the number of times an object has been evicted, whereas the flag indicates whether it currently is evicted. Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> --- drivers/gpu/drm/panthor/panthor_gem.c | 18 ++++++++++++++---- drivers/gpu/drm/panthor/panthor_gem.h | 10 ++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c index 69cef05b6ef7..b6fe20b7e6d0 100644 --- a/drivers/gpu/drm/panthor/panthor_gem.c +++ b/drivers/gpu/drm/panthor/panthor_gem.c @@ -687,6 +687,8 @@ static void panthor_gem_evict_locked(struct panthor_gem_object *bo) if (drm_WARN_ON_ONCE(bo->base.dev, !bo->backing.pages)) return; + atomic_add_unless(&bo->reclaimed_count, 1, INT_MAX); + panthor_gem_dev_map_cleanup_locked(bo); panthor_gem_backing_cleanup_locked(bo); panthor_gem_update_reclaim_state_locked(bo, NULL); @@ -788,6 +790,8 @@ static enum drm_gem_object_status panthor_gem_status(struct drm_gem_object *obj) if (drm_gem_is_imported(&bo->base) || bo->backing.pages) res |= DRM_GEM_OBJECT_RESIDENT; + else if (atomic_read(&bo->reclaimed_count)) + res |= DRM_GEM_OBJECT_EVICTED; return res; } @@ -1595,6 +1599,7 @@ static void panthor_gem_debugfs_print_flag_names(struct seq_file *m) static const char * const gem_state_flags_names[] = { [PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT] = "imported", [PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT] = "exported", + [PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT] = "evicted", }; static const char * const gem_usage_flags_names[] = { @@ -1625,6 +1630,7 @@ static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo, { enum panthor_gem_reclaim_state reclaim_state = bo->reclaim_state; unsigned int refcount = kref_read(&bo->base.refcount); + int reclaimed_count = atomic_read(&bo->reclaimed_count); char creator_info[32] = {}; size_t resident_size; u32 gem_usage_flags = bo->debugfs.flags; @@ -1638,16 +1644,20 @@ static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo, snprintf(creator_info, sizeof(creator_info), "%s/%d", bo->debugfs.creator.process_name, bo->debugfs.creator.tgid); - seq_printf(m, "%-32s%-16d%-16d%-16zd%-16zd0x%-16lx", + seq_printf(m, "%-32s%-16d%-16d%-11d%-16zd%-16zd0x%-16lx", creator_info, bo->base.name, refcount, + reclaimed_count, bo->base.size, resident_size, drm_vma_node_start(&bo->base.vma_node)); if (drm_gem_is_imported(&bo->base)) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED; + else if (!resident_size && reclaimed_count) + gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED; + if (bo->base.dma_buf) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED; @@ -1671,8 +1681,8 @@ static void panthor_gem_debugfs_print_bos(struct panthor_device *ptdev, panthor_gem_debugfs_print_flag_names(m); - seq_puts(m, "created-by global-name refcount size resident-size file-offset state usage label\n"); - seq_puts(m, "----------------------------------------------------------------------------------------------------------------------------------------------\n"); + seq_puts(m, "created-by global-name refcount evictions size resident-size file-offset state usage label\n"); + seq_puts(m, "---------------------------------------------------------------------------------------------------------------------------------------------------------\n"); scoped_guard(mutex, &ptdev->gems.lock) { list_for_each_entry(bo, &ptdev->gems.node, debugfs.node) { @@ -1680,7 +1690,7 @@ static void panthor_gem_debugfs_print_bos(struct panthor_device *ptdev, } } - seq_puts(m, "==============================================================================================================================================\n"); + seq_puts(m, "=========================================================================================================================================================\n"); seq_printf(m, "Total size: %zd, Total resident: %zd, Total reclaimable: %zd\n", totals.size, totals.resident, totals.reclaimable); } diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h index ae0491d0b121..56d63137b4eb 100644 --- a/drivers/gpu/drm/panthor/panthor_gem.h +++ b/drivers/gpu/drm/panthor/panthor_gem.h @@ -19,12 +19,16 @@ struct panthor_vm; enum panthor_debugfs_gem_state_flags { PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT = 0, PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT = 1, + PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT = 2, /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED: GEM BO is PRIME imported. */ PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT), /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED: GEM BO is PRIME exported. */ PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT), + + /** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED: GEM BO is evicted to swap. */ + PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT), }; enum panthor_debugfs_gem_usage_flags { @@ -172,6 +176,12 @@ struct panthor_gem_object { /** @reclaim_state: Cached reclaim state */ enum panthor_gem_reclaim_state reclaim_state; + /** + * @reclaimed_count: How many times object has been evicted to swap. + * The count saturates at %INT_MAX and will never wrap around to 0. + */ + atomic_t reclaimed_count; + /** * @exclusive_vm_root_gem: Root GEM of the exclusive VM this GEM object * is attached to. -- 2.53.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Claude review: drm/panthor: Implement evicted status for GEM objects 2026-04-21 10:45 ` [PATCH v2 2/3] drm/panthor: Implement evicted status for " Nicolas Frattaroli @ 2026-04-22 22:36 ` Claude Code Review Bot 0 siblings, 0 replies; 10+ messages in thread From: Claude Code Review Bot @ 2026-04-22 22:36 UTC (permalink / raw) To: dri-devel-reviews Patch Review This is the meat of the series. It adds `atomic_t reclaimed_count` to `panthor_gem_object`, increments it during eviction, and uses it to report status via both fdinfo and debugfs. **Correctness of the eviction path ordering is good:** ```c atomic_add_unless(&bo->reclaimed_count, 1, INT_MAX); panthor_gem_dev_map_cleanup_locked(bo); panthor_gem_backing_cleanup_locked(bo); ``` The counter is incremented *before* pages are cleared, which avoids a window where a concurrent lockless reader in `panthor_gem_status()` could see the object as neither resident nor evicted. This is the right order. **The status callback logic is correct:** ```c if (drm_gem_is_imported(&bo->base) || bo->backing.pages) res |= DRM_GEM_OBJECT_RESIDENT; else if (atomic_read(&bo->reclaimed_count)) res |= DRM_GEM_OBJECT_EVICTED; ``` The `else if` correctly makes RESIDENT and EVICTED mutually exclusive, and the `reclaimed_count` check distinguishes evicted objects from objects that were never backed. The `atomic_read()` is appropriate here since `panthor_gem_status()` can be called under a spinlock without holding the BO's own lock. **Debugfs evicted state flag logic:** ```c if (drm_gem_is_imported(&bo->base)) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED; else if (!resident_size && reclaimed_count) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED; if (bo->base.dma_buf) gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED; ``` Note that `EVICTED` and `IMPORTED` are mutually exclusive via `else if`, but `EVICTED` and `EXPORTED` are not (an exported BO that gets evicted would show both flags). Is that the desired behavior? An exported BO could conceivably be evicted, so allowing both flags seems reasonable. But the fdinfo path in `panthor_gem_status()` similarly makes EVICTED exclusive with imported — worth confirming this is intentional for imported buffers (which typically have backing managed by the exporter, so they shouldn't get evicted anyway). **Minor: `int reclaimed_count` local variable.** The `atomic_read()` returns `int`, so the local is correctly typed. However, the debugfs format uses `%-11d` which handles 10-digit signed ints. Since the value saturates at INT_MAX (~2.1 billion, 10 digits), `%-11d` (10 digits + 1 space) is exactly right. **No initialization needed** — `panthor_gem_object` is allocated via `kzalloc` (through `drm_gem_shmem_create`), so `reclaimed_count` starts at 0 implicitly. Good. --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-04-22 23:29 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-04-20 15:46 [PATCH 0/2] Let userspace know about swapped out panthor GEM objects Nicolas Frattaroli 2026-04-20 15:46 ` [PATCH 1/2] drm/fdinfo: Add "evicted" memory accounting Nicolas Frattaroli 2026-04-22 23:29 ` Claude review: " Claude Code Review Bot 2026-04-20 15:47 ` [PATCH 2/2] drm/panthor: Implement evicted status for GEM objects Nicolas Frattaroli 2026-04-20 16:17 ` Boris Brezillon 2026-04-20 17:46 ` Nicolas Frattaroli 2026-04-21 7:22 ` Boris Brezillon 2026-04-22 23:29 ` Claude review: " Claude Code Review Bot 2026-04-22 23:29 ` Claude review: Let userspace know about swapped out panthor " Claude Code Review Bot -- strict thread matches above, loose matches on Subject: below -- 2026-04-21 10:45 [PATCH v2 0/3] " Nicolas Frattaroli 2026-04-21 10:45 ` [PATCH v2 2/3] drm/panthor: Implement evicted status for " Nicolas Frattaroli 2026-04-22 22:36 ` Claude review: " Claude Code Review Bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox