* [PATCH v4 0/4] drm/xe: Adjust the bo shrinker batch size
@ 2026-10-16 13:35 Thomas Hellström
2026-10-16 13:35 ` [PATCH v4 1/4] drm/xe: Don't abort the shrinker walk on -EBUSY Thomas Hellström
` (5 more replies)
0 siblings, 6 replies; 18+ messages in thread
From: Thomas Hellström @ 2026-10-16 13:35 UTC (permalink / raw)
To: intel-xe
Cc: Thomas Hellström, Matthew Brost, Matthew Auld,
Maarten Lankhorst
Shamelessly stolen from i915, To avoid gpu stalls for small
shrinker request, Set the shrinker batch size to the average
size of system buffer objects. Use the number of
populated struct ttm_tts to compute the average size.
Sashiko AI review of the v2 posting flagged two issues:
- [High] a pre-existing shrinker accounting double-subtraction bug on
nested external pins (plus a related underflow for imported
dma-bufs, found while fixing it). This has since been fixed and
merged upstream as its own, separate fixes series, so it is no
longer carried as a patch here.
- [Medium] a data race on the unsynchronized read-modify-write of the
shrinker batch size. Fixed in v3 below.
Sashiko AI review of the v3 posting flagged, among others:
- [High] a pre-existing shrinker accounting underflow when the
purgeable state of a pinned bo changes. This is fixed by a
separately posted patch, "drm/xe: Don't transfer shrinker pages for
pinned bos on purgeable state change".
- [High] the standalone purgeable shrinker aborting its LRU walk at
the first non-purgeable object. This turned out to be a
pre-existing bug affecting also the non-purge walk, for example
at imported dma-bufs. Fixed in patch 1/4, placed first so that it
can be backported independently.
v2:
- Fix the average object size estimate to account for the full
shrinkable and purgeable population.
v3:
- Drop the shrinker accounting double-subtraction fix from this
series; it has been fixed and merged upstream separately.
- Patch 3/4: new patch, splitting the bo shrinker into purgeable and
non-purgeable shrinkers, per a suggestion from Matthew Brost.
- Patch 4/4: reworked on top of the shrinker split, and the batch size
update is now performed under the existing shrinker lock, fixing the
data race caught by Sashiko AI review.
v4:
- Patch 1/4: new patch, skipping objects for which xe_bo_shrink()
returns -EBUSY rather than aborting the shrinker walk. (Sashiko)
Thomas Hellström (4):
drm/xe: Don't abort the shrinker walk on -EBUSY
drm/xe: Track number of populated ttm_tts in the shrinker
drm/xe: Split the bo shrinker into purgeable and non-purgeable
shrinkers
drm/xe: Update non-purgeable shrinker batch size based on average BO
size
drivers/gpu/drm/xe/xe_bo.c | 12 +--
drivers/gpu/drm/xe/xe_shrinker.c | 175 ++++++++++++++++++++++---------
drivers/gpu/drm/xe/xe_shrinker.h | 3 +-
3 files changed, 132 insertions(+), 58 deletions(-)
--
2.56.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 1/4] drm/xe: Don't abort the shrinker walk on -EBUSY
2026-10-16 13:35 [PATCH v4 0/4] drm/xe: Adjust the bo shrinker batch size Thomas Hellström
@ 2026-10-16 13:35 ` Thomas Hellström
2026-10-16 13:44 ` sashiko-bot
2026-10-16 13:55 ` Matthew Brost
2026-10-16 13:35 ` [PATCH v4 2/4] drm/xe: Track number of populated ttm_tts in the shrinker Thomas Hellström
` (4 subsequent siblings)
5 siblings, 2 replies; 18+ messages in thread
From: Thomas Hellström @ 2026-10-16 13:35 UTC (permalink / raw)
To: intel-xe
Cc: Thomas Hellström, Christian König, Matthew Brost,
Rodrigo Vivi, stable, Matthew Auld, Maarten Lankhorst
xe_bo_shrink() returns -EBUSY for bos that can't currently be shrunk,
for example imported dma-bufs, bos whose vm is currently validating,
bos that are still busy after the wait timeout, or bos whose backup
fails. The shrinker LRU walk treats any negative return value as
fatal and aborts, which also skips the remaining shrinker passes.
As a result, a single such bo, like an imported dma-buf on the
XE_PL_TT LRU, prevents reclaim of all bos behind it on the LRU.
Skip bos for which xe_bo_shrink() returns -EBUSY and continue the
walk, like the TTM LRU walk does.
v4:
- Patch introduced.
Fixes: 00c8efc3180f ("drm/xe: Add a shrinker for xe bos")
Cc: Christian König <christian.koenig@amd.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: intel-xe@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v6.15+
Assisted-by: LLM
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
drivers/gpu/drm/xe/xe_shrinker.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
index deb4378c1ec1..4e4da76936f4 100644
--- a/drivers/gpu/drm/xe/xe_shrinker.c
+++ b/drivers/gpu/drm/xe/xe_shrinker.c
@@ -113,6 +113,9 @@ static int __xe_shrinker_walk(struct xe_shrinker *shrinker,
continue;
lret = xe_bo_shrink(ctx, ttm_bo, flags, scanned);
+ /* Like the TTM LRU walk, skip bos we can't shrink now. */
+ if (lret == -EBUSY)
+ continue;
if (lret < 0) {
ret = lret;
goto out;
--
2.56.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 2/4] drm/xe: Track number of populated ttm_tts in the shrinker
2026-10-16 13:35 [PATCH v4 0/4] drm/xe: Adjust the bo shrinker batch size Thomas Hellström
2026-10-16 13:35 ` [PATCH v4 1/4] drm/xe: Don't abort the shrinker walk on -EBUSY Thomas Hellström
@ 2026-10-16 13:35 ` Thomas Hellström
2026-10-16 14:26 ` Matthew Brost
2026-10-16 13:35 ` [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers Thomas Hellström
` (3 subsequent siblings)
5 siblings, 1 reply; 18+ messages in thread
From: Thomas Hellström @ 2026-10-16 13:35 UTC (permalink / raw)
To: intel-xe
Cc: Thomas Hellström, Matthew Brost, Matthew Auld,
Maarten Lankhorst
Add a populated_tts counter to struct xe_shrinker to track how many
ttm_tts are currently populated and on the LRU (i.e., shrinkable or
purgeable). This mirrors the existing per-pages accounting but counts
objects rather than pages.
The counter is incremented in xe_ttm_tt_account_add() and decremented
in xe_ttm_tt_account_subtract(), which are already called at the exact
points where pages enter and leave the shrinker's jurisdiction (populate,
unpopulate, pin, and unpin). Purgeable state transfers, which move pages
between the shrinkable and purgeable buckets without changing the total
object count, pass tts=0.
Extend xe_shrinker_mod_pages() with a tts delta parameter so that page
and object accounting can be updated atomically under the same lock.
Assert that populated_tts reaches zero at device teardown, alongside
the existing assertions for shrinkable_pages and purgeable_pages.
No functional change intended; the new field is unused until a follow-up
commit wires it into shrinker batch sizing.
Assisted-by: LLM
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
drivers/gpu/drm/xe/xe_bo.c | 12 ++++++------
drivers/gpu/drm/xe/xe_shrinker.c | 15 +++++++++++----
drivers/gpu/drm/xe/xe_shrinker.h | 3 ++-
3 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 12e523c61c1f..1b74331b15ec 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -456,9 +456,9 @@ static void xe_ttm_tt_account_add(struct xe_device *xe, struct ttm_tt *tt)
struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
if (xe_tt->purgeable)
- xe_shrinker_mod_pages(xe->mem.shrinker, 0, tt->num_pages);
+ xe_shrinker_mod_pages(xe->mem.shrinker, 0, tt->num_pages, 1);
else
- xe_shrinker_mod_pages(xe->mem.shrinker, tt->num_pages, 0);
+ xe_shrinker_mod_pages(xe->mem.shrinker, tt->num_pages, 0, 1);
}
static void xe_ttm_tt_account_subtract(struct xe_device *xe, struct ttm_tt *tt)
@@ -466,9 +466,9 @@ static void xe_ttm_tt_account_subtract(struct xe_device *xe, struct ttm_tt *tt)
struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
if (xe_tt->purgeable)
- xe_shrinker_mod_pages(xe->mem.shrinker, 0, -(long)tt->num_pages);
+ xe_shrinker_mod_pages(xe->mem.shrinker, 0, -(long)tt->num_pages, -1);
else
- xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages, 0);
+ xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages, 0, -1);
}
static bool xe_ttm_bo_is_imported(struct ttm_buffer_object *tbo)
@@ -984,11 +984,11 @@ static void xe_bo_set_purgeable_shrinker(struct xe_bo *bo,
if (!xe_tt->purgeable && new_state == XE_MADV_PURGEABLE_DONTNEED) {
xe_tt->purgeable = true;
/* Transfer pages from shrinkable to purgeable count */
- xe_shrinker_mod_pages(xe->mem.shrinker, -tt_pages, tt_pages);
+ xe_shrinker_mod_pages(xe->mem.shrinker, -tt_pages, tt_pages, 0);
} else if (xe_tt->purgeable && new_state == XE_MADV_PURGEABLE_WILLNEED) {
xe_tt->purgeable = false;
/* Transfer pages from purgeable to shrinkable count */
- xe_shrinker_mod_pages(xe->mem.shrinker, tt_pages, -tt_pages);
+ xe_shrinker_mod_pages(xe->mem.shrinker, tt_pages, -tt_pages, 0);
}
}
diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
index 4e4da76936f4..378022c37a57 100644
--- a/drivers/gpu/drm/xe/xe_shrinker.c
+++ b/drivers/gpu/drm/xe/xe_shrinker.c
@@ -20,6 +20,7 @@
* @lock: Lock protecting accounting.
* @shrinkable_pages: Number of pages that are currently shrinkable.
* @purgeable_pages: Number of pages that are currently purgeable.
+ * @populated_tts: Number of populated ttm_tts currently shrinkable or purgeable.
* @shrink: Pointer to the mm shrinker.
* @pm_worker: Worker to wake up the device if required.
*/
@@ -28,6 +29,7 @@ struct xe_shrinker {
rwlock_t lock;
long shrinkable_pages;
long purgeable_pages;
+ long populated_tts;
struct shrinker *shrink;
struct work_struct pm_worker;
};
@@ -38,19 +40,23 @@ static struct xe_shrinker *to_xe_shrinker(struct shrinker *shrink)
}
/**
- * xe_shrinker_mod_pages() - Modify shrinker page accounting
+ * xe_shrinker_mod_pages() - Modify shrinker page and object accounting
* @shrinker: Pointer to the struct xe_shrinker.
* @shrinkable: Shrinkable pages delta. May be negative.
- * @purgeable: Purgeable page delta. May be negative.
+ * @purgeable: Purgeable pages delta. May be negative.
+ * @tts: Populated ttm_tt count delta. May be negative.
*
- * Modifies the shrinkable and purgeable pages accounting.
+ * Updates the shrinkable and purgeable page counts and the populated
+ * ttm_tt count.
*/
void
-xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable)
+xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable,
+ long tts)
{
write_lock(&shrinker->lock);
shrinker->shrinkable_pages += shrinkable;
shrinker->purgeable_pages += purgeable;
+ shrinker->populated_tts += tts;
write_unlock(&shrinker->lock);
}
@@ -286,6 +292,7 @@ static void xe_shrinker_fini(struct drm_device *drm, void *arg)
xe_assert(shrinker->xe, !shrinker->shrinkable_pages);
xe_assert(shrinker->xe, !shrinker->purgeable_pages);
+ xe_assert(shrinker->xe, !shrinker->populated_tts);
shrinker_free(shrinker->shrink);
flush_work(&shrinker->pm_worker);
kfree(shrinker);
diff --git a/drivers/gpu/drm/xe/xe_shrinker.h b/drivers/gpu/drm/xe/xe_shrinker.h
index 5132ae5192e1..9c63e22b3b73 100644
--- a/drivers/gpu/drm/xe/xe_shrinker.h
+++ b/drivers/gpu/drm/xe/xe_shrinker.h
@@ -9,7 +9,8 @@
struct xe_shrinker;
struct xe_device;
-void xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable);
+void xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable,
+ long tts);
int xe_shrinker_create(struct xe_device *xe);
--
2.56.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers
2026-10-16 13:35 [PATCH v4 0/4] drm/xe: Adjust the bo shrinker batch size Thomas Hellström
2026-10-16 13:35 ` [PATCH v4 1/4] drm/xe: Don't abort the shrinker walk on -EBUSY Thomas Hellström
2026-10-16 13:35 ` [PATCH v4 2/4] drm/xe: Track number of populated ttm_tts in the shrinker Thomas Hellström
@ 2026-10-16 13:35 ` Thomas Hellström
2026-10-16 13:53 ` sashiko-bot
2026-10-16 18:16 ` Matthew Brost
2026-10-16 13:35 ` [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size Thomas Hellström
` (2 subsequent siblings)
5 siblings, 2 replies; 18+ messages in thread
From: Thomas Hellström @ 2026-10-16 13:35 UTC (permalink / raw)
To: intel-xe
Cc: Thomas Hellström, Matthew Brost, Matthew Auld,
Maarten Lankhorst
Purgeable objects are reclaimed by simply discarding their pages, with
no writeback required. They are therefore much cheaper to shrink than
regular shrinkable (non-purgeable) objects, whose reclaim may need to
wait for the GPU or write dirty compressed contents back to a backup
store, and whose contents need to be read back on next use.
Split the single xe_shrinker into two independent struct shrinker
instances registered against the shrinker core, sharing the same
underlying accounting (shrinkable_pages, purgeable_pages,
populated_tts) and locking:
- A purgeable shrinker, whose count_objects() reports only
purgeable_pages, and whose scan_objects() only purges objects.
- A non-purgeable (shrinkable) shrinker, whose count_objects()
reports the shrinkable page count (capped by backup availability)
and whose scan_objects() shrinks non-purgeable objects, and also
purges any purgeable objects it encounters, waking the device via
runtime PM as needed.
Express the cost difference to the shrinker core through the seeks
value: the purgeable shrinker keeps DEFAULT_SEEKS, while the
non-purgeable shrinker uses a higher value,
XE_SHRINKER_NON_PURGEABLE_SEEKS (8). The core scales each shrinker's
scan target inversely with seeks, so purgeable objects receive
proportionally more reclaim pressure than non-purgeable ones, without
one shrinker's behaviour depending on the other's state.
The standalone purge walk relies on the LRU walk skipping
non-purgeable objects, for which xe_bo_shrink() returns -EBUSY,
rather than aborting.
v3:
- Patch introduced. (Matt Brost)
v4:
- The purge walk aborting at the first non-purgeable object is now
fixed by a separate, preceding patch. (Sashiko)
Assisted-by: LLM
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
drivers/gpu/drm/xe/xe_shrinker.c | 109 +++++++++++++++++++------------
1 file changed, 68 insertions(+), 41 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
index 378022c37a57..8e3fe675e0f3 100644
--- a/drivers/gpu/drm/xe/xe_shrinker.c
+++ b/drivers/gpu/drm/xe/xe_shrinker.c
@@ -14,6 +14,15 @@
#include "xe_pm.h"
#include "xe_shrinker.h"
+/*
+ * Reclaiming non-purgeable objects requires GPU idling and writeback to a
+ * backup store, and restoring them requires reading the contents back.
+ * Tell the shrinker core they're costlier to recreate than purgeable
+ * objects, which use DEFAULT_SEEKS, so that purgeable objects are
+ * preferentially reclaimed.
+ */
+#define XE_SHRINKER_NON_PURGEABLE_SEEKS 8
+
/**
* struct xe_shrinker - per-device shrinker
* @xe: Back pointer to the device.
@@ -21,7 +30,8 @@
* @shrinkable_pages: Number of pages that are currently shrinkable.
* @purgeable_pages: Number of pages that are currently purgeable.
* @populated_tts: Number of populated ttm_tts currently shrinkable or purgeable.
- * @shrink: Pointer to the mm shrinker.
+ * @shrink: Pointer to the mm shrinker handling non-purgeable (shrinkable) objects.
+ * @purge_shrink: Pointer to the mm shrinker handling purgeable objects.
* @pm_worker: Worker to wake up the device if required.
*/
struct xe_shrinker {
@@ -31,6 +41,7 @@ struct xe_shrinker {
long purgeable_pages;
long populated_tts;
struct shrinker *shrink;
+ struct shrinker *purge_shrink;
struct work_struct pm_worker;
};
@@ -179,6 +190,19 @@ static int xe_shrinker_walk(struct xe_shrinker *shrinker,
return ret;
}
+static unsigned long
+xe_shrinker_count_purgeable(struct shrinker *shrink, struct shrink_control *sc)
+{
+ struct xe_shrinker *shrinker = to_xe_shrinker(shrink);
+ unsigned long num_pages;
+
+ read_lock(&shrinker->lock);
+ num_pages = shrinker->purgeable_pages;
+ read_unlock(&shrinker->lock);
+
+ return num_pages ? num_pages : SHRINK_EMPTY;
+}
+
static unsigned long
xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
{
@@ -194,7 +218,6 @@ xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
else
num_pages = 0;
- num_pages += shrinker->purgeable_pages;
read_unlock(&shrinker->lock);
return num_pages ? num_pages : SHRINK_EMPTY;
@@ -207,8 +230,7 @@ xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
* If bo shrinking needs an rpm reference and we don't have it (yet),
* that bo will be skipped anyway.
*/
-static bool xe_shrinker_runtime_pm_get(struct xe_shrinker *shrinker, bool force,
- unsigned long nr_to_scan, bool can_backup)
+static bool xe_shrinker_runtime_pm_get(struct xe_shrinker *shrinker)
{
struct xe_device *xe = shrinker->xe;
@@ -216,63 +238,52 @@ static bool xe_shrinker_runtime_pm_get(struct xe_shrinker *shrinker, bool force,
!ttm_backup_bytes_avail())
return false;
- if (!force) {
- read_lock(&shrinker->lock);
- force = (nr_to_scan > shrinker->purgeable_pages && can_backup);
- read_unlock(&shrinker->lock);
- if (!force)
- return false;
- }
-
return __xe_shrinker_runtime_pm_get(shrinker);
}
-static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
+static unsigned long xe_shrinker_scan_purgeable(struct shrinker *shrink,
+ struct shrink_control *sc)
{
struct xe_shrinker *shrinker = to_xe_shrinker(shrink);
struct ttm_operation_ctx ctx = {
.interruptible = false,
.no_wait_gpu = ttm_bo_shrink_avoid_wait(),
};
- unsigned long nr_to_scan, nr_scanned = 0, freed = 0;
+ unsigned long nr_to_scan = sc->nr_to_scan, nr_scanned = 0, freed = 0;
struct xe_bo_shrink_flags shrink_flags = {
.purge = true,
- /* Don't request writeback without __GFP_IO. */
- .writeback = !ctx.no_wait_gpu && (sc->gfp_mask & __GFP_IO),
};
- bool runtime_pm;
- bool purgeable;
- bool can_backup = !!(sc->gfp_mask & __GFP_FS);
-
- nr_to_scan = sc->nr_to_scan;
-
- read_lock(&shrinker->lock);
- purgeable = !!shrinker->purgeable_pages;
- read_unlock(&shrinker->lock);
- /* Might need runtime PM. Try to wake early if it looks like it. */
- runtime_pm = xe_shrinker_runtime_pm_get(shrinker, false, nr_to_scan, can_backup);
-
- if (purgeable && nr_scanned < nr_to_scan)
- xe_shrinker_walk(shrinker, &ctx, shrink_flags,
- nr_to_scan, &nr_scanned, &freed);
+ xe_shrinker_walk(shrinker, &ctx, shrink_flags, nr_to_scan, &nr_scanned, &freed);
sc->nr_scanned = nr_scanned;
- if (nr_scanned >= nr_to_scan || !can_backup)
- goto out;
- /* If we didn't wake before, try to do it now if needed. */
- if (!runtime_pm)
- runtime_pm = xe_shrinker_runtime_pm_get(shrinker, true, 0, can_backup);
+ return nr_scanned ? freed : SHRINK_STOP;
+}
- shrink_flags.purge = false;
+static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
+{
+ struct xe_shrinker *shrinker = to_xe_shrinker(shrink);
+ struct ttm_operation_ctx ctx = {
+ .interruptible = false,
+ .no_wait_gpu = ttm_bo_shrink_avoid_wait(),
+ };
+ unsigned long nr_to_scan = sc->nr_to_scan, nr_scanned = 0, freed = 0;
+ struct xe_bo_shrink_flags shrink_flags = {
+ .purge = false,
+ /* Don't request writeback without __GFP_IO. */
+ .writeback = !ctx.no_wait_gpu && (sc->gfp_mask & __GFP_IO),
+ };
+ bool runtime_pm;
+
+ /* Might need runtime PM to access backed-up or CCS-compressed data. */
+ runtime_pm = xe_shrinker_runtime_pm_get(shrinker);
- xe_shrinker_walk(shrinker, &ctx, shrink_flags,
- nr_to_scan, &nr_scanned, &freed);
+ xe_shrinker_walk(shrinker, &ctx, shrink_flags, nr_to_scan, &nr_scanned, &freed);
sc->nr_scanned = nr_scanned;
-out:
xe_shrinker_runtime_pm_put(shrinker, runtime_pm);
+
return nr_scanned ? freed : SHRINK_STOP;
}
@@ -294,6 +305,7 @@ static void xe_shrinker_fini(struct drm_device *drm, void *arg)
xe_assert(shrinker->xe, !shrinker->purgeable_pages);
xe_assert(shrinker->xe, !shrinker->populated_tts);
shrinker_free(shrinker->shrink);
+ shrinker_free(shrinker->purge_shrink);
flush_work(&shrinker->pm_worker);
kfree(shrinker);
}
@@ -311,8 +323,15 @@ int xe_shrinker_create(struct xe_device *xe)
if (!shrinker)
return -ENOMEM;
- shrinker->shrink = shrinker_alloc(0, "drm-xe_gem:%s", xe->drm.unique);
+ shrinker->purge_shrink = shrinker_alloc(0, "drm-xe_gem-purgeable:%s", xe->drm.unique);
+ if (!shrinker->purge_shrink) {
+ kfree(shrinker);
+ return -ENOMEM;
+ }
+
+ shrinker->shrink = shrinker_alloc(0, "drm-xe_gem-shrinkable:%s", xe->drm.unique);
if (!shrinker->shrink) {
+ shrinker_free(shrinker->purge_shrink);
kfree(shrinker);
return -ENOMEM;
}
@@ -320,10 +339,18 @@ int xe_shrinker_create(struct xe_device *xe)
INIT_WORK(&shrinker->pm_worker, xe_shrinker_pm);
shrinker->xe = xe;
rwlock_init(&shrinker->lock);
+
+ shrinker->purge_shrink->count_objects = xe_shrinker_count_purgeable;
+ shrinker->purge_shrink->scan_objects = xe_shrinker_scan_purgeable;
+ shrinker->purge_shrink->private_data = shrinker;
+ shrinker_register(shrinker->purge_shrink);
+
shrinker->shrink->count_objects = xe_shrinker_count;
shrinker->shrink->scan_objects = xe_shrinker_scan;
shrinker->shrink->private_data = shrinker;
+ shrinker->shrink->seeks = XE_SHRINKER_NON_PURGEABLE_SEEKS;
shrinker_register(shrinker->shrink);
+
xe->mem.shrinker = shrinker;
return drmm_add_action_or_reset(&xe->drm, xe_shrinker_fini, shrinker);
--
2.56.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size
2026-10-16 13:35 [PATCH v4 0/4] drm/xe: Adjust the bo shrinker batch size Thomas Hellström
` (2 preceding siblings ...)
2026-10-16 13:35 ` [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers Thomas Hellström
@ 2026-10-16 13:35 ` Thomas Hellström
2026-10-16 13:45 ` sashiko-bot
2026-10-16 18:44 ` Matthew Brost
2026-10-16 13:45 ` ✓ CI.KUnit: success for drm/xe: Adjust the bo shrinker batch size (rev4) Patchwork
2026-10-16 14:37 ` ✓ Xe.CI.BAT: " Patchwork
5 siblings, 2 replies; 18+ messages in thread
From: Thomas Hellström @ 2026-10-16 13:35 UTC (permalink / raw)
To: intel-xe
Cc: Thomas Hellström, Matthew Brost, Matthew Auld,
Maarten Lankhorst
Update our preferred vmscan batch size for the non-purgeable shrinker
on count passes that allow backup (__GFP_FS), to avoid invoking
scan_objects() for requests too small to free even a single
average-sized GEM object. Our rough estimate for an effective batch
is twice the average number of pages per populated ttm_tt across
the full shrinkable and purgeable population. The factor of two
provides headroom so that most scan invocations can free at least one
GEM object despite variability in object sizes.
The batch value is updated as an exponential moving average,
(old_batch + avg) / 2, to smooth out sudden changes in the object
population. It is floored at 128 pages, the kernel default
SHRINK_BATCH, to ensure the shrinker remains responsive when there
are very few objects.
The populated_tts counter introduced in an earlier commit provides the
object count needed for the average. We inherit the same justification
as the analogous mechanism in i915: shrinking a GEM object has
non-trivial per-object overhead, so firing the shrinker for requests
smaller than a single object is wasteful.
This is only applied to the non-purgeable shrinker: purgeable objects
are reclaimed without writeback or GPU idling, so they're cheap enough
that the core default batch size is fine for them.
v3:
- Original patch reworked on top of shrinker split (Matt Brost)
Assisted-by: LLM
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
drivers/gpu/drm/xe/xe_shrinker.c | 48 ++++++++++++++++++++++++++++----
1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
index 8e3fe675e0f3..955908b3bdf3 100644
--- a/drivers/gpu/drm/xe/xe_shrinker.c
+++ b/drivers/gpu/drm/xe/xe_shrinker.c
@@ -30,6 +30,8 @@
* @shrinkable_pages: Number of pages that are currently shrinkable.
* @purgeable_pages: Number of pages that are currently purgeable.
* @populated_tts: Number of populated ttm_tts currently shrinkable or purgeable.
+ * @batch_avg: Exponential moving average of the preferred non-purgeable
+ * batch size, based on the average populated ttm_tt size.
* @shrink: Pointer to the mm shrinker handling non-purgeable (shrinkable) objects.
* @purge_shrink: Pointer to the mm shrinker handling purgeable objects.
* @pm_worker: Worker to wake up the device if required.
@@ -40,6 +42,7 @@ struct xe_shrinker {
long shrinkable_pages;
long purgeable_pages;
long populated_tts;
+ long batch_avg;
struct shrinker *shrink;
struct shrinker *purge_shrink;
struct work_struct pm_worker;
@@ -203,6 +206,28 @@ xe_shrinker_count_purgeable(struct shrinker *shrink, struct shrink_control *sc)
return num_pages ? num_pages : SHRINK_EMPTY;
}
+/**
+ * DOC: Batch size calculation
+ *
+ * Update our preferred vmscan batch size for the non-purgeable shrinker
+ * on count passes that allow backup (__GFP_FS), to avoid invoking
+ * scan_objects() for requests too small to free even a single
+ * average-sized GEM object. Our rough estimate for an effective batch
+ * is twice the average number of pages per populated ttm_tt across
+ * the full shrinkable and purgeable population. The factor of two
+ * provides headroom so that most scan invocations can free at least one
+ * GEM object despite variability in object sizes.
+ *
+ * The batch value is updated as an exponential moving average,
+ * (old_batch + avg) / 2, to smooth out sudden changes in the object
+ * population. It is floored at 128 pages, the kernel default
+ * SHRINK_BATCH, to ensure the shrinker remains responsive when there
+ * are very few objects.
+ *
+ * We only do this for the non-purgeable shrinker: purgeable objects are
+ * reclaimed without writeback or GPU idling, so shrinking them is cheap
+ * enough that the core default batch size is fine.
+ */
static unsigned long
xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
{
@@ -210,15 +235,26 @@ xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
unsigned long num_pages;
bool can_backup = !!(sc->gfp_mask & __GFP_FS);
+ if (!can_backup)
+ return SHRINK_EMPTY;
+
num_pages = ttm_backup_bytes_avail() >> PAGE_SHIFT;
- read_lock(&shrinker->lock);
+ /* Consistently use write_lock() for simplicity. */
+ write_lock(&shrinker->lock);
- if (can_backup)
- num_pages = min_t(unsigned long, num_pages, shrinker->shrinkable_pages);
- else
- num_pages = 0;
+ num_pages = min_t(unsigned long, num_pages, shrinker->shrinkable_pages);
- read_unlock(&shrinker->lock);
+ if (shrinker->populated_tts) {
+ unsigned long avg = 2 * (shrinker->shrinkable_pages +
+ shrinker->purgeable_pages) /
+ shrinker->populated_tts;
+
+ shrinker->batch_avg = max((shrinker->batch_avg + (long)avg) >> 1,
+ 128L /* default SHRINK_BATCH */);
+ WRITE_ONCE(shrink->batch, shrinker->batch_avg);
+ }
+
+ write_unlock(&shrinker->lock);
return num_pages ? num_pages : SHRINK_EMPTY;
}
--
2.56.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v4 1/4] drm/xe: Don't abort the shrinker walk on -EBUSY
2026-10-16 13:35 ` [PATCH v4 1/4] drm/xe: Don't abort the shrinker walk on -EBUSY Thomas Hellström
@ 2026-10-16 13:44 ` sashiko-bot
2026-10-16 13:55 ` Matthew Brost
1 sibling, 0 replies; 18+ messages in thread
From: sashiko-bot @ 2026-10-16 13:44 UTC (permalink / raw)
To: Thomas Hellström, intel-xe
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] xe: loop termination check bypassed on -EBUSY causing unbounded shrinker scan
--
commit a9661e97694161cd803806ccc4ad309e99a9f298
Author: Thomas Hellström <thomas.hellstrom@linux.intel.com>
drm/xe: Don't abort the shrinker walk on -EBUSY
xe_bo_shrink() returns -EBUSY for bos that can't currently be shrunk.
The shrinker LRU walk treated any negative return value as fatal and
aborted. This commit changes it to skip bos for which xe_bo_shrink()
returns -EBUSY and continues the walk.
> diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
> index deb4378c1ec15..4e4da76936f49 100644
> --- a/drivers/gpu/drm/xe/xe_shrinker.c
> +++ b/drivers/gpu/drm/xe/xe_shrinker.c
> @@ -113,6 +113,9 @@ static int __xe_shrinker_walk(struct xe_shrinker *shrinker,
> continue;
>
> lret = xe_bo_shrink(ctx, ttm_bo, flags, scanned);
> + /* Like the TTM LRU walk, skip bos we can't shrink now. */
> + if (lret == -EBUSY)
> + continue;
[Severity: Medium]
Does this continue statement inadvertently bypass the loop termination check?
In xe_bo_shrink(), the scanned counter is incremented before potentially
returning -EBUSY:
xe_bo_shrink() {
...
*scanned += tt->num_pages;
lret = ttm_bo_shrink(ctx, bo, ...);
...
return lret;
}
If a sequence of buffer objects return -EBUSY from ttm_bo_shrink(), could
this introduce a regression where the shrinker performs an unbounded scan
over the list because the *scanned >= to_scan check at the bottom of the
loop body is bypassed?
> if (lret < 0) {
> ret = lret;
> goto out;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016133523.3622-1-thomas.hellstrom@linux.intel.com?part=1
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size
2026-10-16 13:35 ` [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size Thomas Hellström
@ 2026-10-16 13:45 ` sashiko-bot
2026-10-16 14:06 ` Thomas Hellström
2026-10-16 18:44 ` Matthew Brost
1 sibling, 1 reply; 18+ messages in thread
From: sashiko-bot @ 2026-10-16 13:45 UTC (permalink / raw)
To: Thomas Hellström, intel-xe
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] drm/xe: shrinker count callback serializes direct reclaim via write_lock
--
commit a78bd8842e67f957a2ced6d827e1c4a6430ff29b
Author: Thomas Hellström <thomas.hellstrom@linux.intel.com>
drm/xe: Update non-purgeable shrinker batch size based on average BO size
This commit updates the preferred vmscan batch size for the non-purgeable
shrinker based on the average buffer object size. It introduces an
exponential moving average that is updated during the shrinker count phase.
> diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
> index 8e3fe675e0f34..955908b3bdf3e 100644
> --- a/drivers/gpu/drm/xe/xe_shrinker.c
> +++ b/drivers/gpu/drm/xe/xe_shrinker.c
[ ... ]
> @@ -210,15 +235,26 @@ xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
> unsigned long num_pages;
> bool can_backup = !!(sc->gfp_mask & __GFP_FS);
>
> + if (!can_backup)
> + return SHRINK_EMPTY;
> +
> num_pages = ttm_backup_bytes_avail() >> PAGE_SHIFT;
> - read_lock(&shrinker->lock);
> + /* Consistently use write_lock() for simplicity. */
> + write_lock(&shrinker->lock);
[Severity: Medium]
Will this exclusive write lock create a system-wide performance bottleneck
during memory reclaim?
The core mm subsystem frequently calls the shrinker's count_objects callback
(xe_shrinker_count) from do_shrink_slab() during direct reclaim. This occurs
concurrently across multiple allocating tasks and CPUs when under memory
pressure.
By changing read_lock() to write_lock() to update the batch_avg heuristic,
this forces all concurrent direct reclaimers system-wide to serialize on this
single lock, which could lead to severe lock contention and performance
degradation.
>
> - if (can_backup)
> - num_pages = min_t(unsigned long, num_pages, shrinker->shrinkable_pages);
> - else
> - num_pages = 0;
> + num_pages = min_t(unsigned long, num_pages, shrinker->shrinkable_pages);
>
> - read_unlock(&shrinker->lock);
> + if (shrinker->populated_tts) {
> + unsigned long avg = 2 * (shrinker->shrinkable_pages +
> + shrinker->purgeable_pages) /
> + shrinker->populated_tts;
> +
> + shrinker->batch_avg = max((shrinker->batch_avg + (long)avg) >> 1,
> + 128L /* default SHRINK_BATCH */);
> + WRITE_ONCE(shrink->batch, shrinker->batch_avg);
> + }
> +
> + write_unlock(&shrinker->lock);
>
> return num_pages ? num_pages : SHRINK_EMPTY;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016133523.3622-1-thomas.hellstrom@linux.intel.com?part=4
^ permalink raw reply [flat|nested] 18+ messages in thread
* ✓ CI.KUnit: success for drm/xe: Adjust the bo shrinker batch size (rev4)
2026-10-16 13:35 [PATCH v4 0/4] drm/xe: Adjust the bo shrinker batch size Thomas Hellström
` (3 preceding siblings ...)
2026-10-16 13:35 ` [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size Thomas Hellström
@ 2026-10-16 13:45 ` Patchwork
2026-10-16 14:37 ` ✓ Xe.CI.BAT: " Patchwork
5 siblings, 0 replies; 18+ messages in thread
From: Patchwork @ 2026-10-16 13:45 UTC (permalink / raw)
To: Thomas Hellström; +Cc: intel-xe
== Series Details ==
Series: drm/xe: Adjust the bo shrinker batch size (rev4)
URL : https://patchwork.freedesktop.org/series/166426/
State : success
== Summary ==
+ trap cleanup EXIT
+ kunitconfigs=('/kernel/drivers/gpu/tests/.kunitconfig' '/kernel/drivers/gpu/drm/xe/.kunitconfig' '/kernel/drivers/gpu/drm/tests/.kunitconfig' '/kernel/drivers/gpu/drm/ttm/tests/.kunitconfig' '/kernel/drivers/dma-buf/.kunitconfig')
+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/gpu/tests/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/tests/.kunitconfig
[13:43:13] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[13:43:17] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[13:43:38] Starting KUnit Kernel (1/1)...
[13:43:38] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[13:43:38] ================= gpu_buddy (14 subtests) ==================
[13:43:38] [PASSED] gpu_test_buddy_alloc_limit
[13:43:38] [PASSED] gpu_test_buddy_alloc_optimistic
[13:43:38] [PASSED] gpu_test_buddy_alloc_pessimistic
[13:43:38] [PASSED] gpu_test_buddy_alloc_pathological
[13:43:38] [PASSED] gpu_test_buddy_alloc_contiguous
[13:43:38] [PASSED] gpu_test_buddy_alloc_clear
[13:43:38] [PASSED] gpu_test_buddy_alloc_range
[13:43:39] [PASSED] gpu_test_buddy_alloc_range_bias
[13:43:40] [PASSED] gpu_test_buddy_fragmentation_performance
[13:43:40] [PASSED] gpu_test_buddy_dirty_tracker_performance
[13:43:40] [PASSED] gpu_test_buddy_alloc_exceeds_max_order
[13:43:40] [PASSED] gpu_test_buddy_offset_aligned_allocation
[13:43:40] [PASSED] gpu_test_buddy_subtree_offset_alignment_stress
[13:43:40] [PASSED] gpu_test_buddy_addr_to_block
[13:43:40] ==================== [PASSED] gpu_buddy ====================
[13:43:40] ============================================================
[13:43:40] Testing complete. Ran 14 tests: passed: 14
[13:43:40] Elapsed time: 27.731s total, 4.498s configuring, 21.065s building, 2.128s running
+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/gpu/drm/xe/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
[13:43:41] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[13:43:42] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[13:44:22] Starting KUnit Kernel (1/1)...
[13:44:22] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[13:44:22] ================== guc_buf (11 subtests) ===================
[13:44:22] [PASSED] test_smallest
[13:44:22] [PASSED] test_largest
[13:44:22] [PASSED] test_granular
[13:44:22] [PASSED] test_unique
[13:44:22] [PASSED] test_overlap
[13:44:22] [PASSED] test_reusable
[13:44:22] [PASSED] test_too_big
[13:44:22] [PASSED] test_flush
[13:44:22] [PASSED] test_lookup
[13:44:22] [PASSED] test_data
[13:44:22] [PASSED] test_class
[13:44:22] ===================== [PASSED] guc_buf =====================
[13:44:22] =================== guc_dbm (7 subtests) ===================
[13:44:22] [PASSED] test_empty
[13:44:22] [PASSED] test_default
[13:44:22] ======================== test_size ========================
[13:44:22] [PASSED] 4
[13:44:22] [PASSED] 8
[13:44:22] [PASSED] 32
[13:44:22] [PASSED] 256
[13:44:22] ==================== [PASSED] test_size ====================
[13:44:22] ======================= test_reuse ========================
[13:44:22] [PASSED] 4
[13:44:22] [PASSED] 8
[13:44:22] [PASSED] 32
[13:44:22] [PASSED] 256
[13:44:22] =================== [PASSED] test_reuse ====================
[13:44:22] =================== test_range_overlap ====================
[13:44:22] [PASSED] 4
[13:44:22] [PASSED] 8
[13:44:22] [PASSED] 32
[13:44:22] [PASSED] 256
[13:44:22] =============== [PASSED] test_range_overlap ================
[13:44:22] =================== test_range_compact ====================
[13:44:22] [PASSED] 4
[13:44:22] [PASSED] 8
[13:44:22] [PASSED] 32
[13:44:22] [PASSED] 256
[13:44:22] =============== [PASSED] test_range_compact ================
[13:44:22] ==================== test_range_spare =====================
[13:44:22] [PASSED] 4
[13:44:22] [PASSED] 8
[13:44:22] [PASSED] 32
[13:44:22] [PASSED] 256
[13:44:22] ================ [PASSED] test_range_spare =================
[13:44:22] ===================== [PASSED] guc_dbm =====================
[13:44:22] ================== guc_idm (22 subtests) ===================
[13:44:22] [PASSED] bad_init
[13:44:22] [PASSED] no_init
[13:44:22] [PASSED] init_fini
[13:44:22] [PASSED] check_init_small
[13:44:22] [PASSED] check_init_shared
[13:44:22] [PASSED] check_used
[13:44:22] [PASSED] check_quota
[13:44:22] [PASSED] check_all
[13:44:22] [PASSED] check_limits
[13:44:22] [PASSED] check_overlap
[13:44:22] [PASSED] check_overlap_alloc
[13:44:22] [PASSED] check_overlap_release
[13:44:22] [PASSED] check_overlap_partial_init
[13:44:22] [PASSED] check_overlap_partial_shared_range_blocking
[13:44:22] [PASSED] check_used_usable
[13:44:22] [PASSED] check_used_shareable
[13:44:22] [PASSED] check_used_mixed
[13:44:22] [PASSED] check_release_usable_range
[13:44:22] [PASSED] check_release_shareable_range
[13:44:22] [PASSED] check_split_boundaries
[13:44:22] [PASSED] check_shareable_spare
[13:44:22] [PASSED] check_shareable_spare_fragmented_tail
[13:44:22] ===================== [PASSED] guc_idm =====================
[13:44:22] ============== guc_klv_helpers (13 subtests) ===============
[13:44:22] [PASSED] test_count
[13:44:22] [PASSED] test_encode_u32
[13:44:22] [PASSED] test_encode_u64
[13:44:22] [PASSED] test_encode_string
[13:44:22] [PASSED] test_encode_object_raw
[13:44:22] [PASSED] test_encode_object_klv
[13:44:22] [PASSED] test_encode_object_nested
[13:44:22] [PASSED] test_encode_object_basic
[13:44:22] ===================== test_decode_u16 =====================
[13:44:22] [PASSED] empty
[13:44:22] [PASSED] valid
[13:44:22] [PASSED] max
[13:44:22] [PASSED] big
[13:44:22] [PASSED] long
[13:44:22] ================= [PASSED] test_decode_u16 =================
[13:44:22] ===================== test_decode_u32 =====================
[13:44:22] [PASSED] empty
[13:44:22] [PASSED] valid
[13:44:22] [PASSED] max
[13:44:22] [PASSED] long
[13:44:22] ================= [PASSED] test_decode_u32 =================
[13:44:22] ===================== test_decode_u64 =====================
[13:44:22] [PASSED] empty
[13:44:22] [PASSED] short
[13:44:22] [PASSED] valid
[13:44:22] [PASSED] max
[13:44:22] [PASSED] long
[13:44:22] ================= [PASSED] test_decode_u64 =================
[13:44:22] ===================== test_decode_str =====================
[13:44:22] [PASSED] empty
[13:44:22] [PASSED] one
[13:44:22] [PASSED] one_trash
[13:44:22] [PASSED] two
[13:44:22] [PASSED] two_trash
[13:44:22] [PASSED] three
[13:44:22] [PASSED] dword
[13:44:22] [PASSED] four
[13:44:22] [PASSED] five
[13:44:22] [PASSED] six
[13:44:22] [PASSED] seven
[13:44:22] [PASSED] qword
[13:44:22] ================= [PASSED] test_decode_str =================
[13:44:22] [PASSED] test_print
[13:44:22] ================= [PASSED] guc_klv_helpers =================
[13:44:22] =================== xe_log (4 subtests) ====================
[13:44:22] [PASSED] demo_cper
[13:44:22] [PASSED] demo_dmesg
[13:44:22] ======================= test_dmesg ========================
[13:44:22] [PASSED] test_fatal
[13:44:22] [PASSED] test_fatal_tile
[13:44:22] [PASSED] test_fatal_gt
[13:44:22] [PASSED] test_fatal_comp
[13:44:22] [PASSED] test_fatal_comp_tile
[13:44:22] [PASSED] test_fatal_comp_gt
[13:44:22] [PASSED] test_fatal_all
[13:44:22] [PASSED] test_recoverable
[13:44:22] [PASSED] test_recoverable_tile
[13:44:22] [PASSED] test_recoverable_gt
[13:44:22] [PASSED] test_recoverable_comp
[13:44:22] [PASSED] test_recoverable_comp_tile
[13:44:22] [PASSED] test_recoverable_comp_gt
[13:44:22] [PASSED] test_recoverable_all
[13:44:22] [PASSED] test_info
[13:44:22] [PASSED] test_info_tile
[13:44:22] [PASSED] test_info_gt
[13:44:22] [PASSED] test_info_err
[13:44:22] [PASSED] test_info_comp
[13:44:22] [PASSED] test_info_comp_tile
[13:44:22] [PASSED] test_info_comp_gt
[13:44:22] [PASSED] test_info_all
[13:44:22] [PASSED] test_hw_fatal
[13:44:22] [PASSED] test_hw_recoverable
[13:44:22] [PASSED] test_hw_corrected
[13:44:22] [PASSED] test_hw_informational
[13:44:22] =================== [PASSED] test_dmesg ====================
[13:44:22] ====================== test_invalid =======================
[13:44:22] [SKIPPED] no-component no-location no-warn (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] [SKIPPED] reserved location (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] [SKIPPED] unknown location (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] [SKIPPED] nonzero-device-id location (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] [SKIPPED] invalid-tile-id location (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] [SKIPPED] invalid-gt-id location (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] [SKIPPED] unknown component class (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] [SKIPPED] unknown system component (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] [SKIPPED] unknown hardware component (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] [SKIPPED] unknown component and location (requires CONFIG_DRM_XE_DEBUG)
[13:44:22] ================== [SKIPPED] test_invalid ==================
[13:44:22] ===================== [PASSED] xe_log ======================
[13:44:22] ================== no_relay (3 subtests) ===================
[13:44:22] [PASSED] xe_drops_guc2pf_if_not_ready
[13:44:22] [PASSED] xe_drops_guc2vf_if_not_ready
[13:44:22] [PASSED] xe_rejects_send_if_not_ready
[13:44:22] ==================== [PASSED] no_relay =====================
[13:44:22] ================== pf_relay (14 subtests) ==================
[13:44:22] [PASSED] pf_rejects_guc2pf_too_short
[13:44:22] [PASSED] pf_rejects_guc2pf_too_long
[13:44:22] [PASSED] pf_rejects_guc2pf_no_payload
[13:44:22] [PASSED] pf_fails_no_payload
[13:44:22] [PASSED] pf_fails_bad_origin
[13:44:22] [PASSED] pf_fails_bad_type
[13:44:22] [PASSED] pf_txn_reports_error
[13:44:22] [PASSED] pf_txn_sends_pf2guc
[13:44:22] [PASSED] pf_sends_pf2guc
[13:44:22] [SKIPPED] pf_loopback_nop (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[13:44:22] [SKIPPED] pf_loopback_echo (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[13:44:22] [SKIPPED] pf_loopback_fail (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[13:44:22] [SKIPPED] pf_loopback_busy (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[13:44:22] [SKIPPED] pf_loopback_retry (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[13:44:22] ==================== [PASSED] pf_relay =====================
[13:44:22] ================== vf_relay (3 subtests) ===================
[13:44:22] [PASSED] vf_rejects_guc2vf_too_short
[13:44:22] [PASSED] vf_rejects_guc2vf_too_long
[13:44:22] [PASSED] vf_rejects_guc2vf_no_payload
[13:44:22] ==================== [PASSED] vf_relay =====================
[13:44:22] ================ pf_gt_config (9 subtests) =================
[13:44:22] [PASSED] fair_contexts_1vf
[13:44:22] [PASSED] fair_doorbells_1vf
[13:44:22] [PASSED] fair_ggtt_1vf
[13:44:22] ====================== fair_vram_1vf ======================
[13:44:22] [PASSED] 3.50 GiB
[13:44:22] [PASSED] 11.5 GiB
[13:44:22] [PASSED] 15.5 GiB
[13:44:22] [PASSED] 31.5 GiB
[13:44:22] [PASSED] 63.5 GiB
[13:44:22] [PASSED] 1.91 GiB
[13:44:22] ================== [PASSED] fair_vram_1vf ==================
[13:44:22] ================ fair_vram_1vf_admin_only =================
[13:44:22] [PASSED] 3.50 GiB
[13:44:22] [PASSED] 11.5 GiB
[13:44:22] [PASSED] 15.5 GiB
[13:44:22] [PASSED] 31.5 GiB
[13:44:22] [PASSED] 63.5 GiB
[13:44:22] [PASSED] 1.91 GiB
[13:44:22] ============ [PASSED] fair_vram_1vf_admin_only =============
[13:44:22] ====================== fair_contexts ======================
[13:44:22] [PASSED] 1 VF
[13:44:22] [PASSED] 2 VFs
[13:44:22] [PASSED] 3 VFs
[13:44:22] [PASSED] 4 VFs
[13:44:22] [PASSED] 5 VFs
[13:44:22] [PASSED] 6 VFs
[13:44:22] [PASSED] 7 VFs
[13:44:22] [PASSED] 8 VFs
[13:44:22] [PASSED] 9 VFs
[13:44:22] [PASSED] 10 VFs
[13:44:22] [PASSED] 11 VFs
[13:44:22] [PASSED] 12 VFs
[13:44:22] [PASSED] 13 VFs
[13:44:22] [PASSED] 14 VFs
[13:44:22] [PASSED] 15 VFs
[13:44:22] [PASSED] 16 VFs
[13:44:22] [PASSED] 17 VFs
[13:44:22] [PASSED] 18 VFs
[13:44:22] [PASSED] 19 VFs
[13:44:22] [PASSED] 20 VFs
[13:44:22] [PASSED] 21 VFs
[13:44:22] [PASSED] 22 VFs
[13:44:22] [PASSED] 23 VFs
[13:44:22] [PASSED] 24 VFs
[13:44:22] [PASSED] 25 VFs
[13:44:22] [PASSED] 26 VFs
[13:44:22] [PASSED] 27 VFs
[13:44:22] [PASSED] 28 VFs
[13:44:22] [PASSED] 29 VFs
[13:44:22] [PASSED] 30 VFs
[13:44:22] [PASSED] 31 VFs
[13:44:22] [PASSED] 32 VFs
[13:44:22] [PASSED] 33 VFs
[13:44:22] [PASSED] 34 VFs
[13:44:22] [PASSED] 35 VFs
[13:44:22] [PASSED] 36 VFs
[13:44:22] [PASSED] 37 VFs
[13:44:22] [PASSED] 38 VFs
[13:44:22] [PASSED] 39 VFs
[13:44:22] [PASSED] 40 VFs
[13:44:22] [PASSED] 41 VFs
[13:44:22] [PASSED] 42 VFs
[13:44:22] [PASSED] 43 VFs
[13:44:22] [PASSED] 44 VFs
[13:44:22] [PASSED] 45 VFs
[13:44:22] [PASSED] 46 VFs
[13:44:22] [PASSED] 47 VFs
[13:44:22] [PASSED] 48 VFs
[13:44:22] [PASSED] 49 VFs
[13:44:22] [PASSED] 50 VFs
[13:44:22] [PASSED] 51 VFs
[13:44:22] [PASSED] 52 VFs
[13:44:22] [PASSED] 53 VFs
[13:44:22] [PASSED] 54 VFs
[13:44:22] [PASSED] 55 VFs
[13:44:22] [PASSED] 56 VFs
[13:44:22] [PASSED] 57 VFs
[13:44:22] [PASSED] 58 VFs
[13:44:22] [PASSED] 59 VFs
[13:44:22] [PASSED] 60 VFs
[13:44:22] [PASSED] 61 VFs
[13:44:22] [PASSED] 62 VFs
[13:44:22] [PASSED] 63 VFs
[13:44:22] ================== [PASSED] fair_contexts ==================
[13:44:22] ===================== fair_doorbells ======================
[13:44:22] [PASSED] 1 VF
[13:44:22] [PASSED] 2 VFs
[13:44:22] [PASSED] 3 VFs
[13:44:22] [PASSED] 4 VFs
[13:44:22] [PASSED] 5 VFs
[13:44:22] [PASSED] 6 VFs
[13:44:22] [PASSED] 7 VFs
[13:44:22] [PASSED] 8 VFs
[13:44:22] [PASSED] 9 VFs
[13:44:22] [PASSED] 10 VFs
[13:44:22] [PASSED] 11 VFs
[13:44:22] [PASSED] 12 VFs
[13:44:22] [PASSED] 13 VFs
[13:44:22] [PASSED] 14 VFs
[13:44:22] [PASSED] 15 VFs
[13:44:22] [PASSED] 16 VFs
[13:44:22] [PASSED] 17 VFs
[13:44:22] [PASSED] 18 VFs
[13:44:22] [PASSED] 19 VFs
[13:44:22] [PASSED] 20 VFs
[13:44:22] [PASSED] 21 VFs
[13:44:22] [PASSED] 22 VFs
[13:44:22] [PASSED] 23 VFs
[13:44:22] [PASSED] 24 VFs
[13:44:22] [PASSED] 25 VFs
[13:44:22] [PASSED] 26 VFs
[13:44:22] [PASSED] 27 VFs
[13:44:22] [PASSED] 28 VFs
[13:44:22] [PASSED] 29 VFs
[13:44:22] [PASSED] 30 VFs
[13:44:22] [PASSED] 31 VFs
[13:44:22] [PASSED] 32 VFs
[13:44:22] [PASSED] 33 VFs
[13:44:22] [PASSED] 34 VFs
[13:44:22] [PASSED] 35 VFs
[13:44:22] [PASSED] 36 VFs
[13:44:22] [PASSED] 37 VFs
[13:44:22] [PASSED] 38 VFs
[13:44:22] [PASSED] 39 VFs
[13:44:22] [PASSED] 40 VFs
[13:44:22] [PASSED] 41 VFs
[13:44:22] [PASSED] 42 VFs
[13:44:22] [PASSED] 43 VFs
[13:44:22] [PASSED] 44 VFs
[13:44:22] [PASSED] 45 VFs
[13:44:22] [PASSED] 46 VFs
[13:44:22] [PASSED] 47 VFs
[13:44:22] [PASSED] 48 VFs
[13:44:22] [PASSED] 49 VFs
[13:44:22] [PASSED] 50 VFs
[13:44:22] [PASSED] 51 VFs
[13:44:22] [PASSED] 52 VFs
[13:44:22] [PASSED] 53 VFs
[13:44:22] [PASSED] 54 VFs
[13:44:22] [PASSED] 55 VFs
[13:44:22] [PASSED] 56 VFs
[13:44:22] [PASSED] 57 VFs
[13:44:22] [PASSED] 58 VFs
[13:44:22] [PASSED] 59 VFs
[13:44:22] [PASSED] 60 VFs
[13:44:22] [PASSED] 61 VFs
[13:44:22] [PASSED] 62 VFs
[13:44:22] [PASSED] 63 VFs
[13:44:22] ================= [PASSED] fair_doorbells ==================
[13:44:22] ======================== fair_ggtt ========================
[13:44:22] [PASSED] 1 VF
[13:44:22] [PASSED] 2 VFs
[13:44:22] [PASSED] 3 VFs
[13:44:22] [PASSED] 4 VFs
[13:44:22] [PASSED] 5 VFs
[13:44:22] [PASSED] 6 VFs
[13:44:22] [PASSED] 7 VFs
[13:44:22] [PASSED] 8 VFs
[13:44:22] [PASSED] 9 VFs
[13:44:22] [PASSED] 10 VFs
[13:44:22] [PASSED] 11 VFs
[13:44:22] [PASSED] 12 VFs
[13:44:22] [PASSED] 13 VFs
[13:44:22] [PASSED] 14 VFs
[13:44:22] [PASSED] 15 VFs
[13:44:22] [PASSED] 16 VFs
[13:44:22] [PASSED] 17 VFs
[13:44:22] [PASSED] 18 VFs
[13:44:22] [PASSED] 19 VFs
[13:44:22] [PASSED] 20 VFs
[13:44:22] [PASSED] 21 VFs
[13:44:22] [PASSED] 22 VFs
[13:44:22] [PASSED] 23 VFs
[13:44:22] [PASSED] 24 VFs
[13:44:22] [PASSED] 25 VFs
[13:44:22] [PASSED] 26 VFs
[13:44:22] [PASSED] 27 VFs
[13:44:22] [PASSED] 28 VFs
[13:44:22] [PASSED] 29 VFs
[13:44:22] [PASSED] 30 VFs
[13:44:22] [PASSED] 31 VFs
[13:44:22] [PASSED] 32 VFs
[13:44:22] [PASSED] 33 VFs
[13:44:22] [PASSED] 34 VFs
[13:44:22] [PASSED] 35 VFs
[13:44:22] [PASSED] 36 VFs
[13:44:22] [PASSED] 37 VFs
[13:44:22] [PASSED] 38 VFs
[13:44:22] [PASSED] 39 VFs
[13:44:22] [PASSED] 40 VFs
[13:44:22] [PASSED] 41 VFs
[13:44:22] [PASSED] 42 VFs
[13:44:22] [PASSED] 43 VFs
[13:44:22] [PASSED] 44 VFs
[13:44:22] [PASSED] 45 VFs
[13:44:22] [PASSED] 46 VFs
[13:44:22] [PASSED] 47 VFs
[13:44:22] [PASSED] 48 VFs
[13:44:22] [PASSED] 49 VFs
[13:44:22] [PASSED] 50 VFs
[13:44:22] [PASSED] 51 VFs
[13:44:22] [PASSED] 52 VFs
[13:44:22] [PASSED] 53 VFs
[13:44:22] [PASSED] 54 VFs
[13:44:22] [PASSED] 55 VFs
[13:44:22] [PASSED] 56 VFs
[13:44:22] [PASSED] 57 VFs
[13:44:22] [PASSED] 58 VFs
[13:44:22] [PASSED] 59 VFs
[13:44:22] [PASSED] 60 VFs
[13:44:22] [PASSED] 61 VFs
[13:44:22] [PASSED] 62 VFs
[13:44:22] [PASSED] 63 VFs
[13:44:22] ==================== [PASSED] fair_ggtt ====================
[13:44:22] ======================== fair_vram ========================
[13:44:22] [PASSED] 1 VF
[13:44:22] [PASSED] 2 VFs
[13:44:22] [PASSED] 3 VFs
[13:44:22] [PASSED] 4 VFs
[13:44:22] [PASSED] 5 VFs
[13:44:22] [PASSED] 6 VFs
[13:44:22] [PASSED] 7 VFs
[13:44:22] [PASSED] 8 VFs
[13:44:22] [PASSED] 9 VFs
[13:44:22] [PASSED] 10 VFs
[13:44:22] [PASSED] 11 VFs
[13:44:22] [PASSED] 12 VFs
[13:44:22] [PASSED] 13 VFs
[13:44:22] [PASSED] 14 VFs
[13:44:22] [PASSED] 15 VFs
[13:44:22] [PASSED] 16 VFs
[13:44:22] [PASSED] 17 VFs
[13:44:22] [PASSED] 18 VFs
[13:44:22] [PASSED] 19 VFs
[13:44:22] [PASSED] 20 VFs
[13:44:22] [PASSED] 21 VFs
[13:44:22] [PASSED] 22 VFs
[13:44:22] [PASSED] 23 VFs
[13:44:22] [PASSED] 24 VFs
[13:44:22] [PASSED] 25 VFs
[13:44:22] [PASSED] 26 VFs
[13:44:22] [PASSED] 27 VFs
[13:44:22] [PASSED] 28 VFs
[13:44:22] [PASSED] 29 VFs
[13:44:22] [PASSED] 30 VFs
[13:44:22] [PASSED] 31 VFs
[13:44:22] [PASSED] 32 VFs
[13:44:22] [PASSED] 33 VFs
[13:44:22] [PASSED] 34 VFs
[13:44:22] [PASSED] 35 VFs
[13:44:22] [PASSED] 36 VFs
[13:44:22] [PASSED] 37 VFs
[13:44:22] [PASSED] 38 VFs
[13:44:22] [PASSED] 39 VFs
[13:44:22] [PASSED] 40 VFs
[13:44:22] [PASSED] 41 VFs
[13:44:22] [PASSED] 42 VFs
[13:44:22] [PASSED] 43 VFs
[13:44:22] [PASSED] 44 VFs
[13:44:22] [PASSED] 45 VFs
[13:44:22] [PASSED] 46 VFs
[13:44:22] [PASSED] 47 VFs
[13:44:22] [PASSED] 48 VFs
[13:44:22] [PASSED] 49 VFs
[13:44:22] [PASSED] 50 VFs
[13:44:22] [PASSED] 51 VFs
[13:44:22] [PASSED] 52 VFs
[13:44:22] [PASSED] 53 VFs
[13:44:22] [PASSED] 54 VFs
[13:44:22] [PASSED] 55 VFs
[13:44:22] [PASSED] 56 VFs
[13:44:22] [PASSED] 57 VFs
[13:44:22] [PASSED] 58 VFs
[13:44:22] [PASSED] 59 VFs
[13:44:22] [PASSED] 60 VFs
[13:44:22] [PASSED] 61 VFs
[13:44:22] [PASSED] 62 VFs
[13:44:22] [PASSED] 63 VFs
[13:44:22] ==================== [PASSED] fair_vram ====================
[13:44:22] ================== [PASSED] pf_gt_config ===================
[13:44:22] ===================== lmtt (1 subtest) =====================
[13:44:22] ======================== test_ops =========================
[13:44:22] [PASSED] 2-level
[13:44:22] [PASSED] multi-level
[13:44:22] ==================== [PASSED] test_ops =====================
[13:44:22] ====================== [PASSED] lmtt =======================
[13:44:22] ================= sriov_packet (1 subtest) =================
[13:44:22] [PASSED] test_descriptor_init
[13:44:22] ================== [PASSED] sriov_packet ===================
[13:44:22] ================= pf_service (11 subtests) =================
[13:44:22] [PASSED] pf_negotiate_any
[13:44:22] [PASSED] pf_negotiate_base_match
[13:44:22] [PASSED] pf_negotiate_base_newer
[13:44:22] [PASSED] pf_negotiate_base_next
[13:44:22] [SKIPPED] pf_negotiate_base_older (no older minor)
[13:44:22] [PASSED] pf_negotiate_base_prev
[13:44:22] [PASSED] pf_negotiate_latest_match
[13:44:22] [PASSED] pf_negotiate_latest_newer
[13:44:22] [PASSED] pf_negotiate_latest_next
[13:44:22] [SKIPPED] pf_negotiate_latest_older (no older minor)
[13:44:22] [SKIPPED] pf_negotiate_latest_prev (no prev major)
[13:44:22] =================== [PASSED] pf_service ====================
[13:44:22] ================= xe_guc_g2g (2 subtests) ==================
[13:44:22] ============== xe_live_guc_g2g_kunit_default ==============
[13:44:22] ========= [SKIPPED] xe_live_guc_g2g_kunit_default ==========
[13:44:22] ============== xe_live_guc_g2g_kunit_allmem ===============
[13:44:22] ========== [SKIPPED] xe_live_guc_g2g_kunit_allmem ==========
[13:44:22] =================== [SKIPPED] xe_guc_g2g ===================
[13:44:22] =================== xe_mocs (2 subtests) ===================
[13:44:22] ================ xe_live_mocs_kernel_kunit ================
[13:44:22] =========== [SKIPPED] xe_live_mocs_kernel_kunit ============
[13:44:22] ================ xe_live_mocs_reset_kunit =================
[13:44:22] ============ [SKIPPED] xe_live_mocs_reset_kunit ============
[13:44:22] ==================== [SKIPPED] xe_mocs =====================
[13:44:22] ================= xe_migrate (2 subtests) ==================
[13:44:22] ================= xe_migrate_sanity_kunit =================
[13:44:22] ============ [SKIPPED] xe_migrate_sanity_kunit =============
[13:44:22] ================== xe_validate_ccs_kunit ==================
[13:44:22] ============= [SKIPPED] xe_validate_ccs_kunit ==============
[13:44:22] =================== [SKIPPED] xe_migrate ===================
[13:44:22] ================== xe_dma_buf (1 subtest) ==================
[13:44:22] ==================== xe_dma_buf_kunit =====================
[13:44:22] ================ [SKIPPED] xe_dma_buf_kunit ================
[13:44:22] =================== [SKIPPED] xe_dma_buf ===================
[13:44:22] ================= xe_bo_shrink (1 subtest) =================
[13:44:22] =================== xe_bo_shrink_kunit ====================
[13:44:22] =============== [SKIPPED] xe_bo_shrink_kunit ===============
[13:44:22] ================== [SKIPPED] xe_bo_shrink ==================
[13:44:22] ==================== xe_bo (2 subtests) ====================
[13:44:22] ================== xe_ccs_migrate_kunit ===================
[13:44:22] ============== [SKIPPED] xe_ccs_migrate_kunit ==============
[13:44:22] ==================== xe_bo_evict_kunit ====================
[13:44:22] =============== [SKIPPED] xe_bo_evict_kunit ================
[13:44:22] ===================== [SKIPPED] xe_bo ======================
[13:44:22] =================== xe_any (9 subtests) ====================
[13:44:22] [PASSED] test_to_xe
[13:44:22] [PASSED] test_to_dev
[13:44:22] [PASSED] test_to_pdev
[13:44:22] [PASSED] test_to_drm
[13:44:22] [PASSED] test_if_pdev
[13:44:22] [PASSED] test_if_xe
[13:44:22] [PASSED] test_if_tile
[13:44:22] [PASSED] test_if_gt
[13:44:22] [PASSED] test_to_id
[13:44:22] ===================== [PASSED] xe_any ======================
[13:44:22] ==================== args (13 subtests) ====================
[13:44:22] [PASSED] count_args_test
[13:44:22] [PASSED] call_args_example
[13:44:22] [PASSED] call_args_test
[13:44:22] [PASSED] drop_first_arg_example
[13:44:22] [PASSED] drop_first_arg_test
[13:44:22] [PASSED] first_arg_example
[13:44:22] [PASSED] first_arg_test
[13:44:22] [PASSED] last_arg_example
[13:44:22] [PASSED] last_arg_test
[13:44:22] [PASSED] pick_arg_example
[13:44:22] [PASSED] if_args_example
[13:44:22] [PASSED] if_args_test
[13:44:22] [PASSED] sep_comma_example
[13:44:22] ====================== [PASSED] args =======================
[13:44:22] =================== xe_pci (3 subtests) ====================
[13:44:22] ==================== check_graphics_ip ====================
[13:44:22] [PASSED] 12.00 Xe_LP
[13:44:22] [PASSED] 12.10 Xe_LP+
[13:44:22] [PASSED] 12.55 Xe_HPG
[13:44:22] [PASSED] 12.60 Xe_HPC
[13:44:22] [PASSED] 12.70 Xe_LPG
[13:44:22] [PASSED] 12.71 Xe_LPG
[13:44:22] [PASSED] 12.74 Xe_LPG+
[13:44:22] [PASSED] 20.01 Xe2_HPG
[13:44:22] [PASSED] 20.02 Xe2_HPG
[13:44:22] [PASSED] 20.04 Xe2_LPG
[13:44:22] [PASSED] 30.00 Xe3_LPG
[13:44:22] [PASSED] 30.01 Xe3_LPG
[13:44:22] [PASSED] 30.03 Xe3_LPG
[13:44:22] [PASSED] 30.04 Xe3_LPG
[13:44:22] [PASSED] 30.05 Xe3_LPG
[13:44:22] [PASSED] 35.10 Xe3p_LPG
[13:44:22] [PASSED] 35.11 Xe3p_XPC
[13:44:22] ================ [PASSED] check_graphics_ip ================
[13:44:22] ===================== check_media_ip ======================
[13:44:22] [PASSED] 12.00 Xe_M
[13:44:22] [PASSED] 12.55 Xe_HPM
[13:44:22] [PASSED] 13.00 Xe_LPM+
[13:44:22] [PASSED] 13.01 Xe2_HPM
[13:44:22] [PASSED] 20.00 Xe2_LPM
[13:44:22] [PASSED] 30.00 Xe3_LPM
[13:44:22] [PASSED] 30.02 Xe3_LPM
[13:44:22] [PASSED] 35.00 Xe3p_LPM
[13:44:22] [PASSED] 35.03 Xe3p_HPM
[13:44:22] ================= [PASSED] check_media_ip ==================
[13:44:22] =================== check_platform_desc ===================
[13:44:22] [PASSED] 0x9A60 (TIGERLAKE)
[13:44:22] [PASSED] 0x9A68 (TIGERLAKE)
[13:44:22] [PASSED] 0x9A70 (TIGERLAKE)
[13:44:22] [PASSED] 0x9A40 (TIGERLAKE)
[13:44:22] [PASSED] 0x9A49 (TIGERLAKE)
[13:44:22] [PASSED] 0x9A59 (TIGERLAKE)
[13:44:22] [PASSED] 0x9A78 (TIGERLAKE)
[13:44:22] [PASSED] 0x9AC0 (TIGERLAKE)
[13:44:22] [PASSED] 0x9AC9 (TIGERLAKE)
[13:44:22] [PASSED] 0x9AD9 (TIGERLAKE)
[13:44:22] [PASSED] 0x9AF8 (TIGERLAKE)
[13:44:22] [PASSED] 0x4C80 (ROCKETLAKE)
[13:44:22] [PASSED] 0x4C8A (ROCKETLAKE)
[13:44:22] [PASSED] 0x4C8B (ROCKETLAKE)
[13:44:22] [PASSED] 0x4C8C (ROCKETLAKE)
[13:44:22] [PASSED] 0x4C90 (ROCKETLAKE)
[13:44:22] [PASSED] 0x4C9A (ROCKETLAKE)
[13:44:22] [PASSED] 0x4680 (ALDERLAKE_S)
[13:44:22] [PASSED] 0x4682 (ALDERLAKE_S)
[13:44:22] [PASSED] 0x4688 (ALDERLAKE_S)
[13:44:22] [PASSED] 0x468A (ALDERLAKE_S)
[13:44:22] [PASSED] 0x468B (ALDERLAKE_S)
[13:44:22] [PASSED] 0x4690 (ALDERLAKE_S)
[13:44:22] [PASSED] 0x4692 (ALDERLAKE_S)
[13:44:22] [PASSED] 0x4693 (ALDERLAKE_S)
[13:44:22] [PASSED] 0x46A0 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46A1 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46A2 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46A3 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46A6 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46A8 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46AA (ALDERLAKE_P)
[13:44:22] [PASSED] 0x462A (ALDERLAKE_P)
[13:44:22] [PASSED] 0x4626 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x4628 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46B0 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46B1 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46B2 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46B3 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46C0 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46C1 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46C2 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46C3 (ALDERLAKE_P)
[13:44:22] [PASSED] 0x46D0 (ALDERLAKE_N)
[13:44:22] [PASSED] 0x46D1 (ALDERLAKE_N)
[13:44:22] [PASSED] 0x46D2 (ALDERLAKE_N)
[13:44:22] [PASSED] 0x46D3 (ALDERLAKE_N)
[13:44:22] [PASSED] 0x46D4 (ALDERLAKE_N)
[13:44:22] [PASSED] 0xA721 (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA7A1 (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA7A9 (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA7AC (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA7AD (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA720 (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA7A0 (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA7A8 (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA7AA (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA7AB (ALDERLAKE_P)
[13:44:22] [PASSED] 0xA780 (ALDERLAKE_S)
[13:44:22] [PASSED] 0xA781 (ALDERLAKE_S)
[13:44:22] [PASSED] 0xA782 (ALDERLAKE_S)
[13:44:22] [PASSED] 0xA783 (ALDERLAKE_S)
[13:44:22] [PASSED] 0xA788 (ALDERLAKE_S)
[13:44:22] [PASSED] 0xA789 (ALDERLAKE_S)
[13:44:22] [PASSED] 0xA78A (ALDERLAKE_S)
[13:44:22] [PASSED] 0xA78B (ALDERLAKE_S)
[13:44:22] [PASSED] 0x4905 (DG1)
[13:44:22] [PASSED] 0x4906 (DG1)
[13:44:22] [PASSED] 0x4907 (DG1)
[13:44:22] [PASSED] 0x4908 (DG1)
[13:44:22] [PASSED] 0x4909 (DG1)
[13:44:22] [PASSED] 0x56C0 (DG2)
[13:44:22] [PASSED] 0x56C2 (DG2)
[13:44:22] [PASSED] 0x56C1 (DG2)
[13:44:22] [PASSED] 0x7D51 (METEORLAKE)
[13:44:22] [PASSED] 0x7DD1 (METEORLAKE)
[13:44:22] [PASSED] 0x7D41 (METEORLAKE)
[13:44:22] [PASSED] 0x7D67 (METEORLAKE)
[13:44:22] [PASSED] 0xB640 (METEORLAKE)
[13:44:22] [PASSED] 0x56A0 (DG2)
[13:44:22] [PASSED] 0x56A1 (DG2)
[13:44:22] [PASSED] 0x56A2 (DG2)
[13:44:22] [PASSED] 0x56BE (DG2)
[13:44:22] [PASSED] 0x56BF (DG2)
[13:44:22] [PASSED] 0x5690 (DG2)
[13:44:22] [PASSED] 0x5691 (DG2)
[13:44:22] [PASSED] 0x5692 (DG2)
[13:44:22] [PASSED] 0x56A5 (DG2)
[13:44:22] [PASSED] 0x56A6 (DG2)
[13:44:22] [PASSED] 0x56B0 (DG2)
[13:44:22] [PASSED] 0x56B1 (DG2)
[13:44:22] [PASSED] 0x56BA (DG2)
[13:44:22] [PASSED] 0x56BB (DG2)
[13:44:22] [PASSED] 0x56BC (DG2)
[13:44:22] [PASSED] 0x56BD (DG2)
[13:44:22] [PASSED] 0x5693 (DG2)
[13:44:22] [PASSED] 0x5694 (DG2)
[13:44:22] [PASSED] 0x5695 (DG2)
[13:44:22] [PASSED] 0x56A3 (DG2)
[13:44:22] [PASSED] 0x56A4 (DG2)
[13:44:22] [PASSED] 0x56B2 (DG2)
[13:44:22] [PASSED] 0x56B3 (DG2)
[13:44:22] [PASSED] 0x5696 (DG2)
[13:44:22] [PASSED] 0x5697 (DG2)
[13:44:22] [PASSED] 0xB69 (PVC)
[13:44:22] [PASSED] 0xB6E (PVC)
[13:44:22] [PASSED] 0xBD4 (PVC)
[13:44:22] [PASSED] 0xBD5 (PVC)
[13:44:22] [PASSED] 0xBD6 (PVC)
[13:44:22] [PASSED] 0xBD7 (PVC)
[13:44:22] [PASSED] 0xBD8 (PVC)
[13:44:22] [PASSED] 0xBD9 (PVC)
[13:44:22] [PASSED] 0xBDA (PVC)
[13:44:22] [PASSED] 0xBDB (PVC)
[13:44:22] [PASSED] 0xBE0 (PVC)
[13:44:22] [PASSED] 0xBE1 (PVC)
[13:44:22] [PASSED] 0xBE5 (PVC)
[13:44:22] [PASSED] 0x7D40 (METEORLAKE)
[13:44:22] [PASSED] 0x7D45 (METEORLAKE)
[13:44:22] [PASSED] 0x7D55 (METEORLAKE)
[13:44:22] [PASSED] 0x7D60 (METEORLAKE)
[13:44:22] [PASSED] 0x7DD5 (METEORLAKE)
[13:44:22] [PASSED] 0x6420 (LUNARLAKE)
[13:44:22] [PASSED] 0x64A0 (LUNARLAKE)
[13:44:22] [PASSED] 0x64B0 (LUNARLAKE)
[13:44:22] [PASSED] 0xE202 (BATTLEMAGE)
[13:44:22] [PASSED] 0xE209 (BATTLEMAGE)
[13:44:22] [PASSED] 0xE20B (BATTLEMAGE)
[13:44:22] [PASSED] 0xE20C (BATTLEMAGE)
[13:44:22] [PASSED] 0xE20D (BATTLEMAGE)
[13:44:22] [PASSED] 0xE210 (BATTLEMAGE)
[13:44:22] [PASSED] 0xE211 (BATTLEMAGE)
[13:44:22] [PASSED] 0xE212 (BATTLEMAGE)
[13:44:22] [PASSED] 0xE216 (BATTLEMAGE)
[13:44:22] [PASSED] 0xE220 (BATTLEMAGE)
[13:44:22] [PASSED] 0xE221 (BATTLEMAGE)
[13:44:22] [PASSED] 0xE222 (BATTLEMAGE)
[13:44:22] [PASSED] 0xE223 (BATTLEMAGE)
[13:44:22] [PASSED] 0xB080 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB081 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB082 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB083 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB084 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB085 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB086 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB087 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB08F (PANTHERLAKE)
[13:44:22] [PASSED] 0xB090 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB0A0 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB0A1 (PANTHERLAKE)
[13:44:22] [PASSED] 0xB0B0 (PANTHERLAKE)
[13:44:22] [PASSED] 0xFD80 (PANTHERLAKE)
[13:44:22] [PASSED] 0xFD81 (PANTHERLAKE)
[13:44:22] [PASSED] 0xD740 (NOVALAKE_S)
[13:44:22] [PASSED] 0xD741 (NOVALAKE_S)
[13:44:22] [PASSED] 0xD742 (NOVALAKE_S)
[13:44:22] [PASSED] 0xD743 (NOVALAKE_S)
[13:44:22] [PASSED] 0xD745 (NOVALAKE_S)
[13:44:22] [PASSED] 0xD74A (NOVALAKE_S)
[13:44:22] [PASSED] 0xD74B (NOVALAKE_S)
[13:44:22] [PASSED] 0x674C (CRESCENTISLAND)
[13:44:22] [PASSED] 0x674D (CRESCENTISLAND)
[13:44:22] [PASSED] 0x674E (CRESCENTISLAND)
[13:44:22] [PASSED] 0x674F (CRESCENTISLAND)
[13:44:22] [PASSED] 0x6750 (CRESCENTISLAND)
[13:44:22] [PASSED] 0x6751 (CRESCENTISLAND)
[13:44:22] [PASSED] 0xD750 (NOVALAKE_P)
[13:44:22] [PASSED] 0xD751 (NOVALAKE_P)
[13:44:22] [PASSED] 0xD752 (NOVALAKE_P)
[13:44:22] [PASSED] 0xD753 (NOVALAKE_P)
[13:44:22] [PASSED] 0xD754 (NOVALAKE_P)
[13:44:22] [PASSED] 0xD755 (NOVALAKE_P)
[13:44:22] [PASSED] 0xD756 (NOVALAKE_P)
[13:44:22] [PASSED] 0xD757 (NOVALAKE_P)
[13:44:22] [PASSED] 0xD75F (NOVALAKE_P)
[13:44:22] =============== [PASSED] check_platform_desc ===============
[13:44:22] ===================== [PASSED] xe_pci ======================
[13:44:22] ============= xe_rtp_tables_test (5 subtests) ==============
[13:44:22] ================== xe_rtp_table_gt_test ===================
[13:44:22] [PASSED] gt_was/14011060649
[13:44:22] [PASSED] gt_was/14011059788
[13:44:22] [PASSED] gt_was/14015795083
[13:44:22] [PASSED] gt_was/16021867713
[13:44:22] [PASSED] gt_was/14019449301
[13:44:22] [PASSED] gt_was/16028005424
[13:44:22] [PASSED] gt_was/14026578760
[13:44:22] [PASSED] gt_was/1409420604
[13:44:22] [PASSED] gt_was/1408615072
[13:44:22] [PASSED] gt_was/22010523718
[13:44:22] [PASSED] gt_was/14011006942
[13:44:22] [PASSED] gt_was/14014830051
[13:44:22] [PASSED] gt_was/18018781329
[13:44:22] [PASSED] gt_was/1509235366
[13:44:22] [PASSED] gt_was/18018781329
[13:44:22] [PASSED] gt_was/16016694945
[13:44:22] [PASSED] gt_was/14018575942
[13:44:22] [PASSED] gt_was/22016670082
[13:44:22] [PASSED] gt_was/22016670082
[13:44:22] [PASSED] gt_was/14017421178
[13:44:22] [PASSED] gt_was/16025250150
[13:44:22] [PASSED] gt_was/14021871409
[13:44:22] [PASSED] gt_was/16021865536
[13:44:22] [PASSED] gt_was/14021486841
[13:44:22] [PASSED] gt_was/14025160223
[13:44:22] [PASSED] gt_was/14026144927, 16029437861, 14026127056
[13:44:22] [PASSED] gt_was/14025635424
[13:44:22] [PASSED] gt_was/16028005424
[13:44:22] ============== [PASSED] xe_rtp_table_gt_test ===============
[13:44:22] ================== xe_rtp_table_gt_test ===================
[13:44:22] [PASSED] gt_tunings/Tuning: Blend Fill Caching Optimization Disable
[13:44:22] [PASSED] gt_tunings/Tuning: 32B Access Enable
[13:44:22] [PASSED] gt_tunings/Tuning: L3 cache
[13:44:22] [PASSED] gt_tunings/Tuning: L3 cache - media
[13:44:22] [PASSED] gt_tunings/Tuning: Compression Overfetch
[13:44:22] [PASSED] gt_tunings/Tuning: Compression Overfetch - media
[13:44:22] [PASSED] gt_tunings/Tuning: Enable compressible partial write overfetch in L3
[13:44:22] [PASSED] gt_tunings/Tuning: Enable compressible partial write overfetch in L3 - media
[13:44:22] [PASSED] gt_tunings/Tuning: L2 Overfetch Compressible Only
[13:44:22] [PASSED] gt_tunings/Tuning: L2 Overfetch Compressible Only - media
[13:44:22] [PASSED] gt_tunings/Tuning: Stateless compression control
[13:44:22] [PASSED] gt_tunings/Tuning: Stateless compression control - media
[13:44:22] [PASSED] gt_tunings/Tuning: L3 RW flush all Cache
[13:44:22] [PASSED] gt_tunings/Tuning: L3 RW flush all cache - media
[13:44:22] [PASSED] gt_tunings/Tuning: Set STLB Bank Hash Mode to 4KB
[13:44:22] [PASSED] gt_tunings/Tuning: Force All Non-Compressible Memory Reads to be 256B Overfetches
[13:44:22] ============== [PASSED] xe_rtp_table_gt_test ===============
[13:44:22] ================== xe_rtp_table_oob_test ==================
[13:44:22] [PASSED] oob_was/1607983814
[13:44:22] [PASSED] oob_was/16010904313
[13:44:22] [PASSED] oob_was/18022495364
[13:44:22] [PASSED] oob_was/22012773006
[13:44:22] [PASSED] oob_was/14014475959
[13:44:22] [PASSED] oob_was/22011391025
[13:44:22] [PASSED] oob_was/22012727170
[13:44:22] [PASSED] oob_was/22012727685
[13:44:22] [PASSED] oob_was/22016596838
[13:44:22] [PASSED] oob_was/18020744125
[13:44:22] [PASSED] oob_was/1409600907
[13:44:22] [PASSED] oob_was/22014953428
[13:44:22] [PASSED] oob_was/16017236439
[13:44:22] [PASSED] oob_was/14019821291
[13:44:22] [PASSED] oob_was/14015076503
[13:44:22] [PASSED] oob_was/22016122933
[13:44:22] [PASSED] oob_was/14018913170
[13:44:22] [PASSED] oob_was/14018094691
[13:44:22] [PASSED] oob_was/18024947630
[13:44:22] [PASSED] oob_was/16022287689
[13:44:22] [PASSED] oob_was/13011645652
[13:44:22] [PASSED] oob_was/14022293748
[13:44:22] [PASSED] oob_was/22019794406
[13:44:22] [PASSED] oob_was/22019338487
[13:44:22] [PASSED] oob_was/16023588340
[13:44:22] [PASSED] oob_was/14019789679
[13:44:22] [PASSED] oob_was/14022866841
[13:44:22] [PASSED] oob_was/16021333562
[13:44:22] [PASSED] oob_was/14016712196
[13:44:22] [PASSED] oob_was/14015568240
[13:44:22] [PASSED] oob_was/18013179988
[13:44:22] [PASSED] oob_was/1508761755
[13:44:22] [PASSED] oob_was/16023105232
[13:44:22] [PASSED] oob_was/16026508708
[13:44:22] [PASSED] oob_was/14020001231
[13:44:22] [PASSED] oob_was/16023683509
[13:44:22] [PASSED] oob_was/14025515070
[13:44:22] [PASSED] oob_was/15015404425_disable
[13:44:22] [PASSED] oob_was/16026007364
[13:44:22] [PASSED] oob_was/14020316580
[13:44:22] [PASSED] oob_was/14025883347
[13:44:22] [PASSED] oob_was/16029380221
[13:44:22] [PASSED] oob_was/22022079272
[13:44:22] [PASSED] oob_was/16029897822
[13:44:22] [PASSED] oob_was/14027054324
[13:44:22] [PASSED] oob_was/14025941587
[13:44:22] [PASSED] oob_was/16030224309
[13:44:22] ============== [PASSED] xe_rtp_table_oob_test ==============
[13:44:22] ================ xe_rtp_table_dev_oob_test ================
[13:44:22] [PASSED] device_oob_was/22010954014
[13:44:22] [PASSED] device_oob_was/15015404425
[13:44:22] [PASSED] device_oob_was/22019338487_display
[13:44:22] [PASSED] device_oob_was/14022085890
[13:44:22] [PASSED] device_oob_was/14026539277
[13:44:22] [PASSED] device_oob_was/14026633728
[13:44:22] [PASSED] device_oob_was/14026746987
[13:44:22] [PASSED] device_oob_was/14026779378
[13:44:22] ============ [PASSED] xe_rtp_table_dev_oob_test ============
[13:44:22] ========== xe_rtp_table_missing_upper_bound_test ==========
[13:44:22] [PASSED] register_whitelist/WaAllowPMDepthAndInvocationCountAccessFromUMD, 1408556865
[13:44:22] [PASSED] register_whitelist/1508744258, 14012131227, 1808121037
[13:44:22] [PASSED] register_whitelist/1806527549
[13:44:22] [PASSED] register_whitelist/allow_read_ctx_timestamp
[13:44:22] [PASSED] register_whitelist/allow_read_queue_timestamp
[13:44:22] [PASSED] register_whitelist/16014440446
[13:44:22] [PASSED] register_whitelist/16017236439
[13:44:22] [PASSED] register_whitelist/16020183090
[13:44:22] [PASSED] register_whitelist/14024997852
[13:44:22] [PASSED] register_whitelist/14024997852
[13:44:22] ====== [PASSED] xe_rtp_table_missing_upper_bound_test ======
[13:44:22] =============== [PASSED] xe_rtp_tables_test ================
[13:44:22] =================== xe_rtp (3 subtests) ====================
[13:44:22] =================== xe_rtp_rules_tests ====================
[13:44:22] [PASSED] no
[13:44:22] [PASSED] yes
[13:44:22] [PASSED] no-and-no
[13:44:22] [PASSED] no-and-yes
[13:44:22] [PASSED] yes-and-no
[13:44:22] [PASSED] yes-and-yes
[13:44:22] [PASSED] no-or-no
[13:44:22] [PASSED] no-or-yes
[13:44:22] [PASSED] yes-or-no
[13:44:22] [PASSED] yes-or-yes
[13:44:22] [PASSED] no-yes-or-yes-no
[13:44:22] [PASSED] no-yes-or-yes-yes
[13:44:22] [PASSED] yes-yes-or-no-yes
[13:44:22] [PASSED] yes-yes-or-yes-yes
[13:44:22] [PASSED] no-no-or-yes-or-no
[13:44:22] [PASSED] or
[13:44:22] [PASSED] or-yes
[13:44:22] [PASSED] or-no
[13:44:22] [PASSED] yes-or
[13:44:22] [PASSED] no-or
[13:44:22] [PASSED] no-or-or-yes
[13:44:22] [PASSED] yes-or-or-no
[13:44:22] [PASSED] no-or-or-no
[13:44:22] [PASSED] missing-context-engine-class
[13:44:22] [PASSED] missing-context-engine-class-or-yes
[13:44:22] [PASSED] missing-context-engine-class-or-or-yes
[13:44:22] =============== [PASSED] xe_rtp_rules_tests ================
[13:44:22] =============== xe_rtp_process_to_sr_tests ================
[13:44:22] [PASSED] coalesce-same-reg
[13:44:22] [PASSED] coalesce-same-reg-literal-and-func
[13:44:22] [PASSED] no-match-no-add
[13:44:22] [PASSED] two-regs-two-entries
[13:44:22] [PASSED] clr-one-set-other
[13:44:22] [PASSED] set-field
[13:44:22] [PASSED] conflict-duplicate
[13:44:22] [PASSED] conflict-not-disjoint
[13:44:22] [PASSED] conflict-not-disjoint-literal-and-func
[13:44:22] [PASSED] conflict-reg-type
[13:44:22] [PASSED] bad-mcr-reg-forced-to-regular
[13:44:22] [PASSED] bad-regular-reg-forced-to-mcr
[13:44:22] =========== [PASSED] xe_rtp_process_to_sr_tests ============
[13:44:22] ================== xe_rtp_process_tests ===================
[13:44:22] [PASSED] active1
[13:44:22] [PASSED] active2
[13:44:22] [PASSED] active-inactive
[13:44:22] [PASSED] inactive-active
[13:44:22] [PASSED] inactive-active-inactive
[13:44:22] [PASSED] inactive-inactive-inactive
[13:44:22] ============== [PASSED] xe_rtp_process_tests ===============
[13:44:22] ===================== [PASSED] xe_rtp ======================
[13:44:22] ==================== xe_wa (1 subtest) =====================
[13:44:22] ======================== xe_wa_gt =========================
[13:44:22] [PASSED] TIGERLAKE B0
[13:44:22] [PASSED] DG1 A0
[13:44:22] [PASSED] DG1 B0
[13:44:22] [PASSED] ALDERLAKE_S A0
[13:44:22] [PASSED] ALDERLAKE_S B0
[13:44:22] [PASSED] ALDERLAKE_S C0
[13:44:22] [PASSED] ALDERLAKE_S D0
[13:44:22] [PASSED] ALDERLAKE_P A0
[13:44:22] [PASSED] ALDERLAKE_P B0
[13:44:22] [PASSED] ALDERLAKE_P C0
[13:44:22] [PASSED] ALDERLAKE_S RPLS D0
[13:44:22] [PASSED] ALDERLAKE_P RPLU E0
[13:44:22] [PASSED] DG2 G10 C0
[13:44:22] [PASSED] DG2 G11 B1
[13:44:22] [PASSED] DG2 G12 A1
[13:44:22] [PASSED] METEORLAKE 12.70(Xe_LPG) A0 13.00(Xe_LPM+) A0
[13:44:22] [PASSED] METEORLAKE 12.71(Xe_LPG) A0 13.00(Xe_LPM+) A0
[13:44:22] [PASSED] METEORLAKE 12.74(Xe_LPG+) A0 13.00(Xe_LPM+) A0
[13:44:22] [PASSED] LUNARLAKE 20.04(Xe2_LPG) A0 20.00(Xe2_LPM) A0
[13:44:22] [PASSED] LUNARLAKE 20.04(Xe2_LPG) B0 20.00(Xe2_LPM) A0
[13:44:22] [PASSED] BATTLEMAGE 20.01(Xe2_HPG) A0 13.01(Xe2_HPM) A1
[13:44:22] [PASSED] PANTHERLAKE 30.00(Xe3_LPG) A0 30.00(Xe3_LPM) A0
[13:44:22] ==================== [PASSED] xe_wa_gt =====================
[13:44:22] ====================== [PASSED] xe_wa ======================
[13:44:22] ============================================================
[13:44:22] Testing complete. Ran 837 tests: passed: 809, skipped: 28
[13:44:22] Elapsed time: 41.800s total, 1.876s configuring, 39.158s building, 0.718s running
+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/gpu/drm/tests/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/tests/.kunitconfig
[13:44:22] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[13:44:24] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[13:44:49] Starting KUnit Kernel (1/1)...
[13:44:49] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[13:44:50] ============ drm_test_pick_cmdline (2 subtests) ============
[13:44:50] [PASSED] drm_test_pick_cmdline_res_1920_1080_60
[13:44:50] =============== drm_test_pick_cmdline_named ===============
[13:44:50] [PASSED] NTSC
[13:44:50] [PASSED] NTSC-J
[13:44:50] [PASSED] PAL
[13:44:50] [PASSED] PAL-M
[13:44:50] =========== [PASSED] drm_test_pick_cmdline_named ===========
[13:44:50] ============== [PASSED] drm_test_pick_cmdline ==============
[13:44:50] == drm_test_atomic_get_connector_for_encoder (1 subtest) ===
[13:44:50] [PASSED] drm_test_drm_atomic_get_connector_for_encoder
[13:44:50] ==== [PASSED] drm_test_atomic_get_connector_for_encoder ====
[13:44:50] =========== drm_validate_clone_mode (2 subtests) ===========
[13:44:50] ============== drm_test_check_in_clone_mode ===============
[13:44:50] [PASSED] in_clone_mode
[13:44:50] [PASSED] not_in_clone_mode
[13:44:50] ========== [PASSED] drm_test_check_in_clone_mode ===========
[13:44:50] =============== drm_test_check_valid_clones ===============
[13:44:50] [PASSED] not_in_clone_mode
[13:44:50] [PASSED] valid_clone
[13:44:50] [PASSED] invalid_clone
[13:44:50] =========== [PASSED] drm_test_check_valid_clones ===========
[13:44:50] ============= [PASSED] drm_validate_clone_mode =============
[13:44:50] ============= drm_validate_modeset (1 subtest) =============
[13:44:50] [PASSED] drm_test_check_connector_changed_modeset
[13:44:50] ============== [PASSED] drm_validate_modeset ===============
[13:44:50] ====== drm_test_bridge_get_current_state (1 subtest) =======
[13:44:50] [PASSED] drm_test_drm_bridge_get_current_state_atomic
[13:44:50] ======== [PASSED] drm_test_bridge_get_current_state ========
[13:44:50] ====== drm_test_bridge_helper_reset_crtc (3 subtests) ======
[13:44:50] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic
[13:44:50] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic_disabled
[13:44:50] [PASSED] drm_test_drm_bridge_helper_hdmi_output_bus_fmts
[13:44:50] ======== [PASSED] drm_test_bridge_helper_reset_crtc ========
[13:44:50] ============== drm_bridge_alloc (2 subtests) ===============
[13:44:50] [PASSED] drm_test_drm_bridge_alloc_basic
[13:44:50] [PASSED] drm_test_drm_bridge_alloc_get_put
[13:44:50] ================ [PASSED] drm_bridge_alloc =================
[13:44:50] ============= drm_bridge_bus_fmt (5 subtests) ==============
[13:44:50] [PASSED] drm_test_bridge_rgb_yuv_rgb
[13:44:50] [PASSED] drm_test_bridge_must_convert_to_yuv444
[13:44:50] [PASSED] drm_test_bridge_hdmi_auto_rgb
[13:44:50] [PASSED] drm_test_bridge_auto_first
[13:44:50] [PASSED] drm_test_bridge_rgb_yuv_no_path
[13:44:50] =============== [PASSED] drm_bridge_bus_fmt ================
[13:44:50] ============= drm_cmdline_parser (40 subtests) =============
[13:44:50] [PASSED] drm_test_cmdline_force_d_only
[13:44:50] [PASSED] drm_test_cmdline_force_D_only_dvi
[13:44:50] [PASSED] drm_test_cmdline_force_D_only_hdmi
[13:44:50] [PASSED] drm_test_cmdline_force_D_only_not_digital
[13:44:50] [PASSED] drm_test_cmdline_force_e_only
[13:44:50] [PASSED] drm_test_cmdline_res
[13:44:50] [PASSED] drm_test_cmdline_res_vesa
[13:44:50] [PASSED] drm_test_cmdline_res_vesa_rblank
[13:44:50] [PASSED] drm_test_cmdline_res_rblank
[13:44:50] [PASSED] drm_test_cmdline_res_bpp
[13:44:50] [PASSED] drm_test_cmdline_res_refresh
[13:44:50] [PASSED] drm_test_cmdline_res_bpp_refresh
[13:44:50] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced
[13:44:50] [PASSED] drm_test_cmdline_res_bpp_refresh_margins
[13:44:50] [PASSED] drm_test_cmdline_res_bpp_refresh_force_off
[13:44:50] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on
[13:44:50] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_analog
[13:44:50] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_digital
[13:44:50] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on
[13:44:50] [PASSED] drm_test_cmdline_res_margins_force_on
[13:44:50] [PASSED] drm_test_cmdline_res_vesa_margins
[13:44:50] [PASSED] drm_test_cmdline_name
[13:44:50] [PASSED] drm_test_cmdline_name_bpp
[13:44:50] [PASSED] drm_test_cmdline_name_option
[13:44:50] [PASSED] drm_test_cmdline_name_bpp_option
[13:44:50] [PASSED] drm_test_cmdline_rotate_0
[13:44:50] [PASSED] drm_test_cmdline_rotate_90
[13:44:50] [PASSED] drm_test_cmdline_rotate_180
[13:44:50] [PASSED] drm_test_cmdline_rotate_270
[13:44:50] [PASSED] drm_test_cmdline_hmirror
[13:44:50] [PASSED] drm_test_cmdline_vmirror
[13:44:50] [PASSED] drm_test_cmdline_margin_options
[13:44:50] [PASSED] drm_test_cmdline_multiple_options
[13:44:50] [PASSED] drm_test_cmdline_bpp_extra_and_option
[13:44:50] [PASSED] drm_test_cmdline_extra_and_option
[13:44:50] [PASSED] drm_test_cmdline_freestanding_options
[13:44:50] [PASSED] drm_test_cmdline_freestanding_force_e_and_options
[13:44:50] [PASSED] drm_test_cmdline_panel_orientation
[13:44:50] ================ drm_test_cmdline_invalid =================
[13:44:50] [PASSED] margin_only
[13:44:50] [PASSED] interlace_only
[13:44:50] [PASSED] res_missing_x
[13:44:50] [PASSED] res_missing_y
[13:44:50] [PASSED] res_bad_y
[13:44:50] [PASSED] res_missing_y_bpp
[13:44:50] [PASSED] res_bad_bpp
[13:44:50] [PASSED] res_bad_refresh
[13:44:50] [PASSED] res_bpp_refresh_force_on_off
[13:44:50] [PASSED] res_invalid_mode
[13:44:50] [PASSED] res_bpp_wrong_place_mode
[13:44:50] [PASSED] name_bpp_refresh
[13:44:50] [PASSED] name_refresh
[13:44:50] [PASSED] name_refresh_wrong_mode
[13:44:50] [PASSED] name_refresh_invalid_mode
[13:44:50] [PASSED] rotate_multiple
[13:44:50] [PASSED] rotate_invalid_val
[13:44:50] [PASSED] rotate_truncated
[13:44:50] [PASSED] invalid_option
[13:44:50] [PASSED] invalid_tv_option
[13:44:50] [PASSED] truncated_tv_option
[13:44:50] ============ [PASSED] drm_test_cmdline_invalid =============
[13:44:50] =============== drm_test_cmdline_tv_options ===============
[13:44:50] [PASSED] NTSC
[13:44:50] [PASSED] NTSC_443
[13:44:50] [PASSED] NTSC_J
[13:44:50] [PASSED] PAL
[13:44:50] [PASSED] PAL_M
[13:44:50] [PASSED] PAL_N
[13:44:50] [PASSED] SECAM
[13:44:50] [PASSED] MONO_525
[13:44:50] [PASSED] MONO_625
[13:44:50] =========== [PASSED] drm_test_cmdline_tv_options ===========
[13:44:50] =============== [PASSED] drm_cmdline_parser ================
[13:44:50] ========== drmm_connector_hdmi_init (20 subtests) ==========
[13:44:50] [PASSED] drm_test_connector_hdmi_init_valid
[13:44:50] [PASSED] drm_test_connector_hdmi_init_bpc_8
[13:44:50] [PASSED] drm_test_connector_hdmi_init_bpc_10
[13:44:50] [PASSED] drm_test_connector_hdmi_init_bpc_12
[13:44:50] [PASSED] drm_test_connector_hdmi_init_bpc_invalid
[13:44:50] [PASSED] drm_test_connector_hdmi_init_bpc_null
[13:44:50] [PASSED] drm_test_connector_hdmi_init_formats_empty
[13:44:50] [PASSED] drm_test_connector_hdmi_init_formats_no_rgb
[13:44:50] === drm_test_connector_hdmi_init_formats_yuv420_allowed ===
[13:44:50] [PASSED] supported_formats=0x9 yuv420_allowed=1
[13:44:50] [PASSED] supported_formats=0x9 yuv420_allowed=0
[13:44:50] [PASSED] supported_formats=0x5 yuv420_allowed=1
[13:44:50] [PASSED] supported_formats=0x5 yuv420_allowed=0
[13:44:50] === [PASSED] drm_test_connector_hdmi_init_formats_yuv420_allowed ===
[13:44:50] [PASSED] drm_test_connector_hdmi_init_null_ddc
[13:44:50] [PASSED] drm_test_connector_hdmi_init_null_product
[13:44:50] [PASSED] drm_test_connector_hdmi_init_null_vendor
[13:44:50] [PASSED] drm_test_connector_hdmi_init_product_length_exact
[13:44:50] [PASSED] drm_test_connector_hdmi_init_product_length_too_long
[13:44:50] [PASSED] drm_test_connector_hdmi_init_product_valid
[13:44:50] [PASSED] drm_test_connector_hdmi_init_vendor_length_exact
[13:44:50] [PASSED] drm_test_connector_hdmi_init_vendor_length_too_long
[13:44:50] [PASSED] drm_test_connector_hdmi_init_vendor_valid
[13:44:50] ========= drm_test_connector_hdmi_init_type_valid =========
[13:44:50] [PASSED] HDMI-A
[13:44:50] [PASSED] HDMI-B
[13:44:50] ===== [PASSED] drm_test_connector_hdmi_init_type_valid =====
[13:44:50] ======== drm_test_connector_hdmi_init_type_invalid ========
[13:44:50] [PASSED] Unknown
[13:44:50] [PASSED] VGA
[13:44:50] [PASSED] DVI-I
[13:44:50] [PASSED] DVI-D
[13:44:50] [PASSED] DVI-A
[13:44:50] [PASSED] Composite
[13:44:50] [PASSED] SVIDEO
[13:44:50] [PASSED] LVDS
[13:44:50] [PASSED] Component
[13:44:50] [PASSED] DIN
[13:44:50] [PASSED] DP
[13:44:50] [PASSED] TV
[13:44:50] [PASSED] eDP
[13:44:50] [PASSED] Virtual
[13:44:50] [PASSED] DSI
[13:44:50] [PASSED] DPI
[13:44:50] [PASSED] Writeback
[13:44:50] [PASSED] SPI
[13:44:50] [PASSED] USB
[13:44:50] ==== [PASSED] drm_test_connector_hdmi_init_type_invalid ====
[13:44:50] ============ [PASSED] drmm_connector_hdmi_init =============
[13:44:50] ============= drmm_connector_init (3 subtests) =============
[13:44:50] [PASSED] drm_test_drmm_connector_init
[13:44:50] [PASSED] drm_test_drmm_connector_init_null_ddc
[13:44:50] ========= drm_test_drmm_connector_init_type_valid =========
[13:44:50] [PASSED] Unknown
[13:44:50] [PASSED] VGA
[13:44:50] [PASSED] DVI-I
[13:44:50] [PASSED] DVI-D
[13:44:50] [PASSED] DVI-A
[13:44:50] [PASSED] Composite
[13:44:50] [PASSED] SVIDEO
[13:44:50] [PASSED] LVDS
[13:44:50] [PASSED] Component
[13:44:50] [PASSED] DIN
[13:44:50] [PASSED] DP
[13:44:50] [PASSED] HDMI-A
[13:44:50] [PASSED] HDMI-B
[13:44:50] [PASSED] TV
[13:44:50] [PASSED] eDP
[13:44:50] [PASSED] Virtual
[13:44:50] [PASSED] DSI
[13:44:50] [PASSED] DPI
[13:44:50] [PASSED] Writeback
[13:44:50] [PASSED] SPI
[13:44:50] [PASSED] USB
[13:44:50] ===== [PASSED] drm_test_drmm_connector_init_type_valid =====
[13:44:50] =============== [PASSED] drmm_connector_init ===============
[13:44:50] ========= drm_connector_dynamic_init (6 subtests) ==========
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_init
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_init_null_ddc
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_init_not_added
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_init_properties
[13:44:50] ===== drm_test_drm_connector_dynamic_init_type_valid ======
[13:44:50] [PASSED] Unknown
[13:44:50] [PASSED] VGA
[13:44:50] [PASSED] DVI-I
[13:44:50] [PASSED] DVI-D
[13:44:50] [PASSED] DVI-A
[13:44:50] [PASSED] Composite
[13:44:50] [PASSED] SVIDEO
[13:44:50] [PASSED] LVDS
[13:44:50] [PASSED] Component
[13:44:50] [PASSED] DIN
[13:44:50] [PASSED] DP
[13:44:50] [PASSED] HDMI-A
[13:44:50] [PASSED] HDMI-B
[13:44:50] [PASSED] TV
[13:44:50] [PASSED] eDP
[13:44:50] [PASSED] Virtual
[13:44:50] [PASSED] DSI
[13:44:50] [PASSED] DPI
[13:44:50] [PASSED] Writeback
[13:44:50] [PASSED] SPI
[13:44:50] [PASSED] USB
[13:44:50] = [PASSED] drm_test_drm_connector_dynamic_init_type_valid ==
[13:44:50] ======== drm_test_drm_connector_dynamic_init_name =========
[13:44:50] [PASSED] Unknown
[13:44:50] [PASSED] VGA
[13:44:50] [PASSED] DVI-I
[13:44:50] [PASSED] DVI-D
[13:44:50] [PASSED] DVI-A
[13:44:50] [PASSED] Composite
[13:44:50] [PASSED] SVIDEO
[13:44:50] [PASSED] LVDS
[13:44:50] [PASSED] Component
[13:44:50] [PASSED] DIN
[13:44:50] [PASSED] DP
[13:44:50] [PASSED] HDMI-A
[13:44:50] [PASSED] HDMI-B
[13:44:50] [PASSED] TV
[13:44:50] [PASSED] eDP
[13:44:50] [PASSED] Virtual
[13:44:50] [PASSED] DSI
[13:44:50] [PASSED] DPI
[13:44:50] [PASSED] Writeback
[13:44:50] [PASSED] SPI
[13:44:50] [PASSED] USB
[13:44:50] ==== [PASSED] drm_test_drm_connector_dynamic_init_name =====
[13:44:50] =========== [PASSED] drm_connector_dynamic_init ============
[13:44:50] ==== drm_connector_dynamic_register_early (4 subtests) =====
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_early_on_list
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_early_defer
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_early_no_init
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_early_no_mode_object
[13:44:50] ====== [PASSED] drm_connector_dynamic_register_early =======
[13:44:50] ======= drm_connector_dynamic_register (7 subtests) ========
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_on_list
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_no_defer
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_no_init
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_mode_object
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_sysfs
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_sysfs_name
[13:44:50] [PASSED] drm_test_drm_connector_dynamic_register_debugfs
[13:44:50] ========= [PASSED] drm_connector_dynamic_register ==========
[13:44:50] = drm_connector_attach_broadcast_rgb_property (2 subtests) =
[13:44:50] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property
[13:44:50] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector
[13:44:50] === [PASSED] drm_connector_attach_broadcast_rgb_property ===
[13:44:50] ========== drm_get_tv_mode_from_name (2 subtests) ==========
[13:44:50] ========== drm_test_get_tv_mode_from_name_valid ===========
[13:44:50] [PASSED] NTSC
[13:44:50] [PASSED] NTSC-443
[13:44:50] [PASSED] NTSC-J
[13:44:50] [PASSED] PAL
[13:44:50] [PASSED] PAL-M
[13:44:50] [PASSED] PAL-N
[13:44:50] [PASSED] SECAM
[13:44:50] [PASSED] Mono
[13:44:50] ====== [PASSED] drm_test_get_tv_mode_from_name_valid =======
[13:44:50] [PASSED] drm_test_get_tv_mode_from_name_truncated
[13:44:50] ============ [PASSED] drm_get_tv_mode_from_name ============
[13:44:50] = drm_test_connector_hdmi_compute_mode_clock (12 subtests) =
[13:44:50] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb
[13:44:50] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc
[13:44:50] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1
[13:44:50] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc
[13:44:50] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1
[13:44:50] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_double
[13:44:50] = drm_test_connector_hdmi_compute_mode_clock_yuv420_valid =
[13:44:50] [PASSED] VIC 96
[13:44:50] [PASSED] VIC 97
[13:44:50] [PASSED] VIC 101
[13:44:50] [PASSED] VIC 102
[13:44:50] [PASSED] VIC 106
[13:44:50] [PASSED] VIC 107
[13:44:50] === [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_valid ===
[13:44:50] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc
[13:44:50] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc
[13:44:50] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc
[13:44:50] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc
[13:44:50] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc
[13:44:50] === [PASSED] drm_test_connector_hdmi_compute_mode_clock ====
[13:44:50] == drm_hdmi_connector_get_broadcast_rgb_name (2 subtests) ==
[13:44:50] === drm_test_drm_hdmi_connector_get_broadcast_rgb_name ====
[13:44:50] [PASSED] Automatic
[13:44:50] [PASSED] Full
[13:44:50] [PASSED] Limited 16:235
[13:44:50] === [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name ===
[13:44:50] [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid
[13:44:50] ==== [PASSED] drm_hdmi_connector_get_broadcast_rgb_name ====
[13:44:50] == drm_hdmi_connector_get_output_format_name (2 subtests) ==
[13:44:50] === drm_test_drm_hdmi_connector_get_output_format_name ====
[13:44:50] [PASSED] RGB
[13:44:50] [PASSED] YUV 4:2:0
[13:44:50] [PASSED] YUV 4:2:2
[13:44:50] [PASSED] YUV 4:4:4
[13:44:50] === [PASSED] drm_test_drm_hdmi_connector_get_output_format_name ===
[13:44:50] [PASSED] drm_test_drm_hdmi_connector_get_output_format_name_invalid
[13:44:50] ==== [PASSED] drm_hdmi_connector_get_output_format_name ====
[13:44:50] ============= drm_damage_helper (21 subtests) ==============
[13:44:50] [PASSED] drm_test_damage_iter_no_damage
[13:44:50] [PASSED] drm_test_damage_iter_no_damage_fractional_src
[13:44:50] [PASSED] drm_test_damage_iter_no_damage_src_moved
[13:44:50] [PASSED] drm_test_damage_iter_no_damage_fractional_src_moved
[13:44:50] [PASSED] drm_test_damage_iter_no_damage_not_visible
[13:44:50] [PASSED] drm_test_damage_iter_no_damage_no_crtc
[13:44:50] [PASSED] drm_test_damage_iter_no_damage_no_fb
[13:44:50] [PASSED] drm_test_damage_iter_simple_damage
[13:44:50] [PASSED] drm_test_damage_iter_single_damage
[13:44:50] [PASSED] drm_test_damage_iter_single_damage_intersect_src
[13:44:50] [PASSED] drm_test_damage_iter_single_damage_outside_src
[13:44:50] [PASSED] drm_test_damage_iter_single_damage_fractional_src
[13:44:50] [PASSED] drm_test_damage_iter_single_damage_intersect_fractional_src
[13:44:50] [PASSED] drm_test_damage_iter_single_damage_outside_fractional_src
[13:44:50] [PASSED] drm_test_damage_iter_single_damage_src_moved
[13:44:50] [PASSED] drm_test_damage_iter_single_damage_fractional_src_moved
[13:44:50] [PASSED] drm_test_damage_iter_damage
[13:44:50] [PASSED] drm_test_damage_iter_damage_one_intersect
[13:44:50] [PASSED] drm_test_damage_iter_damage_one_outside
[13:44:50] [PASSED] drm_test_damage_iter_damage_src_moved
[13:44:50] [PASSED] drm_test_damage_iter_damage_not_visible
[13:44:50] ================ [PASSED] drm_damage_helper ================
[13:44:50] ============== drm_dp_mst_helper (3 subtests) ==============
[13:44:50] ============== drm_test_dp_mst_calc_pbn_mode ==============
[13:44:50] [PASSED] Clock 154000 BPP 30 DSC disabled
[13:44:50] [PASSED] Clock 234000 BPP 30 DSC disabled
[13:44:50] [PASSED] Clock 297000 BPP 24 DSC disabled
[13:44:50] [PASSED] Clock 332880 BPP 24 DSC enabled
[13:44:50] [PASSED] Clock 324540 BPP 24 DSC enabled
[13:44:50] ========== [PASSED] drm_test_dp_mst_calc_pbn_mode ==========
[13:44:50] ============== drm_test_dp_mst_calc_pbn_div ===============
[13:44:50] [PASSED] Link rate 2000000 lane count 4
[13:44:50] [PASSED] Link rate 2000000 lane count 2
[13:44:50] [PASSED] Link rate 2000000 lane count 1
[13:44:50] [PASSED] Link rate 1350000 lane count 4
[13:44:50] [PASSED] Link rate 1350000 lane count 2
[13:44:50] [PASSED] Link rate 1350000 lane count 1
[13:44:50] [PASSED] Link rate 1000000 lane count 4
[13:44:50] [PASSED] Link rate 1000000 lane count 2
[13:44:50] [PASSED] Link rate 1000000 lane count 1
[13:44:50] [PASSED] Link rate 810000 lane count 4
[13:44:50] [PASSED] Link rate 810000 lane count 2
[13:44:50] [PASSED] Link rate 810000 lane count 1
[13:44:50] [PASSED] Link rate 540000 lane count 4
[13:44:50] [PASSED] Link rate 540000 lane count 2
[13:44:50] [PASSED] Link rate 540000 lane count 1
[13:44:50] [PASSED] Link rate 270000 lane count 4
[13:44:50] [PASSED] Link rate 270000 lane count 2
[13:44:50] [PASSED] Link rate 270000 lane count 1
[13:44:50] [PASSED] Link rate 162000 lane count 4
[13:44:50] [PASSED] Link rate 162000 lane count 2
[13:44:50] [PASSED] Link rate 162000 lane count 1
[13:44:50] ========== [PASSED] drm_test_dp_mst_calc_pbn_div ===========
[13:44:50] ========= drm_test_dp_mst_sideband_msg_req_decode =========
[13:44:50] [PASSED] DP_ENUM_PATH_RESOURCES with port number
[13:44:50] [PASSED] DP_POWER_UP_PHY with port number
[13:44:50] [PASSED] DP_POWER_DOWN_PHY with port number
[13:44:50] [PASSED] DP_ALLOCATE_PAYLOAD with SDP stream sinks
[13:44:50] [PASSED] DP_ALLOCATE_PAYLOAD with port number
[13:44:50] [PASSED] DP_ALLOCATE_PAYLOAD with VCPI
[13:44:50] [PASSED] DP_ALLOCATE_PAYLOAD with PBN
[13:44:50] [PASSED] DP_QUERY_PAYLOAD with port number
[13:44:50] [PASSED] DP_QUERY_PAYLOAD with VCPI
[13:44:50] [PASSED] DP_REMOTE_DPCD_READ with port number
[13:44:50] [PASSED] DP_REMOTE_DPCD_READ with DPCD address
[13:44:50] [PASSED] DP_REMOTE_DPCD_READ with max number of bytes
[13:44:50] [PASSED] DP_REMOTE_DPCD_WRITE with port number
[13:44:50] [PASSED] DP_REMOTE_DPCD_WRITE with DPCD address
[13:44:50] [PASSED] DP_REMOTE_DPCD_WRITE with data array
[13:44:50] [PASSED] DP_REMOTE_I2C_READ with port number
[13:44:50] [PASSED] DP_REMOTE_I2C_READ with I2C device ID
[13:44:50] [PASSED] DP_REMOTE_I2C_READ with transactions array
[13:44:50] [PASSED] DP_REMOTE_I2C_WRITE with port number
[13:44:50] [PASSED] DP_REMOTE_I2C_WRITE with I2C device ID
[13:44:50] [PASSED] DP_REMOTE_I2C_WRITE with data array
[13:44:50] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream ID
[13:44:50] [PASSED] DP_QUERY_STREAM_ENC_STATUS with client ID
[13:44:50] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream event
[13:44:50] [PASSED] DP_QUERY_STREAM_ENC_STATUS with valid stream event
[13:44:50] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream behavior
[13:44:50] [PASSED] DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior
[13:44:50] ===== [PASSED] drm_test_dp_mst_sideband_msg_req_decode =====
[13:44:50] ================ [PASSED] drm_dp_mst_helper ================
[13:44:50] ================== drm_exec (7 subtests) ===================
[13:44:50] [PASSED] sanitycheck
[13:44:50] [PASSED] test_lock
[13:44:50] [PASSED] test_lock_unlock
[13:44:50] [PASSED] test_duplicates
[13:44:50] [PASSED] test_prepare
[13:44:50] [PASSED] test_prepare_array
[13:44:50] [PASSED] test_multiple_loops
[13:44:50] ==================== [PASSED] drm_exec =====================
[13:44:50] =========== drm_format_helper_test (17 subtests) ===========
[13:44:50] ============== drm_test_fb_xrgb8888_to_gray8 ==============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ========== [PASSED] drm_test_fb_xrgb8888_to_gray8 ==========
[13:44:50] ============= drm_test_fb_xrgb8888_to_rgb332 ==============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb332 ==========
[13:44:50] ============= drm_test_fb_xrgb8888_to_rgb565 ==============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb565 ==========
[13:44:50] ============ drm_test_fb_xrgb8888_to_xrgb1555 =============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ======== [PASSED] drm_test_fb_xrgb8888_to_xrgb1555 =========
[13:44:50] ============ drm_test_fb_xrgb8888_to_argb1555 =============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ======== [PASSED] drm_test_fb_xrgb8888_to_argb1555 =========
[13:44:50] ============ drm_test_fb_xrgb8888_to_rgba5551 =============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ======== [PASSED] drm_test_fb_xrgb8888_to_rgba5551 =========
[13:44:50] ============= drm_test_fb_xrgb8888_to_rgb888 ==============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb888 ==========
[13:44:50] ============= drm_test_fb_xrgb8888_to_bgr888 ==============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ========= [PASSED] drm_test_fb_xrgb8888_to_bgr888 ==========
[13:44:50] ============ drm_test_fb_xrgb8888_to_argb8888 =============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ======== [PASSED] drm_test_fb_xrgb8888_to_argb8888 =========
[13:44:50] =========== drm_test_fb_xrgb8888_to_xrgb2101010 ===========
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ======= [PASSED] drm_test_fb_xrgb8888_to_xrgb2101010 =======
[13:44:50] =========== drm_test_fb_xrgb8888_to_argb2101010 ===========
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ======= [PASSED] drm_test_fb_xrgb8888_to_argb2101010 =======
[13:44:50] ============== drm_test_fb_xrgb8888_to_mono ===============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ========== [PASSED] drm_test_fb_xrgb8888_to_mono ===========
[13:44:50] ==================== drm_test_fb_swab =====================
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ================ [PASSED] drm_test_fb_swab =================
[13:44:50] ============ drm_test_fb_xrgb8888_to_xbgr8888 =============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ======== [PASSED] drm_test_fb_xrgb8888_to_xbgr8888 =========
[13:44:50] ============ drm_test_fb_xrgb8888_to_abgr8888 =============
[13:44:50] [PASSED] single_pixel_source_buffer
[13:44:50] [PASSED] single_pixel_clip_rectangle
[13:44:50] [PASSED] well_known_colors
[13:44:50] [PASSED] destination_pitch
[13:44:50] ======== [PASSED] drm_test_fb_xrgb8888_to_abgr8888 =========
[13:44:50] ================= drm_test_fb_clip_offset =================
[13:44:50] [PASSED] pass through
[13:44:50] [PASSED] horizontal offset
[13:44:50] [PASSED] vertical offset
[13:44:50] [PASSED] horizontal and vertical offset
[13:44:50] [PASSED] horizontal offset (custom pitch)
[13:44:50] [PASSED] vertical offset (custom pitch)
[13:44:50] [PASSED] horizontal and vertical offset (custom pitch)
[13:44:50] ============= [PASSED] drm_test_fb_clip_offset =============
[13:44:50] =================== drm_test_fb_memcpy ====================
[13:44:50] [PASSED] single_pixel_source_buffer: XR24 little-endian (0x34325258)
[13:44:50] [PASSED] single_pixel_source_buffer: XRA8 little-endian (0x38415258)
[13:44:50] [PASSED] single_pixel_source_buffer: YU24 little-endian (0x34325559)
[13:44:50] [PASSED] single_pixel_clip_rectangle: XB24 little-endian (0x34324258)
[13:44:50] [PASSED] single_pixel_clip_rectangle: XRA8 little-endian (0x38415258)
[13:44:50] [PASSED] single_pixel_clip_rectangle: YU24 little-endian (0x34325559)
[13:44:50] [PASSED] well_known_colors: XB24 little-endian (0x34324258)
[13:44:50] [PASSED] well_known_colors: XRA8 little-endian (0x38415258)
[13:44:50] [PASSED] well_known_colors: YU24 little-endian (0x34325559)
[13:44:50] [PASSED] destination_pitch: XB24 little-endian (0x34324258)
[13:44:50] [PASSED] destination_pitch: XRA8 little-endian (0x38415258)
[13:44:50] [PASSED] destination_pitch: YU24 little-endian (0x34325559)
[13:44:50] =============== [PASSED] drm_test_fb_memcpy ================
[13:44:50] ============= [PASSED] drm_format_helper_test ==============
[13:44:50] ================= drm_format (18 subtests) =================
[13:44:50] [PASSED] drm_test_format_block_width_invalid
[13:44:50] [PASSED] drm_test_format_block_width_one_plane
[13:44:50] [PASSED] drm_test_format_block_width_two_plane
[13:44:50] [PASSED] drm_test_format_block_width_three_plane
[13:44:50] [PASSED] drm_test_format_block_width_tiled
[13:44:50] [PASSED] drm_test_format_block_height_invalid
[13:44:50] [PASSED] drm_test_format_block_height_one_plane
[13:44:50] [PASSED] drm_test_format_block_height_two_plane
[13:44:50] [PASSED] drm_test_format_block_height_three_plane
[13:44:50] [PASSED] drm_test_format_block_height_tiled
[13:44:50] [PASSED] drm_test_format_min_pitch_invalid
[13:44:50] [PASSED] drm_test_format_min_pitch_one_plane_8bpp
[13:44:50] [PASSED] drm_test_format_min_pitch_one_plane_16bpp
[13:44:50] [PASSED] drm_test_format_min_pitch_one_plane_24bpp
[13:44:50] [PASSED] drm_test_format_min_pitch_one_plane_32bpp
[13:44:50] [PASSED] drm_test_format_min_pitch_two_plane
[13:44:50] [PASSED] drm_test_format_min_pitch_three_plane_8bpp
[13:44:50] [PASSED] drm_test_format_min_pitch_tiled
[13:44:50] =================== [PASSED] drm_format ====================
[13:44:50] ============== drm_framebuffer (10 subtests) ===============
[13:44:50] ========== drm_test_framebuffer_check_src_coords ==========
[13:44:50] [PASSED] Success: source fits into fb
[13:44:50] [PASSED] Fail: overflowing fb with x-axis coordinate
[13:44:50] [PASSED] Fail: overflowing fb with y-axis coordinate
[13:44:50] [PASSED] Fail: overflowing fb with source width
[13:44:50] [PASSED] Fail: overflowing fb with source height
[13:44:50] ====== [PASSED] drm_test_framebuffer_check_src_coords ======
[13:44:50] [PASSED] drm_test_framebuffer_cleanup
[13:44:50] =============== drm_test_framebuffer_create ===============
[13:44:50] [PASSED] ABGR8888 normal sizes
[13:44:50] [PASSED] ABGR8888 max sizes
[13:44:50] [PASSED] ABGR8888 pitch greater than min required
[13:44:50] [PASSED] ABGR8888 pitch less than min required
[13:44:50] [PASSED] ABGR8888 Invalid width
[13:44:50] [PASSED] ABGR8888 Invalid buffer handle
[13:44:50] [PASSED] No pixel format
[13:44:50] [PASSED] ABGR8888 Width 0
[13:44:50] [PASSED] ABGR8888 Height 0
[13:44:50] [PASSED] ABGR8888 Out of bound height * pitch combination
[13:44:50] [PASSED] ABGR8888 Large buffer offset
[13:44:50] [PASSED] ABGR8888 Buffer offset for inexistent plane
[13:44:50] [PASSED] ABGR8888 Invalid flag
[13:44:50] [PASSED] ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers
[13:44:50] [PASSED] ABGR8888 Valid buffer modifier
[13:44:50] [PASSED] ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
[13:44:50] [PASSED] ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS
[13:44:50] [PASSED] ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS
[13:44:50] [PASSED] NV12 Normal sizes
[13:44:50] [PASSED] NV12 Max sizes
[13:44:50] [PASSED] NV12 Invalid pitch
[13:44:50] [PASSED] NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag
[13:44:50] [PASSED] NV12 different modifier per-plane
[13:44:50] [PASSED] NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
[13:44:50] [PASSED] NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS
[13:44:50] [PASSED] NV12 Modifier for inexistent plane
[13:44:50] [PASSED] NV12 Handle for inexistent plane
[13:44:50] [PASSED] NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS
[13:44:50] [PASSED] YVU420 DRM_MODE_FB_MODIFIERS set without modifier
[13:44:50] [PASSED] YVU420 Normal sizes
[13:44:50] [PASSED] YVU420 Max sizes
[13:44:50] [PASSED] YVU420 Invalid pitch
[13:44:50] [PASSED] YVU420 Different pitches
[13:44:50] [PASSED] YVU420 Different buffer offsets/pitches
[13:44:50] [PASSED] YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS
[13:44:50] [PASSED] YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS
[13:44:50] [PASSED] YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS
[13:44:50] [PASSED] YVU420 Valid modifier
[13:44:50] [PASSED] YVU420 Different modifiers per plane
[13:44:50] [PASSED] YVU420 Modifier for inexistent plane
[13:44:50] [PASSED] YUV420_10BIT Invalid modifier(DRM_FORMAT_MOD_LINEAR)
[13:44:50] [PASSED] X0L2 Normal sizes
[13:44:50] [PASSED] X0L2 Max sizes
[13:44:50] [PASSED] X0L2 Invalid pitch
[13:44:50] [PASSED] X0L2 Pitch greater than minimum required
[13:44:50] [PASSED] X0L2 Handle for inexistent plane
[13:44:50] [PASSED] X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set
[13:44:50] [PASSED] X0L2 Modifier without DRM_MODE_FB_MODIFIERS set
[13:44:50] [PASSED] X0L2 Valid modifier
[13:44:50] [PASSED] X0L2 Modifier for inexistent plane
[13:44:50] =========== [PASSED] drm_test_framebuffer_create ===========
[13:44:50] [PASSED] drm_test_framebuffer_free
[13:44:50] [PASSED] drm_test_framebuffer_init
[13:44:50] [PASSED] drm_test_framebuffer_init_bad_format
[13:44:50] [PASSED] drm_test_framebuffer_init_dev_mismatch
[13:44:50] [PASSED] drm_test_framebuffer_lookup
[13:44:50] [PASSED] drm_test_framebuffer_lookup_inexistent
[13:44:50] [PASSED] drm_test_framebuffer_modifiers_not_supported
[13:44:50] ================= [PASSED] drm_framebuffer =================
[13:44:50] ================ drm_gem_shmem (8 subtests) ================
[13:44:50] [PASSED] drm_gem_shmem_test_obj_create
[13:44:50] [PASSED] drm_gem_shmem_test_obj_create_private
[13:44:50] [PASSED] drm_gem_shmem_test_pin_pages
[13:44:50] [PASSED] drm_gem_shmem_test_vmap
[13:44:50] [PASSED] drm_gem_shmem_test_get_sg_table
[13:44:50] [PASSED] drm_gem_shmem_test_get_pages_sgt
[13:44:50] [PASSED] drm_gem_shmem_test_madvise
[13:44:50] [PASSED] drm_gem_shmem_test_purge
[13:44:50] ================== [PASSED] drm_gem_shmem ==================
[13:44:50] === drm_atomic_helper_connector_hdmi_check (29 subtests) ===
[13:44:50] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode
[13:44:50] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode_vic_1
[13:44:50] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode
[13:44:50] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode_vic_1
[13:44:50] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode
[13:44:50] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode_vic_1
[13:44:50] ====== drm_test_check_broadcast_rgb_cea_mode_yuv420 =======
[13:44:50] [PASSED] Automatic
[13:44:50] [PASSED] Full
[13:44:50] [PASSED] Limited 16:235
[13:44:50] == [PASSED] drm_test_check_broadcast_rgb_cea_mode_yuv420 ===
[13:44:50] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_changed
[13:44:50] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_not_changed
[13:44:50] [PASSED] drm_test_check_disable_connector
[13:44:50] [PASSED] drm_test_check_hdmi_funcs_reject_rate
[13:44:50] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_rgb
[13:44:50] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_yuv420
[13:44:50] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422
[13:44:50] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420
[13:44:50] [PASSED] drm_test_check_driver_unsupported_fallback_yuv420
[13:44:50] [PASSED] drm_test_check_output_bpc_crtc_mode_changed
[13:44:50] [PASSED] drm_test_check_output_bpc_crtc_mode_not_changed
[13:44:50] [PASSED] drm_test_check_output_bpc_dvi
[13:44:50] [PASSED] drm_test_check_output_bpc_format_vic_1
[13:44:50] [PASSED] drm_test_check_output_bpc_format_display_8bpc_only
[13:44:50] [PASSED] drm_test_check_output_bpc_format_display_rgb_only
[13:44:50] [PASSED] drm_test_check_output_bpc_format_driver_8bpc_only
[13:44:50] [PASSED] drm_test_check_output_bpc_format_driver_rgb_only
[13:44:50] [PASSED] drm_test_check_tmds_char_rate_rgb_8bpc
[13:44:50] [PASSED] drm_test_check_tmds_char_rate_rgb_10bpc
[13:44:50] [PASSED] drm_test_check_tmds_char_rate_rgb_12bpc
[13:44:50] ============ drm_test_check_hdmi_color_format =============
[13:44:50] [PASSED] AUTO -> RGB
[13:44:50] [PASSED] YCBCR422 -> YUV422
[13:44:50] [PASSED] YCBCR420 -> YUV420
[13:44:50] [PASSED] YCBCR444 -> YUV444
[13:44:50] [PASSED] RGB -> RGB
[13:44:50] ======== [PASSED] drm_test_check_hdmi_color_format =========
[13:44:50] ======== drm_test_check_hdmi_color_format_420_only ========
[13:44:50] [PASSED] RGB should fail
[13:44:50] [PASSED] YUV444 should fail
[13:44:50] [PASSED] YUV422 should fail
[13:44:50] [PASSED] YUV420 should work
[13:44:50] ==== [PASSED] drm_test_check_hdmi_color_format_420_only ====
[13:44:50] ===== [PASSED] drm_atomic_helper_connector_hdmi_check ======
[13:44:50] === drm_atomic_helper_connector_hdmi_reset (6 subtests) ====
[13:44:50] [PASSED] drm_test_check_broadcast_rgb_value
[13:44:50] [PASSED] drm_test_check_bpc_8_value
[13:44:50] [PASSED] drm_test_check_bpc_10_value
[13:44:50] [PASSED] drm_test_check_bpc_12_value
[13:44:50] [PASSED] drm_test_check_format_value
[13:44:50] [PASSED] drm_test_check_tmds_char_value
[13:44:50] ===== [PASSED] drm_atomic_helper_connector_hdmi_reset ======
[13:44:50] = drm_atomic_helper_connector_hdmi_mode_valid (7 subtests) =
[13:44:50] [PASSED] drm_test_check_mode_valid
[13:44:50] [PASSED] drm_test_check_mode_valid_reject
[13:44:50] [PASSED] drm_test_check_mode_valid_reject_rate
[13:44:50] [PASSED] drm_test_check_mode_valid_reject_max_clock
[13:44:50] [PASSED] drm_test_check_mode_valid_yuv420_only_max_clock
[13:44:50] [PASSED] drm_test_check_mode_valid_reject_yuv420_only_connector
[13:44:50] [PASSED] drm_test_check_mode_valid_accept_yuv420_also_connector_rgb
[13:44:50] === [PASSED] drm_atomic_helper_connector_hdmi_mode_valid ===
[13:44:50] = drm_atomic_helper_connector_hdmi_infoframes (5 subtests) =
[13:44:50] [PASSED] drm_test_check_infoframes
[13:44:50] [PASSED] drm_test_check_reject_avi_infoframe
[13:44:50] [PASSED] drm_test_check_reject_hdr_infoframe_bpc_8
[13:44:50] [PASSED] drm_test_check_reject_hdr_infoframe_bpc_10
[13:44:50] [PASSED] drm_test_check_reject_audio_infoframe
[13:44:50] === [PASSED] drm_atomic_helper_connector_hdmi_infoframes ===
[13:44:50] ================= drm_managed (2 subtests) =================
[13:44:50] [PASSED] drm_test_managed_release_action
[13:44:50] [PASSED] drm_test_managed_run_action
[13:44:50] =================== [PASSED] drm_managed ===================
[13:44:50] =================== drm_mm (6 subtests) ====================
[13:44:50] [PASSED] drm_test_mm_init
[13:44:50] [PASSED] drm_test_mm_debug
[13:44:50] [PASSED] drm_test_mm_align32
[13:44:50] [PASSED] drm_test_mm_align64
[13:44:50] [PASSED] drm_test_mm_lowest
[13:44:50] [PASSED] drm_test_mm_highest
[13:44:50] ===================== [PASSED] drm_mm ======================
[13:44:50] ============= drm_modes_analog_tv (5 subtests) =============
[13:44:50] [PASSED] drm_test_modes_analog_tv_mono_576i
[13:44:50] [PASSED] drm_test_modes_analog_tv_ntsc_480i
[13:44:50] [PASSED] drm_test_modes_analog_tv_ntsc_480i_inlined
[13:44:50] [PASSED] drm_test_modes_analog_tv_pal_576i
[13:44:50] [PASSED] drm_test_modes_analog_tv_pal_576i_inlined
[13:44:50] =============== [PASSED] drm_modes_analog_tv ===============
[13:44:50] ============== drm_panic_helper (3 subtests) ===============
[13:44:50] ============= drm_test_panic_screen_user_map ==============
[13:44:50] [PASSED] Panic screen user, mode: 1024 x 768 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen user, mode: 494 x 494 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen user, mode: 1920 x 1080 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen user, mode: 1024 x 768 RG16 little-endian (0x36314752)
[13:44:50] [PASSED] Panic screen user, mode: 1024 x 768 RG24 little-endian (0x34324752)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1024 x 768 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen kmsg, mode: 494 x 494 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1920 x 1080 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1024 x 768 RG16 little-endian (0x36314752)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1024 x 768 RG24 little-endian (0x34324752)
[13:44:50] ========= [PASSED] drm_test_panic_screen_user_map ==========
[13:44:50] ============= drm_test_panic_screen_user_page =============
[13:44:50] [PASSED] Panic screen user, mode: 1024 x 768 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen user, mode: 494 x 494 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen user, mode: 1920 x 1080 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen user, mode: 1024 x 768 RG16 little-endian (0x36314752)
[13:44:50] [PASSED] Panic screen user, mode: 1024 x 768 RG24 little-endian (0x34324752)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1024 x 768 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen kmsg, mode: 494 x 494 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1920 x 1080 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1024 x 768 RG16 little-endian (0x36314752)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1024 x 768 RG24 little-endian (0x34324752)
[13:44:50] ========= [PASSED] drm_test_panic_screen_user_page =========
[13:44:50] ========== drm_test_panic_screen_user_set_pixel ===========
[13:44:50] [PASSED] Panic screen user, mode: 1024 x 768 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen user, mode: 494 x 494 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen user, mode: 1920 x 1080 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen user, mode: 1024 x 768 RG16 little-endian (0x36314752)
[13:44:50] [PASSED] Panic screen user, mode: 1024 x 768 RG24 little-endian (0x34324752)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1024 x 768 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen kmsg, mode: 494 x 494 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1920 x 1080 XR24 little-endian (0x34325258)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1024 x 768 RG16 little-endian (0x36314752)
[13:44:50] [PASSED] Panic screen kmsg, mode: 1024 x 768 RG24 little-endian (0x34324752)
[13:44:50] ====== [PASSED] drm_test_panic_screen_user_set_pixel =======
[13:44:50] ================ [PASSED] drm_panic_helper =================
[13:44:50] ============== drm_plane_helper (2 subtests) ===============
[13:44:50] =============== drm_test_check_plane_state ================
[13:44:50] [PASSED] clipping_simple
[13:44:50] [PASSED] clipping_rotate_reflect
[13:44:50] [PASSED] positioning_simple
[13:44:50] [PASSED] upscaling
[13:44:50] [PASSED] downscaling
[13:44:50] [PASSED] rounding1
[13:44:50] [PASSED] rounding2
[13:44:50] [PASSED] rounding3
[13:44:50] [PASSED] rounding4
[13:44:50] =========== [PASSED] drm_test_check_plane_state ============
[13:44:50] =========== drm_test_check_invalid_plane_state ============
[13:44:50] [PASSED] positioning_invalid
[13:44:50] [PASSED] upscaling_invalid
[13:44:50] [PASSED] downscaling_invalid
[13:44:50] ======= [PASSED] drm_test_check_invalid_plane_state ========
[13:44:50] ================ [PASSED] drm_plane_helper =================
[13:44:50] ====== drm_connector_helper_tv_get_modes (1 subtest) =======
[13:44:50] ====== drm_test_connector_helper_tv_get_modes_check =======
[13:44:50] [PASSED] None
[13:44:50] [PASSED] PAL
[13:44:50] [PASSED] NTSC
[13:44:50] [PASSED] Both, NTSC Default
[13:44:50] [PASSED] Both, PAL Default
[13:44:50] [PASSED] Both, NTSC Default, with PAL on command-line
[13:44:50] [PASSED] Both, PAL Default, with NTSC on command-line
[13:44:50] == [PASSED] drm_test_connector_helper_tv_get_modes_check ===
[13:44:50] ======== [PASSED] drm_connector_helper_tv_get_modes ========
[13:44:50] ================== drm_rect (9 subtests) ===================
[13:44:50] [PASSED] drm_test_rect_clip_scaled_div_by_zero
[13:44:50] [PASSED] drm_test_rect_clip_scaled_not_clipped
[13:44:50] [PASSED] drm_test_rect_clip_scaled_clipped
[13:44:50] [PASSED] drm_test_rect_clip_scaled_signed_vs_unsigned
[13:44:50] ================= drm_test_rect_intersect =================
[13:44:50] [PASSED] top-left x bottom-right: 2x2+1+1 x 2x2+0+0
[13:44:50] [PASSED] top-right x bottom-left: 2x2+0+0 x 2x2+1-1
[13:44:50] [PASSED] bottom-left x top-right: 2x2+1-1 x 2x2+0+0
[13:44:50] [PASSED] bottom-right x top-left: 2x2+0+0 x 2x2+1+1
[13:44:50] [PASSED] right x left: 2x1+0+0 x 3x1+1+0
[13:44:50] [PASSED] left x right: 3x1+1+0 x 2x1+0+0
[13:44:50] [PASSED] up x bottom: 1x2+0+0 x 1x3+0-1
[13:44:50] [PASSED] bottom x up: 1x3+0-1 x 1x2+0+0
[13:44:50] [PASSED] touching corner: 1x1+0+0 x 2x2+1+1
[13:44:50] [PASSED] touching side: 1x1+0+0 x 1x1+1+0
[13:44:50] [PASSED] equal rects: 2x2+0+0 x 2x2+0+0
[13:44:50] [PASSED] inside another: 2x2+0+0 x 1x1+1+1
[13:44:50] [PASSED] far away: 1x1+0+0 x 1x1+3+6
[13:44:50] [PASSED] points intersecting: 0x0+5+10 x 0x0+5+10
[13:44:50] [PASSED] points not intersecting: 0x0+0+0 x 0x0+5+10
[13:44:50] ============= [PASSED] drm_test_rect_intersect =============
[13:44:50] ================ drm_test_rect_calc_hscale ================
[13:44:50] [PASSED] normal use
[13:44:50] [PASSED] out of max range
[13:44:50] [PASSED] out of min range
[13:44:50] [PASSED] zero dst
[13:44:50] [PASSED] negative src
[13:44:50] [PASSED] negative dst
[13:44:50] ============ [PASSED] drm_test_rect_calc_hscale ============
[13:44:50] ================ drm_test_rect_calc_vscale ================
[13:44:50] [PASSED] normal use
[13:44:50] [PASSED] out of max range
[13:44:50] [PASSED] out of min range
[13:44:50] [PASSED] zero dst
[13:44:50] [PASSED] negative src
[13:44:50] [PASSED] negative dst
[13:44:50] ============ [PASSED] drm_test_rect_calc_vscale ============
[13:44:50] ================== drm_test_rect_rotate ===================
[13:44:50] [PASSED] reflect-x
[13:44:50] [PASSED] reflect-y
[13:44:50] [PASSED] rotate-0
[13:44:50] [PASSED] rotate-90
[13:44:50] [PASSED] rotate-180
[13:44:50] [PASSED] rotate-270
[13:44:50] ============== [PASSED] drm_test_rect_rotate ===============
[13:44:50] ================ drm_test_rect_rotate_inv =================
[13:44:50] [PASSED] reflect-x
[13:44:50] [PASSED] reflect-y
[13:44:50] [PASSED] rotate-0
[13:44:50] [PASSED] rotate-90
[13:44:50] [PASSED] rotate-180
[13:44:50] [PASSED] rotate-270
[13:44:50] ============ [PASSED] drm_test_rect_rotate_inv =============
[13:44:50] ==================== [PASSED] drm_rect =====================
[13:44:50] ============ drm_sysfb_modeset_test (1 subtest) ============
[13:44:50] ============ drm_test_sysfb_build_fourcc_list =============
[13:44:50] [PASSED] no native formats
[13:44:50] [PASSED] XRGB8888 as native format
[13:44:50] [PASSED] remove duplicates
[13:44:50] [PASSED] convert alpha formats
[13:44:50] [PASSED] random formats
[13:44:50] ======== [PASSED] drm_test_sysfb_build_fourcc_list =========
[13:44:50] ============= [PASSED] drm_sysfb_modeset_test ==============
[13:44:50] ================== drm_fixp (2 subtests) ===================
[13:44:50] [PASSED] drm_test_int2fixp
[13:44:50] [PASSED] drm_test_sm2fixp
[13:44:50] ==================== [PASSED] drm_fixp =====================
[13:44:50] ============================================================
[13:44:50] Testing complete. Ran 667 tests: passed: 667
[13:44:50] Elapsed time: 27.408s total, 1.865s configuring, 25.127s building, 0.405s running
+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig
[13:44:50] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[13:44:52] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[13:45:02] Starting KUnit Kernel (1/1)...
[13:45:02] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[13:45:02] ================= ttm_device (5 subtests) ==================
[13:45:02] [PASSED] ttm_device_init_basic
[13:45:02] [PASSED] ttm_device_init_multiple
[13:45:02] [PASSED] ttm_device_fini_basic
[13:45:02] [PASSED] ttm_device_init_no_vma_man
[13:45:02] ================== ttm_device_init_pools ==================
[13:45:02] [PASSED] No DMA allocations, no DMA32 required
[13:45:02] [PASSED] DMA allocations, DMA32 required
[13:45:02] [PASSED] No DMA allocations, DMA32 required
[13:45:02] [PASSED] DMA allocations, no DMA32 required
[13:45:02] ============== [PASSED] ttm_device_init_pools ==============
[13:45:02] =================== [PASSED] ttm_device ====================
[13:45:02] ================== ttm_pool (8 subtests) ===================
[13:45:02] ================== ttm_pool_alloc_basic ===================
[13:45:02] [PASSED] One page
[13:45:02] [PASSED] More than one page
[13:45:02] [PASSED] Above the allocation limit
[13:45:02] [PASSED] One page, with coherent DMA mappings enabled
[13:45:02] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[13:45:02] ============== [PASSED] ttm_pool_alloc_basic ===============
[13:45:02] ============== ttm_pool_alloc_basic_dma_addr ==============
[13:45:02] [PASSED] One page
[13:45:02] [PASSED] More than one page
[13:45:02] [PASSED] Above the allocation limit
[13:45:02] [PASSED] One page, with coherent DMA mappings enabled
[13:45:02] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[13:45:02] ========== [PASSED] ttm_pool_alloc_basic_dma_addr ==========
[13:45:02] [PASSED] ttm_pool_alloc_order_caching_match
[13:45:02] [PASSED] ttm_pool_alloc_caching_mismatch
[13:45:02] [PASSED] ttm_pool_alloc_order_mismatch
[13:45:02] [PASSED] ttm_pool_free_dma_alloc
[13:45:02] [PASSED] ttm_pool_free_no_dma_alloc
[13:45:02] [PASSED] ttm_pool_fini_basic
[13:45:02] ==================== [PASSED] ttm_pool =====================
[13:45:02] ================ ttm_resource (8 subtests) =================
[13:45:02] ================= ttm_resource_init_basic =================
[13:45:02] [PASSED] Init resource in TTM_PL_SYSTEM
[13:45:02] [PASSED] Init resource in TTM_PL_VRAM
[13:45:02] [PASSED] Init resource in a private placement
[13:45:02] [PASSED] Init resource in TTM_PL_SYSTEM, set placement flags
[13:45:02] ============= [PASSED] ttm_resource_init_basic =============
[13:45:02] [PASSED] ttm_resource_init_pinned
[13:45:02] [PASSED] ttm_resource_fini_basic
[13:45:02] [PASSED] ttm_resource_manager_init_basic
[13:45:02] [PASSED] ttm_resource_manager_usage_basic
[13:45:02] [PASSED] ttm_resource_manager_set_used_basic
[13:45:02] [PASSED] ttm_sys_man_alloc_basic
[13:45:02] [PASSED] ttm_sys_man_free_basic
[13:45:02] ================== [PASSED] ttm_resource ===================
[13:45:02] =================== ttm_tt (15 subtests) ===================
[13:45:02] ==================== ttm_tt_init_basic ====================
[13:45:02] [PASSED] Page-aligned size
[13:45:02] [PASSED] Extra pages requested
[13:45:02] ================ [PASSED] ttm_tt_init_basic ================
[13:45:02] [PASSED] ttm_tt_init_misaligned
[13:45:02] [PASSED] ttm_tt_fini_basic
[13:45:02] [PASSED] ttm_tt_fini_sg
[13:45:02] [PASSED] ttm_tt_fini_shmem
[13:45:02] [PASSED] ttm_tt_create_basic
[13:45:02] [PASSED] ttm_tt_create_invalid_bo_type
[13:45:02] [PASSED] ttm_tt_create_ttm_exists
[13:45:02] [PASSED] ttm_tt_create_failed
[13:45:02] [PASSED] ttm_tt_destroy_basic
[13:45:02] [PASSED] ttm_tt_populate_null_ttm
[13:45:02] [PASSED] ttm_tt_populate_populated_ttm
[13:45:02] [PASSED] ttm_tt_unpopulate_basic
[13:45:02] [PASSED] ttm_tt_unpopulate_empty_ttm
[13:45:02] [PASSED] ttm_tt_swapin_basic
[13:45:02] ===================== [PASSED] ttm_tt ======================
[13:45:02] =================== ttm_bo (14 subtests) ===================
[13:45:02] =========== ttm_bo_reserve_optimistic_no_ticket ===========
[13:45:02] [PASSED] Cannot be interrupted and sleeps
[13:45:02] [PASSED] Cannot be interrupted, locks straight away
[13:45:02] [PASSED] Can be interrupted, sleeps
[13:45:02] ======= [PASSED] ttm_bo_reserve_optimistic_no_ticket =======
[13:45:02] [PASSED] ttm_bo_reserve_locked_no_sleep
[13:45:02] [PASSED] ttm_bo_reserve_no_wait_ticket
[13:45:02] [PASSED] ttm_bo_reserve_double_resv
[13:45:02] [PASSED] ttm_bo_reserve_interrupted
[13:45:02] [PASSED] ttm_bo_reserve_deadlock
[13:45:02] [PASSED] ttm_bo_unreserve_basic
[13:45:02] [PASSED] ttm_bo_unreserve_pinned
[13:45:02] [PASSED] ttm_bo_unreserve_bulk
[13:45:02] [PASSED] ttm_bo_fini_basic
[13:45:02] [PASSED] ttm_bo_fini_shared_resv
[13:45:02] [PASSED] ttm_bo_pin_basic
[13:45:02] [PASSED] ttm_bo_pin_unpin_resource
[13:45:02] [PASSED] ttm_bo_multiple_pin_one_unpin
[13:45:02] ===================== [PASSED] ttm_bo ======================
[13:45:02] ============== ttm_bo_validate (22 subtests) ===============
[13:45:02] ============== ttm_bo_init_reserved_sys_man ===============
[13:45:02] [PASSED] Buffer object for userspace
[13:45:02] [PASSED] Kernel buffer object
[13:45:02] [PASSED] Shared buffer object
[13:45:02] ========== [PASSED] ttm_bo_init_reserved_sys_man ===========
[13:45:02] ============== ttm_bo_init_reserved_mock_man ==============
[13:45:02] [PASSED] Buffer object for userspace
[13:45:02] [PASSED] Kernel buffer object
[13:45:02] [PASSED] Shared buffer object
[13:45:02] ========== [PASSED] ttm_bo_init_reserved_mock_man ==========
[13:45:02] [PASSED] ttm_bo_init_reserved_resv
[13:45:02] ================== ttm_bo_validate_basic ==================
[13:45:02] [PASSED] Buffer object for userspace
[13:45:02] [PASSED] Kernel buffer object
[13:45:02] [PASSED] Shared buffer object
[13:45:02] ============== [PASSED] ttm_bo_validate_basic ==============
[13:45:02] [PASSED] ttm_bo_validate_invalid_placement
[13:45:02] ============= ttm_bo_validate_same_placement ==============
[13:45:02] [PASSED] System manager
[13:45:02] [PASSED] VRAM manager
[13:45:02] ========= [PASSED] ttm_bo_validate_same_placement ==========
[13:45:02] [PASSED] ttm_bo_validate_failed_alloc
[13:45:02] [PASSED] ttm_bo_validate_pinned
[13:45:02] [PASSED] ttm_bo_validate_busy_placement
[13:45:02] ================ ttm_bo_validate_multihop =================
[13:45:02] [PASSED] Buffer object for userspace
[13:45:02] [PASSED] Kernel buffer object
[13:45:02] [PASSED] Shared buffer object
[13:45:02] ============ [PASSED] ttm_bo_validate_multihop =============
[13:45:02] ========== ttm_bo_validate_no_placement_signaled ==========
[13:45:02] [PASSED] Buffer object in system domain, no page vector
[13:45:02] [PASSED] Buffer object in system domain with an existing page vector
[13:45:02] ====== [PASSED] ttm_bo_validate_no_placement_signaled ======
[13:45:02] ======== ttm_bo_validate_no_placement_not_signaled ========
[13:45:02] [PASSED] Buffer object for userspace
[13:45:02] [PASSED] Kernel buffer object
[13:45:02] [PASSED] Shared buffer object
[13:45:02] ==== [PASSED] ttm_bo_validate_no_placement_not_signaled ====
[13:45:02] [PASSED] ttm_bo_validate_move_fence_signaled
[13:45:02] ========= ttm_bo_validate_move_fence_not_signaled =========
[13:45:02] [PASSED] Waits for GPU
[13:45:02] [PASSED] Tries to lock straight away
[13:45:02] ===== [PASSED] ttm_bo_validate_move_fence_not_signaled =====
[13:45:02] [PASSED] ttm_bo_validate_swapout
[13:45:02] [PASSED] ttm_bo_validate_happy_evict
[13:45:02] [PASSED] ttm_bo_validate_all_pinned_evict
[13:45:02] [PASSED] ttm_bo_validate_allowed_only_evict
[13:45:02] [PASSED] ttm_bo_validate_deleted_evict
[13:45:02] [PASSED] ttm_bo_validate_busy_domain_evict
[13:45:02] [PASSED] ttm_bo_validate_evict_gutting
[13:45:02] [PASSED] ttm_bo_validate_recrusive_evict
[13:45:02] ================= [PASSED] ttm_bo_validate =================
[13:45:02] ============================================================
[13:45:02] Testing complete. Ran 102 tests: passed: 102
[13:45:02] Elapsed time: 12.316s total, 1.851s configuring, 10.200s building, 0.226s running
+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/dma-buf/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/dma-buf/.kunitconfig
[13:45:02] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[13:45:04] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[13:45:13] Starting KUnit Kernel (1/1)...
[13:45:13] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[13:45:13] =============== dma-buf-fence (12 subtests) ================
[13:45:13] [PASSED] test_sanitycheck
[13:45:13] [PASSED] test_signaling
[13:45:13] [PASSED] test_add_callback
[13:45:13] [PASSED] test_late_add_callback
[13:45:13] [PASSED] test_rm_callback
[13:45:13] [PASSED] test_late_rm_callback
[13:45:13] [PASSED] test_status
[13:45:13] [PASSED] test_error
[13:45:13] [PASSED] test_wait
[13:45:13] [PASSED] test_wait_timeout
[13:45:13] [PASSED] test_stub
[13:45:13] [SKIPPED] test_race_signal_callback (requires at least 2 CPUs)
[13:45:13] ================== [PASSED] dma-buf-fence ==================
[13:45:13] ============ dma-buf-fence-chain (11 subtests) =============
[13:45:13] [PASSED] test_sanitycheck
[13:45:13] [PASSED] test_find_seqno
[13:45:13] [PASSED] test_find_signaled
[13:45:13] [PASSED] test_find_out_of_order
[13:45:18] [PASSED] test_find_gap
[13:45:18] [PASSED] test_find_race
[13:45:18] [PASSED] test_signal_forward
[13:45:18] [PASSED] test_signal_backward
[13:45:18] [PASSED] test_wait_forward
[13:45:18] [PASSED] test_wait_backward
[13:45:18] [PASSED] test_wait_random
[13:45:18] =============== [PASSED] dma-buf-fence-chain ===============
[13:45:18] ============ dma-buf-fence-unwrap (11 subtests) ============
[13:45:18] [PASSED] test_sanitycheck
[13:45:18] [PASSED] test_unwrap_array
[13:45:18] [PASSED] test_unwrap_chain
[13:45:18] [PASSED] test_unwrap_chain_array
[13:45:18] [PASSED] test_unwrap_merge
[13:45:18] [PASSED] test_unwrap_merge_duplicate
[13:45:18] [PASSED] test_unwrap_merge_seqno
[13:45:18] [PASSED] test_unwrap_merge_order
[13:45:18] [PASSED] test_unwrap_merge_complex
[13:45:18] [PASSED] test_unwrap_merge_complex_seqno
[13:45:18] [PASSED] test_dedup_empty
[13:45:18] ============== [PASSED] dma-buf-fence-unwrap ===============
[13:45:18] ================ dma-buf-resv (5 subtests) =================
[13:45:18] [PASSED] test_sanitycheck
[13:45:18] ===================== test_signaling ======================
[13:45:18] [PASSED] kernel
[13:45:18] [PASSED] write
[13:45:18] [PASSED] read
[13:45:18] [PASSED] bookkeep
[13:45:18] ================= [PASSED] test_signaling ==================
[13:45:18] ====================== test_for_each ======================
[13:45:18] [PASSED] kernel
[13:45:18] [PASSED] write
[13:45:18] [PASSED] read
[13:45:18] [PASSED] bookkeep
[13:45:18] ================== [PASSED] test_for_each ==================
[13:45:18] ================= test_for_each_unlocked ==================
[13:45:18] [PASSED] kernel
[13:45:18] [PASSED] write
[13:45:18] [PASSED] read
[13:45:18] [PASSED] bookkeep
[13:45:18] ============= [PASSED] test_for_each_unlocked ==============
[13:45:18] ===================== test_get_fences =====================
[13:45:18] [PASSED] kernel
[13:45:18] [PASSED] write
[13:45:18] [PASSED] read
[13:45:18] [PASSED] bookkeep
[13:45:18] ================= [PASSED] test_get_fences =================
[13:45:18] ================== [PASSED] dma-buf-resv ===================
[13:45:18] ============================================================
[13:45:18] Testing complete. Ran 51 tests: passed: 50, skipped: 1
[13:45:18] Elapsed time: 15.857s total, 1.893s configuring, 8.692s building, 5.266s running
+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers
2026-10-16 13:35 ` [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers Thomas Hellström
@ 2026-10-16 13:53 ` sashiko-bot
2026-10-16 14:09 ` Thomas Hellström
2026-10-16 18:16 ` Matthew Brost
1 sibling, 1 reply; 18+ messages in thread
From: sashiko-bot @ 2026-10-16 13:53 UTC (permalink / raw)
To: Thomas Hellström, intel-xe
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] drm/xe: Use-After-Free of shrinker during DRM device teardown
- [High] drm/xe: O(N^2) CPU lockup in purgeable shrinker due to uncounted LRU skips
--
commit 1e9348c2fe4768de2cf24e4dd9b6188400c84043
Author: Thomas Hellström <thomas.hellstrom@linux.intel.com>
drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers
This commit splits the single xe_shrinker into two independent shrinker
instances: one for purgeable objects and another for non-purgeable
(shrinkable) objects. This allows the shrinker core to apply different
reclaim pressures based on the varying costs of reclaiming these object
types.
> diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
> index 378022c37a57c..8e3fe675e0f34 100644
> --- a/drivers/gpu/drm/xe/xe_shrinker.c
> +++ b/drivers/gpu/drm/xe/xe_shrinker.c
[ ... ]
> @@ -216,63 +238,52 @@ static bool xe_shrinker_runtime_pm_get(struct xe_shrinker *shrinker, bool force,
[ ... ]
> -static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
> +static unsigned long xe_shrinker_scan_purgeable(struct shrinker *shrink,
> + struct shrink_control *sc)
> {
> struct xe_shrinker *shrinker = to_xe_shrinker(shrink);
> struct ttm_operation_ctx ctx = {
> .interruptible = false,
> .no_wait_gpu = ttm_bo_shrink_avoid_wait(),
> };
> - unsigned long nr_to_scan, nr_scanned = 0, freed = 0;
> + unsigned long nr_to_scan = sc->nr_to_scan, nr_scanned = 0, freed = 0;
> struct xe_bo_shrink_flags shrink_flags = {
> .purge = true,
> - /* Don't request writeback without __GFP_IO. */
> - .writeback = !ctx.no_wait_gpu && (sc->gfp_mask & __GFP_IO),
> };
> - bool runtime_pm;
> - bool purgeable;
> - bool can_backup = !!(sc->gfp_mask & __GFP_FS);
> -
> - nr_to_scan = sc->nr_to_scan;
> -
> - read_lock(&shrinker->lock);
> - purgeable = !!shrinker->purgeable_pages;
> - read_unlock(&shrinker->lock);
>
> - /* Might need runtime PM. Try to wake early if it looks like it. */
> - runtime_pm = xe_shrinker_runtime_pm_get(shrinker, false, nr_to_scan, can_backup);
> -
> - if (purgeable && nr_scanned < nr_to_scan)
> - xe_shrinker_walk(shrinker, &ctx, shrink_flags,
> - nr_to_scan, &nr_scanned, &freed);
> + xe_shrinker_walk(shrinker, &ctx, shrink_flags, nr_to_scan, &nr_scanned, &freed);
>
> sc->nr_scanned = nr_scanned;
[Severity: High]
Can this cause an O(N^2) CPU lockup in the purgeable shrinker?
When the memory reclaim core (do_shrink_slab) calls this purgeable scan
routine under memory pressure, xe_shrinker_walk() iterates the LRU list.
However, non-purgeable BOs return -EBUSY and are skipped without advancing
the scanned counter:
drivers/gpu/drm/xe/xe_bo.c:xe_bo_shrink() {
...
if (!(tt->page_flags & TTM_TT_FLAG_EXTERNAL_MAPPABLE) ||
(flags.purge && !xe_tt->purgeable))
return -EBUSY;
...
}
drivers/gpu/drm/xe/xe_shrinker.c:__xe_shrinker_walk() {
...
lret = xe_bo_shrink(ctx, ttm_bo, flags, scanned);
/* Like the TTM LRU walk, skip bos we can't shrink now. */
if (lret == -EBUSY)
continue;
...
}
Since the LRU cursor is initialized locally on each call and non-purgeable
BOs do not increment nr_scanned, every batch rescans all leading
non-purgeable BOs without significantly advancing sc->nr_scanned.
Will this force the shrinker core to repeatedly call this function,
processing the same leading non-purgeable BOs over and over again?
> - if (nr_scanned >= nr_to_scan || !can_backup)
> - goto out;
>
> - /* If we didn't wake before, try to do it now if needed. */
> - if (!runtime_pm)
> - runtime_pm = xe_shrinker_runtime_pm_get(shrinker, true, 0, can_backup);
> + return nr_scanned ? freed : SHRINK_STOP;
> +}
[ ... ]
> @@ -294,6 +305,7 @@ static void xe_shrinker_fini(struct drm_device *drm, void *arg)
> xe_assert(shrinker->xe, !shrinker->purgeable_pages);
> xe_assert(shrinker->xe, !shrinker->populated_tts);
> shrinker_free(shrinker->shrink);
> + shrinker_free(shrinker->purge_shrink);
> flush_work(&shrinker->pm_worker);
> kfree(shrinker);
> }
[Severity: High]
Does this kfree(shrinker) leave xe->mem.shrinker as a dangling pointer?
Because drmm actions execute in LIFO order upon device release,
xe_shrinker_fini() is called before xe_device_destroy().
Later, xe_device_destroy() runs and calls xe_bo_dev_fini() which flushes
the async_free workqueue. Pending BOs in the workqueue will have their
final references dropped, leading to xe_ttm_tt_account_subtract():
drivers/gpu/drm/xe/xe_bo.c:xe_ttm_tt_account_subtract() {
...
if (xe_tt->purgeable)
xe_shrinker_mod_pages(xe->mem.shrinker, 0, -(long)tt->num_pages, -1);
else
xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages, 0, -1);
...
}
Can this lead to a use-after-free and memory corruption when driver unloads?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016133523.3622-1-thomas.hellstrom@linux.intel.com?part=3
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 1/4] drm/xe: Don't abort the shrinker walk on -EBUSY
2026-10-16 13:35 ` [PATCH v4 1/4] drm/xe: Don't abort the shrinker walk on -EBUSY Thomas Hellström
2026-10-16 13:44 ` sashiko-bot
@ 2026-10-16 13:55 ` Matthew Brost
1 sibling, 0 replies; 18+ messages in thread
From: Matthew Brost @ 2026-10-16 13:55 UTC (permalink / raw)
To: Thomas Hellström
Cc: intel-xe, Christian König, Rodrigo Vivi, stable,
Matthew Auld, Maarten Lankhorst
On Fri, Oct 16, 2026 at 03:35:20PM +0200, Thomas Hellström wrote:
> xe_bo_shrink() returns -EBUSY for bos that can't currently be shrunk,
> for example imported dma-bufs, bos whose vm is currently validating,
> bos that are still busy after the wait timeout, or bos whose backup
> fails. The shrinker LRU walk treats any negative return value as
> fatal and aborts, which also skips the remaining shrinker passes.
>
> As a result, a single such bo, like an imported dma-buf on the
> XE_PL_TT LRU, prevents reclaim of all bos behind it on the LRU.
>
> Skip bos for which xe_bo_shrink() returns -EBUSY and continue the
> walk, like the TTM LRU walk does.
>
> v4:
> - Patch introduced.
>
> Fixes: 00c8efc3180f ("drm/xe: Add a shrinker for xe bos")
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
I noticed this on as well.
Reviewed-by: Matthew Brost <matthew.brost@intel.com>`
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: intel-xe@lists.freedesktop.org
> Cc: <stable@vger.kernel.org> # v6.15+
> Assisted-by: LLM
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
> drivers/gpu/drm/xe/xe_shrinker.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
> index deb4378c1ec1..4e4da76936f4 100644
> --- a/drivers/gpu/drm/xe/xe_shrinker.c
> +++ b/drivers/gpu/drm/xe/xe_shrinker.c
> @@ -113,6 +113,9 @@ static int __xe_shrinker_walk(struct xe_shrinker *shrinker,
> continue;
>
> lret = xe_bo_shrink(ctx, ttm_bo, flags, scanned);
> + /* Like the TTM LRU walk, skip bos we can't shrink now. */
> + if (lret == -EBUSY)
> + continue;
> if (lret < 0) {
> ret = lret;
> goto out;
> --
> 2.56.0
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size
2026-10-16 13:45 ` sashiko-bot
@ 2026-10-16 14:06 ` Thomas Hellström
2026-10-16 18:42 ` Matthew Brost
0 siblings, 1 reply; 18+ messages in thread
From: Thomas Hellström @ 2026-10-16 14:06 UTC (permalink / raw)
To: sashiko-reviews, intel-xe
On Fri, 2026-10-16 at 13:45 +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider:
> - [Medium] drm/xe: shrinker count callback serializes direct reclaim
> via write_lock
> --
>
> commit a78bd8842e67f957a2ced6d827e1c4a6430ff29b
> Author: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> drm/xe: Update non-purgeable shrinker batch size based on average BO
> size
>
> This commit updates the preferred vmscan batch size for the non-
> purgeable
> shrinker based on the average buffer object size. It introduces an
> exponential moving average that is updated during the shrinker count
> phase.
>
> > diff --git a/drivers/gpu/drm/xe/xe_shrinker.c
> > b/drivers/gpu/drm/xe/xe_shrinker.c
> > index 8e3fe675e0f34..955908b3bdf3e 100644
> > --- a/drivers/gpu/drm/xe/xe_shrinker.c
> > +++ b/drivers/gpu/drm/xe/xe_shrinker.c
> [ ... ]
> > @@ -210,15 +235,26 @@ xe_shrinker_count(struct shrinker *shrink,
> > struct shrink_control *sc)
> > unsigned long num_pages;
> > bool can_backup = !!(sc->gfp_mask & __GFP_FS);
> >
> > + if (!can_backup)
> > + return SHRINK_EMPTY;
> > +
> > num_pages = ttm_backup_bytes_avail() >> PAGE_SHIFT;
> > - read_lock(&shrinker->lock);
> > + /* Consistently use write_lock() for simplicity. */
> > + write_lock(&shrinker->lock);
>
> [Severity: Medium]
> Will this exclusive write lock create a system-wide performance
> bottleneck
> during memory reclaim?
>
> The core mm subsystem frequently calls the shrinker's count_objects
> callback
> (xe_shrinker_count) from do_shrink_slab() during direct reclaim. This
> occurs
> concurrently across multiple allocating tasks and CPUs when under
> memory
> pressure.
>
> By changing read_lock() to write_lock() to update the batch_avg
> heuristic,
> this forces all concurrent direct reclaimers system-wide to serialize
> on this
> single lock, which could lead to severe lock contention and
> performance
> degradation.
This is grossly overstated. False positive.
/Thomas
>
> >
> > - if (can_backup)
> > - num_pages = min_t(unsigned long, num_pages,
> > shrinker->shrinkable_pages);
> > - else
> > - num_pages = 0;
> > + num_pages = min_t(unsigned long, num_pages, shrinker-
> > >shrinkable_pages);
> >
> > - read_unlock(&shrinker->lock);
> > + if (shrinker->populated_tts) {
> > + unsigned long avg = 2 * (shrinker-
> > >shrinkable_pages +
> > + shrinker-
> > >purgeable_pages) /
> > + shrinker->populated_tts;
> > +
> > + shrinker->batch_avg = max((shrinker->batch_avg +
> > (long)avg) >> 1,
> > + 128L /* default
> > SHRINK_BATCH */);
> > + WRITE_ONCE(shrink->batch, shrinker->batch_avg);
> > + }
> > +
> > + write_unlock(&shrinker->lock);
> >
> > return num_pages ? num_pages : SHRINK_EMPTY;
> > }
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers
2026-10-16 13:53 ` sashiko-bot
@ 2026-10-16 14:09 ` Thomas Hellström
2026-10-16 18:41 ` Matthew Brost
0 siblings, 1 reply; 18+ messages in thread
From: Thomas Hellström @ 2026-10-16 14:09 UTC (permalink / raw)
To: sashiko-reviews, intel-xe
On Fri, 2026-10-16 at 13:53 +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential
> issue(s) to consider:
> - [High] drm/xe: Use-After-Free of shrinker during DRM device
> teardown
> - [High] drm/xe: O(N^2) CPU lockup in purgeable shrinker due to
> uncounted LRU skips
> --
>
> commit 1e9348c2fe4768de2cf24e4dd9b6188400c84043
> Author: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>
> drm/xe: Split the bo shrinker into purgeable and non-purgeable
> shrinkers
>
> This commit splits the single xe_shrinker into two independent
> shrinker
> instances: one for purgeable objects and another for non-purgeable
> (shrinkable) objects. This allows the shrinker core to apply
> different
> reclaim pressures based on the varying costs of reclaiming these
> object
> types.
>
> > diff --git a/drivers/gpu/drm/xe/xe_shrinker.c
> > b/drivers/gpu/drm/xe/xe_shrinker.c
> > index 378022c37a57c..8e3fe675e0f34 100644
> > --- a/drivers/gpu/drm/xe/xe_shrinker.c
> > +++ b/drivers/gpu/drm/xe/xe_shrinker.c
>
> [ ... ]
>
> > @@ -216,63 +238,52 @@ static bool xe_shrinker_runtime_pm_get(struct
> > xe_shrinker *shrinker, bool force,
>
> [ ... ]
>
> > -static unsigned long xe_shrinker_scan(struct shrinker *shrink,
> > struct shrink_control *sc)
> > +static unsigned long xe_shrinker_scan_purgeable(struct shrinker
> > *shrink,
> > + struct
> > shrink_control *sc)
> > {
> > struct xe_shrinker *shrinker = to_xe_shrinker(shrink);
> > struct ttm_operation_ctx ctx = {
> > .interruptible = false,
> > .no_wait_gpu = ttm_bo_shrink_avoid_wait(),
> > };
> > - unsigned long nr_to_scan, nr_scanned = 0, freed = 0;
> > + unsigned long nr_to_scan = sc->nr_to_scan, nr_scanned = 0,
> > freed = 0;
> > struct xe_bo_shrink_flags shrink_flags = {
> > .purge = true,
> > - /* Don't request writeback without __GFP_IO. */
> > - .writeback = !ctx.no_wait_gpu && (sc->gfp_mask &
> > __GFP_IO),
> > };
> > - bool runtime_pm;
> > - bool purgeable;
> > - bool can_backup = !!(sc->gfp_mask & __GFP_FS);
> > -
> > - nr_to_scan = sc->nr_to_scan;
> > -
> > - read_lock(&shrinker->lock);
> > - purgeable = !!shrinker->purgeable_pages;
> > - read_unlock(&shrinker->lock);
> >
> > - /* Might need runtime PM. Try to wake early if it looks
> > like it. */
> > - runtime_pm = xe_shrinker_runtime_pm_get(shrinker, false,
> > nr_to_scan, can_backup);
> > -
> > - if (purgeable && nr_scanned < nr_to_scan)
> > - xe_shrinker_walk(shrinker, &ctx, shrink_flags,
> > - nr_to_scan, &nr_scanned, &freed);
> > + xe_shrinker_walk(shrinker, &ctx, shrink_flags, nr_to_scan,
> > &nr_scanned, &freed);
> >
> > sc->nr_scanned = nr_scanned;
>
> [Severity: High]
> Can this cause an O(N^2) CPU lockup in the purgeable shrinker?
>
> When the memory reclaim core (do_shrink_slab) calls this purgeable
> scan
> routine under memory pressure, xe_shrinker_walk() iterates the LRU
> list.
>
> However, non-purgeable BOs return -EBUSY and are skipped without
> advancing
> the scanned counter:
>
> drivers/gpu/drm/xe/xe_bo.c:xe_bo_shrink() {
> ...
> if (!(tt->page_flags & TTM_TT_FLAG_EXTERNAL_MAPPABLE) ||
> (flags.purge && !xe_tt->purgeable))
> return -EBUSY;
> ...
> }
>
> drivers/gpu/drm/xe/xe_shrinker.c:__xe_shrinker_walk() {
> ...
> lret = xe_bo_shrink(ctx, ttm_bo, flags, scanned);
> /* Like the TTM LRU walk, skip bos we can't shrink now.
> */
> if (lret == -EBUSY)
> continue;
> ...
> }
>
> Since the LRU cursor is initialized locally on each call and non-
> purgeable
> BOs do not increment nr_scanned, every batch rescans all leading
> non-purgeable BOs without significantly advancing sc->nr_scanned.
>
> Will this force the shrinker core to repeatedly call this function,
> processing the same leading non-purgeable BOs over and over again?
This can't happen in practice since purgeable bos are always ordered
before non-purgeable bos on the list.
/Thomas
>
> > - if (nr_scanned >= nr_to_scan || !can_backup)
> > - goto out;
> >
> > - /* If we didn't wake before, try to do it now if needed.
> > */
> > - if (!runtime_pm)
> > - runtime_pm = xe_shrinker_runtime_pm_get(shrinker,
> > true, 0, can_backup);
> > + return nr_scanned ? freed : SHRINK_STOP;
> > +}
>
> [ ... ]
>
> > @@ -294,6 +305,7 @@ static void xe_shrinker_fini(struct drm_device
> > *drm, void *arg)
> > xe_assert(shrinker->xe, !shrinker->purgeable_pages);
> > xe_assert(shrinker->xe, !shrinker->populated_tts);
> > shrinker_free(shrinker->shrink);
> > + shrinker_free(shrinker->purge_shrink);
> > flush_work(&shrinker->pm_worker);
> > kfree(shrinker);
> > }
>
> [Severity: High]
> Does this kfree(shrinker) leave xe->mem.shrinker as a dangling
> pointer?
>
> Because drmm actions execute in LIFO order upon device release,
> xe_shrinker_fini() is called before xe_device_destroy().
>
> Later, xe_device_destroy() runs and calls xe_bo_dev_fini() which
> flushes
> the async_free workqueue. Pending BOs in the workqueue will have
> their
> final references dropped, leading to xe_ttm_tt_account_subtract():
>
> drivers/gpu/drm/xe/xe_bo.c:xe_ttm_tt_account_subtract() {
> ...
> if (xe_tt->purgeable)
> xe_shrinker_mod_pages(xe->mem.shrinker, 0, -(long)tt-
> >num_pages, -1);
> else
> xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages,
> 0, -1);
> ...
> }
>
> Can this lead to a use-after-free and memory corruption when driver
> unloads?
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 2/4] drm/xe: Track number of populated ttm_tts in the shrinker
2026-10-16 13:35 ` [PATCH v4 2/4] drm/xe: Track number of populated ttm_tts in the shrinker Thomas Hellström
@ 2026-10-16 14:26 ` Matthew Brost
0 siblings, 0 replies; 18+ messages in thread
From: Matthew Brost @ 2026-10-16 14:26 UTC (permalink / raw)
To: Thomas Hellström; +Cc: intel-xe, Matthew Auld, Maarten Lankhorst
On Fri, Oct 16, 2026 at 03:35:21PM +0200, Thomas Hellström wrote:
> Add a populated_tts counter to struct xe_shrinker to track how many
> ttm_tts are currently populated and on the LRU (i.e., shrinkable or
> purgeable). This mirrors the existing per-pages accounting but counts
> objects rather than pages.
>
> The counter is incremented in xe_ttm_tt_account_add() and decremented
> in xe_ttm_tt_account_subtract(), which are already called at the exact
> points where pages enter and leave the shrinker's jurisdiction (populate,
> unpopulate, pin, and unpin). Purgeable state transfers, which move pages
> between the shrinkable and purgeable buckets without changing the total
> object count, pass tts=0.
>
> Extend xe_shrinker_mod_pages() with a tts delta parameter so that page
> and object accounting can be updated atomically under the same lock.
>
> Assert that populated_tts reaches zero at device teardown, alongside
> the existing assertions for shrinkable_pages and purgeable_pages.
>
> No functional change intended; the new field is unused until a follow-up
> commit wires it into shrinker batch sizing.
>
> Assisted-by: LLM
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
> ---
> drivers/gpu/drm/xe/xe_bo.c | 12 ++++++------
> drivers/gpu/drm/xe/xe_shrinker.c | 15 +++++++++++----
> drivers/gpu/drm/xe/xe_shrinker.h | 3 ++-
> 3 files changed, 19 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
> index 12e523c61c1f..1b74331b15ec 100644
> --- a/drivers/gpu/drm/xe/xe_bo.c
> +++ b/drivers/gpu/drm/xe/xe_bo.c
> @@ -456,9 +456,9 @@ static void xe_ttm_tt_account_add(struct xe_device *xe, struct ttm_tt *tt)
> struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
>
> if (xe_tt->purgeable)
> - xe_shrinker_mod_pages(xe->mem.shrinker, 0, tt->num_pages);
> + xe_shrinker_mod_pages(xe->mem.shrinker, 0, tt->num_pages, 1);
> else
> - xe_shrinker_mod_pages(xe->mem.shrinker, tt->num_pages, 0);
> + xe_shrinker_mod_pages(xe->mem.shrinker, tt->num_pages, 0, 1);
> }
>
> static void xe_ttm_tt_account_subtract(struct xe_device *xe, struct ttm_tt *tt)
> @@ -466,9 +466,9 @@ static void xe_ttm_tt_account_subtract(struct xe_device *xe, struct ttm_tt *tt)
> struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
>
> if (xe_tt->purgeable)
> - xe_shrinker_mod_pages(xe->mem.shrinker, 0, -(long)tt->num_pages);
> + xe_shrinker_mod_pages(xe->mem.shrinker, 0, -(long)tt->num_pages, -1);
> else
> - xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages, 0);
> + xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages, 0, -1);
> }
>
> static bool xe_ttm_bo_is_imported(struct ttm_buffer_object *tbo)
> @@ -984,11 +984,11 @@ static void xe_bo_set_purgeable_shrinker(struct xe_bo *bo,
> if (!xe_tt->purgeable && new_state == XE_MADV_PURGEABLE_DONTNEED) {
> xe_tt->purgeable = true;
> /* Transfer pages from shrinkable to purgeable count */
> - xe_shrinker_mod_pages(xe->mem.shrinker, -tt_pages, tt_pages);
> + xe_shrinker_mod_pages(xe->mem.shrinker, -tt_pages, tt_pages, 0);
> } else if (xe_tt->purgeable && new_state == XE_MADV_PURGEABLE_WILLNEED) {
> xe_tt->purgeable = false;
> /* Transfer pages from purgeable to shrinkable count */
> - xe_shrinker_mod_pages(xe->mem.shrinker, tt_pages, -tt_pages);
> + xe_shrinker_mod_pages(xe->mem.shrinker, tt_pages, -tt_pages, 0);
> }
> }
>
> diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
> index 4e4da76936f4..378022c37a57 100644
> --- a/drivers/gpu/drm/xe/xe_shrinker.c
> +++ b/drivers/gpu/drm/xe/xe_shrinker.c
> @@ -20,6 +20,7 @@
> * @lock: Lock protecting accounting.
> * @shrinkable_pages: Number of pages that are currently shrinkable.
> * @purgeable_pages: Number of pages that are currently purgeable.
> + * @populated_tts: Number of populated ttm_tts currently shrinkable or purgeable.
> * @shrink: Pointer to the mm shrinker.
> * @pm_worker: Worker to wake up the device if required.
> */
> @@ -28,6 +29,7 @@ struct xe_shrinker {
> rwlock_t lock;
> long shrinkable_pages;
> long purgeable_pages;
> + long populated_tts;
> struct shrinker *shrink;
> struct work_struct pm_worker;
> };
> @@ -38,19 +40,23 @@ static struct xe_shrinker *to_xe_shrinker(struct shrinker *shrink)
> }
>
> /**
> - * xe_shrinker_mod_pages() - Modify shrinker page accounting
> + * xe_shrinker_mod_pages() - Modify shrinker page and object accounting
> * @shrinker: Pointer to the struct xe_shrinker.
> * @shrinkable: Shrinkable pages delta. May be negative.
> - * @purgeable: Purgeable page delta. May be negative.
> + * @purgeable: Purgeable pages delta. May be negative.
> + * @tts: Populated ttm_tt count delta. May be negative.
> *
> - * Modifies the shrinkable and purgeable pages accounting.
> + * Updates the shrinkable and purgeable page counts and the populated
> + * ttm_tt count.
> */
> void
> -xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable)
> +xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable,
> + long tts)
> {
> write_lock(&shrinker->lock);
> shrinker->shrinkable_pages += shrinkable;
> shrinker->purgeable_pages += purgeable;
> + shrinker->populated_tts += tts;
> write_unlock(&shrinker->lock);
> }
>
> @@ -286,6 +292,7 @@ static void xe_shrinker_fini(struct drm_device *drm, void *arg)
>
> xe_assert(shrinker->xe, !shrinker->shrinkable_pages);
> xe_assert(shrinker->xe, !shrinker->purgeable_pages);
> + xe_assert(shrinker->xe, !shrinker->populated_tts);
> shrinker_free(shrinker->shrink);
> flush_work(&shrinker->pm_worker);
> kfree(shrinker);
> diff --git a/drivers/gpu/drm/xe/xe_shrinker.h b/drivers/gpu/drm/xe/xe_shrinker.h
> index 5132ae5192e1..9c63e22b3b73 100644
> --- a/drivers/gpu/drm/xe/xe_shrinker.h
> +++ b/drivers/gpu/drm/xe/xe_shrinker.h
> @@ -9,7 +9,8 @@
> struct xe_shrinker;
> struct xe_device;
>
> -void xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable);
> +void xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable,
> + long tts);
>
> int xe_shrinker_create(struct xe_device *xe);
>
> --
> 2.56.0
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* ✓ Xe.CI.BAT: success for drm/xe: Adjust the bo shrinker batch size (rev4)
2026-10-16 13:35 [PATCH v4 0/4] drm/xe: Adjust the bo shrinker batch size Thomas Hellström
` (4 preceding siblings ...)
2026-10-16 13:45 ` ✓ CI.KUnit: success for drm/xe: Adjust the bo shrinker batch size (rev4) Patchwork
@ 2026-10-16 14:37 ` Patchwork
5 siblings, 0 replies; 18+ messages in thread
From: Patchwork @ 2026-10-16 14:37 UTC (permalink / raw)
To: Thomas Hellström; +Cc: intel-xe
[-- Attachment #1: Type: text/plain, Size: 962 bytes --]
== Series Details ==
Series: drm/xe: Adjust the bo shrinker batch size (rev4)
URL : https://patchwork.freedesktop.org/series/166426/
State : success
== Summary ==
CI Bug Log - changes from xe-5961-728ba1de4cb617e37b0f04258bdd0fc3248bdb39_BAT -> xe-pw-166426v4_BAT
====================================================
Summary
-------
**SUCCESS**
No regressions found.
Participating hosts (15 -> 15)
------------------------------
No changes in participating hosts
Changes
-------
No changes found
Build changes
-------------
* Linux: xe-5961-728ba1de4cb617e37b0f04258bdd0fc3248bdb39 -> xe-pw-166426v4
IGT_9150: 18811c476bfde62ffbb4c0af55cd6f57e36e0dca @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
xe-5961-728ba1de4cb617e37b0f04258bdd0fc3248bdb39: 728ba1de4cb617e37b0f04258bdd0fc3248bdb39
xe-pw-166426v4: 166426v4
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-166426v4/index.html
[-- Attachment #2: Type: text/html, Size: 1510 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers
2026-10-16 13:35 ` [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers Thomas Hellström
2026-10-16 13:53 ` sashiko-bot
@ 2026-10-16 18:16 ` Matthew Brost
1 sibling, 0 replies; 18+ messages in thread
From: Matthew Brost @ 2026-10-16 18:16 UTC (permalink / raw)
To: Thomas Hellström; +Cc: intel-xe, Matthew Auld, Maarten Lankhorst
On Fri, Oct 16, 2026 at 03:35:22PM +0200, Thomas Hellström wrote:
> Purgeable objects are reclaimed by simply discarding their pages, with
> no writeback required. They are therefore much cheaper to shrink than
> regular shrinkable (non-purgeable) objects, whose reclaim may need to
> wait for the GPU or write dirty compressed contents back to a backup
> store, and whose contents need to be read back on next use.
>
> Split the single xe_shrinker into two independent struct shrinker
> instances registered against the shrinker core, sharing the same
> underlying accounting (shrinkable_pages, purgeable_pages,
> populated_tts) and locking:
>
> - A purgeable shrinker, whose count_objects() reports only
> purgeable_pages, and whose scan_objects() only purges objects.
>
> - A non-purgeable (shrinkable) shrinker, whose count_objects()
> reports the shrinkable page count (capped by backup availability)
> and whose scan_objects() shrinks non-purgeable objects, and also
> purges any purgeable objects it encounters, waking the device via
> runtime PM as needed.
>
> Express the cost difference to the shrinker core through the seeks
> value: the purgeable shrinker keeps DEFAULT_SEEKS, while the
> non-purgeable shrinker uses a higher value,
> XE_SHRINKER_NON_PURGEABLE_SEEKS (8). The core scales each shrinker's
> scan target inversely with seeks, so purgeable objects receive
> proportionally more reclaim pressure than non-purgeable ones, without
> one shrinker's behaviour depending on the other's state.
>
> The standalone purge walk relies on the LRU walk skipping
> non-purgeable objects, for which xe_bo_shrink() returns -EBUSY,
> rather than aborting.
>
> v3:
> - Patch introduced. (Matt Brost)
>
> v4:
> - The purge walk aborting at the first non-purgeable object is now
> fixed by a separate, preceding patch. (Sashiko)
>
> Assisted-by: LLM
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
> drivers/gpu/drm/xe/xe_shrinker.c | 109 +++++++++++++++++++------------
> 1 file changed, 68 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
> index 378022c37a57..8e3fe675e0f3 100644
> --- a/drivers/gpu/drm/xe/xe_shrinker.c
> +++ b/drivers/gpu/drm/xe/xe_shrinker.c
> @@ -14,6 +14,15 @@
> #include "xe_pm.h"
> #include "xe_shrinker.h"
>
> +/*
> + * Reclaiming non-purgeable objects requires GPU idling and writeback to a
> + * backup store, and restoring them requires reading the contents back.
> + * Tell the shrinker core they're costlier to recreate than purgeable
> + * objects, which use DEFAULT_SEEKS, so that purgeable objects are
> + * preferentially reclaimed.
> + */
> +#define XE_SHRINKER_NON_PURGEABLE_SEEKS 8
I suggest for full tuning this tied to a Kconfig + plus syfs entry like
I have here [1] so customers can play around with various configs.
[1] https://patchwork.freedesktop.org/series/176251/
Most everything every LGTM, but I think the Sashiko comment it somewhat
valid, I'll reply there.
Matt
> +
> /**
> * struct xe_shrinker - per-device shrinker
> * @xe: Back pointer to the device.
> @@ -21,7 +30,8 @@
> * @shrinkable_pages: Number of pages that are currently shrinkable.
> * @purgeable_pages: Number of pages that are currently purgeable.
> * @populated_tts: Number of populated ttm_tts currently shrinkable or purgeable.
> - * @shrink: Pointer to the mm shrinker.
> + * @shrink: Pointer to the mm shrinker handling non-purgeable (shrinkable) objects.
> + * @purge_shrink: Pointer to the mm shrinker handling purgeable objects.
> * @pm_worker: Worker to wake up the device if required.
> */
> struct xe_shrinker {
> @@ -31,6 +41,7 @@ struct xe_shrinker {
> long purgeable_pages;
> long populated_tts;
> struct shrinker *shrink;
> + struct shrinker *purge_shrink;
> struct work_struct pm_worker;
> };
>
> @@ -179,6 +190,19 @@ static int xe_shrinker_walk(struct xe_shrinker *shrinker,
> return ret;
> }
>
> +static unsigned long
> +xe_shrinker_count_purgeable(struct shrinker *shrink, struct shrink_control *sc)
> +{
> + struct xe_shrinker *shrinker = to_xe_shrinker(shrink);
> + unsigned long num_pages;
> +
> + read_lock(&shrinker->lock);
> + num_pages = shrinker->purgeable_pages;
> + read_unlock(&shrinker->lock);
> +
> + return num_pages ? num_pages : SHRINK_EMPTY;
> +}
> +
> static unsigned long
> xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
> {
> @@ -194,7 +218,6 @@ xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
> else
> num_pages = 0;
>
> - num_pages += shrinker->purgeable_pages;
> read_unlock(&shrinker->lock);
>
> return num_pages ? num_pages : SHRINK_EMPTY;
> @@ -207,8 +230,7 @@ xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
> * If bo shrinking needs an rpm reference and we don't have it (yet),
> * that bo will be skipped anyway.
> */
> -static bool xe_shrinker_runtime_pm_get(struct xe_shrinker *shrinker, bool force,
> - unsigned long nr_to_scan, bool can_backup)
> +static bool xe_shrinker_runtime_pm_get(struct xe_shrinker *shrinker)
> {
> struct xe_device *xe = shrinker->xe;
>
> @@ -216,63 +238,52 @@ static bool xe_shrinker_runtime_pm_get(struct xe_shrinker *shrinker, bool force,
> !ttm_backup_bytes_avail())
> return false;
>
> - if (!force) {
> - read_lock(&shrinker->lock);
> - force = (nr_to_scan > shrinker->purgeable_pages && can_backup);
> - read_unlock(&shrinker->lock);
> - if (!force)
> - return false;
> - }
> -
> return __xe_shrinker_runtime_pm_get(shrinker);
> }
>
> -static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
> +static unsigned long xe_shrinker_scan_purgeable(struct shrinker *shrink,
> + struct shrink_control *sc)
> {
> struct xe_shrinker *shrinker = to_xe_shrinker(shrink);
> struct ttm_operation_ctx ctx = {
> .interruptible = false,
> .no_wait_gpu = ttm_bo_shrink_avoid_wait(),
> };
> - unsigned long nr_to_scan, nr_scanned = 0, freed = 0;
> + unsigned long nr_to_scan = sc->nr_to_scan, nr_scanned = 0, freed = 0;
> struct xe_bo_shrink_flags shrink_flags = {
> .purge = true,
> - /* Don't request writeback without __GFP_IO. */
> - .writeback = !ctx.no_wait_gpu && (sc->gfp_mask & __GFP_IO),
> };
> - bool runtime_pm;
> - bool purgeable;
> - bool can_backup = !!(sc->gfp_mask & __GFP_FS);
> -
> - nr_to_scan = sc->nr_to_scan;
> -
> - read_lock(&shrinker->lock);
> - purgeable = !!shrinker->purgeable_pages;
> - read_unlock(&shrinker->lock);
>
> - /* Might need runtime PM. Try to wake early if it looks like it. */
> - runtime_pm = xe_shrinker_runtime_pm_get(shrinker, false, nr_to_scan, can_backup);
> -
> - if (purgeable && nr_scanned < nr_to_scan)
> - xe_shrinker_walk(shrinker, &ctx, shrink_flags,
> - nr_to_scan, &nr_scanned, &freed);
> + xe_shrinker_walk(shrinker, &ctx, shrink_flags, nr_to_scan, &nr_scanned, &freed);
>
> sc->nr_scanned = nr_scanned;
> - if (nr_scanned >= nr_to_scan || !can_backup)
> - goto out;
>
> - /* If we didn't wake before, try to do it now if needed. */
> - if (!runtime_pm)
> - runtime_pm = xe_shrinker_runtime_pm_get(shrinker, true, 0, can_backup);
> + return nr_scanned ? freed : SHRINK_STOP;
> +}
>
> - shrink_flags.purge = false;
> +static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
> +{
> + struct xe_shrinker *shrinker = to_xe_shrinker(shrink);
> + struct ttm_operation_ctx ctx = {
> + .interruptible = false,
> + .no_wait_gpu = ttm_bo_shrink_avoid_wait(),
> + };
> + unsigned long nr_to_scan = sc->nr_to_scan, nr_scanned = 0, freed = 0;
> + struct xe_bo_shrink_flags shrink_flags = {
> + .purge = false,
> + /* Don't request writeback without __GFP_IO. */
> + .writeback = !ctx.no_wait_gpu && (sc->gfp_mask & __GFP_IO),
> + };
> + bool runtime_pm;
> +
> + /* Might need runtime PM to access backed-up or CCS-compressed data. */
> + runtime_pm = xe_shrinker_runtime_pm_get(shrinker);
>
> - xe_shrinker_walk(shrinker, &ctx, shrink_flags,
> - nr_to_scan, &nr_scanned, &freed);
> + xe_shrinker_walk(shrinker, &ctx, shrink_flags, nr_to_scan, &nr_scanned, &freed);
>
> sc->nr_scanned = nr_scanned;
> -out:
> xe_shrinker_runtime_pm_put(shrinker, runtime_pm);
> +
> return nr_scanned ? freed : SHRINK_STOP;
> }
>
> @@ -294,6 +305,7 @@ static void xe_shrinker_fini(struct drm_device *drm, void *arg)
> xe_assert(shrinker->xe, !shrinker->purgeable_pages);
> xe_assert(shrinker->xe, !shrinker->populated_tts);
> shrinker_free(shrinker->shrink);
> + shrinker_free(shrinker->purge_shrink);
> flush_work(&shrinker->pm_worker);
> kfree(shrinker);
> }
> @@ -311,8 +323,15 @@ int xe_shrinker_create(struct xe_device *xe)
> if (!shrinker)
> return -ENOMEM;
>
> - shrinker->shrink = shrinker_alloc(0, "drm-xe_gem:%s", xe->drm.unique);
> + shrinker->purge_shrink = shrinker_alloc(0, "drm-xe_gem-purgeable:%s", xe->drm.unique);
> + if (!shrinker->purge_shrink) {
> + kfree(shrinker);
> + return -ENOMEM;
> + }
> +
> + shrinker->shrink = shrinker_alloc(0, "drm-xe_gem-shrinkable:%s", xe->drm.unique);
> if (!shrinker->shrink) {
> + shrinker_free(shrinker->purge_shrink);
> kfree(shrinker);
> return -ENOMEM;
> }
> @@ -320,10 +339,18 @@ int xe_shrinker_create(struct xe_device *xe)
> INIT_WORK(&shrinker->pm_worker, xe_shrinker_pm);
> shrinker->xe = xe;
> rwlock_init(&shrinker->lock);
> +
> + shrinker->purge_shrink->count_objects = xe_shrinker_count_purgeable;
> + shrinker->purge_shrink->scan_objects = xe_shrinker_scan_purgeable;
> + shrinker->purge_shrink->private_data = shrinker;
> + shrinker_register(shrinker->purge_shrink);
> +
> shrinker->shrink->count_objects = xe_shrinker_count;
> shrinker->shrink->scan_objects = xe_shrinker_scan;
> shrinker->shrink->private_data = shrinker;
> + shrinker->shrink->seeks = XE_SHRINKER_NON_PURGEABLE_SEEKS;
> shrinker_register(shrinker->shrink);
> +
> xe->mem.shrinker = shrinker;
>
> return drmm_add_action_or_reset(&xe->drm, xe_shrinker_fini, shrinker);
> --
> 2.56.0
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers
2026-10-16 14:09 ` Thomas Hellström
@ 2026-10-16 18:41 ` Matthew Brost
0 siblings, 0 replies; 18+ messages in thread
From: Matthew Brost @ 2026-10-16 18:41 UTC (permalink / raw)
To: Thomas Hellström; +Cc: sashiko-reviews, intel-xe
On Fri, Oct 16, 2026 at 04:09:44PM +0200, Thomas Hellström wrote:
> On Fri, 2026-10-16 at 13:53 +0000, sashiko-bot@kernel.org wrote:
> > Thank you for your contribution! Sashiko AI review found 2 potential
> > issue(s) to consider:
> > - [High] drm/xe: Use-After-Free of shrinker during DRM device
> > teardown
> > - [High] drm/xe: O(N^2) CPU lockup in purgeable shrinker due to
> > uncounted LRU skips
> > --
> >
> > commit 1e9348c2fe4768de2cf24e4dd9b6188400c84043
> > Author: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> >
> > drm/xe: Split the bo shrinker into purgeable and non-purgeable
> > shrinkers
> >
> > This commit splits the single xe_shrinker into two independent
> > shrinker
> > instances: one for purgeable objects and another for non-purgeable
> > (shrinkable) objects. This allows the shrinker core to apply
> > different
> > reclaim pressures based on the varying costs of reclaiming these
> > object
> > types.
> >
> > > diff --git a/drivers/gpu/drm/xe/xe_shrinker.c
> > > b/drivers/gpu/drm/xe/xe_shrinker.c
> > > index 378022c37a57c..8e3fe675e0f34 100644
> > > --- a/drivers/gpu/drm/xe/xe_shrinker.c
> > > +++ b/drivers/gpu/drm/xe/xe_shrinker.c
> >
> > [ ... ]
> >
> > > @@ -216,63 +238,52 @@ static bool xe_shrinker_runtime_pm_get(struct
> > > xe_shrinker *shrinker, bool force,
> >
> > [ ... ]
> >
> > > -static unsigned long xe_shrinker_scan(struct shrinker *shrink,
> > > struct shrink_control *sc)
> > > +static unsigned long xe_shrinker_scan_purgeable(struct shrinker
> > > *shrink,
> > > + struct
> > > shrink_control *sc)
> > > {
> > > struct xe_shrinker *shrinker = to_xe_shrinker(shrink);
> > > struct ttm_operation_ctx ctx = {
> > > .interruptible = false,
> > > .no_wait_gpu = ttm_bo_shrink_avoid_wait(),
> > > };
> > > - unsigned long nr_to_scan, nr_scanned = 0, freed = 0;
> > > + unsigned long nr_to_scan = sc->nr_to_scan, nr_scanned = 0,
> > > freed = 0;
> > > struct xe_bo_shrink_flags shrink_flags = {
> > > .purge = true,
> > > - /* Don't request writeback without __GFP_IO. */
> > > - .writeback = !ctx.no_wait_gpu && (sc->gfp_mask &
> > > __GFP_IO),
> > > };
> > > - bool runtime_pm;
> > > - bool purgeable;
> > > - bool can_backup = !!(sc->gfp_mask & __GFP_FS);
> > > -
> > > - nr_to_scan = sc->nr_to_scan;
> > > -
> > > - read_lock(&shrinker->lock);
> > > - purgeable = !!shrinker->purgeable_pages;
> > > - read_unlock(&shrinker->lock);
> > >
> > > - /* Might need runtime PM. Try to wake early if it looks
> > > like it. */
> > > - runtime_pm = xe_shrinker_runtime_pm_get(shrinker, false,
> > > nr_to_scan, can_backup);
> > > -
> > > - if (purgeable && nr_scanned < nr_to_scan)
> > > - xe_shrinker_walk(shrinker, &ctx, shrink_flags,
> > > - nr_to_scan, &nr_scanned, &freed);
> > > + xe_shrinker_walk(shrinker, &ctx, shrink_flags, nr_to_scan,
> > > &nr_scanned, &freed);
> > >
> > > sc->nr_scanned = nr_scanned;
> >
> > [Severity: High]
> > Can this cause an O(N^2) CPU lockup in the purgeable shrinker?
> >
> > When the memory reclaim core (do_shrink_slab) calls this purgeable
> > scan
> > routine under memory pressure, xe_shrinker_walk() iterates the LRU
> > list.
> >
> > However, non-purgeable BOs return -EBUSY and are skipped without
> > advancing
> > the scanned counter:
> >
> > drivers/gpu/drm/xe/xe_bo.c:xe_bo_shrink() {
> > ...
> > if (!(tt->page_flags & TTM_TT_FLAG_EXTERNAL_MAPPABLE) ||
> > (flags.purge && !xe_tt->purgeable))
> > return -EBUSY;
> > ...
> > }
> >
> > drivers/gpu/drm/xe/xe_shrinker.c:__xe_shrinker_walk() {
> > ...
> > lret = xe_bo_shrink(ctx, ttm_bo, flags, scanned);
> > /* Like the TTM LRU walk, skip bos we can't shrink now.
> > */
> > if (lret == -EBUSY)
> > continue;
> > ...
> > }
> >
> > Since the LRU cursor is initialized locally on each call and non-
> > purgeable
> > BOs do not increment nr_scanned, every batch rescans all leading
> > non-purgeable BOs without significantly advancing sc->nr_scanned.
> >
> > Will this force the shrinker core to repeatedly call this function,
> > processing the same leading non-purgeable BOs over and over again?
>
> This can't happen in practice since purgeable bos are always ordered
> before non-purgeable bos on the list.
>
Is this true, though? If a BO is marked as purged on a hot VM and shares
the VM's bulk-move structure, it would remain hot in the list. Also,
within an individual bulk-move list, I don't think a purgable object is
guaranteed to be at the front of the LRU.
So, at a minimum, BOs marked as purged should be moved to a lower
priority band, as this patch does [1], and reclaim should only walk the
purged-priority band [2].
We can do this in an immediate follow-up after this series merges.
Matt
[1] https://patchwork.freedesktop.org/patch/743454/?series=170454&rev=5
[2] https://patchwork.freedesktop.org/patch/743454/?series=170454&rev=5
> /Thomas
>
>
>
> >
> > > - if (nr_scanned >= nr_to_scan || !can_backup)
> > > - goto out;
> > >
> > > - /* If we didn't wake before, try to do it now if needed.
> > > */
> > > - if (!runtime_pm)
> > > - runtime_pm = xe_shrinker_runtime_pm_get(shrinker,
> > > true, 0, can_backup);
> > > + return nr_scanned ? freed : SHRINK_STOP;
> > > +}
> >
> > [ ... ]
> >
> > > @@ -294,6 +305,7 @@ static void xe_shrinker_fini(struct drm_device
> > > *drm, void *arg)
> > > xe_assert(shrinker->xe, !shrinker->purgeable_pages);
> > > xe_assert(shrinker->xe, !shrinker->populated_tts);
> > > shrinker_free(shrinker->shrink);
> > > + shrinker_free(shrinker->purge_shrink);
> > > flush_work(&shrinker->pm_worker);
> > > kfree(shrinker);
> > > }
> >
> > [Severity: High]
> > Does this kfree(shrinker) leave xe->mem.shrinker as a dangling
> > pointer?
> >
> > Because drmm actions execute in LIFO order upon device release,
> > xe_shrinker_fini() is called before xe_device_destroy().
> >
> > Later, xe_device_destroy() runs and calls xe_bo_dev_fini() which
> > flushes
> > the async_free workqueue. Pending BOs in the workqueue will have
> > their
> > final references dropped, leading to xe_ttm_tt_account_subtract():
> >
> > drivers/gpu/drm/xe/xe_bo.c:xe_ttm_tt_account_subtract() {
> > ...
> > if (xe_tt->purgeable)
> > xe_shrinker_mod_pages(xe->mem.shrinker, 0, -(long)tt-
> > >num_pages, -1);
> > else
> > xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages,
> > 0, -1);
> > ...
> > }
> >
> > Can this lead to a use-after-free and memory corruption when driver
> > unloads?
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size
2026-10-16 14:06 ` Thomas Hellström
@ 2026-10-16 18:42 ` Matthew Brost
0 siblings, 0 replies; 18+ messages in thread
From: Matthew Brost @ 2026-10-16 18:42 UTC (permalink / raw)
To: Thomas Hellström; +Cc: sashiko-reviews, intel-xe
On Fri, Oct 16, 2026 at 04:06:18PM +0200, Thomas Hellström wrote:
> On Fri, 2026-10-16 at 13:45 +0000, sashiko-bot@kernel.org wrote:
> > Thank you for your contribution! Sashiko AI review found 1 potential
> > issue(s) to consider:
> > - [Medium] drm/xe: shrinker count callback serializes direct reclaim
> > via write_lock
> > --
> >
> > commit a78bd8842e67f957a2ced6d827e1c4a6430ff29b
> > Author: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> > drm/xe: Update non-purgeable shrinker batch size based on average BO
> > size
> >
> > This commit updates the preferred vmscan batch size for the non-
> > purgeable
> > shrinker based on the average buffer object size. It introduces an
> > exponential moving average that is updated during the shrinker count
> > phase.
> >
> > > diff --git a/drivers/gpu/drm/xe/xe_shrinker.c
> > > b/drivers/gpu/drm/xe/xe_shrinker.c
> > > index 8e3fe675e0f34..955908b3bdf3e 100644
> > > --- a/drivers/gpu/drm/xe/xe_shrinker.c
> > > +++ b/drivers/gpu/drm/xe/xe_shrinker.c
> > [ ... ]
> > > @@ -210,15 +235,26 @@ xe_shrinker_count(struct shrinker *shrink,
> > > struct shrink_control *sc)
> > > unsigned long num_pages;
> > > bool can_backup = !!(sc->gfp_mask & __GFP_FS);
> > >
> > > + if (!can_backup)
> > > + return SHRINK_EMPTY;
> > > +
> > > num_pages = ttm_backup_bytes_avail() >> PAGE_SHIFT;
> > > - read_lock(&shrinker->lock);
> > > + /* Consistently use write_lock() for simplicity. */
> > > + write_lock(&shrinker->lock);
> >
> > [Severity: Medium]
> > Will this exclusive write lock create a system-wide performance
> > bottleneck
> > during memory reclaim?
> >
> > The core mm subsystem frequently calls the shrinker's count_objects
> > callback
> > (xe_shrinker_count) from do_shrink_slab() during direct reclaim. This
> > occurs
> > concurrently across multiple allocating tasks and CPUs when under
> > memory
> > pressure.
> >
> > By changing read_lock() to write_lock() to update the batch_avg
> > heuristic,
> > this forces all concurrent direct reclaimers system-wide to serialize
> > on this
> > single lock, which could lead to severe lock contention and
> > performance
> > degradation.
>
> This is grossly overstated. False positive.
>
Agree.
Matt
> /Thomas
>
>
>
> >
> > >
> > > - if (can_backup)
> > > - num_pages = min_t(unsigned long, num_pages,
> > > shrinker->shrinkable_pages);
> > > - else
> > > - num_pages = 0;
> > > + num_pages = min_t(unsigned long, num_pages, shrinker-
> > > >shrinkable_pages);
> > >
> > > - read_unlock(&shrinker->lock);
> > > + if (shrinker->populated_tts) {
> > > + unsigned long avg = 2 * (shrinker-
> > > >shrinkable_pages +
> > > + shrinker-
> > > >purgeable_pages) /
> > > + shrinker->populated_tts;
> > > +
> > > + shrinker->batch_avg = max((shrinker->batch_avg +
> > > (long)avg) >> 1,
> > > + 128L /* default
> > > SHRINK_BATCH */);
> > > + WRITE_ONCE(shrink->batch, shrinker->batch_avg);
> > > + }
> > > +
> > > + write_unlock(&shrinker->lock);
> > >
> > > return num_pages ? num_pages : SHRINK_EMPTY;
> > > }
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size
2026-10-16 13:35 ` [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size Thomas Hellström
2026-10-16 13:45 ` sashiko-bot
@ 2026-10-16 18:44 ` Matthew Brost
1 sibling, 0 replies; 18+ messages in thread
From: Matthew Brost @ 2026-10-16 18:44 UTC (permalink / raw)
To: Thomas Hellström; +Cc: intel-xe, Matthew Auld, Maarten Lankhorst
On Fri, Oct 16, 2026 at 03:35:23PM +0200, Thomas Hellström wrote:
> Update our preferred vmscan batch size for the non-purgeable shrinker
> on count passes that allow backup (__GFP_FS), to avoid invoking
> scan_objects() for requests too small to free even a single
> average-sized GEM object. Our rough estimate for an effective batch
> is twice the average number of pages per populated ttm_tt across
> the full shrinkable and purgeable population. The factor of two
> provides headroom so that most scan invocations can free at least one
> GEM object despite variability in object sizes.
>
> The batch value is updated as an exponential moving average,
> (old_batch + avg) / 2, to smooth out sudden changes in the object
> population. It is floored at 128 pages, the kernel default
> SHRINK_BATCH, to ensure the shrinker remains responsive when there
> are very few objects.
>
> The populated_tts counter introduced in an earlier commit provides the
> object count needed for the average. We inherit the same justification
> as the analogous mechanism in i915: shrinking a GEM object has
> non-trivial per-object overhead, so firing the shrinker for requests
> smaller than a single object is wasteful.
>
> This is only applied to the non-purgeable shrinker: purgeable objects
> are reclaimed without writeback or GPU idling, so they're cheap enough
> that the core default batch size is fine for them.
>
> v3:
> - Original patch reworked on top of shrinker split (Matt Brost)
>
> Assisted-by: LLM
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
> ---
> drivers/gpu/drm/xe/xe_shrinker.c | 48 ++++++++++++++++++++++++++++----
> 1 file changed, 42 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
> index 8e3fe675e0f3..955908b3bdf3 100644
> --- a/drivers/gpu/drm/xe/xe_shrinker.c
> +++ b/drivers/gpu/drm/xe/xe_shrinker.c
> @@ -30,6 +30,8 @@
> * @shrinkable_pages: Number of pages that are currently shrinkable.
> * @purgeable_pages: Number of pages that are currently purgeable.
> * @populated_tts: Number of populated ttm_tts currently shrinkable or purgeable.
> + * @batch_avg: Exponential moving average of the preferred non-purgeable
> + * batch size, based on the average populated ttm_tt size.
> * @shrink: Pointer to the mm shrinker handling non-purgeable (shrinkable) objects.
> * @purge_shrink: Pointer to the mm shrinker handling purgeable objects.
> * @pm_worker: Worker to wake up the device if required.
> @@ -40,6 +42,7 @@ struct xe_shrinker {
> long shrinkable_pages;
> long purgeable_pages;
> long populated_tts;
> + long batch_avg;
> struct shrinker *shrink;
> struct shrinker *purge_shrink;
> struct work_struct pm_worker;
> @@ -203,6 +206,28 @@ xe_shrinker_count_purgeable(struct shrinker *shrink, struct shrink_control *sc)
> return num_pages ? num_pages : SHRINK_EMPTY;
> }
>
> +/**
> + * DOC: Batch size calculation
> + *
> + * Update our preferred vmscan batch size for the non-purgeable shrinker
> + * on count passes that allow backup (__GFP_FS), to avoid invoking
> + * scan_objects() for requests too small to free even a single
> + * average-sized GEM object. Our rough estimate for an effective batch
> + * is twice the average number of pages per populated ttm_tt across
> + * the full shrinkable and purgeable population. The factor of two
> + * provides headroom so that most scan invocations can free at least one
> + * GEM object despite variability in object sizes.
> + *
> + * The batch value is updated as an exponential moving average,
> + * (old_batch + avg) / 2, to smooth out sudden changes in the object
> + * population. It is floored at 128 pages, the kernel default
> + * SHRINK_BATCH, to ensure the shrinker remains responsive when there
> + * are very few objects.
> + *
> + * We only do this for the non-purgeable shrinker: purgeable objects are
> + * reclaimed without writeback or GPU idling, so shrinking them is cheap
> + * enough that the core default batch size is fine.
> + */
> static unsigned long
> xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
> {
> @@ -210,15 +235,26 @@ xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
> unsigned long num_pages;
> bool can_backup = !!(sc->gfp_mask & __GFP_FS);
>
> + if (!can_backup)
> + return SHRINK_EMPTY;
> +
> num_pages = ttm_backup_bytes_avail() >> PAGE_SHIFT;
> - read_lock(&shrinker->lock);
> + /* Consistently use write_lock() for simplicity. */
> + write_lock(&shrinker->lock);
>
> - if (can_backup)
> - num_pages = min_t(unsigned long, num_pages, shrinker->shrinkable_pages);
> - else
> - num_pages = 0;
> + num_pages = min_t(unsigned long, num_pages, shrinker->shrinkable_pages);
>
> - read_unlock(&shrinker->lock);
> + if (shrinker->populated_tts) {
> + unsigned long avg = 2 * (shrinker->shrinkable_pages +
> + shrinker->purgeable_pages) /
> + shrinker->populated_tts;
> +
> + shrinker->batch_avg = max((shrinker->batch_avg + (long)avg) >> 1,
> + 128L /* default SHRINK_BATCH */);
> + WRITE_ONCE(shrink->batch, shrinker->batch_avg);
> + }
> +
> + write_unlock(&shrinker->lock);
>
> return num_pages ? num_pages : SHRINK_EMPTY;
> }
> --
> 2.56.0
>
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2026-10-16 18:44 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 13:35 [PATCH v4 0/4] drm/xe: Adjust the bo shrinker batch size Thomas Hellström
2026-10-16 13:35 ` [PATCH v4 1/4] drm/xe: Don't abort the shrinker walk on -EBUSY Thomas Hellström
2026-10-16 13:44 ` sashiko-bot
2026-10-16 13:55 ` Matthew Brost
2026-10-16 13:35 ` [PATCH v4 2/4] drm/xe: Track number of populated ttm_tts in the shrinker Thomas Hellström
2026-10-16 14:26 ` Matthew Brost
2026-10-16 13:35 ` [PATCH v4 3/4] drm/xe: Split the bo shrinker into purgeable and non-purgeable shrinkers Thomas Hellström
2026-10-16 13:53 ` sashiko-bot
2026-10-16 14:09 ` Thomas Hellström
2026-10-16 18:41 ` Matthew Brost
2026-10-16 18:16 ` Matthew Brost
2026-10-16 13:35 ` [PATCH v4 4/4] drm/xe: Update non-purgeable shrinker batch size based on average BO size Thomas Hellström
2026-10-16 13:45 ` sashiko-bot
2026-10-16 14:06 ` Thomas Hellström
2026-10-16 18:42 ` Matthew Brost
2026-10-16 18:44 ` Matthew Brost
2026-10-16 13:45 ` ✓ CI.KUnit: success for drm/xe: Adjust the bo shrinker batch size (rev4) Patchwork
2026-10-16 14:37 ` ✓ Xe.CI.BAT: " Patchwork
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.