* [PATCH v3 01/11] drm/xe: Add normalize_invalidation_range
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-12 23:27 ` [PATCH v3 02/11] drm/xe: Make usm.asid_to_vm allocation use GFP_NOWAIT Matthew Brost
` (11 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Extract the code that determines the alignment of TLB invalidation into
a helper function — normalize_invalidation_range. This will be useful
when adding context-based invalidations to the GuC TLB invalidation
backend.
Signed-off-by: Nirmoy Das <nirmoy.das@intel.com>
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Stuart Summers <stuart.summers@intel.com>
---
drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 71 +++++++++++++--------------
1 file changed, 35 insertions(+), 36 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
index 774467befbb9..43f6dbcb2bc2 100644
--- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
@@ -111,6 +111,38 @@ static int send_page_reclaim(struct xe_guc *guc, u32 seqno,
G2H_LEN_DW_PAGE_RECLAMATION, 1);
}
+static u64 normalize_invalidation_range(struct xe_gt *gt, u64 *start, u64 *end)
+{
+ u64 orig_start = *start;
+ u64 length = *end - *start;
+ u64 align;
+
+ if (length < SZ_4K)
+ length = SZ_4K;
+
+ align = roundup_pow_of_two(length);
+ *start = ALIGN_DOWN(*start, align);
+ *end = ALIGN(*end, align);
+ length = align;
+ while (*start + length < *end) {
+ length <<= 1;
+ *start = ALIGN_DOWN(orig_start, length);
+ }
+
+ if (length >= SZ_2M) {
+ length = max_t(u64, SZ_16M, length);
+ *start = ALIGN_DOWN(orig_start, length);
+ }
+
+ xe_gt_assert(gt, length >= SZ_4K);
+ xe_gt_assert(gt, is_power_of_2(length));
+ xe_gt_assert(gt, !(length & GENMASK(ilog2(SZ_16M) - 1,
+ ilog2(SZ_2M) + 1)));
+ xe_gt_assert(gt, IS_ALIGNED(*start, length));
+
+ return length;
+}
+
/*
* Ensure that roundup_pow_of_two(length) doesn't overflow.
* Note that roundup_pow_of_two() operates on unsigned long,
@@ -138,48 +170,15 @@ static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
length > MAX_RANGE_TLB_INVALIDATION_LENGTH) {
action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL);
} else {
- u64 orig_start = start;
- u64 align;
-
- if (length < SZ_4K)
- length = SZ_4K;
-
- /*
- * We need to invalidate a higher granularity if start address
- * is not aligned to length. When start is not aligned with
- * length we need to find the length large enough to create an
- * address mask covering the required range.
- */
- align = roundup_pow_of_two(length);
- start = ALIGN_DOWN(start, align);
- end = ALIGN(end, align);
- length = align;
- while (start + length < end) {
- length <<= 1;
- start = ALIGN_DOWN(orig_start, length);
- }
-
- /*
- * Minimum invalidation size for a 2MB page that the hardware
- * expects is 16MB
- */
- if (length >= SZ_2M) {
- length = max_t(u64, SZ_16M, length);
- start = ALIGN_DOWN(orig_start, length);
- }
-
- xe_gt_assert(gt, length >= SZ_4K);
- xe_gt_assert(gt, is_power_of_2(length));
- xe_gt_assert(gt, !(length & GENMASK(ilog2(SZ_16M) - 1,
- ilog2(SZ_2M) + 1)));
- xe_gt_assert(gt, IS_ALIGNED(start, length));
+ u64 normalize_len = normalize_invalidation_range(gt, &start,
+ &end);
/* Flush on NULL case, Media is not required to modify flush due to no PPC so NOP */
action[len++] = MAKE_INVAL_OP_FLUSH(XE_GUC_TLB_INVAL_PAGE_SELECTIVE, !prl_sa);
action[len++] = asid;
action[len++] = lower_32_bits(start);
action[len++] = upper_32_bits(start);
- action[len++] = ilog2(length) - ilog2(SZ_4K);
+ action[len++] = ilog2(normalize_len) - ilog2(SZ_4K);
}
xe_gt_assert(gt, len <= MAX_TLB_INVALIDATION_LEN);
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v3 02/11] drm/xe: Make usm.asid_to_vm allocation use GFP_NOWAIT
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
2026-01-12 23:27 ` [PATCH v3 01/11] drm/xe: Add normalize_invalidation_range Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-12 23:27 ` [PATCH v3 03/11] drm/xe: Add xe_device_asid_to_vm helper Matthew Brost
` (10 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Ensure the asid_to_vm lookup is reclaim-safe so it can be performed
during TLB invalidations, which is necessary for context-based TLB
invalidation support.
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Stuart Summers <stuart.summers@intel.com>
---
drivers/gpu/drm/xe/xe_vm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 694f592a0f01..bdb04d6bf39c 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1654,7 +1654,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)
down_write(&xe->usm.lock);
err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm,
XA_LIMIT(1, XE_MAX_ASID - 1),
- &xe->usm.next_asid, GFP_KERNEL);
+ &xe->usm.next_asid, GFP_NOWAIT);
up_write(&xe->usm.lock);
if (err < 0)
goto err_close;
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v3 03/11] drm/xe: Add xe_device_asid_to_vm helper
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
2026-01-12 23:27 ` [PATCH v3 01/11] drm/xe: Add normalize_invalidation_range Matthew Brost
2026-01-12 23:27 ` [PATCH v3 02/11] drm/xe: Make usm.asid_to_vm allocation use GFP_NOWAIT Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-13 1:01 ` Summers, Stuart
2026-01-12 23:27 ` [PATCH v3 04/11] drm/xe: Add vm to exec queues association Matthew Brost
` (9 subsequent siblings)
12 siblings, 1 reply; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Introduce the xe_device_asid_to_vm helper, which can be used throughout
the driver to resolve the VM from a given ASID.
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
---
drivers/gpu/drm/xe/xe_device.c | 25 +++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_device.h | 4 ++++
2 files changed, 29 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index e400ad5c9f9e..445cf6da9dc7 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -1417,3 +1417,28 @@ const char *xe_wedged_mode_to_string(enum xe_wedged_mode mode)
return "<invalid>";
}
}
+
+/**
+ * xe_device_asid_to_vm() - Find VM from ASID
+ * @xe: the &xe_device
+ * @asid: Address space ID
+ *
+ * Find a VM from ASID and take a reference to VM which caller must drop.
+ * Reclaim safe.
+ *
+ * Return: VM on success, ERR_PTR on failure
+ */
+struct xe_vm *xe_device_asid_to_vm(struct xe_device *xe, u32 asid)
+{
+ struct xe_vm *vm;
+
+ down_read(&xe->usm.lock);
+ vm = xa_load(&xe->usm.asid_to_vm, asid);
+ if (vm)
+ xe_vm_get(vm);
+ else
+ vm = ERR_PTR(-EINVAL);
+ up_read(&xe->usm.lock);
+
+ return vm;
+}
diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h
index 3740143790db..10d04c324257 100644
--- a/drivers/gpu/drm/xe/xe_device.h
+++ b/drivers/gpu/drm/xe/xe_device.h
@@ -6,6 +6,8 @@
#ifndef _XE_DEVICE_H_
#define _XE_DEVICE_H_
+struct xe_vm;
+
#include <drm/drm_util.h>
#include "xe_device_types.h"
@@ -204,6 +206,8 @@ int xe_is_injection_active(void);
bool xe_is_xe_file(const struct file *file);
+struct xe_vm *xe_device_asid_to_vm(struct xe_device *xe, u32 asid);
+
/*
* Occasionally it is seen that the G2H worker starts running after a delay of more than
* a second even after being queued and activated by the Linux workqueue subsystem. This
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH v3 03/11] drm/xe: Add xe_device_asid_to_vm helper
2026-01-12 23:27 ` [PATCH v3 03/11] drm/xe: Add xe_device_asid_to_vm helper Matthew Brost
@ 2026-01-13 1:01 ` Summers, Stuart
2026-01-13 1:36 ` Matthew Brost
0 siblings, 1 reply; 24+ messages in thread
From: Summers, Stuart @ 2026-01-13 1:01 UTC (permalink / raw)
To: intel-xe@lists.freedesktop.org, Brost, Matthew
On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> Introduce the xe_device_asid_to_vm helper, which can be used
> throughout
> the driver to resolve the VM from a given ASID.
>
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
> ---
> drivers/gpu/drm/xe/xe_device.c | 25 +++++++++++++++++++++++++
> drivers/gpu/drm/xe/xe_device.h | 4 ++++
> 2 files changed, 29 insertions(+)
>
> diff --git a/drivers/gpu/drm/xe/xe_device.c
> b/drivers/gpu/drm/xe/xe_device.c
> index e400ad5c9f9e..445cf6da9dc7 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -1417,3 +1417,28 @@ const char *xe_wedged_mode_to_string(enum
> xe_wedged_mode mode)
> return "<invalid>";
> }
> }
> +
> +/**
> + * xe_device_asid_to_vm() - Find VM from ASID
> + * @xe: the &xe_device
> + * @asid: Address space ID
> + *
> + * Find a VM from ASID and take a reference to VM which caller must
> drop.
> + * Reclaim safe.
> + *
> + * Return: VM on success, ERR_PTR on failure
> + */
> +struct xe_vm *xe_device_asid_to_vm(struct xe_device *xe, u32 asid)
> +{
> + struct xe_vm *vm;
> +
> + down_read(&xe->usm.lock);
> + vm = xa_load(&xe->usm.asid_to_vm, asid);
> + if (vm)
> + xe_vm_get(vm);
> + else
> + vm = ERR_PTR(-EINVAL);
> + up_read(&xe->usm.lock);
> +
> + return vm;
> +}
> diff --git a/drivers/gpu/drm/xe/xe_device.h
> b/drivers/gpu/drm/xe/xe_device.h
> index 3740143790db..10d04c324257 100644
> --- a/drivers/gpu/drm/xe/xe_device.h
> +++ b/drivers/gpu/drm/xe/xe_device.h
> @@ -6,6 +6,8 @@
> #ifndef _XE_DEVICE_H_
> #define _XE_DEVICE_H_
>
> +struct xe_vm;
Can you move this down below the include statements below?
Otherwise:
Reviewed-by: Stuart Summers <stuart.summers@intel.com>
Thanks,
Stuart
> +
> #include <drm/drm_util.h>
>
> #include "xe_device_types.h"
> @@ -204,6 +206,8 @@ int xe_is_injection_active(void);
>
> bool xe_is_xe_file(const struct file *file);
>
> +struct xe_vm *xe_device_asid_to_vm(struct xe_device *xe, u32 asid);
> +
> /*
> * Occasionally it is seen that the G2H worker starts running after
> a delay of more than
> * a second even after being queued and activated by the Linux
> workqueue subsystem. This
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v3 03/11] drm/xe: Add xe_device_asid_to_vm helper
2026-01-13 1:01 ` Summers, Stuart
@ 2026-01-13 1:36 ` Matthew Brost
0 siblings, 0 replies; 24+ messages in thread
From: Matthew Brost @ 2026-01-13 1:36 UTC (permalink / raw)
To: Summers, Stuart; +Cc: intel-xe@lists.freedesktop.org
On Mon, Jan 12, 2026 at 06:01:27PM -0700, Summers, Stuart wrote:
> On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> > Introduce the xe_device_asid_to_vm helper, which can be used
> > throughout
> > the driver to resolve the VM from a given ASID.
> >
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
> > ---
> > drivers/gpu/drm/xe/xe_device.c | 25 +++++++++++++++++++++++++
> > drivers/gpu/drm/xe/xe_device.h | 4 ++++
> > 2 files changed, 29 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/xe/xe_device.c
> > b/drivers/gpu/drm/xe/xe_device.c
> > index e400ad5c9f9e..445cf6da9dc7 100644
> > --- a/drivers/gpu/drm/xe/xe_device.c
> > +++ b/drivers/gpu/drm/xe/xe_device.c
> > @@ -1417,3 +1417,28 @@ const char *xe_wedged_mode_to_string(enum
> > xe_wedged_mode mode)
> > return "<invalid>";
> > }
> > }
> > +
> > +/**
> > + * xe_device_asid_to_vm() - Find VM from ASID
> > + * @xe: the &xe_device
> > + * @asid: Address space ID
> > + *
> > + * Find a VM from ASID and take a reference to VM which caller must
> > drop.
> > + * Reclaim safe.
> > + *
> > + * Return: VM on success, ERR_PTR on failure
> > + */
> > +struct xe_vm *xe_device_asid_to_vm(struct xe_device *xe, u32 asid)
> > +{
> > + struct xe_vm *vm;
> > +
> > + down_read(&xe->usm.lock);
> > + vm = xa_load(&xe->usm.asid_to_vm, asid);
> > + if (vm)
> > + xe_vm_get(vm);
> > + else
> > + vm = ERR_PTR(-EINVAL);
> > + up_read(&xe->usm.lock);
> > +
> > + return vm;
> > +}
> > diff --git a/drivers/gpu/drm/xe/xe_device.h
> > b/drivers/gpu/drm/xe/xe_device.h
> > index 3740143790db..10d04c324257 100644
> > --- a/drivers/gpu/drm/xe/xe_device.h
> > +++ b/drivers/gpu/drm/xe/xe_device.h
> > @@ -6,6 +6,8 @@
> > #ifndef _XE_DEVICE_H_
> > #define _XE_DEVICE_H_
> >
> > +struct xe_vm;
>
> Can you move this down below the include statements below?
>
Yes, will do.
Matt
> Otherwise:
> Reviewed-by: Stuart Summers <stuart.summers@intel.com>
>
> Thanks,
> Stuart
>
> > +
> > #include <drm/drm_util.h>
> >
> > #include "xe_device_types.h"
> > @@ -204,6 +206,8 @@ int xe_is_injection_active(void);
> >
> > bool xe_is_xe_file(const struct file *file);
> >
> > +struct xe_vm *xe_device_asid_to_vm(struct xe_device *xe, u32 asid);
> > +
> > /*
> > * Occasionally it is seen that the G2H worker starts running after
> > a delay of more than
> > * a second even after being queued and activated by the Linux
> > workqueue subsystem. This
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v3 04/11] drm/xe: Add vm to exec queues association
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (2 preceding siblings ...)
2026-01-12 23:27 ` [PATCH v3 03/11] drm/xe: Add xe_device_asid_to_vm helper Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-13 1:04 ` Summers, Stuart
2026-01-12 23:27 ` [PATCH v3 05/11] drm/xe: Taint TLB invalidation seqno lock with GFP_KERNEL Matthew Brost
` (8 subsequent siblings)
12 siblings, 1 reply; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Maintain a list of exec queues per vm which will be used by TLB
invalidation code to do context-ID based tlb invalidations.
Signed-off-by: Nirmoy Das <nirmoy.das@intel.com>
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Stuart Summers <stuart.summers@intel.com>
---
drivers/gpu/drm/xe/xe_device.h | 7 ----
drivers/gpu/drm/xe/xe_device_types.h | 7 ++++
drivers/gpu/drm/xe/xe_exec_queue.c | 7 +++-
drivers/gpu/drm/xe/xe_exec_queue_types.h | 3 ++
drivers/gpu/drm/xe/xe_vm.c | 46 ++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_vm.h | 3 ++
drivers/gpu/drm/xe/xe_vm_types.h | 13 +++++++
7 files changed, 78 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h
index 10d04c324257..db939fc82f71 100644
--- a/drivers/gpu/drm/xe/xe_device.h
+++ b/drivers/gpu/drm/xe/xe_device.h
@@ -62,13 +62,6 @@ static inline struct xe_tile *xe_device_get_root_tile(struct xe_device *xe)
return &xe->tiles[0];
}
-/*
- * Highest GT/tile count for any platform. Used only for memory allocation
- * sizing. Any logic looping over GTs or mapping userspace GT IDs into GT
- * structures should use the per-platform xe->info.max_gt_per_tile instead.
- */
-#define XE_MAX_GT_PER_TILE 2
-
static inline struct xe_gt *xe_device_get_gt(struct xe_device *xe, u8 gt_id)
{
struct xe_tile *tile;
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 4dab3057f58d..8db870aaa382 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -79,6 +79,13 @@ enum xe_wedged_mode {
#define XE_GT1 1
#define XE_MAX_TILES_PER_DEVICE (XE_GT1 + 1)
+/*
+ * Highest GT/tile count for any platform. Used only for memory allocation
+ * sizing. Any logic looping over GTs or mapping userspace GT IDs into GT
+ * structures should use the per-platform xe->info.max_gt_per_tile instead.
+ */
+#define XE_MAX_GT_PER_TILE 2
+
#define XE_MAX_ASID (BIT(20))
#define IS_PLATFORM_STEP(_xe, _platform, min_step, max_step) \
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index b5737563ee14..ce309d848916 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -154,8 +154,10 @@ static void __xe_exec_queue_free(struct xe_exec_queue *q)
if (xe_exec_queue_is_multi_queue(q))
xe_exec_queue_group_cleanup(q);
- if (q->vm)
+ if (q->vm) {
+ xe_vm_remove_exec_queue(q->vm, q);
xe_vm_put(q->vm);
+ }
if (q->xef)
xe_file_put(q->xef);
@@ -226,6 +228,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
q->ring_ops = gt->ring_ops[hwe->class];
q->ops = gt->exec_queue_ops;
INIT_LIST_HEAD(&q->lr.link);
+ INIT_LIST_HEAD(&q->vm_exec_queue_link);
INIT_LIST_HEAD(&q->multi_gt_link);
INIT_LIST_HEAD(&q->hw_engine_group_link);
INIT_LIST_HEAD(&q->pxp.link);
@@ -1205,6 +1208,8 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
}
q->xef = xe_file_get(xef);
+ if (eci[0].engine_class != DRM_XE_ENGINE_CLASS_VM_BIND)
+ xe_vm_add_exec_queue(vm, q);
/* user id alloc must always be last in ioctl to prevent UAF */
err = xa_alloc(&xef->exec_queue.xa, &id, q, xa_limit_32b, GFP_KERNEL);
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index 5fc516b0bb77..d3e2789cf5bc 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -205,6 +205,9 @@ struct xe_exec_queue {
struct dma_fence *last_fence;
} tlb_inval[XE_EXEC_QUEUE_TLB_INVAL_COUNT];
+ /** @vm_exec_queue_link: Link to track exec queue within a VM's list of exec queues. */
+ struct list_head vm_exec_queue_link;
+
/** @pxp: PXP info tracking */
struct {
/** @pxp.type: PXP session type used by this queue */
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index bdb04d6bf39c..3a1a1bd74d8d 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1530,11 +1530,23 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)
INIT_WORK(&vm->destroy_work, vm_destroy_work_func);
INIT_LIST_HEAD(&vm->preempt.exec_queues);
+ INIT_LIST_HEAD(&vm->exec_queues.list);
if (flags & XE_VM_FLAG_FAULT_MODE)
vm->preempt.min_run_period_ms = xe->min_run_period_pf_ms;
else
vm->preempt.min_run_period_ms = xe->min_run_period_lr_ms;
+ init_rwsem(&vm->exec_queues.lock);
+ if (IS_ENABLED(CONFIG_PROVE_LOCKING)) {
+ fs_reclaim_acquire(GFP_KERNEL);
+ might_lock(&vm->exec_queues.lock);
+ fs_reclaim_release(GFP_KERNEL);
+
+ down_read(&vm->exec_queues.lock);
+ might_lock(&xe_root_mmio_gt(xe)->uc.guc.ct.lock);
+ up_read(&vm->exec_queues.lock);
+ }
+
for_each_tile(tile, xe, id)
xe_range_fence_tree_init(&vm->rftree[id]);
@@ -4570,3 +4582,37 @@ int xe_vm_alloc_cpu_addr_mirror_vma(struct xe_vm *vm, uint64_t start, uint64_t r
return xe_vm_alloc_vma(vm, &map_req, false);
}
+/**
+ * xe_vm_add_exec_queue() - Add exec queue to VM
+ * @vm: The VM.
+ * @q: The exec_queue
+ */
+void xe_vm_add_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
+{
+ /* User VMs and queues only */
+ xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_KERNEL));
+ xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_PERMANENT));
+ xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_VM));
+ xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_MIGRATE));
+ xe_assert(vm->xe, vm->xef);
+
+ down_write(&vm->exec_queues.lock);
+ list_add(&q->vm_exec_queue_link, &vm->exec_queues.list);
+ ++vm->exec_queues.count[q->gt->info.id];
+ up_write(&vm->exec_queues.lock);
+}
+
+/**
+ * xe_vm_remove_exec_queue() - Remove exec queue from VM
+ * @vm: The VM.
+ * @q: The exec_queue
+ */
+void xe_vm_remove_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
+{
+ down_write(&vm->exec_queues.lock);
+ if (!list_empty(&q->vm_exec_queue_link)) {
+ list_del(&q->vm_exec_queue_link);
+ --vm->exec_queues.count[q->gt->info.id];
+ }
+ up_write(&vm->exec_queues.lock);
+}
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index 6cc98df47291..288115c7844a 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -287,6 +287,9 @@ static inline struct dma_resv *xe_vm_resv(struct xe_vm *vm)
void xe_vm_kill(struct xe_vm *vm, bool unlocked);
+void xe_vm_add_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q);
+void xe_vm_remove_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q);
+
/**
* xe_vm_assert_held(vm) - Assert that the vm's reservation object is held.
* @vm: The vm
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index 437f64202f3b..87318a4f5b08 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -298,6 +298,19 @@ struct xe_vm {
struct list_head pm_activate_link;
} preempt;
+ /** @exec_queues: Manages list of exec queues attached to this VM, protected by lock. */
+ struct {
+ /** @exec_queues.list: list of exec queues attached to this VM */
+ struct list_head list;
+ /**
+ * @exec_queues.count: count of exec queues attached to this VM,
+ * per GT
+ */
+ int count[XE_MAX_TILES_PER_DEVICE * XE_MAX_GT_PER_TILE];
+ /** @exec_queues.lock: lock to protect exec_queues list */
+ struct rw_semaphore lock;
+ } exec_queues;
+
/** @um: unified memory state */
struct {
/** @asid: address space ID, unique to each VM */
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH v3 04/11] drm/xe: Add vm to exec queues association
2026-01-12 23:27 ` [PATCH v3 04/11] drm/xe: Add vm to exec queues association Matthew Brost
@ 2026-01-13 1:04 ` Summers, Stuart
2026-01-13 1:30 ` Matthew Brost
0 siblings, 1 reply; 24+ messages in thread
From: Summers, Stuart @ 2026-01-13 1:04 UTC (permalink / raw)
To: intel-xe@lists.freedesktop.org, Brost, Matthew
On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> Maintain a list of exec queues per vm which will be used by TLB
> invalidation code to do context-ID based tlb invalidations.
>
> Signed-off-by: Nirmoy Das <nirmoy.das@intel.com>
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> Reviewed-by: Stuart Summers <stuart.summers@intel.com>
> ---
> drivers/gpu/drm/xe/xe_device.h | 7 ----
> drivers/gpu/drm/xe/xe_device_types.h | 7 ++++
> drivers/gpu/drm/xe/xe_exec_queue.c | 7 +++-
> drivers/gpu/drm/xe/xe_exec_queue_types.h | 3 ++
> drivers/gpu/drm/xe/xe_vm.c | 46
> ++++++++++++++++++++++++
> drivers/gpu/drm/xe/xe_vm.h | 3 ++
> drivers/gpu/drm/xe/xe_vm_types.h | 13 +++++++
> 7 files changed, 78 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_device.h
> b/drivers/gpu/drm/xe/xe_device.h
> index 10d04c324257..db939fc82f71 100644
> --- a/drivers/gpu/drm/xe/xe_device.h
> +++ b/drivers/gpu/drm/xe/xe_device.h
> @@ -62,13 +62,6 @@ static inline struct xe_tile
> *xe_device_get_root_tile(struct xe_device *xe)
> return &xe->tiles[0];
> }
>
> -/*
> - * Highest GT/tile count for any platform. Used only for memory
> allocation
> - * sizing. Any logic looping over GTs or mapping userspace GT IDs
> into GT
> - * structures should use the per-platform xe->info.max_gt_per_tile
> instead.
> - */
> -#define XE_MAX_GT_PER_TILE 2
> -
> static inline struct xe_gt *xe_device_get_gt(struct xe_device *xe,
> u8 gt_id)
> {
> struct xe_tile *tile;
> diff --git a/drivers/gpu/drm/xe/xe_device_types.h
> b/drivers/gpu/drm/xe/xe_device_types.h
> index 4dab3057f58d..8db870aaa382 100644
> --- a/drivers/gpu/drm/xe/xe_device_types.h
> +++ b/drivers/gpu/drm/xe/xe_device_types.h
> @@ -79,6 +79,13 @@ enum xe_wedged_mode {
> #define XE_GT1 1
> #define XE_MAX_TILES_PER_DEVICE (XE_GT1 + 1)
>
> +/*
> + * Highest GT/tile count for any platform. Used only for memory
> allocation
> + * sizing. Any logic looping over GTs or mapping userspace GT IDs
> into GT
> + * structures should use the per-platform xe->info.max_gt_per_tile
> instead.
> + */
> +#define XE_MAX_GT_PER_TILE 2
> +
> #define XE_MAX_ASID (BIT(20))
>
> #define IS_PLATFORM_STEP(_xe, _platform, min_step, max_step) \
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c
> b/drivers/gpu/drm/xe/xe_exec_queue.c
> index b5737563ee14..ce309d848916 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> @@ -154,8 +154,10 @@ static void __xe_exec_queue_free(struct
> xe_exec_queue *q)
> if (xe_exec_queue_is_multi_queue(q))
> xe_exec_queue_group_cleanup(q);
>
> - if (q->vm)
> + if (q->vm) {
> + xe_vm_remove_exec_queue(q->vm, q);
> xe_vm_put(q->vm);
> + }
>
> if (q->xef)
> xe_file_put(q->xef);
> @@ -226,6 +228,7 @@ static struct xe_exec_queue
> *__xe_exec_queue_alloc(struct xe_device *xe,
> q->ring_ops = gt->ring_ops[hwe->class];
> q->ops = gt->exec_queue_ops;
> INIT_LIST_HEAD(&q->lr.link);
> + INIT_LIST_HEAD(&q->vm_exec_queue_link);
> INIT_LIST_HEAD(&q->multi_gt_link);
> INIT_LIST_HEAD(&q->hw_engine_group_link);
> INIT_LIST_HEAD(&q->pxp.link);
> @@ -1205,6 +1208,8 @@ int xe_exec_queue_create_ioctl(struct
> drm_device *dev, void *data,
> }
>
> q->xef = xe_file_get(xef);
> + if (eci[0].engine_class != DRM_XE_ENGINE_CLASS_VM_BIND)
> + xe_vm_add_exec_queue(vm, q);
This still will hit an issue if we're sending a TLB invalidation before
we register the context with GuC, just to reiterate... of course we
agreed to move forward here.
>
> /* user id alloc must always be last in ioctl to prevent UAF
> */
> err = xa_alloc(&xef->exec_queue.xa, &id, q, xa_limit_32b,
> GFP_KERNEL);
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> index 5fc516b0bb77..d3e2789cf5bc 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> @@ -205,6 +205,9 @@ struct xe_exec_queue {
> struct dma_fence *last_fence;
> } tlb_inval[XE_EXEC_QUEUE_TLB_INVAL_COUNT];
>
> + /** @vm_exec_queue_link: Link to track exec queue within a
> VM's list of exec queues. */
> + struct list_head vm_exec_queue_link;
> +
> /** @pxp: PXP info tracking */
> struct {
> /** @pxp.type: PXP session type used by this queue */
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index bdb04d6bf39c..3a1a1bd74d8d 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1530,11 +1530,23 @@ struct xe_vm *xe_vm_create(struct xe_device
> *xe, u32 flags, struct xe_file *xef)
> INIT_WORK(&vm->destroy_work, vm_destroy_work_func);
>
> INIT_LIST_HEAD(&vm->preempt.exec_queues);
> + INIT_LIST_HEAD(&vm->exec_queues.list);
> if (flags & XE_VM_FLAG_FAULT_MODE)
> vm->preempt.min_run_period_ms = xe-
> >min_run_period_pf_ms;
> else
> vm->preempt.min_run_period_ms = xe-
> >min_run_period_lr_ms;
>
> + init_rwsem(&vm->exec_queues.lock);
> + if (IS_ENABLED(CONFIG_PROVE_LOCKING)) {
> + fs_reclaim_acquire(GFP_KERNEL);
> + might_lock(&vm->exec_queues.lock);
> + fs_reclaim_release(GFP_KERNEL);
> +
> + down_read(&vm->exec_queues.lock);
> + might_lock(&xe_root_mmio_gt(xe)->uc.guc.ct.lock);
> + up_read(&vm->exec_queues.lock);
> + }
> +
> for_each_tile(tile, xe, id)
> xe_range_fence_tree_init(&vm->rftree[id]);
>
> @@ -4570,3 +4582,37 @@ int xe_vm_alloc_cpu_addr_mirror_vma(struct
> xe_vm *vm, uint64_t start, uint64_t r
> return xe_vm_alloc_vma(vm, &map_req, false);
> }
>
> +/**
> + * xe_vm_add_exec_queue() - Add exec queue to VM
> + * @vm: The VM.
> + * @q: The exec_queue
> + */
> +void xe_vm_add_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
> +{
> + /* User VMs and queues only */
> + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_KERNEL));
> + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_PERMANENT));
> + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_VM));
> + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_MIGRATE));
> + xe_assert(vm->xe, vm->xef);
Can you add a check here against has_ctx_tlb_inval? No need to maintain
this list if the platform doesn't support this invalidation.
Can we also assert that the q->vm is the same as the vm being passed
above? We want to make sure we aren't adding a queue from another VM
here.
Thanks,
Stuart
> +
> + down_write(&vm->exec_queues.lock);
> + list_add(&q->vm_exec_queue_link, &vm->exec_queues.list);
> + ++vm->exec_queues.count[q->gt->info.id];
> + up_write(&vm->exec_queues.lock);
> +}
> +
> +/**
> + * xe_vm_remove_exec_queue() - Remove exec queue from VM
> + * @vm: The VM.
> + * @q: The exec_queue
> + */
> +void xe_vm_remove_exec_queue(struct xe_vm *vm, struct xe_exec_queue
> *q)
> +{
> + down_write(&vm->exec_queues.lock);
> + if (!list_empty(&q->vm_exec_queue_link)) {
> + list_del(&q->vm_exec_queue_link);
> + --vm->exec_queues.count[q->gt->info.id];
> + }
> + up_write(&vm->exec_queues.lock);
> +}
> diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
> index 6cc98df47291..288115c7844a 100644
> --- a/drivers/gpu/drm/xe/xe_vm.h
> +++ b/drivers/gpu/drm/xe/xe_vm.h
> @@ -287,6 +287,9 @@ static inline struct dma_resv *xe_vm_resv(struct
> xe_vm *vm)
>
> void xe_vm_kill(struct xe_vm *vm, bool unlocked);
>
> +void xe_vm_add_exec_queue(struct xe_vm *vm, struct xe_exec_queue
> *q);
> +void xe_vm_remove_exec_queue(struct xe_vm *vm, struct xe_exec_queue
> *q);
> +
> /**
> * xe_vm_assert_held(vm) - Assert that the vm's reservation object
> is held.
> * @vm: The vm
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> b/drivers/gpu/drm/xe/xe_vm_types.h
> index 437f64202f3b..87318a4f5b08 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -298,6 +298,19 @@ struct xe_vm {
> struct list_head pm_activate_link;
> } preempt;
>
> + /** @exec_queues: Manages list of exec queues attached to
> this VM, protected by lock. */
> + struct {
> + /** @exec_queues.list: list of exec queues attached
> to this VM */
> + struct list_head list;
> + /**
> + * @exec_queues.count: count of exec queues attached
> to this VM,
> + * per GT
> + */
> + int count[XE_MAX_TILES_PER_DEVICE *
> XE_MAX_GT_PER_TILE];
> + /** @exec_queues.lock: lock to protect exec_queues
> list */
> + struct rw_semaphore lock;
> + } exec_queues;
> +
> /** @um: unified memory state */
> struct {
> /** @asid: address space ID, unique to each VM */
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v3 04/11] drm/xe: Add vm to exec queues association
2026-01-13 1:04 ` Summers, Stuart
@ 2026-01-13 1:30 ` Matthew Brost
2026-01-13 21:55 ` Summers, Stuart
0 siblings, 1 reply; 24+ messages in thread
From: Matthew Brost @ 2026-01-13 1:30 UTC (permalink / raw)
To: Summers, Stuart; +Cc: intel-xe@lists.freedesktop.org
On Mon, Jan 12, 2026 at 06:04:53PM -0700, Summers, Stuart wrote:
> On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> > Maintain a list of exec queues per vm which will be used by TLB
> > invalidation code to do context-ID based tlb invalidations.
> >
> > Signed-off-by: Nirmoy Das <nirmoy.das@intel.com>
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > Reviewed-by: Stuart Summers <stuart.summers@intel.com>
> > ---
> > drivers/gpu/drm/xe/xe_device.h | 7 ----
> > drivers/gpu/drm/xe/xe_device_types.h | 7 ++++
> > drivers/gpu/drm/xe/xe_exec_queue.c | 7 +++-
> > drivers/gpu/drm/xe/xe_exec_queue_types.h | 3 ++
> > drivers/gpu/drm/xe/xe_vm.c | 46
> > ++++++++++++++++++++++++
> > drivers/gpu/drm/xe/xe_vm.h | 3 ++
> > drivers/gpu/drm/xe/xe_vm_types.h | 13 +++++++
> > 7 files changed, 78 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/xe/xe_device.h
> > b/drivers/gpu/drm/xe/xe_device.h
> > index 10d04c324257..db939fc82f71 100644
> > --- a/drivers/gpu/drm/xe/xe_device.h
> > +++ b/drivers/gpu/drm/xe/xe_device.h
> > @@ -62,13 +62,6 @@ static inline struct xe_tile
> > *xe_device_get_root_tile(struct xe_device *xe)
> > return &xe->tiles[0];
> > }
> >
> > -/*
> > - * Highest GT/tile count for any platform. Used only for memory
> > allocation
> > - * sizing. Any logic looping over GTs or mapping userspace GT IDs
> > into GT
> > - * structures should use the per-platform xe->info.max_gt_per_tile
> > instead.
> > - */
> > -#define XE_MAX_GT_PER_TILE 2
> > -
> > static inline struct xe_gt *xe_device_get_gt(struct xe_device *xe,
> > u8 gt_id)
> > {
> > struct xe_tile *tile;
> > diff --git a/drivers/gpu/drm/xe/xe_device_types.h
> > b/drivers/gpu/drm/xe/xe_device_types.h
> > index 4dab3057f58d..8db870aaa382 100644
> > --- a/drivers/gpu/drm/xe/xe_device_types.h
> > +++ b/drivers/gpu/drm/xe/xe_device_types.h
> > @@ -79,6 +79,13 @@ enum xe_wedged_mode {
> > #define XE_GT1 1
> > #define XE_MAX_TILES_PER_DEVICE (XE_GT1 + 1)
> >
> > +/*
> > + * Highest GT/tile count for any platform. Used only for memory
> > allocation
> > + * sizing. Any logic looping over GTs or mapping userspace GT IDs
> > into GT
> > + * structures should use the per-platform xe->info.max_gt_per_tile
> > instead.
> > + */
> > +#define XE_MAX_GT_PER_TILE 2
> > +
> > #define XE_MAX_ASID (BIT(20))
> >
> > #define IS_PLATFORM_STEP(_xe, _platform, min_step, max_step) \
> > diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c
> > b/drivers/gpu/drm/xe/xe_exec_queue.c
> > index b5737563ee14..ce309d848916 100644
> > --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> > +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> > @@ -154,8 +154,10 @@ static void __xe_exec_queue_free(struct
> > xe_exec_queue *q)
> > if (xe_exec_queue_is_multi_queue(q))
> > xe_exec_queue_group_cleanup(q);
> >
> > - if (q->vm)
> > + if (q->vm) {
> > + xe_vm_remove_exec_queue(q->vm, q);
> > xe_vm_put(q->vm);
> > + }
> >
> > if (q->xef)
> > xe_file_put(q->xef);
> > @@ -226,6 +228,7 @@ static struct xe_exec_queue
> > *__xe_exec_queue_alloc(struct xe_device *xe,
> > q->ring_ops = gt->ring_ops[hwe->class];
> > q->ops = gt->exec_queue_ops;
> > INIT_LIST_HEAD(&q->lr.link);
> > + INIT_LIST_HEAD(&q->vm_exec_queue_link);
> > INIT_LIST_HEAD(&q->multi_gt_link);
> > INIT_LIST_HEAD(&q->hw_engine_group_link);
> > INIT_LIST_HEAD(&q->pxp.link);
> > @@ -1205,6 +1208,8 @@ int xe_exec_queue_create_ioctl(struct
> > drm_device *dev, void *data,
> > }
> >
> > q->xef = xe_file_get(xef);
> > + if (eci[0].engine_class != DRM_XE_ENGINE_CLASS_VM_BIND)
> > + xe_vm_add_exec_queue(vm, q);
>
> This still will hit an issue if we're sending a TLB invalidation before
> we register the context with GuC, just to reiterate... of course we
> agreed to move forward here.
>
Ah, no. The active vfunc called in last patch prevents against this.
> >
> > /* user id alloc must always be last in ioctl to prevent UAF
> > */
> > err = xa_alloc(&xef->exec_queue.xa, &id, q, xa_limit_32b,
> > GFP_KERNEL);
> > diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> > b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> > index 5fc516b0bb77..d3e2789cf5bc 100644
> > --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> > +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> > @@ -205,6 +205,9 @@ struct xe_exec_queue {
> > struct dma_fence *last_fence;
> > } tlb_inval[XE_EXEC_QUEUE_TLB_INVAL_COUNT];
> >
> > + /** @vm_exec_queue_link: Link to track exec queue within a
> > VM's list of exec queues. */
> > + struct list_head vm_exec_queue_link;
> > +
> > /** @pxp: PXP info tracking */
> > struct {
> > /** @pxp.type: PXP session type used by this queue */
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index bdb04d6bf39c..3a1a1bd74d8d 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1530,11 +1530,23 @@ struct xe_vm *xe_vm_create(struct xe_device
> > *xe, u32 flags, struct xe_file *xef)
> > INIT_WORK(&vm->destroy_work, vm_destroy_work_func);
> >
> > INIT_LIST_HEAD(&vm->preempt.exec_queues);
> > + INIT_LIST_HEAD(&vm->exec_queues.list);
> > if (flags & XE_VM_FLAG_FAULT_MODE)
> > vm->preempt.min_run_period_ms = xe-
> > >min_run_period_pf_ms;
> > else
> > vm->preempt.min_run_period_ms = xe-
> > >min_run_period_lr_ms;
> >
> > + init_rwsem(&vm->exec_queues.lock);
> > + if (IS_ENABLED(CONFIG_PROVE_LOCKING)) {
> > + fs_reclaim_acquire(GFP_KERNEL);
> > + might_lock(&vm->exec_queues.lock);
> > + fs_reclaim_release(GFP_KERNEL);
> > +
> > + down_read(&vm->exec_queues.lock);
> > + might_lock(&xe_root_mmio_gt(xe)->uc.guc.ct.lock);
> > + up_read(&vm->exec_queues.lock);
> > + }
> > +
> > for_each_tile(tile, xe, id)
> > xe_range_fence_tree_init(&vm->rftree[id]);
> >
> > @@ -4570,3 +4582,37 @@ int xe_vm_alloc_cpu_addr_mirror_vma(struct
> > xe_vm *vm, uint64_t start, uint64_t r
> > return xe_vm_alloc_vma(vm, &map_req, false);
> > }
> >
> > +/**
> > + * xe_vm_add_exec_queue() - Add exec queue to VM
> > + * @vm: The VM.
> > + * @q: The exec_queue
> > + */
> > +void xe_vm_add_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
> > +{
> > + /* User VMs and queues only */
> > + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_KERNEL));
> > + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_PERMANENT));
> > + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_VM));
> > + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_MIGRATE));
> > + xe_assert(vm->xe, vm->xef);
>
> Can you add a check here against has_ctx_tlb_inval? No need to maintain
> this list if the platform doesn't support this invalidation.
>
Yes, I do that.
> Can we also assert that the q->vm is the same as the vm being passed
> above? We want to make sure we aren't adding a queue from another VM
> here.
>
Yes, I can also do that.
Matt
> Thanks,
> Stuart
>
> > +
> > + down_write(&vm->exec_queues.lock);
> > + list_add(&q->vm_exec_queue_link, &vm->exec_queues.list);
> > + ++vm->exec_queues.count[q->gt->info.id];
> > + up_write(&vm->exec_queues.lock);
> > +}
> > +
> > +/**
> > + * xe_vm_remove_exec_queue() - Remove exec queue from VM
> > + * @vm: The VM.
> > + * @q: The exec_queue
> > + */
> > +void xe_vm_remove_exec_queue(struct xe_vm *vm, struct xe_exec_queue
> > *q)
> > +{
> > + down_write(&vm->exec_queues.lock);
> > + if (!list_empty(&q->vm_exec_queue_link)) {
> > + list_del(&q->vm_exec_queue_link);
> > + --vm->exec_queues.count[q->gt->info.id];
> > + }
> > + up_write(&vm->exec_queues.lock);
> > +}
> > diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
> > index 6cc98df47291..288115c7844a 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.h
> > +++ b/drivers/gpu/drm/xe/xe_vm.h
> > @@ -287,6 +287,9 @@ static inline struct dma_resv *xe_vm_resv(struct
> > xe_vm *vm)
> >
> > void xe_vm_kill(struct xe_vm *vm, bool unlocked);
> >
> > +void xe_vm_add_exec_queue(struct xe_vm *vm, struct xe_exec_queue
> > *q);
> > +void xe_vm_remove_exec_queue(struct xe_vm *vm, struct xe_exec_queue
> > *q);
> > +
> > /**
> > * xe_vm_assert_held(vm) - Assert that the vm's reservation object
> > is held.
> > * @vm: The vm
> > diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> > b/drivers/gpu/drm/xe/xe_vm_types.h
> > index 437f64202f3b..87318a4f5b08 100644
> > --- a/drivers/gpu/drm/xe/xe_vm_types.h
> > +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> > @@ -298,6 +298,19 @@ struct xe_vm {
> > struct list_head pm_activate_link;
> > } preempt;
> >
> > + /** @exec_queues: Manages list of exec queues attached to
> > this VM, protected by lock. */
> > + struct {
> > + /** @exec_queues.list: list of exec queues attached
> > to this VM */
> > + struct list_head list;
> > + /**
> > + * @exec_queues.count: count of exec queues attached
> > to this VM,
> > + * per GT
> > + */
> > + int count[XE_MAX_TILES_PER_DEVICE *
> > XE_MAX_GT_PER_TILE];
> > + /** @exec_queues.lock: lock to protect exec_queues
> > list */
> > + struct rw_semaphore lock;
> > + } exec_queues;
> > +
> > /** @um: unified memory state */
> > struct {
> > /** @asid: address space ID, unique to each VM */
>
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v3 04/11] drm/xe: Add vm to exec queues association
2026-01-13 1:30 ` Matthew Brost
@ 2026-01-13 21:55 ` Summers, Stuart
0 siblings, 0 replies; 24+ messages in thread
From: Summers, Stuart @ 2026-01-13 21:55 UTC (permalink / raw)
To: Brost, Matthew; +Cc: intel-xe@lists.freedesktop.org
On Mon, 2026-01-12 at 17:30 -0800, Matthew Brost wrote:
> On Mon, Jan 12, 2026 at 06:04:53PM -0700, Summers, Stuart wrote:
> > On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> > > Maintain a list of exec queues per vm which will be used by TLB
> > > invalidation code to do context-ID based tlb invalidations.
> > >
> > > Signed-off-by: Nirmoy Das <nirmoy.das@intel.com>
> > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > Reviewed-by: Stuart Summers <stuart.summers@intel.com>
> > > ---
> > > drivers/gpu/drm/xe/xe_device.h | 7 ----
> > > drivers/gpu/drm/xe/xe_device_types.h | 7 ++++
> > > drivers/gpu/drm/xe/xe_exec_queue.c | 7 +++-
> > > drivers/gpu/drm/xe/xe_exec_queue_types.h | 3 ++
> > > drivers/gpu/drm/xe/xe_vm.c | 46
> > > ++++++++++++++++++++++++
> > > drivers/gpu/drm/xe/xe_vm.h | 3 ++
> > > drivers/gpu/drm/xe/xe_vm_types.h | 13 +++++++
> > > 7 files changed, 78 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_device.h
> > > b/drivers/gpu/drm/xe/xe_device.h
> > > index 10d04c324257..db939fc82f71 100644
> > > --- a/drivers/gpu/drm/xe/xe_device.h
> > > +++ b/drivers/gpu/drm/xe/xe_device.h
> > > @@ -62,13 +62,6 @@ static inline struct xe_tile
> > > *xe_device_get_root_tile(struct xe_device *xe)
> > > return &xe->tiles[0];
> > > }
> > >
> > > -/*
> > > - * Highest GT/tile count for any platform. Used only for memory
> > > allocation
> > > - * sizing. Any logic looping over GTs or mapping userspace GT
> > > IDs
> > > into GT
> > > - * structures should use the per-platform xe-
> > > >info.max_gt_per_tile
> > > instead.
> > > - */
> > > -#define XE_MAX_GT_PER_TILE 2
> > > -
> > > static inline struct xe_gt *xe_device_get_gt(struct xe_device
> > > *xe,
> > > u8 gt_id)
> > > {
> > > struct xe_tile *tile;
> > > diff --git a/drivers/gpu/drm/xe/xe_device_types.h
> > > b/drivers/gpu/drm/xe/xe_device_types.h
> > > index 4dab3057f58d..8db870aaa382 100644
> > > --- a/drivers/gpu/drm/xe/xe_device_types.h
> > > +++ b/drivers/gpu/drm/xe/xe_device_types.h
> > > @@ -79,6 +79,13 @@ enum xe_wedged_mode {
> > > #define XE_GT1 1
> > > #define XE_MAX_TILES_PER_DEVICE (XE_GT1 + 1)
> > >
> > > +/*
> > > + * Highest GT/tile count for any platform. Used only for memory
> > > allocation
> > > + * sizing. Any logic looping over GTs or mapping userspace GT
> > > IDs
> > > into GT
> > > + * structures should use the per-platform xe-
> > > >info.max_gt_per_tile
> > > instead.
> > > + */
> > > +#define XE_MAX_GT_PER_TILE 2
> > > +
> > > #define XE_MAX_ASID (BIT(20))
> > >
> > > #define IS_PLATFORM_STEP(_xe, _platform, min_step, max_step) \
> > > diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c
> > > b/drivers/gpu/drm/xe/xe_exec_queue.c
> > > index b5737563ee14..ce309d848916 100644
> > > --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> > > +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> > > @@ -154,8 +154,10 @@ static void __xe_exec_queue_free(struct
> > > xe_exec_queue *q)
> > > if (xe_exec_queue_is_multi_queue(q))
> > > xe_exec_queue_group_cleanup(q);
> > >
> > > - if (q->vm)
> > > + if (q->vm) {
> > > + xe_vm_remove_exec_queue(q->vm, q);
> > > xe_vm_put(q->vm);
> > > + }
> > >
> > > if (q->xef)
> > > xe_file_put(q->xef);
> > > @@ -226,6 +228,7 @@ static struct xe_exec_queue
> > > *__xe_exec_queue_alloc(struct xe_device *xe,
> > > q->ring_ops = gt->ring_ops[hwe->class];
> > > q->ops = gt->exec_queue_ops;
> > > INIT_LIST_HEAD(&q->lr.link);
> > > + INIT_LIST_HEAD(&q->vm_exec_queue_link);
> > > INIT_LIST_HEAD(&q->multi_gt_link);
> > > INIT_LIST_HEAD(&q->hw_engine_group_link);
> > > INIT_LIST_HEAD(&q->pxp.link);
> > > @@ -1205,6 +1208,8 @@ int xe_exec_queue_create_ioctl(struct
> > > drm_device *dev, void *data,
> > > }
> > >
> > > q->xef = xe_file_get(xef);
> > > + if (eci[0].engine_class != DRM_XE_ENGINE_CLASS_VM_BIND)
> > > + xe_vm_add_exec_queue(vm, q);
> >
> > This still will hit an issue if we're sending a TLB invalidation
> > before
> > we register the context with GuC, just to reiterate... of course we
> > agreed to move forward here.
> >
>
> Ah, no. The active vfunc called in last patch prevents against this.
Yeah sorry I hadn't looked over that patch in as much detail in the
review yesterday yet. But I see it. Went ahead and responded in the
latest series.
Thanks,
Stuart
>
> > >
> > > /* user id alloc must always be last in ioctl to prevent
> > > UAF
> > > */
> > > err = xa_alloc(&xef->exec_queue.xa, &id, q, xa_limit_32b,
> > > GFP_KERNEL);
> > > diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> > > b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> > > index 5fc516b0bb77..d3e2789cf5bc 100644
> > > --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> > > +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> > > @@ -205,6 +205,9 @@ struct xe_exec_queue {
> > > struct dma_fence *last_fence;
> > > } tlb_inval[XE_EXEC_QUEUE_TLB_INVAL_COUNT];
> > >
> > > + /** @vm_exec_queue_link: Link to track exec queue within
> > > a
> > > VM's list of exec queues. */
> > > + struct list_head vm_exec_queue_link;
> > > +
> > > /** @pxp: PXP info tracking */
> > > struct {
> > > /** @pxp.type: PXP session type used by this
> > > queue */
> > > diff --git a/drivers/gpu/drm/xe/xe_vm.c
> > > b/drivers/gpu/drm/xe/xe_vm.c
> > > index bdb04d6bf39c..3a1a1bd74d8d 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm.c
> > > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > > @@ -1530,11 +1530,23 @@ struct xe_vm *xe_vm_create(struct
> > > xe_device
> > > *xe, u32 flags, struct xe_file *xef)
> > > INIT_WORK(&vm->destroy_work, vm_destroy_work_func);
> > >
> > > INIT_LIST_HEAD(&vm->preempt.exec_queues);
> > > + INIT_LIST_HEAD(&vm->exec_queues.list);
> > > if (flags & XE_VM_FLAG_FAULT_MODE)
> > > vm->preempt.min_run_period_ms = xe-
> > > > min_run_period_pf_ms;
> > > else
> > > vm->preempt.min_run_period_ms = xe-
> > > > min_run_period_lr_ms;
> > >
> > > + init_rwsem(&vm->exec_queues.lock);
> > > + if (IS_ENABLED(CONFIG_PROVE_LOCKING)) {
> > > + fs_reclaim_acquire(GFP_KERNEL);
> > > + might_lock(&vm->exec_queues.lock);
> > > + fs_reclaim_release(GFP_KERNEL);
> > > +
> > > + down_read(&vm->exec_queues.lock);
> > > + might_lock(&xe_root_mmio_gt(xe)->uc.guc.ct.lock);
> > > + up_read(&vm->exec_queues.lock);
> > > + }
> > > +
> > > for_each_tile(tile, xe, id)
> > > xe_range_fence_tree_init(&vm->rftree[id]);
> > >
> > > @@ -4570,3 +4582,37 @@ int xe_vm_alloc_cpu_addr_mirror_vma(struct
> > > xe_vm *vm, uint64_t start, uint64_t r
> > > return xe_vm_alloc_vma(vm, &map_req, false);
> > > }
> > >
> > > +/**
> > > + * xe_vm_add_exec_queue() - Add exec queue to VM
> > > + * @vm: The VM.
> > > + * @q: The exec_queue
> > > + */
> > > +void xe_vm_add_exec_queue(struct xe_vm *vm, struct xe_exec_queue
> > > *q)
> > > +{
> > > + /* User VMs and queues only */
> > > + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_KERNEL));
> > > + xe_assert(vm->xe, !(q->flags &
> > > EXEC_QUEUE_FLAG_PERMANENT));
> > > + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_VM));
> > > + xe_assert(vm->xe, !(q->flags & EXEC_QUEUE_FLAG_MIGRATE));
> > > + xe_assert(vm->xe, vm->xef);
> >
> > Can you add a check here against has_ctx_tlb_inval? No need to
> > maintain
> > this list if the platform doesn't support this invalidation.
> >
>
> Yes, I do that.
>
> > Can we also assert that the q->vm is the same as the vm being
> > passed
> > above? We want to make sure we aren't adding a queue from another
> > VM
> > here.
> >
>
> Yes, I can also do that.
>
> Matt
>
> > Thanks,
> > Stuart
> >
> > > +
> > > + down_write(&vm->exec_queues.lock);
> > > + list_add(&q->vm_exec_queue_link, &vm->exec_queues.list);
> > > + ++vm->exec_queues.count[q->gt->info.id];
> > > + up_write(&vm->exec_queues.lock);
> > > +}
> > > +
> > > +/**
> > > + * xe_vm_remove_exec_queue() - Remove exec queue from VM
> > > + * @vm: The VM.
> > > + * @q: The exec_queue
> > > + */
> > > +void xe_vm_remove_exec_queue(struct xe_vm *vm, struct
> > > xe_exec_queue
> > > *q)
> > > +{
> > > + down_write(&vm->exec_queues.lock);
> > > + if (!list_empty(&q->vm_exec_queue_link)) {
> > > + list_del(&q->vm_exec_queue_link);
> > > + --vm->exec_queues.count[q->gt->info.id];
> > > + }
> > > + up_write(&vm->exec_queues.lock);
> > > +}
> > > diff --git a/drivers/gpu/drm/xe/xe_vm.h
> > > b/drivers/gpu/drm/xe/xe_vm.h
> > > index 6cc98df47291..288115c7844a 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm.h
> > > +++ b/drivers/gpu/drm/xe/xe_vm.h
> > > @@ -287,6 +287,9 @@ static inline struct dma_resv
> > > *xe_vm_resv(struct
> > > xe_vm *vm)
> > >
> > > void xe_vm_kill(struct xe_vm *vm, bool unlocked);
> > >
> > > +void xe_vm_add_exec_queue(struct xe_vm *vm, struct xe_exec_queue
> > > *q);
> > > +void xe_vm_remove_exec_queue(struct xe_vm *vm, struct
> > > xe_exec_queue
> > > *q);
> > > +
> > > /**
> > > * xe_vm_assert_held(vm) - Assert that the vm's reservation
> > > object
> > > is held.
> > > * @vm: The vm
> > > diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> > > b/drivers/gpu/drm/xe/xe_vm_types.h
> > > index 437f64202f3b..87318a4f5b08 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm_types.h
> > > +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> > > @@ -298,6 +298,19 @@ struct xe_vm {
> > > struct list_head pm_activate_link;
> > > } preempt;
> > >
> > > + /** @exec_queues: Manages list of exec queues attached to
> > > this VM, protected by lock. */
> > > + struct {
> > > + /** @exec_queues.list: list of exec queues
> > > attached
> > > to this VM */
> > > + struct list_head list;
> > > + /**
> > > + * @exec_queues.count: count of exec queues
> > > attached
> > > to this VM,
> > > + * per GT
> > > + */
> > > + int count[XE_MAX_TILES_PER_DEVICE *
> > > XE_MAX_GT_PER_TILE];
> > > + /** @exec_queues.lock: lock to protect
> > > exec_queues
> > > list */
> > > + struct rw_semaphore lock;
> > > + } exec_queues;
> > > +
> > > /** @um: unified memory state */
> > > struct {
> > > /** @asid: address space ID, unique to each VM */
> >
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v3 05/11] drm/xe: Taint TLB invalidation seqno lock with GFP_KERNEL
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (3 preceding siblings ...)
2026-01-12 23:27 ` [PATCH v3 04/11] drm/xe: Add vm to exec queues association Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-12 23:27 ` [PATCH v3 06/11] drm/xe: Rename send_tlb_inval_ppgtt to send_tlb_inval_asid_ppgtt Matthew Brost
` (7 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Taint TLB invalidation seqno lock with GFP_KERNEL as TLB invalidations
can be in the path of reclaim (e.g., MMU notifiers).
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
---
drivers/gpu/drm/xe/xe_tlb_inval.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c
index dec042248164..014a78502fe5 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval.c
@@ -114,6 +114,16 @@ static void tlb_inval_fini(struct drm_device *drm, void *arg)
xe_tlb_inval_reset(tlb_inval);
}
+static void primelockdep(struct xe_tlb_inval *tlb_inval)
+{
+ if (!IS_ENABLED(CONFIG_LOCKDEP))
+ return;
+
+ fs_reclaim_acquire(GFP_KERNEL);
+ might_lock(&tlb_inval->seqno_lock);
+ fs_reclaim_release(GFP_KERNEL);
+}
+
/**
* xe_gt_tlb_inval_init - Initialize TLB invalidation state
* @gt: GT structure
@@ -140,6 +150,8 @@ int xe_gt_tlb_inval_init_early(struct xe_gt *gt)
if (err)
return err;
+ primelockdep(tlb_inval);
+
tlb_inval->job_wq = drmm_alloc_ordered_workqueue(&xe->drm,
"gt-tbl-inval-job-wq",
WQ_MEM_RECLAIM);
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v3 06/11] drm/xe: Rename send_tlb_inval_ppgtt to send_tlb_inval_asid_ppgtt
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (4 preceding siblings ...)
2026-01-12 23:27 ` [PATCH v3 05/11] drm/xe: Taint TLB invalidation seqno lock with GFP_KERNEL Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-12 23:27 ` [PATCH v3 07/11] drm/xe: Add send_tlb_inval_ppgtt helper Matthew Brost
` (6 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Context-based TLB invalidations have their own set of GuC TLB
invalidation operations. Rename the current PPGTT invalidation function,
which operates on ASIDs, to a more descriptive name that reflects its
purpose.
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Stuart Summers <stuart.summers@intel.com>
---
drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
index 43f6dbcb2bc2..a6a1c371a28e 100644
--- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
@@ -150,9 +150,9 @@ static u64 normalize_invalidation_range(struct xe_gt *gt, u64 *start, u64 *end)
*/
#define MAX_RANGE_TLB_INVALIDATION_LENGTH (rounddown_pow_of_two(ULONG_MAX))
-static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
- u64 start, u64 end, u32 asid,
- struct drm_suballoc *prl_sa)
+static int send_tlb_inval_asid_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
+ u64 start, u64 end, u32 asid,
+ struct drm_suballoc *prl_sa)
{
#define MAX_TLB_INVALIDATION_LEN 7
struct xe_guc *guc = tlb_inval->private;
@@ -219,7 +219,7 @@ static long tlb_inval_timeout_delay(struct xe_tlb_inval *tlb_inval)
static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
.all = send_tlb_inval_all,
.ggtt = send_tlb_inval_ggtt,
- .ppgtt = send_tlb_inval_ppgtt,
+ .ppgtt = send_tlb_inval_asid_ppgtt,
.initialized = tlb_inval_initialized,
.flush = tlb_inval_flush,
.timeout_delay = tlb_inval_timeout_delay,
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v3 07/11] drm/xe: Add send_tlb_inval_ppgtt helper
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (5 preceding siblings ...)
2026-01-12 23:27 ` [PATCH v3 06/11] drm/xe: Rename send_tlb_inval_ppgtt to send_tlb_inval_asid_ppgtt Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-12 23:27 ` [PATCH v3 08/11] drm/xe: Add xe_tlb_inval_idle helper Matthew Brost
` (5 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Extract the common code that issues a TLB invalidation H2G for PPGTTs
into a helper function. This helper can be reused for both ASID-based
and context-based TLB invalidations.
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Stuart Summers <stuart.summers@intel.com>
---
drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 30 +++++++++++++++++++--------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
index a6a1c371a28e..070d2e2cb7c9 100644
--- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
@@ -150,20 +150,16 @@ static u64 normalize_invalidation_range(struct xe_gt *gt, u64 *start, u64 *end)
*/
#define MAX_RANGE_TLB_INVALIDATION_LENGTH (rounddown_pow_of_two(ULONG_MAX))
-static int send_tlb_inval_asid_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
- u64 start, u64 end, u32 asid,
- struct drm_suballoc *prl_sa)
+static int send_tlb_inval_ppgtt(struct xe_guc *guc, u32 seqno, u64 start,
+ u64 end, u32 id, u32 type,
+ struct drm_suballoc *prl_sa)
{
#define MAX_TLB_INVALIDATION_LEN 7
- struct xe_guc *guc = tlb_inval->private;
struct xe_gt *gt = guc_to_gt(guc);
u32 action[MAX_TLB_INVALIDATION_LEN];
u64 length = end - start;
int len = 0, err;
- if (guc_to_xe(guc)->info.force_execlist)
- return -ECANCELED;
-
action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
action[len++] = !prl_sa ? seqno : TLB_INVALIDATION_SEQNO_INVALID;
if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
@@ -174,14 +170,15 @@ static int send_tlb_inval_asid_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
&end);
/* Flush on NULL case, Media is not required to modify flush due to no PPC so NOP */
- action[len++] = MAKE_INVAL_OP_FLUSH(XE_GUC_TLB_INVAL_PAGE_SELECTIVE, !prl_sa);
- action[len++] = asid;
+ action[len++] = MAKE_INVAL_OP_FLUSH(type, !prl_sa);
+ action[len++] = id;
action[len++] = lower_32_bits(start);
action[len++] = upper_32_bits(start);
action[len++] = ilog2(normalize_len) - ilog2(SZ_4K);
}
xe_gt_assert(gt, len <= MAX_TLB_INVALIDATION_LEN);
+#undef MAX_TLB_INVALIDATION_LEN
err = send_tlb_inval(guc, action, len);
if (!err && prl_sa)
@@ -189,6 +186,21 @@ static int send_tlb_inval_asid_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
return err;
}
+static int send_tlb_inval_asid_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
+ u64 start, u64 end, u32 asid,
+ struct drm_suballoc *prl_sa)
+{
+ struct xe_guc *guc = tlb_inval->private;
+
+ lockdep_assert_held(&tlb_inval->seqno_lock);
+
+ if (guc_to_xe(guc)->info.force_execlist)
+ return -ECANCELED;
+
+ return send_tlb_inval_ppgtt(guc, seqno, start, end, asid,
+ XE_GUC_TLB_INVAL_PAGE_SELECTIVE, prl_sa);
+}
+
static bool tlb_inval_initialized(struct xe_tlb_inval *tlb_inval)
{
struct xe_guc *guc = tlb_inval->private;
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v3 08/11] drm/xe: Add xe_tlb_inval_idle helper
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (6 preceding siblings ...)
2026-01-12 23:27 ` [PATCH v3 07/11] drm/xe: Add send_tlb_inval_ppgtt helper Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-12 23:27 ` [PATCH v3 09/11] drm/xe: Add exec queue active vfunc Matthew Brost
` (4 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Introduce the xe_tlb_inval_idle helper to detect whether any TLB
invalidations are currently in flight. This is used in context-based TLB
invalidations to determine whether dummy TLB invalidations need to be
sent to maintain proper TLB invalidation fence ordering..
v2:
- Implement xe_tlb_inval_idle based on pending list
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Stuart Summers <stuart.summers@intel.com>
---
drivers/gpu/drm/xe/xe_tlb_inval.c | 21 +++++++++++++++++++++
drivers/gpu/drm/xe/xe_tlb_inval.h | 2 ++
2 files changed, 23 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c
index 014a78502fe5..daabc9370510 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval.c
@@ -44,11 +44,14 @@ static void xe_tlb_inval_fence_fini(struct xe_tlb_inval_fence *fence)
static void
xe_tlb_inval_fence_signal(struct xe_tlb_inval_fence *fence)
{
+ struct xe_tlb_inval *tlb_inval = fence->tlb_inval;
bool stack = test_bit(FENCE_STACK_BIT, &fence->base.flags);
lockdep_assert_held(&fence->tlb_inval->pending_lock);
list_del(&fence->link);
+ if (list_empty(&tlb_inval->pending_fences))
+ cancel_delayed_work(&tlb_inval->fence_tdr);
trace_xe_tlb_inval_fence_signal(fence->tlb_inval->xe, fence);
xe_tlb_inval_fence_fini(fence);
dma_fence_signal(&fence->base);
@@ -464,3 +467,21 @@ void xe_tlb_inval_fence_init(struct xe_tlb_inval *tlb_inval,
dma_fence_get(&fence->base);
fence->tlb_inval = tlb_inval;
}
+
+/**
+ * xe_tlb_inval_idle() - Initialize TLB invalidation is idle
+ * @tlb_inval: TLB invalidation client
+ *
+ * Check the TLB invalidation seqno to determine if it is idle (i.e., no TLB
+ * invalidations are in flight). Expected to be called in the backend after the
+ * fence has been added to the pending list, and takes this into account.
+ *
+ * Return: True if TLB invalidation client is idle, False otherwise
+ */
+bool xe_tlb_inval_idle(struct xe_tlb_inval *tlb_inval)
+{
+ lockdep_assert_held(&tlb_inval->seqno_lock);
+
+ guard(spinlock_irq)(&tlb_inval->pending_lock);
+ return list_is_singular(&tlb_inval->pending_fences);
+}
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.h b/drivers/gpu/drm/xe/xe_tlb_inval.h
index 858d0690f995..62089254fa23 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval.h
+++ b/drivers/gpu/drm/xe/xe_tlb_inval.h
@@ -43,4 +43,6 @@ xe_tlb_inval_fence_wait(struct xe_tlb_inval_fence *fence)
void xe_tlb_inval_done_handler(struct xe_tlb_inval *tlb_inval, int seqno);
+bool xe_tlb_inval_idle(struct xe_tlb_inval *tlb_inval);
+
#endif /* _XE_TLB_INVAL_ */
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v3 09/11] drm/xe: Add exec queue active vfunc
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (7 preceding siblings ...)
2026-01-12 23:27 ` [PATCH v3 08/11] drm/xe: Add xe_tlb_inval_idle helper Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-12 23:27 ` [PATCH v3 10/11] drm/xe: Add context-based invalidation to GuC TLB invalidation backend Matthew Brost
` (3 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
If an exec queue is inactive (e.g., not registered or scheduling is
disabled), TLB invalidations are not issued for that queue. Add a
virtual function to determine the active state, which TLB invalidation
logic can hook into.
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
drivers/gpu/drm/xe/xe_exec_queue_types.h | 2 ++
drivers/gpu/drm/xe/xe_execlist.c | 7 +++++++
drivers/gpu/drm/xe/xe_guc_submit.c | 6 ++++++
3 files changed, 15 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index d3e2789cf5bc..9cca558c5809 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -298,6 +298,8 @@ struct xe_exec_queue_ops {
void (*resume)(struct xe_exec_queue *q);
/** @reset_status: check exec queue reset status */
bool (*reset_status)(struct xe_exec_queue *q);
+ /** @active: check exec queue is active */
+ bool (*active)(struct xe_exec_queue *q);
};
#endif
diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c
index 46c17a18a3f4..e4a2674f48c7 100644
--- a/drivers/gpu/drm/xe/xe_execlist.c
+++ b/drivers/gpu/drm/xe/xe_execlist.c
@@ -469,6 +469,12 @@ static bool execlist_exec_queue_reset_status(struct xe_exec_queue *q)
return false;
}
+static bool execlist_exec_queue_active(struct xe_exec_queue *q)
+{
+ /* NIY */
+ return false;
+}
+
static const struct xe_exec_queue_ops execlist_exec_queue_ops = {
.init = execlist_exec_queue_init,
.kill = execlist_exec_queue_kill,
@@ -481,6 +487,7 @@ static const struct xe_exec_queue_ops execlist_exec_queue_ops = {
.suspend_wait = execlist_exec_queue_suspend_wait,
.resume = execlist_exec_queue_resume,
.reset_status = execlist_exec_queue_reset_status,
+ .active = execlist_exec_queue_active,
};
int xe_execlist_init(struct xe_gt *gt)
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index be8fa76baf1d..19282e5ca897 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -2203,6 +2203,11 @@ static bool guc_exec_queue_reset_status(struct xe_exec_queue *q)
return exec_queue_reset(q) || exec_queue_killed_or_banned_or_wedged(q);
}
+static bool guc_exec_queue_active(struct xe_exec_queue *q)
+{
+ return exec_queue_enabled(q) && !exec_queue_pending_disable(q);
+}
+
/*
* All of these functions are an abstraction layer which other parts of Xe can
* use to trap into the GuC backend. All of these functions, aside from init,
@@ -2222,6 +2227,7 @@ static const struct xe_exec_queue_ops guc_exec_queue_ops = {
.suspend_wait = guc_exec_queue_suspend_wait,
.resume = guc_exec_queue_resume,
.reset_status = guc_exec_queue_reset_status,
+ .active = guc_exec_queue_active,
};
static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v3 10/11] drm/xe: Add context-based invalidation to GuC TLB invalidation backend
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (8 preceding siblings ...)
2026-01-12 23:27 ` [PATCH v3 09/11] drm/xe: Add exec queue active vfunc Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-13 1:28 ` Summers, Stuart
2026-01-12 23:27 ` [PATCH v3 11/11] drm/xe: Enable context TLB invalidations for CI Matthew Brost
` (2 subsequent siblings)
12 siblings, 1 reply; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Introduce context-based invalidation support to the GuC TLB invalidation
backend. This is implemented by iterating over each exec queue per GT
within a VM, skipping inactive queues, and issuing a context-based (GuC
ID) H2G TLB invalidation. All H2G messages, except the final one, are
sent with an invalid seqno, which the G2H handler drops to ensure the
TLB invalidation fence is only signaled once all H2G messages are
completed.
A watermark mechanism is also added to switch between context-based TLB
invalidations and full device-wide invalidations, as the return on
investment for context-based invalidation diminishes when many exec
queues are mapped.
v2:
- Fix checkpatch warnings
v3:
- Rebase on PRL
- Use ref counting to avoid racing with deregisters
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
drivers/gpu/drm/xe/xe_device_types.h | 2 +
drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 145 +++++++++++++++++++++++++-
drivers/gpu/drm/xe/xe_pci.c | 1 +
drivers/gpu/drm/xe/xe_pci_types.h | 1 +
4 files changed, 145 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 8db870aaa382..b51acff4edcd 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -358,6 +358,8 @@ struct xe_device {
u8 has_pre_prod_wa:1;
/** @info.has_pxp: Device has PXP support */
u8 has_pxp:1;
+ /** @info.has_ctx_tlb_inval: Has context based TLB invalidations */
+ u8 has_ctx_tlb_inval:1;
/** @info.has_range_tlb_inval: Has range based TLB invalidations */
u8 has_range_tlb_inval:1;
/** @info.has_soc_remapper_sysctrl: Has SoC remapper system controller */
diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
index 070d2e2cb7c9..328eced5f692 100644
--- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
@@ -6,15 +6,19 @@
#include "abi/guc_actions_abi.h"
#include "xe_device.h"
+#include "xe_exec_queue.h"
+#include "xe_exec_queue_types.h"
#include "xe_gt_stats.h"
#include "xe_gt_types.h"
#include "xe_guc.h"
#include "xe_guc_ct.h"
+#include "xe_guc_exec_queue_types.h"
#include "xe_guc_tlb_inval.h"
#include "xe_force_wake.h"
#include "xe_mmio.h"
#include "xe_sa.h"
#include "xe_tlb_inval.h"
+#include "xe_vm.h"
#include "regs/xe_guc_regs.h"
@@ -156,10 +160,16 @@ static int send_tlb_inval_ppgtt(struct xe_guc *guc, u32 seqno, u64 start,
{
#define MAX_TLB_INVALIDATION_LEN 7
struct xe_gt *gt = guc_to_gt(guc);
+ struct xe_device *xe = guc_to_xe(guc);
u32 action[MAX_TLB_INVALIDATION_LEN];
u64 length = end - start;
int len = 0, err;
+ xe_gt_assert(gt, (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE &&
+ !xe->info.has_ctx_tlb_inval) ||
+ (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX &&
+ xe->info.has_ctx_tlb_inval));
+
action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
action[len++] = !prl_sa ? seqno : TLB_INVALIDATION_SEQNO_INVALID;
if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
@@ -168,9 +178,11 @@ static int send_tlb_inval_ppgtt(struct xe_guc *guc, u32 seqno, u64 start,
} else {
u64 normalize_len = normalize_invalidation_range(gt, &start,
&end);
+ bool need_flush = !prl_sa &&
+ seqno != TLB_INVALIDATION_SEQNO_INVALID;
/* Flush on NULL case, Media is not required to modify flush due to no PPC so NOP */
- action[len++] = MAKE_INVAL_OP_FLUSH(type, !prl_sa);
+ action[len++] = MAKE_INVAL_OP_FLUSH(type, need_flush);
action[len++] = id;
action[len++] = lower_32_bits(start);
action[len++] = upper_32_bits(start);
@@ -181,8 +193,10 @@ static int send_tlb_inval_ppgtt(struct xe_guc *guc, u32 seqno, u64 start,
#undef MAX_TLB_INVALIDATION_LEN
err = send_tlb_inval(guc, action, len);
- if (!err && prl_sa)
+ if (!err && prl_sa) {
+ xe_gt_assert(gt, seqno != TLB_INVALIDATION_SEQNO_INVALID);
err = send_page_reclaim(guc, seqno, xe_sa_bo_gpu_addr(prl_sa));
+ }
return err;
}
@@ -201,6 +215,114 @@ static int send_tlb_inval_asid_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
XE_GUC_TLB_INVAL_PAGE_SELECTIVE, prl_sa);
}
+static bool queue_mapped_in_guc(struct xe_guc *guc, struct xe_exec_queue *q)
+{
+ return q->gt == guc_to_gt(guc);
+}
+
+static int send_tlb_inval_ctx_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
+ u64 start, u64 end, u32 asid,
+ struct drm_suballoc *prl_sa)
+{
+ struct xe_guc *guc = tlb_inval->private;
+ struct xe_device *xe = guc_to_xe(guc);
+ struct xe_exec_queue *q, *next, *last_q = NULL;
+ struct xe_vm *vm;
+ LIST_HEAD(tlb_inval_list);
+ int err = 0;
+
+ lockdep_assert_held(&tlb_inval->seqno_lock);
+
+ if (xe->info.force_execlist)
+ return -ECANCELED;
+
+ vm = xe_device_asid_to_vm(xe, asid);
+ if (IS_ERR(vm))
+ return PTR_ERR(vm);
+
+ down_read(&vm->exec_queues.lock);
+
+ /*
+ * XXX: Randomly picking a threshold for now. This will need to be
+ * tuned based on expected UMD queue counts and performance profiling.
+ */
+#define EXEC_QUEUE_COUNT_FULL_THRESHOLD 8
+ if (vm->exec_queues.count[guc_to_gt(guc)->info.id] >=
+ EXEC_QUEUE_COUNT_FULL_THRESHOLD) {
+ u32 action[] = {
+ XE_GUC_ACTION_TLB_INVALIDATION,
+ seqno,
+ MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL),
+ };
+
+ err = send_tlb_inval(guc, action, ARRAY_SIZE(action));
+ goto err_unlock;
+ }
+#undef EXEC_QUEUE_COUNT_FULL_THRESHOLD
+
+ /*
+ * Move exec queues to a temporary list to issue invalidations. The exec
+ * queue must be mapped in the current GuC, active, and a reference must
+ * be taken to prevent concurrent deregistrations.
+ */
+ list_for_each_entry_safe(q, next, &vm->exec_queues.list,
+ vm_exec_queue_link)
+ if (queue_mapped_in_guc(guc, q) && q->ops->active(q) &&
+ xe_exec_queue_get_unless_zero(q)) {
+ last_q = q;
+ list_move_tail(&q->vm_exec_queue_link, &tlb_inval_list);
+ }
+
+ if (!last_q) {
+ /*
+ * We can't break fence ordering for TLB invalidation jobs, if
+ * TLB invalidations are inflight issue a dummy invalidation to
+ * maintain ordering. Nor can we move safely the seqno_recv when
+ * returning -ECANCELED if TLB invalidations are in flight. Use
+ * GGTT invalidation as dummy invalidation given ASID
+ * invalidations are unsupported here.
+ */
+ if (xe_tlb_inval_idle(tlb_inval))
+ err = -ECANCELED;
+ else
+ err = send_tlb_inval_ggtt(tlb_inval, seqno);
+ goto err_unlock;
+ }
+
+ list_for_each_entry_safe(q, next, &tlb_inval_list, vm_exec_queue_link) {
+ struct drm_suballoc *__prl_sa = NULL;
+ int __seqno = TLB_INVALIDATION_SEQNO_INVALID;
+ u32 type = XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX;
+
+ xe_assert(xe, q->vm == vm);
+
+ if (err)
+ goto unref;
+
+ if (last_q == q) {
+ __prl_sa = prl_sa;
+ __seqno = seqno;
+ }
+
+ err = send_tlb_inval_ppgtt(guc, __seqno, start, end,
+ q->guc->id, type, __prl_sa);
+
+unref:
+ /*
+ * Must always return exec queue to original list / drop
+ * reference
+ */
+ xe_exec_queue_put(q);
+ list_move_tail(&q->vm_exec_queue_link, &vm->exec_queues.list);
+ }
+
+err_unlock:
+ up_read(&vm->exec_queues.lock);
+ xe_vm_put(vm);
+
+ return err;
+}
+
static bool tlb_inval_initialized(struct xe_tlb_inval *tlb_inval)
{
struct xe_guc *guc = tlb_inval->private;
@@ -228,7 +350,7 @@ static long tlb_inval_timeout_delay(struct xe_tlb_inval *tlb_inval)
return hw_tlb_timeout + 2 * delay;
}
-static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
+static const struct xe_tlb_inval_ops guc_tlb_inval_asid_ops = {
.all = send_tlb_inval_all,
.ggtt = send_tlb_inval_ggtt,
.ppgtt = send_tlb_inval_asid_ppgtt,
@@ -237,6 +359,15 @@ static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
.timeout_delay = tlb_inval_timeout_delay,
};
+static const struct xe_tlb_inval_ops guc_tlb_inval_ctx_ops = {
+ .ggtt = send_tlb_inval_ggtt,
+ .all = send_tlb_inval_all,
+ .ppgtt = send_tlb_inval_ctx_ppgtt,
+ .initialized = tlb_inval_initialized,
+ .flush = tlb_inval_flush,
+ .timeout_delay = tlb_inval_timeout_delay,
+};
+
/**
* xe_guc_tlb_inval_init_early() - Init GuC TLB invalidation early
* @guc: GuC object
@@ -248,8 +379,14 @@ static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
void xe_guc_tlb_inval_init_early(struct xe_guc *guc,
struct xe_tlb_inval *tlb_inval)
{
+ struct xe_device *xe = guc_to_xe(guc);
+
tlb_inval->private = guc;
- tlb_inval->ops = &guc_tlb_inval_ops;
+
+ if (xe->info.has_ctx_tlb_inval)
+ tlb_inval->ops = &guc_tlb_inval_ctx_ops;
+ else
+ tlb_inval->ops = &guc_tlb_inval_asid_ops;
}
/**
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 91e0553a8163..6ea1199f703e 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -889,6 +889,7 @@ static int xe_info_init(struct xe_device *xe,
xe->info.has_device_atomics_on_smem = 1;
xe->info.has_range_tlb_inval = graphics_desc->has_range_tlb_inval;
+ xe->info.has_ctx_tlb_inval = graphics_desc->has_ctx_tlb_inval;
xe->info.has_usm = graphics_desc->has_usm;
xe->info.has_64bit_timestamp = graphics_desc->has_64bit_timestamp;
diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h
index 5f20f56571d1..000b54cbcd0e 100644
--- a/drivers/gpu/drm/xe/xe_pci_types.h
+++ b/drivers/gpu/drm/xe/xe_pci_types.h
@@ -71,6 +71,7 @@ struct xe_graphics_desc {
u8 has_atomic_enable_pte_bit:1;
u8 has_indirect_ring_state:1;
u8 has_range_tlb_inval:1;
+ u8 has_ctx_tlb_inval:1;
u8 has_usm:1;
u8 has_64bit_timestamp:1;
};
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH v3 10/11] drm/xe: Add context-based invalidation to GuC TLB invalidation backend
2026-01-12 23:27 ` [PATCH v3 10/11] drm/xe: Add context-based invalidation to GuC TLB invalidation backend Matthew Brost
@ 2026-01-13 1:28 ` Summers, Stuart
2026-01-13 1:34 ` Matthew Brost
0 siblings, 1 reply; 24+ messages in thread
From: Summers, Stuart @ 2026-01-13 1:28 UTC (permalink / raw)
To: intel-xe@lists.freedesktop.org, Brost, Matthew
On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> Introduce context-based invalidation support to the GuC TLB
> invalidation
> backend. This is implemented by iterating over each exec queue per GT
> within a VM, skipping inactive queues, and issuing a context-based
> (GuC
> ID) H2G TLB invalidation. All H2G messages, except the final one, are
> sent with an invalid seqno, which the G2H handler drops to ensure the
> TLB invalidation fence is only signaled once all H2G messages are
> completed.
>
> A watermark mechanism is also added to switch between context-based
> TLB
> invalidations and full device-wide invalidations, as the return on
> investment for context-based invalidation diminishes when many exec
> queues are mapped.
>
> v2:
> - Fix checkpatch warnings
> v3:
> - Rebase on PRL
> - Use ref counting to avoid racing with deregisters
>
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> ---
> drivers/gpu/drm/xe/xe_device_types.h | 2 +
> drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 145
> +++++++++++++++++++++++++-
> drivers/gpu/drm/xe/xe_pci.c | 1 +
> drivers/gpu/drm/xe/xe_pci_types.h | 1 +
> 4 files changed, 145 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_device_types.h
> b/drivers/gpu/drm/xe/xe_device_types.h
> index 8db870aaa382..b51acff4edcd 100644
> --- a/drivers/gpu/drm/xe/xe_device_types.h
> +++ b/drivers/gpu/drm/xe/xe_device_types.h
> @@ -358,6 +358,8 @@ struct xe_device {
> u8 has_pre_prod_wa:1;
> /** @info.has_pxp: Device has PXP support */
> u8 has_pxp:1;
> + /** @info.has_ctx_tlb_inval: Has context based TLB
> invalidations */
> + u8 has_ctx_tlb_inval:1;
> /** @info.has_range_tlb_inval: Has range based TLB
> invalidations */
> u8 has_range_tlb_inval:1;
> /** @info.has_soc_remapper_sysctrl: Has SoC remapper
> system controller */
> diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> index 070d2e2cb7c9..328eced5f692 100644
> --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> @@ -6,15 +6,19 @@
> #include "abi/guc_actions_abi.h"
>
> #include "xe_device.h"
> +#include "xe_exec_queue.h"
> +#include "xe_exec_queue_types.h"
> #include "xe_gt_stats.h"
> #include "xe_gt_types.h"
> #include "xe_guc.h"
> #include "xe_guc_ct.h"
> +#include "xe_guc_exec_queue_types.h"
> #include "xe_guc_tlb_inval.h"
> #include "xe_force_wake.h"
> #include "xe_mmio.h"
> #include "xe_sa.h"
> #include "xe_tlb_inval.h"
> +#include "xe_vm.h"
>
> #include "regs/xe_guc_regs.h"
>
> @@ -156,10 +160,16 @@ static int send_tlb_inval_ppgtt(struct xe_guc
> *guc, u32 seqno, u64 start,
> {
> #define MAX_TLB_INVALIDATION_LEN 7
> struct xe_gt *gt = guc_to_gt(guc);
> + struct xe_device *xe = guc_to_xe(guc);
> u32 action[MAX_TLB_INVALIDATION_LEN];
> u64 length = end - start;
> int len = 0, err;
>
> + xe_gt_assert(gt, (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE &&
> + !xe->info.has_ctx_tlb_inval) ||
> + (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX &&
> + xe->info.has_ctx_tlb_inval));
> +
> action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
> action[len++] = !prl_sa ? seqno :
> TLB_INVALIDATION_SEQNO_INVALID;
> if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
> @@ -168,9 +178,11 @@ static int send_tlb_inval_ppgtt(struct xe_guc
> *guc, u32 seqno, u64 start,
> } else {
> u64 normalize_len = normalize_invalidation_range(gt,
> &start,
>
> &end);
> + bool need_flush = !prl_sa &&
> + seqno != TLB_INVALIDATION_SEQNO_INVALID;
>
> /* Flush on NULL case, Media is not required to
> modify flush due to no PPC so NOP */
> - action[len++] = MAKE_INVAL_OP_FLUSH(type, !prl_sa);
> + action[len++] = MAKE_INVAL_OP_FLUSH(type,
> need_flush);
> action[len++] = id;
> action[len++] = lower_32_bits(start);
> action[len++] = upper_32_bits(start);
> @@ -181,8 +193,10 @@ static int send_tlb_inval_ppgtt(struct xe_guc
> *guc, u32 seqno, u64 start,
> #undef MAX_TLB_INVALIDATION_LEN
>
> err = send_tlb_inval(guc, action, len);
> - if (!err && prl_sa)
> + if (!err && prl_sa) {
> + xe_gt_assert(gt, seqno !=
> TLB_INVALIDATION_SEQNO_INVALID);
> err = send_page_reclaim(guc, seqno,
> xe_sa_bo_gpu_addr(prl_sa));
> + }
> return err;
> }
>
> @@ -201,6 +215,114 @@ static int send_tlb_inval_asid_ppgtt(struct
> xe_tlb_inval *tlb_inval, u32 seqno,
> XE_GUC_TLB_INVAL_PAGE_SELECTIVE,
> prl_sa);
> }
>
> +static bool queue_mapped_in_guc(struct xe_guc *guc, struct
> xe_exec_queue *q)
> +{
> + return q->gt == guc_to_gt(guc);
> +}
> +
> +static int send_tlb_inval_ctx_ppgtt(struct xe_tlb_inval *tlb_inval,
> u32 seqno,
> + u64 start, u64 end, u32 asid,
> + struct drm_suballoc *prl_sa)
> +{
> + struct xe_guc *guc = tlb_inval->private;
> + struct xe_device *xe = guc_to_xe(guc);
> + struct xe_exec_queue *q, *next, *last_q = NULL;
> + struct xe_vm *vm;
> + LIST_HEAD(tlb_inval_list);
> + int err = 0;
> +
> + lockdep_assert_held(&tlb_inval->seqno_lock);
> +
> + if (xe->info.force_execlist)
> + return -ECANCELED;
> +
> + vm = xe_device_asid_to_vm(xe, asid);
> + if (IS_ERR(vm))
> + return PTR_ERR(vm);
> +
> + down_read(&vm->exec_queues.lock);
> +
> + /*
> + * XXX: Randomly picking a threshold for now. This will need
> to be
> + * tuned based on expected UMD queue counts and performance
> profiling.
> + */
> +#define EXEC_QUEUE_COUNT_FULL_THRESHOLD 8
> + if (vm->exec_queues.count[guc_to_gt(guc)->info.id] >=
> + EXEC_QUEUE_COUNT_FULL_THRESHOLD) {
> + u32 action[] = {
> + XE_GUC_ACTION_TLB_INVALIDATION,
> + seqno,
> + MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL),
> + };
> +
> + err = send_tlb_inval(guc, action,
> ARRAY_SIZE(action));
> + goto err_unlock;
> + }
> +#undef EXEC_QUEUE_COUNT_FULL_THRESHOLD
> +
> + /*
> + * Move exec queues to a temporary list to issue
> invalidations. The exec
> + * queue must be mapped in the current GuC, active, and a
> reference must
> + * be taken to prevent concurrent deregistrations.
> + */
> + list_for_each_entry_safe(q, next, &vm->exec_queues.list,
> + vm_exec_queue_link)
Nitpick: I'd prefer braces around the the if here so we aren't nesting
the multi-line condition within this list_for_each loop.
> + if (queue_mapped_in_guc(guc, q) && q->ops->active(q)
> &&
> + xe_exec_queue_get_unless_zero(q)) {
> + last_q = q;
> + list_move_tail(&q->vm_exec_queue_link,
> &tlb_inval_list);
> + }
> +
> + if (!last_q) {
> + /*
> + * We can't break fence ordering for TLB invalidation
> jobs, if
> + * TLB invalidations are inflight issue a dummy
> invalidation to
> + * maintain ordering. Nor can we move safely the
> seqno_recv when
> + * returning -ECANCELED if TLB invalidations are in
> flight. Use
> + * GGTT invalidation as dummy invalidation given ASID
> + * invalidations are unsupported here.
> + */
> + if (xe_tlb_inval_idle(tlb_inval))
> + err = -ECANCELED;
> + else
> + err = send_tlb_inval_ggtt(tlb_inval, seqno);
Can you give a little more context on this line actually? So this is
going to send down a 0x3 type invalidation to GuC (TLB_INVAL_GUC). GuC
is still doing an invalidation to hardware when we write this. Is that
the expectation with this?
> + goto err_unlock;
> + }
> +
> + list_for_each_entry_safe(q, next, &tlb_inval_list,
> vm_exec_queue_link) {
> + struct drm_suballoc *__prl_sa = NULL;
> + int __seqno = TLB_INVALIDATION_SEQNO_INVALID;
> + u32 type = XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX;
> +
> + xe_assert(xe, q->vm == vm);
> +
> + if (err)
> + goto unref;
> +
> + if (last_q == q) {
> + __prl_sa = prl_sa;
> + __seqno = seqno;
> + }
> +
> + err = send_tlb_inval_ppgtt(guc, __seqno, start, end,
> + q->guc->id, type,
> __prl_sa);
> +
> +unref:
> + /*
> + * Must always return exec queue to original list /
> drop
> + * reference
> + */
> + xe_exec_queue_put(q);
> + list_move_tail(&q->vm_exec_queue_link, &vm-
> >exec_queues.list);
Will get back on this one... need to spend a little more time and do
some testing.
Thanks,
Stuart
> + }
> +
> +err_unlock:
> + up_read(&vm->exec_queues.lock);
> + xe_vm_put(vm);
> +
> + return err;
> +}
> +
> static bool tlb_inval_initialized(struct xe_tlb_inval *tlb_inval)
> {
> struct xe_guc *guc = tlb_inval->private;
> @@ -228,7 +350,7 @@ static long tlb_inval_timeout_delay(struct
> xe_tlb_inval *tlb_inval)
> return hw_tlb_timeout + 2 * delay;
> }
>
> -static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
> +static const struct xe_tlb_inval_ops guc_tlb_inval_asid_ops = {
> .all = send_tlb_inval_all,
> .ggtt = send_tlb_inval_ggtt,
> .ppgtt = send_tlb_inval_asid_ppgtt,
> @@ -237,6 +359,15 @@ static const struct xe_tlb_inval_ops
> guc_tlb_inval_ops = {
> .timeout_delay = tlb_inval_timeout_delay,
> };
>
> +static const struct xe_tlb_inval_ops guc_tlb_inval_ctx_ops = {
> + .ggtt = send_tlb_inval_ggtt,
> + .all = send_tlb_inval_all,
> + .ppgtt = send_tlb_inval_ctx_ppgtt,
> + .initialized = tlb_inval_initialized,
> + .flush = tlb_inval_flush,
> + .timeout_delay = tlb_inval_timeout_delay,
> +};
> +
> /**
> * xe_guc_tlb_inval_init_early() - Init GuC TLB invalidation early
> * @guc: GuC object
> @@ -248,8 +379,14 @@ static const struct xe_tlb_inval_ops
> guc_tlb_inval_ops = {
> void xe_guc_tlb_inval_init_early(struct xe_guc *guc,
> struct xe_tlb_inval *tlb_inval)
> {
> + struct xe_device *xe = guc_to_xe(guc);
> +
> tlb_inval->private = guc;
> - tlb_inval->ops = &guc_tlb_inval_ops;
> +
> + if (xe->info.has_ctx_tlb_inval)
> + tlb_inval->ops = &guc_tlb_inval_ctx_ops;
> + else
> + tlb_inval->ops = &guc_tlb_inval_asid_ops;
> }
>
> /**
> diff --git a/drivers/gpu/drm/xe/xe_pci.c
> b/drivers/gpu/drm/xe/xe_pci.c
> index 91e0553a8163..6ea1199f703e 100644
> --- a/drivers/gpu/drm/xe/xe_pci.c
> +++ b/drivers/gpu/drm/xe/xe_pci.c
> @@ -889,6 +889,7 @@ static int xe_info_init(struct xe_device *xe,
> xe->info.has_device_atomics_on_smem = 1;
>
> xe->info.has_range_tlb_inval = graphics_desc-
> >has_range_tlb_inval;
> + xe->info.has_ctx_tlb_inval = graphics_desc-
> >has_ctx_tlb_inval;
> xe->info.has_usm = graphics_desc->has_usm;
> xe->info.has_64bit_timestamp = graphics_desc-
> >has_64bit_timestamp;
>
> diff --git a/drivers/gpu/drm/xe/xe_pci_types.h
> b/drivers/gpu/drm/xe/xe_pci_types.h
> index 5f20f56571d1..000b54cbcd0e 100644
> --- a/drivers/gpu/drm/xe/xe_pci_types.h
> +++ b/drivers/gpu/drm/xe/xe_pci_types.h
> @@ -71,6 +71,7 @@ struct xe_graphics_desc {
> u8 has_atomic_enable_pte_bit:1;
> u8 has_indirect_ring_state:1;
> u8 has_range_tlb_inval:1;
> + u8 has_ctx_tlb_inval:1;
> u8 has_usm:1;
> u8 has_64bit_timestamp:1;
> };
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v3 10/11] drm/xe: Add context-based invalidation to GuC TLB invalidation backend
2026-01-13 1:28 ` Summers, Stuart
@ 2026-01-13 1:34 ` Matthew Brost
2026-01-13 22:36 ` Summers, Stuart
0 siblings, 1 reply; 24+ messages in thread
From: Matthew Brost @ 2026-01-13 1:34 UTC (permalink / raw)
To: Summers, Stuart; +Cc: intel-xe@lists.freedesktop.org
On Mon, Jan 12, 2026 at 06:28:01PM -0700, Summers, Stuart wrote:
> On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> > Introduce context-based invalidation support to the GuC TLB
> > invalidation
> > backend. This is implemented by iterating over each exec queue per GT
> > within a VM, skipping inactive queues, and issuing a context-based
> > (GuC
> > ID) H2G TLB invalidation. All H2G messages, except the final one, are
> > sent with an invalid seqno, which the G2H handler drops to ensure the
> > TLB invalidation fence is only signaled once all H2G messages are
> > completed.
> >
> > A watermark mechanism is also added to switch between context-based
> > TLB
> > invalidations and full device-wide invalidations, as the return on
> > investment for context-based invalidation diminishes when many exec
> > queues are mapped.
> >
> > v2:
> > - Fix checkpatch warnings
> > v3:
> > - Rebase on PRL
> > - Use ref counting to avoid racing with deregisters
> >
> > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > ---
> > drivers/gpu/drm/xe/xe_device_types.h | 2 +
> > drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 145
> > +++++++++++++++++++++++++-
> > drivers/gpu/drm/xe/xe_pci.c | 1 +
> > drivers/gpu/drm/xe/xe_pci_types.h | 1 +
> > 4 files changed, 145 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/xe/xe_device_types.h
> > b/drivers/gpu/drm/xe/xe_device_types.h
> > index 8db870aaa382..b51acff4edcd 100644
> > --- a/drivers/gpu/drm/xe/xe_device_types.h
> > +++ b/drivers/gpu/drm/xe/xe_device_types.h
> > @@ -358,6 +358,8 @@ struct xe_device {
> > u8 has_pre_prod_wa:1;
> > /** @info.has_pxp: Device has PXP support */
> > u8 has_pxp:1;
> > + /** @info.has_ctx_tlb_inval: Has context based TLB
> > invalidations */
> > + u8 has_ctx_tlb_inval:1;
> > /** @info.has_range_tlb_inval: Has range based TLB
> > invalidations */
> > u8 has_range_tlb_inval:1;
> > /** @info.has_soc_remapper_sysctrl: Has SoC remapper
> > system controller */
> > diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > index 070d2e2cb7c9..328eced5f692 100644
> > --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > @@ -6,15 +6,19 @@
> > #include "abi/guc_actions_abi.h"
> >
> > #include "xe_device.h"
> > +#include "xe_exec_queue.h"
> > +#include "xe_exec_queue_types.h"
> > #include "xe_gt_stats.h"
> > #include "xe_gt_types.h"
> > #include "xe_guc.h"
> > #include "xe_guc_ct.h"
> > +#include "xe_guc_exec_queue_types.h"
> > #include "xe_guc_tlb_inval.h"
> > #include "xe_force_wake.h"
> > #include "xe_mmio.h"
> > #include "xe_sa.h"
> > #include "xe_tlb_inval.h"
> > +#include "xe_vm.h"
> >
> > #include "regs/xe_guc_regs.h"
> >
> > @@ -156,10 +160,16 @@ static int send_tlb_inval_ppgtt(struct xe_guc
> > *guc, u32 seqno, u64 start,
> > {
> > #define MAX_TLB_INVALIDATION_LEN 7
> > struct xe_gt *gt = guc_to_gt(guc);
> > + struct xe_device *xe = guc_to_xe(guc);
> > u32 action[MAX_TLB_INVALIDATION_LEN];
> > u64 length = end - start;
> > int len = 0, err;
> >
> > + xe_gt_assert(gt, (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE &&
> > + !xe->info.has_ctx_tlb_inval) ||
> > + (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX &&
> > + xe->info.has_ctx_tlb_inval));
> > +
> > action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
> > action[len++] = !prl_sa ? seqno :
> > TLB_INVALIDATION_SEQNO_INVALID;
> > if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
> > @@ -168,9 +178,11 @@ static int send_tlb_inval_ppgtt(struct xe_guc
> > *guc, u32 seqno, u64 start,
> > } else {
> > u64 normalize_len = normalize_invalidation_range(gt,
> > &start,
> >
> > &end);
> > + bool need_flush = !prl_sa &&
> > + seqno != TLB_INVALIDATION_SEQNO_INVALID;
> >
> > /* Flush on NULL case, Media is not required to
> > modify flush due to no PPC so NOP */
> > - action[len++] = MAKE_INVAL_OP_FLUSH(type, !prl_sa);
> > + action[len++] = MAKE_INVAL_OP_FLUSH(type,
> > need_flush);
> > action[len++] = id;
> > action[len++] = lower_32_bits(start);
> > action[len++] = upper_32_bits(start);
> > @@ -181,8 +193,10 @@ static int send_tlb_inval_ppgtt(struct xe_guc
> > *guc, u32 seqno, u64 start,
> > #undef MAX_TLB_INVALIDATION_LEN
> >
> > err = send_tlb_inval(guc, action, len);
> > - if (!err && prl_sa)
> > + if (!err && prl_sa) {
> > + xe_gt_assert(gt, seqno !=
> > TLB_INVALIDATION_SEQNO_INVALID);
> > err = send_page_reclaim(guc, seqno,
> > xe_sa_bo_gpu_addr(prl_sa));
> > + }
> > return err;
> > }
> >
> > @@ -201,6 +215,114 @@ static int send_tlb_inval_asid_ppgtt(struct
> > xe_tlb_inval *tlb_inval, u32 seqno,
> > XE_GUC_TLB_INVAL_PAGE_SELECTIVE,
> > prl_sa);
> > }
> >
> > +static bool queue_mapped_in_guc(struct xe_guc *guc, struct
> > xe_exec_queue *q)
> > +{
> > + return q->gt == guc_to_gt(guc);
> > +}
> > +
> > +static int send_tlb_inval_ctx_ppgtt(struct xe_tlb_inval *tlb_inval,
> > u32 seqno,
> > + u64 start, u64 end, u32 asid,
> > + struct drm_suballoc *prl_sa)
> > +{
> > + struct xe_guc *guc = tlb_inval->private;
> > + struct xe_device *xe = guc_to_xe(guc);
> > + struct xe_exec_queue *q, *next, *last_q = NULL;
> > + struct xe_vm *vm;
> > + LIST_HEAD(tlb_inval_list);
> > + int err = 0;
> > +
> > + lockdep_assert_held(&tlb_inval->seqno_lock);
> > +
> > + if (xe->info.force_execlist)
> > + return -ECANCELED;
> > +
> > + vm = xe_device_asid_to_vm(xe, asid);
> > + if (IS_ERR(vm))
> > + return PTR_ERR(vm);
> > +
> > + down_read(&vm->exec_queues.lock);
> > +
> > + /*
> > + * XXX: Randomly picking a threshold for now. This will need
> > to be
> > + * tuned based on expected UMD queue counts and performance
> > profiling.
> > + */
> > +#define EXEC_QUEUE_COUNT_FULL_THRESHOLD 8
> > + if (vm->exec_queues.count[guc_to_gt(guc)->info.id] >=
> > + EXEC_QUEUE_COUNT_FULL_THRESHOLD) {
> > + u32 action[] = {
> > + XE_GUC_ACTION_TLB_INVALIDATION,
> > + seqno,
> > + MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL),
> > + };
> > +
> > + err = send_tlb_inval(guc, action,
> > ARRAY_SIZE(action));
> > + goto err_unlock;
> > + }
> > +#undef EXEC_QUEUE_COUNT_FULL_THRESHOLD
> > +
> > + /*
> > + * Move exec queues to a temporary list to issue
> > invalidations. The exec
> > + * queue must be mapped in the current GuC, active, and a
> > reference must
> > + * be taken to prevent concurrent deregistrations.
> > + */
> > + list_for_each_entry_safe(q, next, &vm->exec_queues.list,
> > + vm_exec_queue_link)
>
> Nitpick: I'd prefer braces around the the if here so we aren't nesting
> the multi-line condition within this list_for_each loop.
>
Sure. CI and local testing is showing this loop explodes too. I'm
reasing two GTs are modifying the list at the same time as I'm just
using a read lock here. I think vm->exec_queues.list needs to be per GT
actually or just use a mutex to protect the list.
> > + if (queue_mapped_in_guc(guc, q) && q->ops->active(q)
> > &&
> > + xe_exec_queue_get_unless_zero(q)) {
> > + last_q = q;
> > + list_move_tail(&q->vm_exec_queue_link,
> > &tlb_inval_list);
> > + }
> > +
> > + if (!last_q) {
> > + /*
> > + * We can't break fence ordering for TLB invalidation
> > jobs, if
> > + * TLB invalidations are inflight issue a dummy
> > invalidation to
> > + * maintain ordering. Nor can we move safely the
> > seqno_recv when
> > + * returning -ECANCELED if TLB invalidations are in
> > flight. Use
> > + * GGTT invalidation as dummy invalidation given ASID
> > + * invalidations are unsupported here.
> > + */
> > + if (xe_tlb_inval_idle(tlb_inval))
> > + err = -ECANCELED;
> > + else
> > + err = send_tlb_inval_ggtt(tlb_inval, seqno);
>
> Can you give a little more context on this line actually? So this is
> going to send down a 0x3 type invalidation to GuC (TLB_INVAL_GUC). GuC
> is still doing an invalidation to hardware when we write this. Is that
> the expectation with this?
>
Yes, I think I explain this in the comment above. We are issuing a dummy
invalidation to maintain ordering when required, this would be GuC TLBs.
Not ideal but we can't break dma-fencing ordering and this case so be
exceedingly rare.
> > + goto err_unlock;
> > + }
> > +
> > + list_for_each_entry_safe(q, next, &tlb_inval_list,
> > vm_exec_queue_link) {
> > + struct drm_suballoc *__prl_sa = NULL;
> > + int __seqno = TLB_INVALIDATION_SEQNO_INVALID;
> > + u32 type = XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX;
> > +
> > + xe_assert(xe, q->vm == vm);
> > +
> > + if (err)
> > + goto unref;
> > +
> > + if (last_q == q) {
> > + __prl_sa = prl_sa;
> > + __seqno = seqno;
> > + }
> > +
> > + err = send_tlb_inval_ppgtt(guc, __seqno, start, end,
> > + q->guc->id, type,
> > __prl_sa);
> > +
> > +unref:
> > + /*
> > + * Must always return exec queue to original list /
> > drop
> > + * reference
> > + */
> > + xe_exec_queue_put(q);
> > + list_move_tail(&q->vm_exec_queue_link, &vm-
> > >exec_queues.list);
>
> Will get back on this one... need to spend a little more time and do
> some testing.
>
I probably should flip the put for clarity but this is in fact safe as
queue's memory can't disapear if vm->exec_queues.lock is held.
Matt
> Thanks,
> Stuart
>
> > + }
> > +
> > +err_unlock:
> > + up_read(&vm->exec_queues.lock);
> > + xe_vm_put(vm);
> > +
> > + return err;
> > +}
> > +
> > static bool tlb_inval_initialized(struct xe_tlb_inval *tlb_inval)
> > {
> > struct xe_guc *guc = tlb_inval->private;
> > @@ -228,7 +350,7 @@ static long tlb_inval_timeout_delay(struct
> > xe_tlb_inval *tlb_inval)
> > return hw_tlb_timeout + 2 * delay;
> > }
> >
> > -static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
> > +static const struct xe_tlb_inval_ops guc_tlb_inval_asid_ops = {
> > .all = send_tlb_inval_all,
> > .ggtt = send_tlb_inval_ggtt,
> > .ppgtt = send_tlb_inval_asid_ppgtt,
> > @@ -237,6 +359,15 @@ static const struct xe_tlb_inval_ops
> > guc_tlb_inval_ops = {
> > .timeout_delay = tlb_inval_timeout_delay,
> > };
> >
> > +static const struct xe_tlb_inval_ops guc_tlb_inval_ctx_ops = {
> > + .ggtt = send_tlb_inval_ggtt,
> > + .all = send_tlb_inval_all,
> > + .ppgtt = send_tlb_inval_ctx_ppgtt,
> > + .initialized = tlb_inval_initialized,
> > + .flush = tlb_inval_flush,
> > + .timeout_delay = tlb_inval_timeout_delay,
> > +};
> > +
> > /**
> > * xe_guc_tlb_inval_init_early() - Init GuC TLB invalidation early
> > * @guc: GuC object
> > @@ -248,8 +379,14 @@ static const struct xe_tlb_inval_ops
> > guc_tlb_inval_ops = {
> > void xe_guc_tlb_inval_init_early(struct xe_guc *guc,
> > struct xe_tlb_inval *tlb_inval)
> > {
> > + struct xe_device *xe = guc_to_xe(guc);
> > +
> > tlb_inval->private = guc;
> > - tlb_inval->ops = &guc_tlb_inval_ops;
> > +
> > + if (xe->info.has_ctx_tlb_inval)
> > + tlb_inval->ops = &guc_tlb_inval_ctx_ops;
> > + else
> > + tlb_inval->ops = &guc_tlb_inval_asid_ops;
> > }
> >
> > /**
> > diff --git a/drivers/gpu/drm/xe/xe_pci.c
> > b/drivers/gpu/drm/xe/xe_pci.c
> > index 91e0553a8163..6ea1199f703e 100644
> > --- a/drivers/gpu/drm/xe/xe_pci.c
> > +++ b/drivers/gpu/drm/xe/xe_pci.c
> > @@ -889,6 +889,7 @@ static int xe_info_init(struct xe_device *xe,
> > xe->info.has_device_atomics_on_smem = 1;
> >
> > xe->info.has_range_tlb_inval = graphics_desc-
> > >has_range_tlb_inval;
> > + xe->info.has_ctx_tlb_inval = graphics_desc-
> > >has_ctx_tlb_inval;
> > xe->info.has_usm = graphics_desc->has_usm;
> > xe->info.has_64bit_timestamp = graphics_desc-
> > >has_64bit_timestamp;
> >
> > diff --git a/drivers/gpu/drm/xe/xe_pci_types.h
> > b/drivers/gpu/drm/xe/xe_pci_types.h
> > index 5f20f56571d1..000b54cbcd0e 100644
> > --- a/drivers/gpu/drm/xe/xe_pci_types.h
> > +++ b/drivers/gpu/drm/xe/xe_pci_types.h
> > @@ -71,6 +71,7 @@ struct xe_graphics_desc {
> > u8 has_atomic_enable_pte_bit:1;
> > u8 has_indirect_ring_state:1;
> > u8 has_range_tlb_inval:1;
> > + u8 has_ctx_tlb_inval:1;
> > u8 has_usm:1;
> > u8 has_64bit_timestamp:1;
> > };
>
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v3 10/11] drm/xe: Add context-based invalidation to GuC TLB invalidation backend
2026-01-13 1:34 ` Matthew Brost
@ 2026-01-13 22:36 ` Summers, Stuart
2026-01-14 16:09 ` Matthew Brost
0 siblings, 1 reply; 24+ messages in thread
From: Summers, Stuart @ 2026-01-13 22:36 UTC (permalink / raw)
To: Brost, Matthew; +Cc: intel-xe@lists.freedesktop.org
On Mon, 2026-01-12 at 17:34 -0800, Matthew Brost wrote:
> On Mon, Jan 12, 2026 at 06:28:01PM -0700, Summers, Stuart wrote:
> > On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> > > Introduce context-based invalidation support to the GuC TLB
> > > invalidation
> > > backend. This is implemented by iterating over each exec queue
> > > per GT
> > > within a VM, skipping inactive queues, and issuing a context-
> > > based
> > > (GuC
> > > ID) H2G TLB invalidation. All H2G messages, except the final one,
> > > are
> > > sent with an invalid seqno, which the G2H handler drops to ensure
> > > the
> > > TLB invalidation fence is only signaled once all H2G messages are
> > > completed.
> > >
> > > A watermark mechanism is also added to switch between context-
> > > based
> > > TLB
> > > invalidations and full device-wide invalidations, as the return
> > > on
> > > investment for context-based invalidation diminishes when many
> > > exec
> > > queues are mapped.
> > >
> > > v2:
> > > - Fix checkpatch warnings
> > > v3:
> > > - Rebase on PRL
> > > - Use ref counting to avoid racing with deregisters
> > >
> > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > ---
> > > drivers/gpu/drm/xe/xe_device_types.h | 2 +
> > > drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 145
> > > +++++++++++++++++++++++++-
> > > drivers/gpu/drm/xe/xe_pci.c | 1 +
> > > drivers/gpu/drm/xe/xe_pci_types.h | 1 +
> > > 4 files changed, 145 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_device_types.h
> > > b/drivers/gpu/drm/xe/xe_device_types.h
> > > index 8db870aaa382..b51acff4edcd 100644
> > > --- a/drivers/gpu/drm/xe/xe_device_types.h
> > > +++ b/drivers/gpu/drm/xe/xe_device_types.h
> > > @@ -358,6 +358,8 @@ struct xe_device {
> > > u8 has_pre_prod_wa:1;
> > > /** @info.has_pxp: Device has PXP support */
> > > u8 has_pxp:1;
> > > + /** @info.has_ctx_tlb_inval: Has context based
> > > TLB
> > > invalidations */
> > > + u8 has_ctx_tlb_inval:1;
> > > /** @info.has_range_tlb_inval: Has range based
> > > TLB
> > > invalidations */
> > > u8 has_range_tlb_inval:1;
> > > /** @info.has_soc_remapper_sysctrl: Has SoC
> > > remapper
> > > system controller */
> > > diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > index 070d2e2cb7c9..328eced5f692 100644
> > > --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > @@ -6,15 +6,19 @@
> > > #include "abi/guc_actions_abi.h"
> > >
> > > #include "xe_device.h"
> > > +#include "xe_exec_queue.h"
> > > +#include "xe_exec_queue_types.h"
> > > #include "xe_gt_stats.h"
> > > #include "xe_gt_types.h"
> > > #include "xe_guc.h"
> > > #include "xe_guc_ct.h"
> > > +#include "xe_guc_exec_queue_types.h"
> > > #include "xe_guc_tlb_inval.h"
> > > #include "xe_force_wake.h"
> > > #include "xe_mmio.h"
> > > #include "xe_sa.h"
> > > #include "xe_tlb_inval.h"
> > > +#include "xe_vm.h"
> > >
> > > #include "regs/xe_guc_regs.h"
> > >
> > > @@ -156,10 +160,16 @@ static int send_tlb_inval_ppgtt(struct
> > > xe_guc
> > > *guc, u32 seqno, u64 start,
> > > {
> > > #define MAX_TLB_INVALIDATION_LEN 7
> > > struct xe_gt *gt = guc_to_gt(guc);
> > > + struct xe_device *xe = guc_to_xe(guc);
> > > u32 action[MAX_TLB_INVALIDATION_LEN];
> > > u64 length = end - start;
> > > int len = 0, err;
> > >
> > > + xe_gt_assert(gt, (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE
> > > &&
> > > + !xe->info.has_ctx_tlb_inval) ||
> > > + (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX
> > > &&
> > > + xe->info.has_ctx_tlb_inval));
> > > +
> > > action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
> > > action[len++] = !prl_sa ? seqno :
> > > TLB_INVALIDATION_SEQNO_INVALID;
> > > if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
> > > @@ -168,9 +178,11 @@ static int send_tlb_inval_ppgtt(struct
> > > xe_guc
> > > *guc, u32 seqno, u64 start,
> > > } else {
> > > u64 normalize_len =
> > > normalize_invalidation_range(gt,
> > > &start,
> > >
> > > &end);
> > > + bool need_flush = !prl_sa &&
> > > + seqno != TLB_INVALIDATION_SEQNO_INVALID;
> > >
> > > /* Flush on NULL case, Media is not required to
> > > modify flush due to no PPC so NOP */
> > > - action[len++] = MAKE_INVAL_OP_FLUSH(type,
> > > !prl_sa);
> > > + action[len++] = MAKE_INVAL_OP_FLUSH(type,
> > > need_flush);
> > > action[len++] = id;
> > > action[len++] = lower_32_bits(start);
> > > action[len++] = upper_32_bits(start);
> > > @@ -181,8 +193,10 @@ static int send_tlb_inval_ppgtt(struct
> > > xe_guc
> > > *guc, u32 seqno, u64 start,
> > > #undef MAX_TLB_INVALIDATION_LEN
> > >
> > > err = send_tlb_inval(guc, action, len);
> > > - if (!err && prl_sa)
> > > + if (!err && prl_sa) {
> > > + xe_gt_assert(gt, seqno !=
> > > TLB_INVALIDATION_SEQNO_INVALID);
> > > err = send_page_reclaim(guc, seqno,
> > > xe_sa_bo_gpu_addr(prl_sa));
> > > + }
> > > return err;
> > > }
> > >
> > > @@ -201,6 +215,114 @@ static int send_tlb_inval_asid_ppgtt(struct
> > > xe_tlb_inval *tlb_inval, u32 seqno,
> > >
> > > XE_GUC_TLB_INVAL_PAGE_SELECTIVE,
> > > prl_sa);
> > > }
> > >
> > > +static bool queue_mapped_in_guc(struct xe_guc *guc, struct
> > > xe_exec_queue *q)
> > > +{
> > > + return q->gt == guc_to_gt(guc);
> > > +}
> > > +
> > > +static int send_tlb_inval_ctx_ppgtt(struct xe_tlb_inval
> > > *tlb_inval,
> > > u32 seqno,
> > > + u64 start, u64 end, u32 asid,
> > > + struct drm_suballoc *prl_sa)
> > > +{
> > > + struct xe_guc *guc = tlb_inval->private;
> > > + struct xe_device *xe = guc_to_xe(guc);
> > > + struct xe_exec_queue *q, *next, *last_q = NULL;
> > > + struct xe_vm *vm;
> > > + LIST_HEAD(tlb_inval_list);
> > > + int err = 0;
> > > +
> > > + lockdep_assert_held(&tlb_inval->seqno_lock);
> > > +
> > > + if (xe->info.force_execlist)
> > > + return -ECANCELED;
> > > +
> > > + vm = xe_device_asid_to_vm(xe, asid);
> > > + if (IS_ERR(vm))
> > > + return PTR_ERR(vm);
> > > +
> > > + down_read(&vm->exec_queues.lock);
> > > +
> > > + /*
> > > + * XXX: Randomly picking a threshold for now. This will
> > > need
> > > to be
> > > + * tuned based on expected UMD queue counts and
> > > performance
> > > profiling.
> > > + */
> > > +#define EXEC_QUEUE_COUNT_FULL_THRESHOLD 8
> > > + if (vm->exec_queues.count[guc_to_gt(guc)->info.id] >=
> > > + EXEC_QUEUE_COUNT_FULL_THRESHOLD) {
> > > + u32 action[] = {
> > > + XE_GUC_ACTION_TLB_INVALIDATION,
> > > + seqno,
> > > + MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL),
> > > + };
> > > +
> > > + err = send_tlb_inval(guc, action,
> > > ARRAY_SIZE(action));
> > > + goto err_unlock;
> > > + }
> > > +#undef EXEC_QUEUE_COUNT_FULL_THRESHOLD
> > > +
> > > + /*
> > > + * Move exec queues to a temporary list to issue
> > > invalidations. The exec
> > > + * queue must be mapped in the current GuC, active, and a
> > > reference must
> > > + * be taken to prevent concurrent deregistrations.
> > > + */
> > > + list_for_each_entry_safe(q, next, &vm->exec_queues.list,
> > > + vm_exec_queue_link)
> >
> > Nitpick: I'd prefer braces around the the if here so we aren't
> > nesting
> > the multi-line condition within this list_for_each loop.
> >
>
> Sure. CI and local testing is showing this loop explodes too. I'm
> reasing two GTs are modifying the list at the same time as I'm just
> using a read lock here. I think vm->exec_queues.list needs to be per
> GT
> actually or just use a mutex to protect the list.
>
> > > + if (queue_mapped_in_guc(guc, q) && q->ops-
> > > >active(q)
> > > &&
> > > + xe_exec_queue_get_unless_zero(q)) {
> > > + last_q = q;
> > > + list_move_tail(&q->vm_exec_queue_link,
> > > &tlb_inval_list);
> > > + }
> > > +
> > > + if (!last_q) {
> > > + /*
> > > + * We can't break fence ordering for TLB
> > > invalidation
> > > jobs, if
> > > + * TLB invalidations are inflight issue a dummy
> > > invalidation to
> > > + * maintain ordering. Nor can we move safely the
> > > seqno_recv when
> > > + * returning -ECANCELED if TLB invalidations are
> > > in
> > > flight. Use
> > > + * GGTT invalidation as dummy invalidation given
> > > ASID
> > > + * invalidations are unsupported here.
> > > + */
> > > + if (xe_tlb_inval_idle(tlb_inval))
> > > + err = -ECANCELED;
> > > + else
> > > + err = send_tlb_inval_ggtt(tlb_inval,
> > > seqno);
> >
> > Can you give a little more context on this line actually? So this
> > is
> > going to send down a 0x3 type invalidation to GuC (TLB_INVAL_GUC).
> > GuC
> > is still doing an invalidation to hardware when we write this. Is
> > that
> > the expectation with this?
> >
>
> Yes, I think I explain this in the comment above. We are issuing a
> dummy
> invalidation to maintain ordering when required, this would be GuC
> TLBs.
> Not ideal but we can't break dma-fencing ordering and this case so be
> exceedingly rare.
Yeah the reasoning is clear to me. It just wasn't clear what would
happen with this GuC invalidation. Looking through the GuC source, I
see this is sending with Granularity of 0x1. This is "All mappings
within ASID and VF" according to bspec. We aren't actually passing an
ASID here and it looks like GuC isn't programming anything into that
field in the descriptor. So we'd have to get unlucky with a 0 (I
believe - can't find where they're clearing this at a glance) ASID
which seems unlikely.
So from the hardware side, there will be a lookup and failure to find
the ASID and the transaction should be dropped.
I think on current hardware this is ok and the invalidation still
completes at the GuC level (GuC receives the ack from hardware) and we
shouldn't get an invalidation timeout in the KMD. But there's always a
chance this could change in the future.
Can you add a comment here indicating this? Basically something like:
Expectation is that hardware will drop this request since GuC submits
an ASID based request without an ASID.
Thanks,
Stuart
>
> > > + goto err_unlock;
> > > + }
> > > +
> > > + list_for_each_entry_safe(q, next, &tlb_inval_list,
> > > vm_exec_queue_link) {
> > > + struct drm_suballoc *__prl_sa = NULL;
> > > + int __seqno = TLB_INVALIDATION_SEQNO_INVALID;
> > > + u32 type = XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX;
> > > +
> > > + xe_assert(xe, q->vm == vm);
> > > +
> > > + if (err)
> > > + goto unref;
> > > +
> > > + if (last_q == q) {
> > > + __prl_sa = prl_sa;
> > > + __seqno = seqno;
> > > + }
> > > +
> > > + err = send_tlb_inval_ppgtt(guc, __seqno, start,
> > > end,
> > > + q->guc->id, type,
> > > __prl_sa);
> > > +
> > > +unref:
> > > + /*
> > > + * Must always return exec queue to original list
> > > /
> > > drop
> > > + * reference
> > > + */
> > > + xe_exec_queue_put(q);
> > > + list_move_tail(&q->vm_exec_queue_link, &vm-
> > > > exec_queues.list);
> >
> > Will get back on this one... need to spend a little more time and
> > do
> > some testing.
> >
>
> I probably should flip the put for clarity but this is in fact safe
> as
> queue's memory can't disapear if vm->exec_queues.lock is held.
>
> Matt
>
> > Thanks,
> > Stuart
> >
> > > + }
> > > +
> > > +err_unlock:
> > > + up_read(&vm->exec_queues.lock);
> > > + xe_vm_put(vm);
> > > +
> > > + return err;
> > > +}
> > > +
> > > static bool tlb_inval_initialized(struct xe_tlb_inval
> > > *tlb_inval)
> > > {
> > > struct xe_guc *guc = tlb_inval->private;
> > > @@ -228,7 +350,7 @@ static long tlb_inval_timeout_delay(struct
> > > xe_tlb_inval *tlb_inval)
> > > return hw_tlb_timeout + 2 * delay;
> > > }
> > >
> > > -static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
> > > +static const struct xe_tlb_inval_ops guc_tlb_inval_asid_ops = {
> > > .all = send_tlb_inval_all,
> > > .ggtt = send_tlb_inval_ggtt,
> > > .ppgtt = send_tlb_inval_asid_ppgtt,
> > > @@ -237,6 +359,15 @@ static const struct xe_tlb_inval_ops
> > > guc_tlb_inval_ops = {
> > > .timeout_delay = tlb_inval_timeout_delay,
> > > };
> > >
> > > +static const struct xe_tlb_inval_ops guc_tlb_inval_ctx_ops = {
> > > + .ggtt = send_tlb_inval_ggtt,
> > > + .all = send_tlb_inval_all,
> > > + .ppgtt = send_tlb_inval_ctx_ppgtt,
> > > + .initialized = tlb_inval_initialized,
> > > + .flush = tlb_inval_flush,
> > > + .timeout_delay = tlb_inval_timeout_delay,
> > > +};
> > > +
> > > /**
> > > * xe_guc_tlb_inval_init_early() - Init GuC TLB invalidation
> > > early
> > > * @guc: GuC object
> > > @@ -248,8 +379,14 @@ static const struct xe_tlb_inval_ops
> > > guc_tlb_inval_ops = {
> > > void xe_guc_tlb_inval_init_early(struct xe_guc *guc,
> > > struct xe_tlb_inval *tlb_inval)
> > > {
> > > + struct xe_device *xe = guc_to_xe(guc);
> > > +
> > > tlb_inval->private = guc;
> > > - tlb_inval->ops = &guc_tlb_inval_ops;
> > > +
> > > + if (xe->info.has_ctx_tlb_inval)
> > > + tlb_inval->ops = &guc_tlb_inval_ctx_ops;
> > > + else
> > > + tlb_inval->ops = &guc_tlb_inval_asid_ops;
> > > }
> > >
> > > /**
> > > diff --git a/drivers/gpu/drm/xe/xe_pci.c
> > > b/drivers/gpu/drm/xe/xe_pci.c
> > > index 91e0553a8163..6ea1199f703e 100644
> > > --- a/drivers/gpu/drm/xe/xe_pci.c
> > > +++ b/drivers/gpu/drm/xe/xe_pci.c
> > > @@ -889,6 +889,7 @@ static int xe_info_init(struct xe_device *xe,
> > > xe->info.has_device_atomics_on_smem = 1;
> > >
> > > xe->info.has_range_tlb_inval = graphics_desc-
> > > > has_range_tlb_inval;
> > > + xe->info.has_ctx_tlb_inval = graphics_desc-
> > > > has_ctx_tlb_inval;
> > > xe->info.has_usm = graphics_desc->has_usm;
> > > xe->info.has_64bit_timestamp = graphics_desc-
> > > > has_64bit_timestamp;
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_pci_types.h
> > > b/drivers/gpu/drm/xe/xe_pci_types.h
> > > index 5f20f56571d1..000b54cbcd0e 100644
> > > --- a/drivers/gpu/drm/xe/xe_pci_types.h
> > > +++ b/drivers/gpu/drm/xe/xe_pci_types.h
> > > @@ -71,6 +71,7 @@ struct xe_graphics_desc {
> > > u8 has_atomic_enable_pte_bit:1;
> > > u8 has_indirect_ring_state:1;
> > > u8 has_range_tlb_inval:1;
> > > + u8 has_ctx_tlb_inval:1;
> > > u8 has_usm:1;
> > > u8 has_64bit_timestamp:1;
> > > };
> >
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v3 10/11] drm/xe: Add context-based invalidation to GuC TLB invalidation backend
2026-01-13 22:36 ` Summers, Stuart
@ 2026-01-14 16:09 ` Matthew Brost
2026-01-14 23:45 ` Summers, Stuart
0 siblings, 1 reply; 24+ messages in thread
From: Matthew Brost @ 2026-01-14 16:09 UTC (permalink / raw)
To: Summers, Stuart; +Cc: intel-xe@lists.freedesktop.org
On Tue, Jan 13, 2026 at 03:36:59PM -0700, Summers, Stuart wrote:
> On Mon, 2026-01-12 at 17:34 -0800, Matthew Brost wrote:
> > On Mon, Jan 12, 2026 at 06:28:01PM -0700, Summers, Stuart wrote:
> > > On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> > > > Introduce context-based invalidation support to the GuC TLB
> > > > invalidation
> > > > backend. This is implemented by iterating over each exec queue
> > > > per GT
> > > > within a VM, skipping inactive queues, and issuing a context-
> > > > based
> > > > (GuC
> > > > ID) H2G TLB invalidation. All H2G messages, except the final one,
> > > > are
> > > > sent with an invalid seqno, which the G2H handler drops to ensure
> > > > the
> > > > TLB invalidation fence is only signaled once all H2G messages are
> > > > completed.
> > > >
> > > > A watermark mechanism is also added to switch between context-
> > > > based
> > > > TLB
> > > > invalidations and full device-wide invalidations, as the return
> > > > on
> > > > investment for context-based invalidation diminishes when many
> > > > exec
> > > > queues are mapped.
> > > >
> > > > v2:
> > > > - Fix checkpatch warnings
> > > > v3:
> > > > - Rebase on PRL
> > > > - Use ref counting to avoid racing with deregisters
> > > >
> > > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > > ---
> > > > drivers/gpu/drm/xe/xe_device_types.h | 2 +
> > > > drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 145
> > > > +++++++++++++++++++++++++-
> > > > drivers/gpu/drm/xe/xe_pci.c | 1 +
> > > > drivers/gpu/drm/xe/xe_pci_types.h | 1 +
> > > > 4 files changed, 145 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/xe/xe_device_types.h
> > > > b/drivers/gpu/drm/xe/xe_device_types.h
> > > > index 8db870aaa382..b51acff4edcd 100644
> > > > --- a/drivers/gpu/drm/xe/xe_device_types.h
> > > > +++ b/drivers/gpu/drm/xe/xe_device_types.h
> > > > @@ -358,6 +358,8 @@ struct xe_device {
> > > > u8 has_pre_prod_wa:1;
> > > > /** @info.has_pxp: Device has PXP support */
> > > > u8 has_pxp:1;
> > > > + /** @info.has_ctx_tlb_inval: Has context based
> > > > TLB
> > > > invalidations */
> > > > + u8 has_ctx_tlb_inval:1;
> > > > /** @info.has_range_tlb_inval: Has range based
> > > > TLB
> > > > invalidations */
> > > > u8 has_range_tlb_inval:1;
> > > > /** @info.has_soc_remapper_sysctrl: Has SoC
> > > > remapper
> > > > system controller */
> > > > diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > > b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > > index 070d2e2cb7c9..328eced5f692 100644
> > > > --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > > +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > > @@ -6,15 +6,19 @@
> > > > #include "abi/guc_actions_abi.h"
> > > >
> > > > #include "xe_device.h"
> > > > +#include "xe_exec_queue.h"
> > > > +#include "xe_exec_queue_types.h"
> > > > #include "xe_gt_stats.h"
> > > > #include "xe_gt_types.h"
> > > > #include "xe_guc.h"
> > > > #include "xe_guc_ct.h"
> > > > +#include "xe_guc_exec_queue_types.h"
> > > > #include "xe_guc_tlb_inval.h"
> > > > #include "xe_force_wake.h"
> > > > #include "xe_mmio.h"
> > > > #include "xe_sa.h"
> > > > #include "xe_tlb_inval.h"
> > > > +#include "xe_vm.h"
> > > >
> > > > #include "regs/xe_guc_regs.h"
> > > >
> > > > @@ -156,10 +160,16 @@ static int send_tlb_inval_ppgtt(struct
> > > > xe_guc
> > > > *guc, u32 seqno, u64 start,
> > > > {
> > > > #define MAX_TLB_INVALIDATION_LEN 7
> > > > struct xe_gt *gt = guc_to_gt(guc);
> > > > + struct xe_device *xe = guc_to_xe(guc);
> > > > u32 action[MAX_TLB_INVALIDATION_LEN];
> > > > u64 length = end - start;
> > > > int len = 0, err;
> > > >
> > > > + xe_gt_assert(gt, (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE
> > > > &&
> > > > + !xe->info.has_ctx_tlb_inval) ||
> > > > + (type == XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX
> > > > &&
> > > > + xe->info.has_ctx_tlb_inval));
> > > > +
> > > > action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
> > > > action[len++] = !prl_sa ? seqno :
> > > > TLB_INVALIDATION_SEQNO_INVALID;
> > > > if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
> > > > @@ -168,9 +178,11 @@ static int send_tlb_inval_ppgtt(struct
> > > > xe_guc
> > > > *guc, u32 seqno, u64 start,
> > > > } else {
> > > > u64 normalize_len =
> > > > normalize_invalidation_range(gt,
> > > > &start,
> > > >
> > > > &end);
> > > > + bool need_flush = !prl_sa &&
> > > > + seqno != TLB_INVALIDATION_SEQNO_INVALID;
> > > >
> > > > /* Flush on NULL case, Media is not required to
> > > > modify flush due to no PPC so NOP */
> > > > - action[len++] = MAKE_INVAL_OP_FLUSH(type,
> > > > !prl_sa);
> > > > + action[len++] = MAKE_INVAL_OP_FLUSH(type,
> > > > need_flush);
> > > > action[len++] = id;
> > > > action[len++] = lower_32_bits(start);
> > > > action[len++] = upper_32_bits(start);
> > > > @@ -181,8 +193,10 @@ static int send_tlb_inval_ppgtt(struct
> > > > xe_guc
> > > > *guc, u32 seqno, u64 start,
> > > > #undef MAX_TLB_INVALIDATION_LEN
> > > >
> > > > err = send_tlb_inval(guc, action, len);
> > > > - if (!err && prl_sa)
> > > > + if (!err && prl_sa) {
> > > > + xe_gt_assert(gt, seqno !=
> > > > TLB_INVALIDATION_SEQNO_INVALID);
> > > > err = send_page_reclaim(guc, seqno,
> > > > xe_sa_bo_gpu_addr(prl_sa));
> > > > + }
> > > > return err;
> > > > }
> > > >
> > > > @@ -201,6 +215,114 @@ static int send_tlb_inval_asid_ppgtt(struct
> > > > xe_tlb_inval *tlb_inval, u32 seqno,
> > > >
> > > > XE_GUC_TLB_INVAL_PAGE_SELECTIVE,
> > > > prl_sa);
> > > > }
> > > >
> > > > +static bool queue_mapped_in_guc(struct xe_guc *guc, struct
> > > > xe_exec_queue *q)
> > > > +{
> > > > + return q->gt == guc_to_gt(guc);
> > > > +}
> > > > +
> > > > +static int send_tlb_inval_ctx_ppgtt(struct xe_tlb_inval
> > > > *tlb_inval,
> > > > u32 seqno,
> > > > + u64 start, u64 end, u32 asid,
> > > > + struct drm_suballoc *prl_sa)
> > > > +{
> > > > + struct xe_guc *guc = tlb_inval->private;
> > > > + struct xe_device *xe = guc_to_xe(guc);
> > > > + struct xe_exec_queue *q, *next, *last_q = NULL;
> > > > + struct xe_vm *vm;
> > > > + LIST_HEAD(tlb_inval_list);
> > > > + int err = 0;
> > > > +
> > > > + lockdep_assert_held(&tlb_inval->seqno_lock);
> > > > +
> > > > + if (xe->info.force_execlist)
> > > > + return -ECANCELED;
> > > > +
> > > > + vm = xe_device_asid_to_vm(xe, asid);
> > > > + if (IS_ERR(vm))
> > > > + return PTR_ERR(vm);
> > > > +
> > > > + down_read(&vm->exec_queues.lock);
> > > > +
> > > > + /*
> > > > + * XXX: Randomly picking a threshold for now. This will
> > > > need
> > > > to be
> > > > + * tuned based on expected UMD queue counts and
> > > > performance
> > > > profiling.
> > > > + */
> > > > +#define EXEC_QUEUE_COUNT_FULL_THRESHOLD 8
> > > > + if (vm->exec_queues.count[guc_to_gt(guc)->info.id] >=
> > > > + EXEC_QUEUE_COUNT_FULL_THRESHOLD) {
> > > > + u32 action[] = {
> > > > + XE_GUC_ACTION_TLB_INVALIDATION,
> > > > + seqno,
> > > > + MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL),
> > > > + };
> > > > +
> > > > + err = send_tlb_inval(guc, action,
> > > > ARRAY_SIZE(action));
> > > > + goto err_unlock;
> > > > + }
> > > > +#undef EXEC_QUEUE_COUNT_FULL_THRESHOLD
> > > > +
> > > > + /*
> > > > + * Move exec queues to a temporary list to issue
> > > > invalidations. The exec
> > > > + * queue must be mapped in the current GuC, active, and a
> > > > reference must
> > > > + * be taken to prevent concurrent deregistrations.
> > > > + */
> > > > + list_for_each_entry_safe(q, next, &vm->exec_queues.list,
> > > > + vm_exec_queue_link)
> > >
> > > Nitpick: I'd prefer braces around the the if here so we aren't
> > > nesting
> > > the multi-line condition within this list_for_each loop.
> > >
> >
> > Sure. CI and local testing is showing this loop explodes too. I'm
> > reasing two GTs are modifying the list at the same time as I'm just
> > using a read lock here. I think vm->exec_queues.list needs to be per
> > GT
> > actually or just use a mutex to protect the list.
> >
> > > > + if (queue_mapped_in_guc(guc, q) && q->ops-
> > > > >active(q)
> > > > &&
> > > > + xe_exec_queue_get_unless_zero(q)) {
> > > > + last_q = q;
> > > > + list_move_tail(&q->vm_exec_queue_link,
> > > > &tlb_inval_list);
> > > > + }
> > > > +
> > > > + if (!last_q) {
> > > > + /*
> > > > + * We can't break fence ordering for TLB
> > > > invalidation
> > > > jobs, if
> > > > + * TLB invalidations are inflight issue a dummy
> > > > invalidation to
> > > > + * maintain ordering. Nor can we move safely the
> > > > seqno_recv when
> > > > + * returning -ECANCELED if TLB invalidations are
> > > > in
> > > > flight. Use
> > > > + * GGTT invalidation as dummy invalidation given
> > > > ASID
> > > > + * invalidations are unsupported here.
> > > > + */
> > > > + if (xe_tlb_inval_idle(tlb_inval))
> > > > + err = -ECANCELED;
> > > > + else
> > > > + err = send_tlb_inval_ggtt(tlb_inval,
> > > > seqno);
> > >
> > > Can you give a little more context on this line actually? So this
> > > is
> > > going to send down a 0x3 type invalidation to GuC (TLB_INVAL_GUC).
> > > GuC
> > > is still doing an invalidation to hardware when we write this. Is
> > > that
> > > the expectation with this?
> > >
> >
> > Yes, I think I explain this in the comment above. We are issuing a
> > dummy
> > invalidation to maintain ordering when required, this would be GuC
> > TLBs.
> > Not ideal but we can't break dma-fencing ordering and this case so be
> > exceedingly rare.
>
> Yeah the reasoning is clear to me. It just wasn't clear what would
> happen with this GuC invalidation. Looking through the GuC source, I
> see this is sending with Granularity of 0x1. This is "All mappings
> within ASID and VF" according to bspec. We aren't actually passing an
> ASID here and it looks like GuC isn't programming anything into that
> field in the descriptor. So we'd have to get unlucky with a 0 (I
> believe - can't find where they're clearing this at a glance) ASID
> which seems unlikely.
>
> So from the hardware side, there will be a lookup and failure to find
> the ASID and the transaction should be dropped.
>
> I think on current hardware this is ok and the invalidation still
> completes at the GuC level (GuC receives the ack from hardware) and we
> shouldn't get an invalidation timeout in the KMD. But there's always a
> chance this could change in the future.
>
> Can you add a comment here indicating this? Basically something like:
> Expectation is that hardware will drop this request since GuC submits
> an ASID based request without an ASID.
This is a GuC GGTT TLB invalidation - not a full PPGTT or PASID
invalidation. For example when we create or destroy a GGTT mapping, this
is the type of invalidation we issue there.
I picked GuC GGTT invalidation as I figure this was less costly than a
full PPGTT invalidation but that is just a guess. Are ASID based
invalidations available on platforms that want context based
invalidations - my guess is no and maybe even confirmed that at one
point by looking at GuC source.
I already have comment above indicating this is a GGTT based
invalidation.
Matt
>
> Thanks,
> Stuart
>
> >
> > > > + goto err_unlock;
> > > > + }
> > > > +
> > > > + list_for_each_entry_safe(q, next, &tlb_inval_list,
> > > > vm_exec_queue_link) {
> > > > + struct drm_suballoc *__prl_sa = NULL;
> > > > + int __seqno = TLB_INVALIDATION_SEQNO_INVALID;
> > > > + u32 type = XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX;
> > > > +
> > > > + xe_assert(xe, q->vm == vm);
> > > > +
> > > > + if (err)
> > > > + goto unref;
> > > > +
> > > > + if (last_q == q) {
> > > > + __prl_sa = prl_sa;
> > > > + __seqno = seqno;
> > > > + }
> > > > +
> > > > + err = send_tlb_inval_ppgtt(guc, __seqno, start,
> > > > end,
> > > > + q->guc->id, type,
> > > > __prl_sa);
> > > > +
> > > > +unref:
> > > > + /*
> > > > + * Must always return exec queue to original list
> > > > /
> > > > drop
> > > > + * reference
> > > > + */
> > > > + xe_exec_queue_put(q);
> > > > + list_move_tail(&q->vm_exec_queue_link, &vm-
> > > > > exec_queues.list);
> > >
> > > Will get back on this one... need to spend a little more time and
> > > do
> > > some testing.
> > >
> >
> > I probably should flip the put for clarity but this is in fact safe
> > as
> > queue's memory can't disapear if vm->exec_queues.lock is held.
> >
> > Matt
> >
> > > Thanks,
> > > Stuart
> > >
> > > > + }
> > > > +
> > > > +err_unlock:
> > > > + up_read(&vm->exec_queues.lock);
> > > > + xe_vm_put(vm);
> > > > +
> > > > + return err;
> > > > +}
> > > > +
> > > > static bool tlb_inval_initialized(struct xe_tlb_inval
> > > > *tlb_inval)
> > > > {
> > > > struct xe_guc *guc = tlb_inval->private;
> > > > @@ -228,7 +350,7 @@ static long tlb_inval_timeout_delay(struct
> > > > xe_tlb_inval *tlb_inval)
> > > > return hw_tlb_timeout + 2 * delay;
> > > > }
> > > >
> > > > -static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
> > > > +static const struct xe_tlb_inval_ops guc_tlb_inval_asid_ops = {
> > > > .all = send_tlb_inval_all,
> > > > .ggtt = send_tlb_inval_ggtt,
> > > > .ppgtt = send_tlb_inval_asid_ppgtt,
> > > > @@ -237,6 +359,15 @@ static const struct xe_tlb_inval_ops
> > > > guc_tlb_inval_ops = {
> > > > .timeout_delay = tlb_inval_timeout_delay,
> > > > };
> > > >
> > > > +static const struct xe_tlb_inval_ops guc_tlb_inval_ctx_ops = {
> > > > + .ggtt = send_tlb_inval_ggtt,
> > > > + .all = send_tlb_inval_all,
> > > > + .ppgtt = send_tlb_inval_ctx_ppgtt,
> > > > + .initialized = tlb_inval_initialized,
> > > > + .flush = tlb_inval_flush,
> > > > + .timeout_delay = tlb_inval_timeout_delay,
> > > > +};
> > > > +
> > > > /**
> > > > * xe_guc_tlb_inval_init_early() - Init GuC TLB invalidation
> > > > early
> > > > * @guc: GuC object
> > > > @@ -248,8 +379,14 @@ static const struct xe_tlb_inval_ops
> > > > guc_tlb_inval_ops = {
> > > > void xe_guc_tlb_inval_init_early(struct xe_guc *guc,
> > > > struct xe_tlb_inval *tlb_inval)
> > > > {
> > > > + struct xe_device *xe = guc_to_xe(guc);
> > > > +
> > > > tlb_inval->private = guc;
> > > > - tlb_inval->ops = &guc_tlb_inval_ops;
> > > > +
> > > > + if (xe->info.has_ctx_tlb_inval)
> > > > + tlb_inval->ops = &guc_tlb_inval_ctx_ops;
> > > > + else
> > > > + tlb_inval->ops = &guc_tlb_inval_asid_ops;
> > > > }
> > > >
> > > > /**
> > > > diff --git a/drivers/gpu/drm/xe/xe_pci.c
> > > > b/drivers/gpu/drm/xe/xe_pci.c
> > > > index 91e0553a8163..6ea1199f703e 100644
> > > > --- a/drivers/gpu/drm/xe/xe_pci.c
> > > > +++ b/drivers/gpu/drm/xe/xe_pci.c
> > > > @@ -889,6 +889,7 @@ static int xe_info_init(struct xe_device *xe,
> > > > xe->info.has_device_atomics_on_smem = 1;
> > > >
> > > > xe->info.has_range_tlb_inval = graphics_desc-
> > > > > has_range_tlb_inval;
> > > > + xe->info.has_ctx_tlb_inval = graphics_desc-
> > > > > has_ctx_tlb_inval;
> > > > xe->info.has_usm = graphics_desc->has_usm;
> > > > xe->info.has_64bit_timestamp = graphics_desc-
> > > > > has_64bit_timestamp;
> > > >
> > > > diff --git a/drivers/gpu/drm/xe/xe_pci_types.h
> > > > b/drivers/gpu/drm/xe/xe_pci_types.h
> > > > index 5f20f56571d1..000b54cbcd0e 100644
> > > > --- a/drivers/gpu/drm/xe/xe_pci_types.h
> > > > +++ b/drivers/gpu/drm/xe/xe_pci_types.h
> > > > @@ -71,6 +71,7 @@ struct xe_graphics_desc {
> > > > u8 has_atomic_enable_pte_bit:1;
> > > > u8 has_indirect_ring_state:1;
> > > > u8 has_range_tlb_inval:1;
> > > > + u8 has_ctx_tlb_inval:1;
> > > > u8 has_usm:1;
> > > > u8 has_64bit_timestamp:1;
> > > > };
> > >
>
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v3 10/11] drm/xe: Add context-based invalidation to GuC TLB invalidation backend
2026-01-14 16:09 ` Matthew Brost
@ 2026-01-14 23:45 ` Summers, Stuart
0 siblings, 0 replies; 24+ messages in thread
From: Summers, Stuart @ 2026-01-14 23:45 UTC (permalink / raw)
To: Brost, Matthew; +Cc: intel-xe@lists.freedesktop.org
On Wed, 2026-01-14 at 08:09 -0800, Matthew Brost wrote:
> On Tue, Jan 13, 2026 at 03:36:59PM -0700, Summers, Stuart wrote:
> > On Mon, 2026-01-12 at 17:34 -0800, Matthew Brost wrote:
> > > On Mon, Jan 12, 2026 at 06:28:01PM -0700, Summers, Stuart wrote:
> > > > On Mon, 2026-01-12 at 15:27 -0800, Matthew Brost wrote:
> > > > > Introduce context-based invalidation support to the GuC TLB
> > > > > invalidation
> > > > > backend. This is implemented by iterating over each exec
> > > > > queue
> > > > > per GT
> > > > > within a VM, skipping inactive queues, and issuing a context-
> > > > > based
> > > > > (GuC
> > > > > ID) H2G TLB invalidation. All H2G messages, except the final
> > > > > one,
> > > > > are
> > > > > sent with an invalid seqno, which the G2H handler drops to
> > > > > ensure
> > > > > the
> > > > > TLB invalidation fence is only signaled once all H2G messages
> > > > > are
> > > > > completed.
> > > > >
> > > > > A watermark mechanism is also added to switch between
> > > > > context-
> > > > > based
> > > > > TLB
> > > > > invalidations and full device-wide invalidations, as the
> > > > > return
> > > > > on
> > > > > investment for context-based invalidation diminishes when
> > > > > many
> > > > > exec
> > > > > queues are mapped.
> > > > >
> > > > > v2:
> > > > > - Fix checkpatch warnings
> > > > > v3:
> > > > > - Rebase on PRL
> > > > > - Use ref counting to avoid racing with deregisters
> > > > >
> > > > > Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> > > > > ---
> > > > > drivers/gpu/drm/xe/xe_device_types.h | 2 +
> > > > > drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 145
> > > > > +++++++++++++++++++++++++-
> > > > > drivers/gpu/drm/xe/xe_pci.c | 1 +
> > > > > drivers/gpu/drm/xe/xe_pci_types.h | 1 +
> > > > > 4 files changed, 145 insertions(+), 4 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/xe/xe_device_types.h
> > > > > b/drivers/gpu/drm/xe/xe_device_types.h
> > > > > index 8db870aaa382..b51acff4edcd 100644
> > > > > --- a/drivers/gpu/drm/xe/xe_device_types.h
> > > > > +++ b/drivers/gpu/drm/xe/xe_device_types.h
> > > > > @@ -358,6 +358,8 @@ struct xe_device {
> > > > > u8 has_pre_prod_wa:1;
> > > > > /** @info.has_pxp: Device has PXP support */
> > > > > u8 has_pxp:1;
> > > > > + /** @info.has_ctx_tlb_inval: Has context
> > > > > based
> > > > > TLB
> > > > > invalidations */
> > > > > + u8 has_ctx_tlb_inval:1;
> > > > > /** @info.has_range_tlb_inval: Has range
> > > > > based
> > > > > TLB
> > > > > invalidations */
> > > > > u8 has_range_tlb_inval:1;
> > > > > /** @info.has_soc_remapper_sysctrl: Has SoC
> > > > > remapper
> > > > > system controller */
> > > > > diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > > > b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > > > index 070d2e2cb7c9..328eced5f692 100644
> > > > > --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > > > +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > > > > @@ -6,15 +6,19 @@
> > > > > #include "abi/guc_actions_abi.h"
> > > > >
> > > > > #include "xe_device.h"
> > > > > +#include "xe_exec_queue.h"
> > > > > +#include "xe_exec_queue_types.h"
> > > > > #include "xe_gt_stats.h"
> > > > > #include "xe_gt_types.h"
> > > > > #include "xe_guc.h"
> > > > > #include "xe_guc_ct.h"
> > > > > +#include "xe_guc_exec_queue_types.h"
> > > > > #include "xe_guc_tlb_inval.h"
> > > > > #include "xe_force_wake.h"
> > > > > #include "xe_mmio.h"
> > > > > #include "xe_sa.h"
> > > > > #include "xe_tlb_inval.h"
> > > > > +#include "xe_vm.h"
> > > > >
> > > > > #include "regs/xe_guc_regs.h"
> > > > >
> > > > > @@ -156,10 +160,16 @@ static int send_tlb_inval_ppgtt(struct
> > > > > xe_guc
> > > > > *guc, u32 seqno, u64 start,
> > > > > {
> > > > > #define MAX_TLB_INVALIDATION_LEN 7
> > > > > struct xe_gt *gt = guc_to_gt(guc);
> > > > > + struct xe_device *xe = guc_to_xe(guc);
> > > > > u32 action[MAX_TLB_INVALIDATION_LEN];
> > > > > u64 length = end - start;
> > > > > int len = 0, err;
> > > > >
> > > > > + xe_gt_assert(gt, (type ==
> > > > > XE_GUC_TLB_INVAL_PAGE_SELECTIVE
> > > > > &&
> > > > > + !xe->info.has_ctx_tlb_inval) ||
> > > > > + (type ==
> > > > > XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX
> > > > > &&
> > > > > + xe->info.has_ctx_tlb_inval));
> > > > > +
> > > > > action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
> > > > > action[len++] = !prl_sa ? seqno :
> > > > > TLB_INVALIDATION_SEQNO_INVALID;
> > > > > if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
> > > > > @@ -168,9 +178,11 @@ static int send_tlb_inval_ppgtt(struct
> > > > > xe_guc
> > > > > *guc, u32 seqno, u64 start,
> > > > > } else {
> > > > > u64 normalize_len =
> > > > > normalize_invalidation_range(gt,
> > > > > &start,
> > > > >
> > > > >
> > > > > &end);
> > > > > + bool need_flush = !prl_sa &&
> > > > > + seqno !=
> > > > > TLB_INVALIDATION_SEQNO_INVALID;
> > > > >
> > > > > /* Flush on NULL case, Media is not required
> > > > > to
> > > > > modify flush due to no PPC so NOP */
> > > > > - action[len++] = MAKE_INVAL_OP_FLUSH(type,
> > > > > !prl_sa);
> > > > > + action[len++] = MAKE_INVAL_OP_FLUSH(type,
> > > > > need_flush);
> > > > > action[len++] = id;
> > > > > action[len++] = lower_32_bits(start);
> > > > > action[len++] = upper_32_bits(start);
> > > > > @@ -181,8 +193,10 @@ static int send_tlb_inval_ppgtt(struct
> > > > > xe_guc
> > > > > *guc, u32 seqno, u64 start,
> > > > > #undef MAX_TLB_INVALIDATION_LEN
> > > > >
> > > > > err = send_tlb_inval(guc, action, len);
> > > > > - if (!err && prl_sa)
> > > > > + if (!err && prl_sa) {
> > > > > + xe_gt_assert(gt, seqno !=
> > > > > TLB_INVALIDATION_SEQNO_INVALID);
> > > > > err = send_page_reclaim(guc, seqno,
> > > > > xe_sa_bo_gpu_addr(prl_sa));
> > > > > + }
> > > > > return err;
> > > > > }
> > > > >
> > > > > @@ -201,6 +215,114 @@ static int
> > > > > send_tlb_inval_asid_ppgtt(struct
> > > > > xe_tlb_inval *tlb_inval, u32 seqno,
> > > > >
> > > > > XE_GUC_TLB_INVAL_PAGE_SELECTIVE,
> > > > > prl_sa);
> > > > > }
> > > > >
> > > > > +static bool queue_mapped_in_guc(struct xe_guc *guc, struct
> > > > > xe_exec_queue *q)
> > > > > +{
> > > > > + return q->gt == guc_to_gt(guc);
> > > > > +}
> > > > > +
> > > > > +static int send_tlb_inval_ctx_ppgtt(struct xe_tlb_inval
> > > > > *tlb_inval,
> > > > > u32 seqno,
> > > > > + u64 start, u64 end, u32
> > > > > asid,
> > > > > + struct drm_suballoc
> > > > > *prl_sa)
> > > > > +{
> > > > > + struct xe_guc *guc = tlb_inval->private;
> > > > > + struct xe_device *xe = guc_to_xe(guc);
> > > > > + struct xe_exec_queue *q, *next, *last_q = NULL;
> > > > > + struct xe_vm *vm;
> > > > > + LIST_HEAD(tlb_inval_list);
> > > > > + int err = 0;
> > > > > +
> > > > > + lockdep_assert_held(&tlb_inval->seqno_lock);
> > > > > +
> > > > > + if (xe->info.force_execlist)
> > > > > + return -ECANCELED;
> > > > > +
> > > > > + vm = xe_device_asid_to_vm(xe, asid);
> > > > > + if (IS_ERR(vm))
> > > > > + return PTR_ERR(vm);
> > > > > +
> > > > > + down_read(&vm->exec_queues.lock);
> > > > > +
> > > > > + /*
> > > > > + * XXX: Randomly picking a threshold for now. This
> > > > > will
> > > > > need
> > > > > to be
> > > > > + * tuned based on expected UMD queue counts and
> > > > > performance
> > > > > profiling.
> > > > > + */
> > > > > +#define EXEC_QUEUE_COUNT_FULL_THRESHOLD 8
> > > > > + if (vm->exec_queues.count[guc_to_gt(guc)->info.id] >=
> > > > > + EXEC_QUEUE_COUNT_FULL_THRESHOLD) {
> > > > > + u32 action[] = {
> > > > > + XE_GUC_ACTION_TLB_INVALIDATION,
> > > > > + seqno,
> > > > > + MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL),
> > > > > + };
> > > > > +
> > > > > + err = send_tlb_inval(guc, action,
> > > > > ARRAY_SIZE(action));
> > > > > + goto err_unlock;
> > > > > + }
> > > > > +#undef EXEC_QUEUE_COUNT_FULL_THRESHOLD
> > > > > +
> > > > > + /*
> > > > > + * Move exec queues to a temporary list to issue
> > > > > invalidations. The exec
> > > > > + * queue must be mapped in the current GuC, active,
> > > > > and a
> > > > > reference must
> > > > > + * be taken to prevent concurrent deregistrations.
> > > > > + */
> > > > > + list_for_each_entry_safe(q, next, &vm-
> > > > > >exec_queues.list,
> > > > > + vm_exec_queue_link)
> > > >
> > > > Nitpick: I'd prefer braces around the the if here so we aren't
> > > > nesting
> > > > the multi-line condition within this list_for_each loop.
> > > >
> > >
> > > Sure. CI and local testing is showing this loop explodes too. I'm
> > > reasing two GTs are modifying the list at the same time as I'm
> > > just
> > > using a read lock here. I think vm->exec_queues.list needs to be
> > > per
> > > GT
> > > actually or just use a mutex to protect the list.
> > >
> > > > > + if (queue_mapped_in_guc(guc, q) && q->ops-
> > > > > > active(q)
> > > > > &&
> > > > > + xe_exec_queue_get_unless_zero(q)) {
> > > > > + last_q = q;
> > > > > + list_move_tail(&q-
> > > > > >vm_exec_queue_link,
> > > > > &tlb_inval_list);
> > > > > + }
> > > > > +
> > > > > + if (!last_q) {
> > > > > + /*
> > > > > + * We can't break fence ordering for TLB
> > > > > invalidation
> > > > > jobs, if
> > > > > + * TLB invalidations are inflight issue a
> > > > > dummy
> > > > > invalidation to
> > > > > + * maintain ordering. Nor can we move safely
> > > > > the
> > > > > seqno_recv when
> > > > > + * returning -ECANCELED if TLB invalidations
> > > > > are
> > > > > in
> > > > > flight. Use
> > > > > + * GGTT invalidation as dummy invalidation
> > > > > given
> > > > > ASID
> > > > > + * invalidations are unsupported here.
> > > > > + */
> > > > > + if (xe_tlb_inval_idle(tlb_inval))
> > > > > + err = -ECANCELED;
> > > > > + else
> > > > > + err = send_tlb_inval_ggtt(tlb_inval,
> > > > > seqno);
> > > >
> > > > Can you give a little more context on this line actually? So
> > > > this
> > > > is
> > > > going to send down a 0x3 type invalidation to GuC
> > > > (TLB_INVAL_GUC).
> > > > GuC
> > > > is still doing an invalidation to hardware when we write this.
> > > > Is
> > > > that
> > > > the expectation with this?
> > > >
> > >
> > > Yes, I think I explain this in the comment above. We are issuing
> > > a
> > > dummy
> > > invalidation to maintain ordering when required, this would be
> > > GuC
> > > TLBs.
> > > Not ideal but we can't break dma-fencing ordering and this case
> > > so be
> > > exceedingly rare.
> >
> > Yeah the reasoning is clear to me. It just wasn't clear what would
> > happen with this GuC invalidation. Looking through the GuC source,
> > I
> > see this is sending with Granularity of 0x1. This is "All mappings
> > within ASID and VF" according to bspec. We aren't actually passing
> > an
> > ASID here and it looks like GuC isn't programming anything into
> > that
> > field in the descriptor. So we'd have to get unlucky with a 0 (I
> > believe - can't find where they're clearing this at a glance) ASID
> > which seems unlikely.
> >
> > So from the hardware side, there will be a lookup and failure to
> > find
> > the ASID and the transaction should be dropped.
> >
> > I think on current hardware this is ok and the invalidation still
> > completes at the GuC level (GuC receives the ack from hardware) and
> > we
> > shouldn't get an invalidation timeout in the KMD. But there's
> > always a
> > chance this could change in the future.
> >
> > Can you add a comment here indicating this? Basically something
> > like:
> > Expectation is that hardware will drop this request since GuC
> > submits
> > an ASID based request without an ASID.
>
> This is a GuC GGTT TLB invalidation - not a full PPGTT or PASID
Ok I see a newer note in bspec now about GGTT for this granularity...
https://gfxspecs.intel.com/Predator/Home/Index/59311
So yeah no problem with what you have.
Thanks,
Stuart
> invalidation. For example when we create or destroy a GGTT mapping,
> this
> is the type of invalidation we issue there.
>
> I picked GuC GGTT invalidation as I figure this was less costly than
> a
> full PPGTT invalidation but that is just a guess. Are ASID based
> invalidations available on platforms that want context based
> invalidations - my guess is no and maybe even confirmed that at one
> point by looking at GuC source.
>
> I already have comment above indicating this is a GGTT based
> invalidation.
>
> Matt
>
> >
> > Thanks,
> > Stuart
> >
> > >
> > > > > + goto err_unlock;
> > > > > + }
> > > > > +
> > > > > + list_for_each_entry_safe(q, next, &tlb_inval_list,
> > > > > vm_exec_queue_link) {
> > > > > + struct drm_suballoc *__prl_sa = NULL;
> > > > > + int __seqno = TLB_INVALIDATION_SEQNO_INVALID;
> > > > > + u32 type =
> > > > > XE_GUC_TLB_INVAL_PAGE_SELECTIVE_CTX;
> > > > > +
> > > > > + xe_assert(xe, q->vm == vm);
> > > > > +
> > > > > + if (err)
> > > > > + goto unref;
> > > > > +
> > > > > + if (last_q == q) {
> > > > > + __prl_sa = prl_sa;
> > > > > + __seqno = seqno;
> > > > > + }
> > > > > +
> > > > > + err = send_tlb_inval_ppgtt(guc, __seqno,
> > > > > start,
> > > > > end,
> > > > > + q->guc->id, type,
> > > > > __prl_sa);
> > > > > +
> > > > > +unref:
> > > > > + /*
> > > > > + * Must always return exec queue to original
> > > > > list
> > > > > /
> > > > > drop
> > > > > + * reference
> > > > > + */
> > > > > + xe_exec_queue_put(q);
> > > > > + list_move_tail(&q->vm_exec_queue_link, &vm-
> > > > > > exec_queues.list);
> > > >
> > > > Will get back on this one... need to spend a little more time
> > > > and
> > > > do
> > > > some testing.
> > > >
> > >
> > > I probably should flip the put for clarity but this is in fact
> > > safe
> > > as
> > > queue's memory can't disapear if vm->exec_queues.lock is held.
> > >
> > > Matt
> > >
> > > > Thanks,
> > > > Stuart
> > > >
> > > > > + }
> > > > > +
> > > > > +err_unlock:
> > > > > + up_read(&vm->exec_queues.lock);
> > > > > + xe_vm_put(vm);
> > > > > +
> > > > > + return err;
> > > > > +}
> > > > > +
> > > > > static bool tlb_inval_initialized(struct xe_tlb_inval
> > > > > *tlb_inval)
> > > > > {
> > > > > struct xe_guc *guc = tlb_inval->private;
> > > > > @@ -228,7 +350,7 @@ static long
> > > > > tlb_inval_timeout_delay(struct
> > > > > xe_tlb_inval *tlb_inval)
> > > > > return hw_tlb_timeout + 2 * delay;
> > > > > }
> > > > >
> > > > > -static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
> > > > > +static const struct xe_tlb_inval_ops guc_tlb_inval_asid_ops
> > > > > = {
> > > > > .all = send_tlb_inval_all,
> > > > > .ggtt = send_tlb_inval_ggtt,
> > > > > .ppgtt = send_tlb_inval_asid_ppgtt,
> > > > > @@ -237,6 +359,15 @@ static const struct xe_tlb_inval_ops
> > > > > guc_tlb_inval_ops = {
> > > > > .timeout_delay = tlb_inval_timeout_delay,
> > > > > };
> > > > >
> > > > > +static const struct xe_tlb_inval_ops guc_tlb_inval_ctx_ops =
> > > > > {
> > > > > + .ggtt = send_tlb_inval_ggtt,
> > > > > + .all = send_tlb_inval_all,
> > > > > + .ppgtt = send_tlb_inval_ctx_ppgtt,
> > > > > + .initialized = tlb_inval_initialized,
> > > > > + .flush = tlb_inval_flush,
> > > > > + .timeout_delay = tlb_inval_timeout_delay,
> > > > > +};
> > > > > +
> > > > > /**
> > > > > * xe_guc_tlb_inval_init_early() - Init GuC TLB invalidation
> > > > > early
> > > > > * @guc: GuC object
> > > > > @@ -248,8 +379,14 @@ static const struct xe_tlb_inval_ops
> > > > > guc_tlb_inval_ops = {
> > > > > void xe_guc_tlb_inval_init_early(struct xe_guc *guc,
> > > > > struct xe_tlb_inval
> > > > > *tlb_inval)
> > > > > {
> > > > > + struct xe_device *xe = guc_to_xe(guc);
> > > > > +
> > > > > tlb_inval->private = guc;
> > > > > - tlb_inval->ops = &guc_tlb_inval_ops;
> > > > > +
> > > > > + if (xe->info.has_ctx_tlb_inval)
> > > > > + tlb_inval->ops = &guc_tlb_inval_ctx_ops;
> > > > > + else
> > > > > + tlb_inval->ops = &guc_tlb_inval_asid_ops;
> > > > > }
> > > > >
> > > > > /**
> > > > > diff --git a/drivers/gpu/drm/xe/xe_pci.c
> > > > > b/drivers/gpu/drm/xe/xe_pci.c
> > > > > index 91e0553a8163..6ea1199f703e 100644
> > > > > --- a/drivers/gpu/drm/xe/xe_pci.c
> > > > > +++ b/drivers/gpu/drm/xe/xe_pci.c
> > > > > @@ -889,6 +889,7 @@ static int xe_info_init(struct xe_device
> > > > > *xe,
> > > > > xe->info.has_device_atomics_on_smem = 1;
> > > > >
> > > > > xe->info.has_range_tlb_inval = graphics_desc-
> > > > > > has_range_tlb_inval;
> > > > > + xe->info.has_ctx_tlb_inval = graphics_desc-
> > > > > > has_ctx_tlb_inval;
> > > > > xe->info.has_usm = graphics_desc->has_usm;
> > > > > xe->info.has_64bit_timestamp = graphics_desc-
> > > > > > has_64bit_timestamp;
> > > > >
> > > > > diff --git a/drivers/gpu/drm/xe/xe_pci_types.h
> > > > > b/drivers/gpu/drm/xe/xe_pci_types.h
> > > > > index 5f20f56571d1..000b54cbcd0e 100644
> > > > > --- a/drivers/gpu/drm/xe/xe_pci_types.h
> > > > > +++ b/drivers/gpu/drm/xe/xe_pci_types.h
> > > > > @@ -71,6 +71,7 @@ struct xe_graphics_desc {
> > > > > u8 has_atomic_enable_pte_bit:1;
> > > > > u8 has_indirect_ring_state:1;
> > > > > u8 has_range_tlb_inval:1;
> > > > > + u8 has_ctx_tlb_inval:1;
> > > > > u8 has_usm:1;
> > > > > u8 has_64bit_timestamp:1;
> > > > > };
> > > >
> >
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v3 11/11] drm/xe: Enable context TLB invalidations for CI
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (9 preceding siblings ...)
2026-01-12 23:27 ` [PATCH v3 10/11] drm/xe: Add context-based invalidation to GuC TLB invalidation backend Matthew Brost
@ 2026-01-12 23:27 ` Matthew Brost
2026-01-12 23:37 ` ✓ CI.KUnit: success for Context based TLB invalidations (rev3) Patchwork
2026-01-13 0:17 ` ✗ Xe.CI.BAT: failure " Patchwork
12 siblings, 0 replies; 24+ messages in thread
From: Matthew Brost @ 2026-01-12 23:27 UTC (permalink / raw)
To: intel-xe; +Cc: stuart.summers
Do not review, CI only.
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
drivers/gpu/drm/xe/xe_pci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 6ea1199f703e..8a03bed61378 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -96,6 +96,7 @@ static const struct xe_graphics_desc graphics_xelpg = {
.has_asid = 1, \
.has_atomic_enable_pte_bit = 1, \
.has_range_tlb_inval = 1, \
+ .has_ctx_tlb_inval = 1, \
.has_usm = 1, \
.has_64bit_timestamp = 1, \
.hw_engine_mask = \
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* ✓ CI.KUnit: success for Context based TLB invalidations (rev3)
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (10 preceding siblings ...)
2026-01-12 23:27 ` [PATCH v3 11/11] drm/xe: Enable context TLB invalidations for CI Matthew Brost
@ 2026-01-12 23:37 ` Patchwork
2026-01-13 0:17 ` ✗ Xe.CI.BAT: failure " Patchwork
12 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2026-01-12 23:37 UTC (permalink / raw)
To: Matthew Brost; +Cc: intel-xe
== Series Details ==
Series: Context based TLB invalidations (rev3)
URL : https://patchwork.freedesktop.org/series/156874/
State : success
== Summary ==
+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
[23:35:53] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[23:35:58] 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
[23:36:29] Starting KUnit Kernel (1/1)...
[23:36:29] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[23:36:29] ================== guc_buf (11 subtests) ===================
[23:36:29] [PASSED] test_smallest
[23:36:29] [PASSED] test_largest
[23:36:29] [PASSED] test_granular
[23:36:29] [PASSED] test_unique
[23:36:29] [PASSED] test_overlap
[23:36:29] [PASSED] test_reusable
[23:36:29] [PASSED] test_too_big
[23:36:29] [PASSED] test_flush
[23:36:29] [PASSED] test_lookup
[23:36:29] [PASSED] test_data
[23:36:29] [PASSED] test_class
[23:36:29] ===================== [PASSED] guc_buf =====================
[23:36:29] =================== guc_dbm (7 subtests) ===================
[23:36:29] [PASSED] test_empty
[23:36:29] [PASSED] test_default
[23:36:29] ======================== test_size ========================
[23:36:29] [PASSED] 4
[23:36:29] [PASSED] 8
[23:36:29] [PASSED] 32
[23:36:29] [PASSED] 256
[23:36:29] ==================== [PASSED] test_size ====================
[23:36:29] ======================= test_reuse ========================
[23:36:29] [PASSED] 4
[23:36:29] [PASSED] 8
[23:36:29] [PASSED] 32
[23:36:29] [PASSED] 256
[23:36:29] =================== [PASSED] test_reuse ====================
[23:36:29] =================== test_range_overlap ====================
[23:36:29] [PASSED] 4
[23:36:29] [PASSED] 8
[23:36:29] [PASSED] 32
[23:36:29] [PASSED] 256
[23:36:29] =============== [PASSED] test_range_overlap ================
[23:36:29] =================== test_range_compact ====================
[23:36:29] [PASSED] 4
[23:36:29] [PASSED] 8
[23:36:29] [PASSED] 32
[23:36:29] [PASSED] 256
[23:36:29] =============== [PASSED] test_range_compact ================
[23:36:29] ==================== test_range_spare =====================
[23:36:29] [PASSED] 4
[23:36:29] [PASSED] 8
[23:36:29] [PASSED] 32
[23:36:29] [PASSED] 256
[23:36:29] ================ [PASSED] test_range_spare =================
[23:36:29] ===================== [PASSED] guc_dbm =====================
[23:36:29] =================== guc_idm (6 subtests) ===================
[23:36:29] [PASSED] bad_init
[23:36:29] [PASSED] no_init
[23:36:29] [PASSED] init_fini
[23:36:29] [PASSED] check_used
[23:36:29] [PASSED] check_quota
[23:36:29] [PASSED] check_all
[23:36:29] ===================== [PASSED] guc_idm =====================
[23:36:29] ================== no_relay (3 subtests) ===================
[23:36:29] [PASSED] xe_drops_guc2pf_if_not_ready
[23:36:29] [PASSED] xe_drops_guc2vf_if_not_ready
[23:36:29] [PASSED] xe_rejects_send_if_not_ready
[23:36:29] ==================== [PASSED] no_relay =====================
[23:36:29] ================== pf_relay (14 subtests) ==================
[23:36:29] [PASSED] pf_rejects_guc2pf_too_short
[23:36:29] [PASSED] pf_rejects_guc2pf_too_long
[23:36:29] [PASSED] pf_rejects_guc2pf_no_payload
[23:36:29] [PASSED] pf_fails_no_payload
[23:36:29] [PASSED] pf_fails_bad_origin
[23:36:29] [PASSED] pf_fails_bad_type
[23:36:29] [PASSED] pf_txn_reports_error
[23:36:29] [PASSED] pf_txn_sends_pf2guc
[23:36:29] [PASSED] pf_sends_pf2guc
[23:36:29] [SKIPPED] pf_loopback_nop
[23:36:29] [SKIPPED] pf_loopback_echo
[23:36:29] [SKIPPED] pf_loopback_fail
[23:36:29] [SKIPPED] pf_loopback_busy
[23:36:29] [SKIPPED] pf_loopback_retry
[23:36:29] ==================== [PASSED] pf_relay =====================
[23:36:29] ================== vf_relay (3 subtests) ===================
[23:36:29] [PASSED] vf_rejects_guc2vf_too_short
[23:36:29] [PASSED] vf_rejects_guc2vf_too_long
[23:36:29] [PASSED] vf_rejects_guc2vf_no_payload
[23:36:29] ==================== [PASSED] vf_relay =====================
[23:36:29] ================ pf_gt_config (6 subtests) =================
[23:36:29] [PASSED] fair_contexts_1vf
[23:36:29] [PASSED] fair_doorbells_1vf
[23:36:29] [PASSED] fair_ggtt_1vf
[23:36:29] ====================== fair_contexts ======================
[23:36:29] [PASSED] 1 VF
[23:36:29] [PASSED] 2 VFs
[23:36:29] [PASSED] 3 VFs
[23:36:29] [PASSED] 4 VFs
[23:36:29] [PASSED] 5 VFs
[23:36:29] [PASSED] 6 VFs
[23:36:29] [PASSED] 7 VFs
[23:36:29] [PASSED] 8 VFs
[23:36:29] [PASSED] 9 VFs
[23:36:29] [PASSED] 10 VFs
[23:36:29] [PASSED] 11 VFs
[23:36:29] [PASSED] 12 VFs
[23:36:29] [PASSED] 13 VFs
[23:36:29] [PASSED] 14 VFs
[23:36:29] [PASSED] 15 VFs
[23:36:29] [PASSED] 16 VFs
[23:36:29] [PASSED] 17 VFs
[23:36:29] [PASSED] 18 VFs
[23:36:29] [PASSED] 19 VFs
[23:36:29] [PASSED] 20 VFs
[23:36:29] [PASSED] 21 VFs
[23:36:29] [PASSED] 22 VFs
[23:36:29] [PASSED] 23 VFs
[23:36:29] [PASSED] 24 VFs
[23:36:29] [PASSED] 25 VFs
[23:36:29] [PASSED] 26 VFs
[23:36:29] [PASSED] 27 VFs
[23:36:29] [PASSED] 28 VFs
[23:36:29] [PASSED] 29 VFs
[23:36:29] [PASSED] 30 VFs
[23:36:29] [PASSED] 31 VFs
[23:36:29] [PASSED] 32 VFs
[23:36:29] [PASSED] 33 VFs
[23:36:29] [PASSED] 34 VFs
[23:36:29] [PASSED] 35 VFs
[23:36:29] [PASSED] 36 VFs
[23:36:29] [PASSED] 37 VFs
[23:36:29] [PASSED] 38 VFs
[23:36:29] [PASSED] 39 VFs
[23:36:29] [PASSED] 40 VFs
[23:36:29] [PASSED] 41 VFs
[23:36:29] [PASSED] 42 VFs
[23:36:29] [PASSED] 43 VFs
[23:36:29] [PASSED] 44 VFs
[23:36:29] [PASSED] 45 VFs
[23:36:29] [PASSED] 46 VFs
[23:36:29] [PASSED] 47 VFs
[23:36:29] [PASSED] 48 VFs
[23:36:29] [PASSED] 49 VFs
[23:36:29] [PASSED] 50 VFs
[23:36:29] [PASSED] 51 VFs
[23:36:29] [PASSED] 52 VFs
[23:36:29] [PASSED] 53 VFs
[23:36:29] [PASSED] 54 VFs
[23:36:29] [PASSED] 55 VFs
[23:36:29] [PASSED] 56 VFs
[23:36:29] [PASSED] 57 VFs
[23:36:29] [PASSED] 58 VFs
[23:36:29] [PASSED] 59 VFs
[23:36:29] [PASSED] 60 VFs
[23:36:29] [PASSED] 61 VFs
[23:36:29] [PASSED] 62 VFs
[23:36:29] [PASSED] 63 VFs
[23:36:29] ================== [PASSED] fair_contexts ==================
[23:36:29] ===================== fair_doorbells ======================
[23:36:29] [PASSED] 1 VF
[23:36:29] [PASSED] 2 VFs
[23:36:29] [PASSED] 3 VFs
[23:36:29] [PASSED] 4 VFs
[23:36:29] [PASSED] 5 VFs
[23:36:29] [PASSED] 6 VFs
[23:36:29] [PASSED] 7 VFs
[23:36:29] [PASSED] 8 VFs
[23:36:29] [PASSED] 9 VFs
[23:36:29] [PASSED] 10 VFs
[23:36:29] [PASSED] 11 VFs
[23:36:29] [PASSED] 12 VFs
[23:36:29] [PASSED] 13 VFs
[23:36:29] [PASSED] 14 VFs
[23:36:29] [PASSED] 15 VFs
[23:36:29] [PASSED] 16 VFs
[23:36:29] [PASSED] 17 VFs
[23:36:29] [PASSED] 18 VFs
[23:36:29] [PASSED] 19 VFs
[23:36:29] [PASSED] 20 VFs
[23:36:29] [PASSED] 21 VFs
[23:36:29] [PASSED] 22 VFs
[23:36:29] [PASSED] 23 VFs
[23:36:29] [PASSED] 24 VFs
[23:36:29] [PASSED] 25 VFs
[23:36:29] [PASSED] 26 VFs
[23:36:29] [PASSED] 27 VFs
[23:36:29] [PASSED] 28 VFs
[23:36:29] [PASSED] 29 VFs
[23:36:29] [PASSED] 30 VFs
[23:36:29] [PASSED] 31 VFs
[23:36:29] [PASSED] 32 VFs
[23:36:29] [PASSED] 33 VFs
[23:36:29] [PASSED] 34 VFs
[23:36:29] [PASSED] 35 VFs
[23:36:29] [PASSED] 36 VFs
[23:36:29] [PASSED] 37 VFs
[23:36:29] [PASSED] 38 VFs
[23:36:29] [PASSED] 39 VFs
[23:36:29] [PASSED] 40 VFs
[23:36:29] [PASSED] 41 VFs
[23:36:29] [PASSED] 42 VFs
[23:36:29] [PASSED] 43 VFs
[23:36:29] [PASSED] 44 VFs
[23:36:29] [PASSED] 45 VFs
[23:36:29] [PASSED] 46 VFs
[23:36:29] [PASSED] 47 VFs
[23:36:29] [PASSED] 48 VFs
[23:36:29] [PASSED] 49 VFs
[23:36:29] [PASSED] 50 VFs
[23:36:29] [PASSED] 51 VFs
[23:36:29] [PASSED] 52 VFs
[23:36:29] [PASSED] 53 VFs
[23:36:29] [PASSED] 54 VFs
[23:36:29] [PASSED] 55 VFs
[23:36:29] [PASSED] 56 VFs
[23:36:29] [PASSED] 57 VFs
[23:36:29] [PASSED] 58 VFs
[23:36:29] [PASSED] 59 VFs
[23:36:29] [PASSED] 60 VFs
[23:36:29] [PASSED] 61 VFs
[23:36:29] [PASSED] 62 VFs
[23:36:29] [PASSED] 63 VFs
[23:36:29] ================= [PASSED] fair_doorbells ==================
[23:36:29] ======================== fair_ggtt ========================
[23:36:29] [PASSED] 1 VF
[23:36:29] [PASSED] 2 VFs
[23:36:29] [PASSED] 3 VFs
[23:36:29] [PASSED] 4 VFs
[23:36:29] [PASSED] 5 VFs
[23:36:29] [PASSED] 6 VFs
[23:36:29] [PASSED] 7 VFs
[23:36:29] [PASSED] 8 VFs
[23:36:29] [PASSED] 9 VFs
[23:36:29] [PASSED] 10 VFs
[23:36:29] [PASSED] 11 VFs
[23:36:29] [PASSED] 12 VFs
[23:36:29] [PASSED] 13 VFs
[23:36:29] [PASSED] 14 VFs
[23:36:29] [PASSED] 15 VFs
[23:36:29] [PASSED] 16 VFs
[23:36:29] [PASSED] 17 VFs
[23:36:29] [PASSED] 18 VFs
[23:36:29] [PASSED] 19 VFs
[23:36:29] [PASSED] 20 VFs
[23:36:29] [PASSED] 21 VFs
[23:36:29] [PASSED] 22 VFs
[23:36:29] [PASSED] 23 VFs
[23:36:29] [PASSED] 24 VFs
[23:36:29] [PASSED] 25 VFs
[23:36:29] [PASSED] 26 VFs
[23:36:29] [PASSED] 27 VFs
[23:36:29] [PASSED] 28 VFs
[23:36:29] [PASSED] 29 VFs
[23:36:29] [PASSED] 30 VFs
[23:36:29] [PASSED] 31 VFs
[23:36:29] [PASSED] 32 VFs
[23:36:29] [PASSED] 33 VFs
[23:36:29] [PASSED] 34 VFs
[23:36:29] [PASSED] 35 VFs
[23:36:29] [PASSED] 36 VFs
[23:36:29] [PASSED] 37 VFs
[23:36:29] [PASSED] 38 VFs
[23:36:29] [PASSED] 39 VFs
[23:36:29] [PASSED] 40 VFs
[23:36:29] [PASSED] 41 VFs
[23:36:29] [PASSED] 42 VFs
[23:36:29] [PASSED] 43 VFs
[23:36:29] [PASSED] 44 VFs
[23:36:29] [PASSED] 45 VFs
[23:36:29] [PASSED] 46 VFs
[23:36:29] [PASSED] 47 VFs
[23:36:29] [PASSED] 48 VFs
[23:36:29] [PASSED] 49 VFs
[23:36:29] [PASSED] 50 VFs
[23:36:29] [PASSED] 51 VFs
[23:36:29] [PASSED] 52 VFs
[23:36:29] [PASSED] 53 VFs
[23:36:29] [PASSED] 54 VFs
[23:36:29] [PASSED] 55 VFs
[23:36:29] [PASSED] 56 VFs
[23:36:29] [PASSED] 57 VFs
[23:36:29] [PASSED] 58 VFs
[23:36:29] [PASSED] 59 VFs
[23:36:29] [PASSED] 60 VFs
[23:36:29] [PASSED] 61 VFs
[23:36:29] [PASSED] 62 VFs
[23:36:29] [PASSED] 63 VFs
[23:36:29] ==================== [PASSED] fair_ggtt ====================
[23:36:29] ================== [PASSED] pf_gt_config ===================
[23:36:29] ===================== lmtt (1 subtest) =====================
[23:36:29] ======================== test_ops =========================
[23:36:29] [PASSED] 2-level
[23:36:29] [PASSED] multi-level
[23:36:29] ==================== [PASSED] test_ops =====================
[23:36:29] ====================== [PASSED] lmtt =======================
[23:36:29] ================= pf_service (11 subtests) =================
[23:36:29] [PASSED] pf_negotiate_any
[23:36:29] [PASSED] pf_negotiate_base_match
[23:36:29] [PASSED] pf_negotiate_base_newer
[23:36:29] [PASSED] pf_negotiate_base_next
[23:36:29] [SKIPPED] pf_negotiate_base_older
[23:36:29] [PASSED] pf_negotiate_base_prev
[23:36:29] [PASSED] pf_negotiate_latest_match
[23:36:29] [PASSED] pf_negotiate_latest_newer
[23:36:29] [PASSED] pf_negotiate_latest_next
[23:36:29] [SKIPPED] pf_negotiate_latest_older
[23:36:29] [SKIPPED] pf_negotiate_latest_prev
[23:36:29] =================== [PASSED] pf_service ====================
[23:36:29] ================= xe_guc_g2g (2 subtests) ==================
[23:36:29] ============== xe_live_guc_g2g_kunit_default ==============
[23:36:29] ========= [SKIPPED] xe_live_guc_g2g_kunit_default ==========
[23:36:29] ============== xe_live_guc_g2g_kunit_allmem ===============
[23:36:29] ========== [SKIPPED] xe_live_guc_g2g_kunit_allmem ==========
[23:36:29] =================== [SKIPPED] xe_guc_g2g ===================
[23:36:29] =================== xe_mocs (2 subtests) ===================
[23:36:29] ================ xe_live_mocs_kernel_kunit ================
[23:36:29] =========== [SKIPPED] xe_live_mocs_kernel_kunit ============
[23:36:29] ================ xe_live_mocs_reset_kunit =================
[23:36:29] ============ [SKIPPED] xe_live_mocs_reset_kunit ============
[23:36:29] ==================== [SKIPPED] xe_mocs =====================
[23:36:29] ================= xe_migrate (2 subtests) ==================
[23:36:29] ================= xe_migrate_sanity_kunit =================
[23:36:29] ============ [SKIPPED] xe_migrate_sanity_kunit =============
[23:36:29] ================== xe_validate_ccs_kunit ==================
[23:36:29] ============= [SKIPPED] xe_validate_ccs_kunit ==============
[23:36:29] =================== [SKIPPED] xe_migrate ===================
[23:36:29] ================== xe_dma_buf (1 subtest) ==================
[23:36:29] ==================== xe_dma_buf_kunit =====================
[23:36:29] ================ [SKIPPED] xe_dma_buf_kunit ================
[23:36:29] =================== [SKIPPED] xe_dma_buf ===================
[23:36:29] ================= xe_bo_shrink (1 subtest) =================
[23:36:29] =================== xe_bo_shrink_kunit ====================
[23:36:29] =============== [SKIPPED] xe_bo_shrink_kunit ===============
[23:36:29] ================== [SKIPPED] xe_bo_shrink ==================
[23:36:29] ==================== xe_bo (2 subtests) ====================
[23:36:29] ================== xe_ccs_migrate_kunit ===================
[23:36:29] ============== [SKIPPED] xe_ccs_migrate_kunit ==============
[23:36:29] ==================== xe_bo_evict_kunit ====================
[23:36:29] =============== [SKIPPED] xe_bo_evict_kunit ================
[23:36:29] ===================== [SKIPPED] xe_bo ======================
[23:36:29] ==================== args (13 subtests) ====================
[23:36:29] [PASSED] count_args_test
[23:36:29] [PASSED] call_args_example
[23:36:29] [PASSED] call_args_test
[23:36:29] [PASSED] drop_first_arg_example
[23:36:29] [PASSED] drop_first_arg_test
[23:36:29] [PASSED] first_arg_example
[23:36:29] [PASSED] first_arg_test
[23:36:29] [PASSED] last_arg_example
[23:36:29] [PASSED] last_arg_test
[23:36:29] [PASSED] pick_arg_example
[23:36:29] [PASSED] if_args_example
[23:36:29] [PASSED] if_args_test
[23:36:29] [PASSED] sep_comma_example
[23:36:29] ====================== [PASSED] args =======================
[23:36:29] =================== xe_pci (3 subtests) ====================
[23:36:29] ==================== check_graphics_ip ====================
[23:36:29] [PASSED] 12.00 Xe_LP
[23:36:29] [PASSED] 12.10 Xe_LP+
[23:36:29] [PASSED] 12.55 Xe_HPG
[23:36:29] [PASSED] 12.60 Xe_HPC
[23:36:29] [PASSED] 12.70 Xe_LPG
[23:36:29] [PASSED] 12.71 Xe_LPG
[23:36:29] [PASSED] 12.74 Xe_LPG+
[23:36:29] [PASSED] 20.01 Xe2_HPG
[23:36:29] [PASSED] 20.02 Xe2_HPG
[23:36:29] [PASSED] 20.04 Xe2_LPG
[23:36:29] [PASSED] 30.00 Xe3_LPG
[23:36:29] [PASSED] 30.01 Xe3_LPG
[23:36:29] [PASSED] 30.03 Xe3_LPG
[23:36:29] [PASSED] 30.04 Xe3_LPG
[23:36:29] [PASSED] 30.05 Xe3_LPG
[23:36:29] [PASSED] 35.11 Xe3p_XPC
[23:36:29] ================ [PASSED] check_graphics_ip ================
[23:36:29] ===================== check_media_ip ======================
[23:36:29] [PASSED] 12.00 Xe_M
[23:36:29] [PASSED] 12.55 Xe_HPM
[23:36:29] [PASSED] 13.00 Xe_LPM+
[23:36:29] [PASSED] 13.01 Xe2_HPM
[23:36:29] [PASSED] 20.00 Xe2_LPM
[23:36:29] [PASSED] 30.00 Xe3_LPM
[23:36:29] [PASSED] 30.02 Xe3_LPM
[23:36:29] [PASSED] 35.00 Xe3p_LPM
[23:36:29] [PASSED] 35.03 Xe3p_HPM
[23:36:29] ================= [PASSED] check_media_ip ==================
[23:36:29] =================== check_platform_desc ===================
[23:36:29] [PASSED] 0x9A60 (TIGERLAKE)
[23:36:29] [PASSED] 0x9A68 (TIGERLAKE)
[23:36:29] [PASSED] 0x9A70 (TIGERLAKE)
[23:36:29] [PASSED] 0x9A40 (TIGERLAKE)
[23:36:29] [PASSED] 0x9A49 (TIGERLAKE)
[23:36:29] [PASSED] 0x9A59 (TIGERLAKE)
[23:36:29] [PASSED] 0x9A78 (TIGERLAKE)
[23:36:29] [PASSED] 0x9AC0 (TIGERLAKE)
[23:36:29] [PASSED] 0x9AC9 (TIGERLAKE)
[23:36:29] [PASSED] 0x9AD9 (TIGERLAKE)
[23:36:29] [PASSED] 0x9AF8 (TIGERLAKE)
[23:36:29] [PASSED] 0x4C80 (ROCKETLAKE)
[23:36:29] [PASSED] 0x4C8A (ROCKETLAKE)
[23:36:29] [PASSED] 0x4C8B (ROCKETLAKE)
[23:36:29] [PASSED] 0x4C8C (ROCKETLAKE)
[23:36:29] [PASSED] 0x4C90 (ROCKETLAKE)
[23:36:29] [PASSED] 0x4C9A (ROCKETLAKE)
[23:36:29] [PASSED] 0x4680 (ALDERLAKE_S)
[23:36:29] [PASSED] 0x4682 (ALDERLAKE_S)
[23:36:29] [PASSED] 0x4688 (ALDERLAKE_S)
[23:36:29] [PASSED] 0x468A (ALDERLAKE_S)
[23:36:29] [PASSED] 0x468B (ALDERLAKE_S)
[23:36:29] [PASSED] 0x4690 (ALDERLAKE_S)
[23:36:29] [PASSED] 0x4692 (ALDERLAKE_S)
[23:36:29] [PASSED] 0x4693 (ALDERLAKE_S)
[23:36:29] [PASSED] 0x46A0 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46A1 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46A2 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46A3 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46A6 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46A8 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46AA (ALDERLAKE_P)
[23:36:29] [PASSED] 0x462A (ALDERLAKE_P)
[23:36:29] [PASSED] 0x4626 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x4628 (ALDERLAKE_P)
stty: 'standard input': Inappropriate ioctl for device
[23:36:29] [PASSED] 0x46B0 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46B1 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46B2 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46B3 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46C0 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46C1 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46C2 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46C3 (ALDERLAKE_P)
[23:36:29] [PASSED] 0x46D0 (ALDERLAKE_N)
[23:36:29] [PASSED] 0x46D1 (ALDERLAKE_N)
[23:36:29] [PASSED] 0x46D2 (ALDERLAKE_N)
[23:36:29] [PASSED] 0x46D3 (ALDERLAKE_N)
[23:36:29] [PASSED] 0x46D4 (ALDERLAKE_N)
[23:36:29] [PASSED] 0xA721 (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA7A1 (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA7A9 (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA7AC (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA7AD (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA720 (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA7A0 (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA7A8 (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA7AA (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA7AB (ALDERLAKE_P)
[23:36:29] [PASSED] 0xA780 (ALDERLAKE_S)
[23:36:29] [PASSED] 0xA781 (ALDERLAKE_S)
[23:36:29] [PASSED] 0xA782 (ALDERLAKE_S)
[23:36:29] [PASSED] 0xA783 (ALDERLAKE_S)
[23:36:29] [PASSED] 0xA788 (ALDERLAKE_S)
[23:36:29] [PASSED] 0xA789 (ALDERLAKE_S)
[23:36:29] [PASSED] 0xA78A (ALDERLAKE_S)
[23:36:29] [PASSED] 0xA78B (ALDERLAKE_S)
[23:36:29] [PASSED] 0x4905 (DG1)
[23:36:29] [PASSED] 0x4906 (DG1)
[23:36:29] [PASSED] 0x4907 (DG1)
[23:36:29] [PASSED] 0x4908 (DG1)
[23:36:29] [PASSED] 0x4909 (DG1)
[23:36:29] [PASSED] 0x56C0 (DG2)
[23:36:29] [PASSED] 0x56C2 (DG2)
[23:36:29] [PASSED] 0x56C1 (DG2)
[23:36:29] [PASSED] 0x7D51 (METEORLAKE)
[23:36:29] [PASSED] 0x7DD1 (METEORLAKE)
[23:36:29] [PASSED] 0x7D41 (METEORLAKE)
[23:36:29] [PASSED] 0x7D67 (METEORLAKE)
[23:36:29] [PASSED] 0xB640 (METEORLAKE)
[23:36:29] [PASSED] 0x56A0 (DG2)
[23:36:29] [PASSED] 0x56A1 (DG2)
[23:36:29] [PASSED] 0x56A2 (DG2)
[23:36:29] [PASSED] 0x56BE (DG2)
[23:36:29] [PASSED] 0x56BF (DG2)
[23:36:29] [PASSED] 0x5690 (DG2)
[23:36:29] [PASSED] 0x5691 (DG2)
[23:36:29] [PASSED] 0x5692 (DG2)
[23:36:29] [PASSED] 0x56A5 (DG2)
[23:36:29] [PASSED] 0x56A6 (DG2)
[23:36:29] [PASSED] 0x56B0 (DG2)
[23:36:29] [PASSED] 0x56B1 (DG2)
[23:36:29] [PASSED] 0x56BA (DG2)
[23:36:29] [PASSED] 0x56BB (DG2)
[23:36:29] [PASSED] 0x56BC (DG2)
[23:36:29] [PASSED] 0x56BD (DG2)
[23:36:29] [PASSED] 0x5693 (DG2)
[23:36:29] [PASSED] 0x5694 (DG2)
[23:36:29] [PASSED] 0x5695 (DG2)
[23:36:29] [PASSED] 0x56A3 (DG2)
[23:36:29] [PASSED] 0x56A4 (DG2)
[23:36:29] [PASSED] 0x56B2 (DG2)
[23:36:29] [PASSED] 0x56B3 (DG2)
[23:36:29] [PASSED] 0x5696 (DG2)
[23:36:29] [PASSED] 0x5697 (DG2)
[23:36:29] [PASSED] 0xB69 (PVC)
[23:36:29] [PASSED] 0xB6E (PVC)
[23:36:29] [PASSED] 0xBD4 (PVC)
[23:36:29] [PASSED] 0xBD5 (PVC)
[23:36:29] [PASSED] 0xBD6 (PVC)
[23:36:29] [PASSED] 0xBD7 (PVC)
[23:36:29] [PASSED] 0xBD8 (PVC)
[23:36:29] [PASSED] 0xBD9 (PVC)
[23:36:29] [PASSED] 0xBDA (PVC)
[23:36:29] [PASSED] 0xBDB (PVC)
[23:36:29] [PASSED] 0xBE0 (PVC)
[23:36:29] [PASSED] 0xBE1 (PVC)
[23:36:29] [PASSED] 0xBE5 (PVC)
[23:36:29] [PASSED] 0x7D40 (METEORLAKE)
[23:36:29] [PASSED] 0x7D45 (METEORLAKE)
[23:36:29] [PASSED] 0x7D55 (METEORLAKE)
[23:36:29] [PASSED] 0x7D60 (METEORLAKE)
[23:36:29] [PASSED] 0x7DD5 (METEORLAKE)
[23:36:29] [PASSED] 0x6420 (LUNARLAKE)
[23:36:29] [PASSED] 0x64A0 (LUNARLAKE)
[23:36:29] [PASSED] 0x64B0 (LUNARLAKE)
[23:36:29] [PASSED] 0xE202 (BATTLEMAGE)
[23:36:29] [PASSED] 0xE209 (BATTLEMAGE)
[23:36:29] [PASSED] 0xE20B (BATTLEMAGE)
[23:36:29] [PASSED] 0xE20C (BATTLEMAGE)
[23:36:29] [PASSED] 0xE20D (BATTLEMAGE)
[23:36:29] [PASSED] 0xE210 (BATTLEMAGE)
[23:36:29] [PASSED] 0xE211 (BATTLEMAGE)
[23:36:29] [PASSED] 0xE212 (BATTLEMAGE)
[23:36:29] [PASSED] 0xE216 (BATTLEMAGE)
[23:36:29] [PASSED] 0xE220 (BATTLEMAGE)
[23:36:29] [PASSED] 0xE221 (BATTLEMAGE)
[23:36:29] [PASSED] 0xE222 (BATTLEMAGE)
[23:36:29] [PASSED] 0xE223 (BATTLEMAGE)
[23:36:29] [PASSED] 0xB080 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB081 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB082 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB083 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB084 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB085 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB086 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB087 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB08F (PANTHERLAKE)
[23:36:29] [PASSED] 0xB090 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB0A0 (PANTHERLAKE)
[23:36:29] [PASSED] 0xB0B0 (PANTHERLAKE)
[23:36:29] [PASSED] 0xFD80 (PANTHERLAKE)
[23:36:29] [PASSED] 0xFD81 (PANTHERLAKE)
[23:36:29] [PASSED] 0xD740 (NOVALAKE_S)
[23:36:29] [PASSED] 0xD741 (NOVALAKE_S)
[23:36:29] [PASSED] 0xD742 (NOVALAKE_S)
[23:36:29] [PASSED] 0xD743 (NOVALAKE_S)
[23:36:29] [PASSED] 0xD744 (NOVALAKE_S)
[23:36:29] [PASSED] 0xD745 (NOVALAKE_S)
[23:36:29] [PASSED] 0x674C (CRESCENTISLAND)
[23:36:29] =============== [PASSED] check_platform_desc ===============
[23:36:29] ===================== [PASSED] xe_pci ======================
[23:36:29] =================== xe_rtp (2 subtests) ====================
[23:36:29] =============== xe_rtp_process_to_sr_tests ================
[23:36:29] [PASSED] coalesce-same-reg
[23:36:29] [PASSED] no-match-no-add
[23:36:29] [PASSED] match-or
[23:36:29] [PASSED] match-or-xfail
[23:36:29] [PASSED] no-match-no-add-multiple-rules
[23:36:29] [PASSED] two-regs-two-entries
[23:36:29] [PASSED] clr-one-set-other
[23:36:29] [PASSED] set-field
[23:36:29] [PASSED] conflict-duplicate
[23:36:29] [PASSED] conflict-not-disjoint
[23:36:29] [PASSED] conflict-reg-type
[23:36:29] =========== [PASSED] xe_rtp_process_to_sr_tests ============
[23:36:29] ================== xe_rtp_process_tests ===================
[23:36:29] [PASSED] active1
[23:36:29] [PASSED] active2
[23:36:29] [PASSED] active-inactive
[23:36:29] [PASSED] inactive-active
[23:36:29] [PASSED] inactive-1st_or_active-inactive
[23:36:29] [PASSED] inactive-2nd_or_active-inactive
[23:36:29] [PASSED] inactive-last_or_active-inactive
[23:36:29] [PASSED] inactive-no_or_active-inactive
[23:36:29] ============== [PASSED] xe_rtp_process_tests ===============
[23:36:29] ===================== [PASSED] xe_rtp ======================
[23:36:29] ==================== xe_wa (1 subtest) =====================
[23:36:29] ======================== xe_wa_gt =========================
[23:36:29] [PASSED] TIGERLAKE B0
[23:36:29] [PASSED] DG1 A0
[23:36:29] [PASSED] DG1 B0
[23:36:29] [PASSED] ALDERLAKE_S A0
[23:36:29] [PASSED] ALDERLAKE_S B0
[23:36:29] [PASSED] ALDERLAKE_S C0
[23:36:29] [PASSED] ALDERLAKE_S D0
[23:36:29] [PASSED] ALDERLAKE_P A0
[23:36:29] [PASSED] ALDERLAKE_P B0
[23:36:29] [PASSED] ALDERLAKE_P C0
[23:36:29] [PASSED] ALDERLAKE_S RPLS D0
[23:36:29] [PASSED] ALDERLAKE_P RPLU E0
[23:36:29] [PASSED] DG2 G10 C0
[23:36:29] [PASSED] DG2 G11 B1
[23:36:29] [PASSED] DG2 G12 A1
[23:36:29] [PASSED] METEORLAKE 12.70(Xe_LPG) A0 13.00(Xe_LPM+) A0
[23:36:29] [PASSED] METEORLAKE 12.71(Xe_LPG) A0 13.00(Xe_LPM+) A0
[23:36:29] [PASSED] METEORLAKE 12.74(Xe_LPG+) A0 13.00(Xe_LPM+) A0
[23:36:29] [PASSED] LUNARLAKE 20.04(Xe2_LPG) A0 20.00(Xe2_LPM) A0
[23:36:29] [PASSED] LUNARLAKE 20.04(Xe2_LPG) B0 20.00(Xe2_LPM) A0
[23:36:29] [PASSED] BATTLEMAGE 20.01(Xe2_HPG) A0 13.01(Xe2_HPM) A1
[23:36:29] [PASSED] PANTHERLAKE 30.00(Xe3_LPG) A0 30.00(Xe3_LPM) A0
[23:36:29] ==================== [PASSED] xe_wa_gt =====================
[23:36:29] ====================== [PASSED] xe_wa ======================
[23:36:29] ============================================================
[23:36:29] Testing complete. Ran 512 tests: passed: 494, skipped: 18
[23:36:29] Elapsed time: 36.081s total, 4.292s configuring, 31.271s building, 0.464s running
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/tests/.kunitconfig
[23:36:30] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[23:36:31] 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
[23:36:57] Starting KUnit Kernel (1/1)...
[23:36:57] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[23:36:57] ============ drm_test_pick_cmdline (2 subtests) ============
[23:36:57] [PASSED] drm_test_pick_cmdline_res_1920_1080_60
[23:36:57] =============== drm_test_pick_cmdline_named ===============
[23:36:57] [PASSED] NTSC
[23:36:57] [PASSED] NTSC-J
[23:36:57] [PASSED] PAL
[23:36:57] [PASSED] PAL-M
[23:36:57] =========== [PASSED] drm_test_pick_cmdline_named ===========
[23:36:57] ============== [PASSED] drm_test_pick_cmdline ==============
[23:36:57] == drm_test_atomic_get_connector_for_encoder (1 subtest) ===
[23:36:57] [PASSED] drm_test_drm_atomic_get_connector_for_encoder
[23:36:57] ==== [PASSED] drm_test_atomic_get_connector_for_encoder ====
[23:36:57] =========== drm_validate_clone_mode (2 subtests) ===========
[23:36:57] ============== drm_test_check_in_clone_mode ===============
[23:36:57] [PASSED] in_clone_mode
[23:36:57] [PASSED] not_in_clone_mode
[23:36:57] ========== [PASSED] drm_test_check_in_clone_mode ===========
[23:36:57] =============== drm_test_check_valid_clones ===============
[23:36:57] [PASSED] not_in_clone_mode
[23:36:57] [PASSED] valid_clone
[23:36:57] [PASSED] invalid_clone
[23:36:57] =========== [PASSED] drm_test_check_valid_clones ===========
[23:36:57] ============= [PASSED] drm_validate_clone_mode =============
[23:36:57] ============= drm_validate_modeset (1 subtest) =============
[23:36:57] [PASSED] drm_test_check_connector_changed_modeset
[23:36:57] ============== [PASSED] drm_validate_modeset ===============
[23:36:57] ====== drm_test_bridge_get_current_state (2 subtests) ======
[23:36:57] [PASSED] drm_test_drm_bridge_get_current_state_atomic
[23:36:57] [PASSED] drm_test_drm_bridge_get_current_state_legacy
[23:36:57] ======== [PASSED] drm_test_bridge_get_current_state ========
[23:36:57] ====== drm_test_bridge_helper_reset_crtc (3 subtests) ======
[23:36:57] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic
[23:36:57] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic_disabled
[23:36:57] [PASSED] drm_test_drm_bridge_helper_reset_crtc_legacy
[23:36:57] ======== [PASSED] drm_test_bridge_helper_reset_crtc ========
[23:36:57] ============== drm_bridge_alloc (2 subtests) ===============
[23:36:57] [PASSED] drm_test_drm_bridge_alloc_basic
[23:36:57] [PASSED] drm_test_drm_bridge_alloc_get_put
[23:36:57] ================ [PASSED] drm_bridge_alloc =================
[23:36:57] ================== drm_buddy (8 subtests) ==================
[23:36:57] [PASSED] drm_test_buddy_alloc_limit
[23:36:57] [PASSED] drm_test_buddy_alloc_optimistic
[23:36:57] [PASSED] drm_test_buddy_alloc_pessimistic
[23:36:57] [PASSED] drm_test_buddy_alloc_pathological
[23:36:57] [PASSED] drm_test_buddy_alloc_contiguous
[23:36:57] [PASSED] drm_test_buddy_alloc_clear
[23:36:57] [PASSED] drm_test_buddy_alloc_range_bias
[23:36:57] [PASSED] drm_test_buddy_fragmentation_performance
[23:36:57] ==================== [PASSED] drm_buddy ====================
[23:36:57] ============= drm_cmdline_parser (40 subtests) =============
[23:36:57] [PASSED] drm_test_cmdline_force_d_only
[23:36:57] [PASSED] drm_test_cmdline_force_D_only_dvi
[23:36:57] [PASSED] drm_test_cmdline_force_D_only_hdmi
[23:36:57] [PASSED] drm_test_cmdline_force_D_only_not_digital
[23:36:57] [PASSED] drm_test_cmdline_force_e_only
[23:36:57] [PASSED] drm_test_cmdline_res
[23:36:57] [PASSED] drm_test_cmdline_res_vesa
[23:36:57] [PASSED] drm_test_cmdline_res_vesa_rblank
[23:36:57] [PASSED] drm_test_cmdline_res_rblank
[23:36:57] [PASSED] drm_test_cmdline_res_bpp
[23:36:57] [PASSED] drm_test_cmdline_res_refresh
[23:36:57] [PASSED] drm_test_cmdline_res_bpp_refresh
[23:36:57] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced
[23:36:57] [PASSED] drm_test_cmdline_res_bpp_refresh_margins
[23:36:57] [PASSED] drm_test_cmdline_res_bpp_refresh_force_off
[23:36:57] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on
[23:36:57] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_analog
[23:36:57] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_digital
[23:36:57] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on
[23:36:57] [PASSED] drm_test_cmdline_res_margins_force_on
[23:36:57] [PASSED] drm_test_cmdline_res_vesa_margins
[23:36:57] [PASSED] drm_test_cmdline_name
[23:36:57] [PASSED] drm_test_cmdline_name_bpp
[23:36:57] [PASSED] drm_test_cmdline_name_option
[23:36:57] [PASSED] drm_test_cmdline_name_bpp_option
[23:36:57] [PASSED] drm_test_cmdline_rotate_0
[23:36:57] [PASSED] drm_test_cmdline_rotate_90
[23:36:57] [PASSED] drm_test_cmdline_rotate_180
[23:36:57] [PASSED] drm_test_cmdline_rotate_270
[23:36:57] [PASSED] drm_test_cmdline_hmirror
[23:36:57] [PASSED] drm_test_cmdline_vmirror
[23:36:57] [PASSED] drm_test_cmdline_margin_options
[23:36:57] [PASSED] drm_test_cmdline_multiple_options
[23:36:57] [PASSED] drm_test_cmdline_bpp_extra_and_option
[23:36:57] [PASSED] drm_test_cmdline_extra_and_option
[23:36:57] [PASSED] drm_test_cmdline_freestanding_options
[23:36:57] [PASSED] drm_test_cmdline_freestanding_force_e_and_options
[23:36:57] [PASSED] drm_test_cmdline_panel_orientation
[23:36:57] ================ drm_test_cmdline_invalid =================
[23:36:57] [PASSED] margin_only
[23:36:57] [PASSED] interlace_only
[23:36:57] [PASSED] res_missing_x
[23:36:57] [PASSED] res_missing_y
[23:36:57] [PASSED] res_bad_y
[23:36:57] [PASSED] res_missing_y_bpp
[23:36:57] [PASSED] res_bad_bpp
[23:36:57] [PASSED] res_bad_refresh
[23:36:57] [PASSED] res_bpp_refresh_force_on_off
[23:36:57] [PASSED] res_invalid_mode
[23:36:57] [PASSED] res_bpp_wrong_place_mode
[23:36:57] [PASSED] name_bpp_refresh
[23:36:57] [PASSED] name_refresh
[23:36:57] [PASSED] name_refresh_wrong_mode
[23:36:57] [PASSED] name_refresh_invalid_mode
[23:36:57] [PASSED] rotate_multiple
[23:36:57] [PASSED] rotate_invalid_val
[23:36:57] [PASSED] rotate_truncated
[23:36:57] [PASSED] invalid_option
[23:36:57] [PASSED] invalid_tv_option
[23:36:57] [PASSED] truncated_tv_option
[23:36:57] ============ [PASSED] drm_test_cmdline_invalid =============
[23:36:57] =============== drm_test_cmdline_tv_options ===============
[23:36:57] [PASSED] NTSC
[23:36:57] [PASSED] NTSC_443
[23:36:57] [PASSED] NTSC_J
[23:36:57] [PASSED] PAL
[23:36:57] [PASSED] PAL_M
[23:36:57] [PASSED] PAL_N
[23:36:57] [PASSED] SECAM
[23:36:57] [PASSED] MONO_525
[23:36:57] [PASSED] MONO_625
[23:36:57] =========== [PASSED] drm_test_cmdline_tv_options ===========
[23:36:57] =============== [PASSED] drm_cmdline_parser ================
[23:36:57] ========== drmm_connector_hdmi_init (20 subtests) ==========
[23:36:57] [PASSED] drm_test_connector_hdmi_init_valid
[23:36:57] [PASSED] drm_test_connector_hdmi_init_bpc_8
[23:36:57] [PASSED] drm_test_connector_hdmi_init_bpc_10
[23:36:57] [PASSED] drm_test_connector_hdmi_init_bpc_12
[23:36:57] [PASSED] drm_test_connector_hdmi_init_bpc_invalid
[23:36:57] [PASSED] drm_test_connector_hdmi_init_bpc_null
[23:36:57] [PASSED] drm_test_connector_hdmi_init_formats_empty
[23:36:57] [PASSED] drm_test_connector_hdmi_init_formats_no_rgb
[23:36:57] === drm_test_connector_hdmi_init_formats_yuv420_allowed ===
[23:36:57] [PASSED] supported_formats=0x9 yuv420_allowed=1
[23:36:57] [PASSED] supported_formats=0x9 yuv420_allowed=0
[23:36:57] [PASSED] supported_formats=0x3 yuv420_allowed=1
[23:36:57] [PASSED] supported_formats=0x3 yuv420_allowed=0
[23:36:57] === [PASSED] drm_test_connector_hdmi_init_formats_yuv420_allowed ===
[23:36:57] [PASSED] drm_test_connector_hdmi_init_null_ddc
[23:36:57] [PASSED] drm_test_connector_hdmi_init_null_product
[23:36:57] [PASSED] drm_test_connector_hdmi_init_null_vendor
[23:36:57] [PASSED] drm_test_connector_hdmi_init_product_length_exact
[23:36:57] [PASSED] drm_test_connector_hdmi_init_product_length_too_long
[23:36:57] [PASSED] drm_test_connector_hdmi_init_product_valid
[23:36:57] [PASSED] drm_test_connector_hdmi_init_vendor_length_exact
[23:36:57] [PASSED] drm_test_connector_hdmi_init_vendor_length_too_long
[23:36:57] [PASSED] drm_test_connector_hdmi_init_vendor_valid
[23:36:57] ========= drm_test_connector_hdmi_init_type_valid =========
[23:36:57] [PASSED] HDMI-A
[23:36:57] [PASSED] HDMI-B
[23:36:57] ===== [PASSED] drm_test_connector_hdmi_init_type_valid =====
[23:36:57] ======== drm_test_connector_hdmi_init_type_invalid ========
[23:36:57] [PASSED] Unknown
[23:36:57] [PASSED] VGA
[23:36:57] [PASSED] DVI-I
[23:36:57] [PASSED] DVI-D
[23:36:57] [PASSED] DVI-A
[23:36:57] [PASSED] Composite
[23:36:57] [PASSED] SVIDEO
[23:36:57] [PASSED] LVDS
[23:36:57] [PASSED] Component
[23:36:57] [PASSED] DIN
[23:36:57] [PASSED] DP
[23:36:57] [PASSED] TV
[23:36:57] [PASSED] eDP
[23:36:57] [PASSED] Virtual
[23:36:57] [PASSED] DSI
[23:36:57] [PASSED] DPI
[23:36:57] [PASSED] Writeback
[23:36:57] [PASSED] SPI
[23:36:57] [PASSED] USB
[23:36:57] ==== [PASSED] drm_test_connector_hdmi_init_type_invalid ====
[23:36:57] ============ [PASSED] drmm_connector_hdmi_init =============
[23:36:57] ============= drmm_connector_init (3 subtests) =============
[23:36:57] [PASSED] drm_test_drmm_connector_init
[23:36:57] [PASSED] drm_test_drmm_connector_init_null_ddc
[23:36:57] ========= drm_test_drmm_connector_init_type_valid =========
[23:36:57] [PASSED] Unknown
[23:36:57] [PASSED] VGA
[23:36:57] [PASSED] DVI-I
[23:36:57] [PASSED] DVI-D
[23:36:57] [PASSED] DVI-A
[23:36:57] [PASSED] Composite
[23:36:57] [PASSED] SVIDEO
[23:36:57] [PASSED] LVDS
[23:36:57] [PASSED] Component
[23:36:57] [PASSED] DIN
[23:36:57] [PASSED] DP
[23:36:57] [PASSED] HDMI-A
[23:36:57] [PASSED] HDMI-B
[23:36:57] [PASSED] TV
[23:36:57] [PASSED] eDP
[23:36:57] [PASSED] Virtual
[23:36:57] [PASSED] DSI
[23:36:57] [PASSED] DPI
[23:36:57] [PASSED] Writeback
[23:36:57] [PASSED] SPI
[23:36:57] [PASSED] USB
[23:36:57] ===== [PASSED] drm_test_drmm_connector_init_type_valid =====
[23:36:57] =============== [PASSED] drmm_connector_init ===============
[23:36:57] ========= drm_connector_dynamic_init (6 subtests) ==========
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_init
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_init_null_ddc
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_init_not_added
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_init_properties
[23:36:57] ===== drm_test_drm_connector_dynamic_init_type_valid ======
[23:36:57] [PASSED] Unknown
[23:36:57] [PASSED] VGA
[23:36:57] [PASSED] DVI-I
[23:36:57] [PASSED] DVI-D
[23:36:57] [PASSED] DVI-A
[23:36:57] [PASSED] Composite
[23:36:57] [PASSED] SVIDEO
[23:36:57] [PASSED] LVDS
[23:36:57] [PASSED] Component
[23:36:57] [PASSED] DIN
[23:36:57] [PASSED] DP
[23:36:57] [PASSED] HDMI-A
[23:36:57] [PASSED] HDMI-B
[23:36:57] [PASSED] TV
[23:36:57] [PASSED] eDP
[23:36:57] [PASSED] Virtual
[23:36:57] [PASSED] DSI
[23:36:57] [PASSED] DPI
[23:36:57] [PASSED] Writeback
[23:36:57] [PASSED] SPI
[23:36:57] [PASSED] USB
[23:36:57] = [PASSED] drm_test_drm_connector_dynamic_init_type_valid ==
[23:36:57] ======== drm_test_drm_connector_dynamic_init_name =========
[23:36:57] [PASSED] Unknown
[23:36:57] [PASSED] VGA
[23:36:57] [PASSED] DVI-I
[23:36:57] [PASSED] DVI-D
[23:36:57] [PASSED] DVI-A
[23:36:57] [PASSED] Composite
[23:36:57] [PASSED] SVIDEO
[23:36:57] [PASSED] LVDS
[23:36:57] [PASSED] Component
[23:36:57] [PASSED] DIN
[23:36:57] [PASSED] DP
[23:36:57] [PASSED] HDMI-A
[23:36:57] [PASSED] HDMI-B
[23:36:57] [PASSED] TV
[23:36:57] [PASSED] eDP
[23:36:57] [PASSED] Virtual
[23:36:57] [PASSED] DSI
[23:36:57] [PASSED] DPI
[23:36:57] [PASSED] Writeback
[23:36:57] [PASSED] SPI
[23:36:57] [PASSED] USB
[23:36:57] ==== [PASSED] drm_test_drm_connector_dynamic_init_name =====
[23:36:57] =========== [PASSED] drm_connector_dynamic_init ============
[23:36:57] ==== drm_connector_dynamic_register_early (4 subtests) =====
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_early_on_list
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_early_defer
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_early_no_init
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_early_no_mode_object
[23:36:57] ====== [PASSED] drm_connector_dynamic_register_early =======
[23:36:57] ======= drm_connector_dynamic_register (7 subtests) ========
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_on_list
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_no_defer
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_no_init
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_mode_object
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_sysfs
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_sysfs_name
[23:36:57] [PASSED] drm_test_drm_connector_dynamic_register_debugfs
[23:36:57] ========= [PASSED] drm_connector_dynamic_register ==========
[23:36:57] = drm_connector_attach_broadcast_rgb_property (2 subtests) =
[23:36:57] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property
[23:36:57] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector
[23:36:57] === [PASSED] drm_connector_attach_broadcast_rgb_property ===
[23:36:57] ========== drm_get_tv_mode_from_name (2 subtests) ==========
[23:36:57] ========== drm_test_get_tv_mode_from_name_valid ===========
[23:36:57] [PASSED] NTSC
[23:36:57] [PASSED] NTSC-443
[23:36:57] [PASSED] NTSC-J
[23:36:57] [PASSED] PAL
[23:36:57] [PASSED] PAL-M
[23:36:57] [PASSED] PAL-N
[23:36:57] [PASSED] SECAM
[23:36:57] [PASSED] Mono
[23:36:57] ====== [PASSED] drm_test_get_tv_mode_from_name_valid =======
[23:36:57] [PASSED] drm_test_get_tv_mode_from_name_truncated
[23:36:57] ============ [PASSED] drm_get_tv_mode_from_name ============
[23:36:57] = drm_test_connector_hdmi_compute_mode_clock (12 subtests) =
[23:36:57] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb
[23:36:57] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc
[23:36:57] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1
[23:36:57] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc
[23:36:57] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1
[23:36:57] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_double
[23:36:57] = drm_test_connector_hdmi_compute_mode_clock_yuv420_valid =
[23:36:57] [PASSED] VIC 96
[23:36:57] [PASSED] VIC 97
[23:36:57] [PASSED] VIC 101
[23:36:57] [PASSED] VIC 102
[23:36:57] [PASSED] VIC 106
[23:36:57] [PASSED] VIC 107
[23:36:57] === [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_valid ===
[23:36:57] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc
[23:36:57] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc
[23:36:57] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc
[23:36:57] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc
[23:36:57] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc
[23:36:57] === [PASSED] drm_test_connector_hdmi_compute_mode_clock ====
[23:36:57] == drm_hdmi_connector_get_broadcast_rgb_name (2 subtests) ==
[23:36:57] === drm_test_drm_hdmi_connector_get_broadcast_rgb_name ====
[23:36:57] [PASSED] Automatic
[23:36:57] [PASSED] Full
[23:36:57] [PASSED] Limited 16:235
[23:36:57] === [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name ===
[23:36:57] [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid
[23:36:57] ==== [PASSED] drm_hdmi_connector_get_broadcast_rgb_name ====
[23:36:57] == drm_hdmi_connector_get_output_format_name (2 subtests) ==
[23:36:57] === drm_test_drm_hdmi_connector_get_output_format_name ====
[23:36:57] [PASSED] RGB
[23:36:57] [PASSED] YUV 4:2:0
[23:36:57] [PASSED] YUV 4:2:2
[23:36:57] [PASSED] YUV 4:4:4
[23:36:57] === [PASSED] drm_test_drm_hdmi_connector_get_output_format_name ===
[23:36:57] [PASSED] drm_test_drm_hdmi_connector_get_output_format_name_invalid
[23:36:57] ==== [PASSED] drm_hdmi_connector_get_output_format_name ====
[23:36:57] ============= drm_damage_helper (21 subtests) ==============
[23:36:57] [PASSED] drm_test_damage_iter_no_damage
[23:36:57] [PASSED] drm_test_damage_iter_no_damage_fractional_src
[23:36:57] [PASSED] drm_test_damage_iter_no_damage_src_moved
[23:36:57] [PASSED] drm_test_damage_iter_no_damage_fractional_src_moved
[23:36:57] [PASSED] drm_test_damage_iter_no_damage_not_visible
[23:36:57] [PASSED] drm_test_damage_iter_no_damage_no_crtc
[23:36:57] [PASSED] drm_test_damage_iter_no_damage_no_fb
[23:36:57] [PASSED] drm_test_damage_iter_simple_damage
[23:36:57] [PASSED] drm_test_damage_iter_single_damage
[23:36:57] [PASSED] drm_test_damage_iter_single_damage_intersect_src
[23:36:57] [PASSED] drm_test_damage_iter_single_damage_outside_src
[23:36:57] [PASSED] drm_test_damage_iter_single_damage_fractional_src
[23:36:57] [PASSED] drm_test_damage_iter_single_damage_intersect_fractional_src
[23:36:57] [PASSED] drm_test_damage_iter_single_damage_outside_fractional_src
[23:36:57] [PASSED] drm_test_damage_iter_single_damage_src_moved
[23:36:57] [PASSED] drm_test_damage_iter_single_damage_fractional_src_moved
[23:36:57] [PASSED] drm_test_damage_iter_damage
[23:36:57] [PASSED] drm_test_damage_iter_damage_one_intersect
[23:36:57] [PASSED] drm_test_damage_iter_damage_one_outside
[23:36:57] [PASSED] drm_test_damage_iter_damage_src_moved
[23:36:57] [PASSED] drm_test_damage_iter_damage_not_visible
[23:36:57] ================ [PASSED] drm_damage_helper ================
[23:36:57] ============== drm_dp_mst_helper (3 subtests) ==============
[23:36:57] ============== drm_test_dp_mst_calc_pbn_mode ==============
[23:36:57] [PASSED] Clock 154000 BPP 30 DSC disabled
[23:36:57] [PASSED] Clock 234000 BPP 30 DSC disabled
[23:36:57] [PASSED] Clock 297000 BPP 24 DSC disabled
[23:36:57] [PASSED] Clock 332880 BPP 24 DSC enabled
[23:36:57] [PASSED] Clock 324540 BPP 24 DSC enabled
[23:36:57] ========== [PASSED] drm_test_dp_mst_calc_pbn_mode ==========
[23:36:57] ============== drm_test_dp_mst_calc_pbn_div ===============
[23:36:57] [PASSED] Link rate 2000000 lane count 4
[23:36:57] [PASSED] Link rate 2000000 lane count 2
[23:36:57] [PASSED] Link rate 2000000 lane count 1
[23:36:57] [PASSED] Link rate 1350000 lane count 4
[23:36:57] [PASSED] Link rate 1350000 lane count 2
[23:36:57] [PASSED] Link rate 1350000 lane count 1
[23:36:57] [PASSED] Link rate 1000000 lane count 4
[23:36:57] [PASSED] Link rate 1000000 lane count 2
[23:36:57] [PASSED] Link rate 1000000 lane count 1
[23:36:57] [PASSED] Link rate 810000 lane count 4
[23:36:57] [PASSED] Link rate 810000 lane count 2
[23:36:57] [PASSED] Link rate 810000 lane count 1
[23:36:57] [PASSED] Link rate 540000 lane count 4
[23:36:57] [PASSED] Link rate 540000 lane count 2
[23:36:57] [PASSED] Link rate 540000 lane count 1
[23:36:57] [PASSED] Link rate 270000 lane count 4
[23:36:57] [PASSED] Link rate 270000 lane count 2
[23:36:57] [PASSED] Link rate 270000 lane count 1
[23:36:57] [PASSED] Link rate 162000 lane count 4
[23:36:57] [PASSED] Link rate 162000 lane count 2
[23:36:57] [PASSED] Link rate 162000 lane count 1
[23:36:57] ========== [PASSED] drm_test_dp_mst_calc_pbn_div ===========
[23:36:57] ========= drm_test_dp_mst_sideband_msg_req_decode =========
[23:36:57] [PASSED] DP_ENUM_PATH_RESOURCES with port number
[23:36:57] [PASSED] DP_POWER_UP_PHY with port number
[23:36:57] [PASSED] DP_POWER_DOWN_PHY with port number
[23:36:57] [PASSED] DP_ALLOCATE_PAYLOAD with SDP stream sinks
[23:36:57] [PASSED] DP_ALLOCATE_PAYLOAD with port number
[23:36:57] [PASSED] DP_ALLOCATE_PAYLOAD with VCPI
[23:36:57] [PASSED] DP_ALLOCATE_PAYLOAD with PBN
[23:36:57] [PASSED] DP_QUERY_PAYLOAD with port number
[23:36:57] [PASSED] DP_QUERY_PAYLOAD with VCPI
[23:36:57] [PASSED] DP_REMOTE_DPCD_READ with port number
[23:36:57] [PASSED] DP_REMOTE_DPCD_READ with DPCD address
[23:36:57] [PASSED] DP_REMOTE_DPCD_READ with max number of bytes
[23:36:57] [PASSED] DP_REMOTE_DPCD_WRITE with port number
[23:36:57] [PASSED] DP_REMOTE_DPCD_WRITE with DPCD address
[23:36:57] [PASSED] DP_REMOTE_DPCD_WRITE with data array
[23:36:57] [PASSED] DP_REMOTE_I2C_READ with port number
[23:36:57] [PASSED] DP_REMOTE_I2C_READ with I2C device ID
[23:36:57] [PASSED] DP_REMOTE_I2C_READ with transactions array
[23:36:57] [PASSED] DP_REMOTE_I2C_WRITE with port number
[23:36:57] [PASSED] DP_REMOTE_I2C_WRITE with I2C device ID
[23:36:57] [PASSED] DP_REMOTE_I2C_WRITE with data array
[23:36:57] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream ID
[23:36:57] [PASSED] DP_QUERY_STREAM_ENC_STATUS with client ID
[23:36:57] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream event
[23:36:57] [PASSED] DP_QUERY_STREAM_ENC_STATUS with valid stream event
[23:36:57] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream behavior
[23:36:57] [PASSED] DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior
[23:36:57] ===== [PASSED] drm_test_dp_mst_sideband_msg_req_decode =====
[23:36:57] ================ [PASSED] drm_dp_mst_helper ================
[23:36:57] ================== drm_exec (7 subtests) ===================
[23:36:57] [PASSED] sanitycheck
[23:36:57] [PASSED] test_lock
[23:36:57] [PASSED] test_lock_unlock
[23:36:57] [PASSED] test_duplicates
[23:36:57] [PASSED] test_prepare
[23:36:57] [PASSED] test_prepare_array
[23:36:57] [PASSED] test_multiple_loops
[23:36:57] ==================== [PASSED] drm_exec =====================
[23:36:57] =========== drm_format_helper_test (17 subtests) ===========
[23:36:57] ============== drm_test_fb_xrgb8888_to_gray8 ==============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ========== [PASSED] drm_test_fb_xrgb8888_to_gray8 ==========
[23:36:57] ============= drm_test_fb_xrgb8888_to_rgb332 ==============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb332 ==========
[23:36:57] ============= drm_test_fb_xrgb8888_to_rgb565 ==============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb565 ==========
[23:36:57] ============ drm_test_fb_xrgb8888_to_xrgb1555 =============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ======== [PASSED] drm_test_fb_xrgb8888_to_xrgb1555 =========
[23:36:57] ============ drm_test_fb_xrgb8888_to_argb1555 =============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ======== [PASSED] drm_test_fb_xrgb8888_to_argb1555 =========
[23:36:57] ============ drm_test_fb_xrgb8888_to_rgba5551 =============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ======== [PASSED] drm_test_fb_xrgb8888_to_rgba5551 =========
[23:36:57] ============= drm_test_fb_xrgb8888_to_rgb888 ==============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb888 ==========
[23:36:57] ============= drm_test_fb_xrgb8888_to_bgr888 ==============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ========= [PASSED] drm_test_fb_xrgb8888_to_bgr888 ==========
[23:36:57] ============ drm_test_fb_xrgb8888_to_argb8888 =============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ======== [PASSED] drm_test_fb_xrgb8888_to_argb8888 =========
[23:36:57] =========== drm_test_fb_xrgb8888_to_xrgb2101010 ===========
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ======= [PASSED] drm_test_fb_xrgb8888_to_xrgb2101010 =======
[23:36:57] =========== drm_test_fb_xrgb8888_to_argb2101010 ===========
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ======= [PASSED] drm_test_fb_xrgb8888_to_argb2101010 =======
[23:36:57] ============== drm_test_fb_xrgb8888_to_mono ===============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ========== [PASSED] drm_test_fb_xrgb8888_to_mono ===========
[23:36:57] ==================== drm_test_fb_swab =====================
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ================ [PASSED] drm_test_fb_swab =================
[23:36:57] ============ drm_test_fb_xrgb8888_to_xbgr8888 =============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ======== [PASSED] drm_test_fb_xrgb8888_to_xbgr8888 =========
[23:36:57] ============ drm_test_fb_xrgb8888_to_abgr8888 =============
[23:36:57] [PASSED] single_pixel_source_buffer
[23:36:57] [PASSED] single_pixel_clip_rectangle
[23:36:57] [PASSED] well_known_colors
[23:36:57] [PASSED] destination_pitch
[23:36:57] ======== [PASSED] drm_test_fb_xrgb8888_to_abgr8888 =========
[23:36:57] ================= drm_test_fb_clip_offset =================
[23:36:57] [PASSED] pass through
[23:36:57] [PASSED] horizontal offset
[23:36:57] [PASSED] vertical offset
[23:36:57] [PASSED] horizontal and vertical offset
[23:36:57] [PASSED] horizontal offset (custom pitch)
[23:36:57] [PASSED] vertical offset (custom pitch)
[23:36:57] [PASSED] horizontal and vertical offset (custom pitch)
[23:36:57] ============= [PASSED] drm_test_fb_clip_offset =============
[23:36:57] =================== drm_test_fb_memcpy ====================
[23:36:57] [PASSED] single_pixel_source_buffer: XR24 little-endian (0x34325258)
[23:36:57] [PASSED] single_pixel_source_buffer: XRA8 little-endian (0x38415258)
[23:36:57] [PASSED] single_pixel_source_buffer: YU24 little-endian (0x34325559)
[23:36:57] [PASSED] single_pixel_clip_rectangle: XB24 little-endian (0x34324258)
[23:36:57] [PASSED] single_pixel_clip_rectangle: XRA8 little-endian (0x38415258)
[23:36:57] [PASSED] single_pixel_clip_rectangle: YU24 little-endian (0x34325559)
[23:36:57] [PASSED] well_known_colors: XB24 little-endian (0x34324258)
[23:36:57] [PASSED] well_known_colors: XRA8 little-endian (0x38415258)
[23:36:57] [PASSED] well_known_colors: YU24 little-endian (0x34325559)
[23:36:57] [PASSED] destination_pitch: XB24 little-endian (0x34324258)
[23:36:57] [PASSED] destination_pitch: XRA8 little-endian (0x38415258)
[23:36:57] [PASSED] destination_pitch: YU24 little-endian (0x34325559)
[23:36:57] =============== [PASSED] drm_test_fb_memcpy ================
[23:36:57] ============= [PASSED] drm_format_helper_test ==============
[23:36:57] ================= drm_format (18 subtests) =================
[23:36:57] [PASSED] drm_test_format_block_width_invalid
[23:36:57] [PASSED] drm_test_format_block_width_one_plane
[23:36:57] [PASSED] drm_test_format_block_width_two_plane
[23:36:57] [PASSED] drm_test_format_block_width_three_plane
[23:36:57] [PASSED] drm_test_format_block_width_tiled
[23:36:57] [PASSED] drm_test_format_block_height_invalid
[23:36:57] [PASSED] drm_test_format_block_height_one_plane
[23:36:57] [PASSED] drm_test_format_block_height_two_plane
[23:36:57] [PASSED] drm_test_format_block_height_three_plane
[23:36:57] [PASSED] drm_test_format_block_height_tiled
[23:36:57] [PASSED] drm_test_format_min_pitch_invalid
[23:36:57] [PASSED] drm_test_format_min_pitch_one_plane_8bpp
[23:36:57] [PASSED] drm_test_format_min_pitch_one_plane_16bpp
[23:36:57] [PASSED] drm_test_format_min_pitch_one_plane_24bpp
[23:36:57] [PASSED] drm_test_format_min_pitch_one_plane_32bpp
[23:36:57] [PASSED] drm_test_format_min_pitch_two_plane
[23:36:57] [PASSED] drm_test_format_min_pitch_three_plane_8bpp
[23:36:57] [PASSED] drm_test_format_min_pitch_tiled
[23:36:57] =================== [PASSED] drm_format ====================
[23:36:57] ============== drm_framebuffer (10 subtests) ===============
[23:36:57] ========== drm_test_framebuffer_check_src_coords ==========
[23:36:57] [PASSED] Success: source fits into fb
[23:36:57] [PASSED] Fail: overflowing fb with x-axis coordinate
[23:36:57] [PASSED] Fail: overflowing fb with y-axis coordinate
[23:36:57] [PASSED] Fail: overflowing fb with source width
[23:36:57] [PASSED] Fail: overflowing fb with source height
[23:36:57] ====== [PASSED] drm_test_framebuffer_check_src_coords ======
[23:36:57] [PASSED] drm_test_framebuffer_cleanup
[23:36:57] =============== drm_test_framebuffer_create ===============
[23:36:57] [PASSED] ABGR8888 normal sizes
[23:36:57] [PASSED] ABGR8888 max sizes
[23:36:57] [PASSED] ABGR8888 pitch greater than min required
[23:36:57] [PASSED] ABGR8888 pitch less than min required
[23:36:57] [PASSED] ABGR8888 Invalid width
[23:36:57] [PASSED] ABGR8888 Invalid buffer handle
[23:36:57] [PASSED] No pixel format
[23:36:57] [PASSED] ABGR8888 Width 0
[23:36:57] [PASSED] ABGR8888 Height 0
[23:36:57] [PASSED] ABGR8888 Out of bound height * pitch combination
[23:36:57] [PASSED] ABGR8888 Large buffer offset
[23:36:57] [PASSED] ABGR8888 Buffer offset for inexistent plane
[23:36:57] [PASSED] ABGR8888 Invalid flag
[23:36:57] [PASSED] ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers
[23:36:57] [PASSED] ABGR8888 Valid buffer modifier
[23:36:57] [PASSED] ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
[23:36:57] [PASSED] ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS
[23:36:57] [PASSED] ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS
[23:36:57] [PASSED] NV12 Normal sizes
[23:36:57] [PASSED] NV12 Max sizes
[23:36:57] [PASSED] NV12 Invalid pitch
[23:36:57] [PASSED] NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag
[23:36:57] [PASSED] NV12 different modifier per-plane
[23:36:57] [PASSED] NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
[23:36:57] [PASSED] NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS
[23:36:57] [PASSED] NV12 Modifier for inexistent plane
[23:36:57] [PASSED] NV12 Handle for inexistent plane
[23:36:57] [PASSED] NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS
[23:36:57] [PASSED] YVU420 DRM_MODE_FB_MODIFIERS set without modifier
[23:36:57] [PASSED] YVU420 Normal sizes
[23:36:57] [PASSED] YVU420 Max sizes
[23:36:57] [PASSED] YVU420 Invalid pitch
[23:36:57] [PASSED] YVU420 Different pitches
[23:36:57] [PASSED] YVU420 Different buffer offsets/pitches
[23:36:57] [PASSED] YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS
[23:36:57] [PASSED] YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS
[23:36:57] [PASSED] YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS
[23:36:57] [PASSED] YVU420 Valid modifier
[23:36:57] [PASSED] YVU420 Different modifiers per plane
[23:36:57] [PASSED] YVU420 Modifier for inexistent plane
[23:36:57] [PASSED] YUV420_10BIT Invalid modifier(DRM_FORMAT_MOD_LINEAR)
[23:36:57] [PASSED] X0L2 Normal sizes
[23:36:57] [PASSED] X0L2 Max sizes
[23:36:57] [PASSED] X0L2 Invalid pitch
[23:36:57] [PASSED] X0L2 Pitch greater than minimum required
[23:36:57] [PASSED] X0L2 Handle for inexistent plane
[23:36:57] [PASSED] X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set
[23:36:57] [PASSED] X0L2 Modifier without DRM_MODE_FB_MODIFIERS set
[23:36:57] [PASSED] X0L2 Valid modifier
[23:36:57] [PASSED] X0L2 Modifier for inexistent plane
[23:36:57] =========== [PASSED] drm_test_framebuffer_create ===========
[23:36:57] [PASSED] drm_test_framebuffer_free
[23:36:57] [PASSED] drm_test_framebuffer_init
[23:36:57] [PASSED] drm_test_framebuffer_init_bad_format
[23:36:57] [PASSED] drm_test_framebuffer_init_dev_mismatch
[23:36:57] [PASSED] drm_test_framebuffer_lookup
[23:36:57] [PASSED] drm_test_framebuffer_lookup_inexistent
[23:36:57] [PASSED] drm_test_framebuffer_modifiers_not_supported
[23:36:57] ================= [PASSED] drm_framebuffer =================
[23:36:57] ================ drm_gem_shmem (8 subtests) ================
[23:36:57] [PASSED] drm_gem_shmem_test_obj_create
[23:36:57] [PASSED] drm_gem_shmem_test_obj_create_private
[23:36:57] [PASSED] drm_gem_shmem_test_pin_pages
[23:36:57] [PASSED] drm_gem_shmem_test_vmap
[23:36:57] [PASSED] drm_gem_shmem_test_get_sg_table
[23:36:57] [PASSED] drm_gem_shmem_test_get_pages_sgt
[23:36:57] [PASSED] drm_gem_shmem_test_madvise
[23:36:57] [PASSED] drm_gem_shmem_test_purge
[23:36:57] ================== [PASSED] drm_gem_shmem ==================
[23:36:57] === drm_atomic_helper_connector_hdmi_check (27 subtests) ===
[23:36:57] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode
[23:36:57] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode_vic_1
[23:36:57] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode
[23:36:57] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode_vic_1
[23:36:57] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode
[23:36:57] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode_vic_1
[23:36:57] ====== drm_test_check_broadcast_rgb_cea_mode_yuv420 =======
[23:36:57] [PASSED] Automatic
[23:36:57] [PASSED] Full
[23:36:57] [PASSED] Limited 16:235
[23:36:57] == [PASSED] drm_test_check_broadcast_rgb_cea_mode_yuv420 ===
[23:36:57] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_changed
[23:36:57] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_not_changed
[23:36:57] [PASSED] drm_test_check_disable_connector
[23:36:57] [PASSED] drm_test_check_hdmi_funcs_reject_rate
[23:36:57] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_rgb
[23:36:57] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_yuv420
[23:36:57] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422
[23:36:57] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420
[23:36:57] [PASSED] drm_test_check_driver_unsupported_fallback_yuv420
[23:36:57] [PASSED] drm_test_check_output_bpc_crtc_mode_changed
[23:36:57] [PASSED] drm_test_check_output_bpc_crtc_mode_not_changed
[23:36:57] [PASSED] drm_test_check_output_bpc_dvi
[23:36:57] [PASSED] drm_test_check_output_bpc_format_vic_1
[23:36:57] [PASSED] drm_test_check_output_bpc_format_display_8bpc_only
[23:36:57] [PASSED] drm_test_check_output_bpc_format_display_rgb_only
[23:36:57] [PASSED] drm_test_check_output_bpc_format_driver_8bpc_only
[23:36:57] [PASSED] drm_test_check_output_bpc_format_driver_rgb_only
[23:36:57] [PASSED] drm_test_check_tmds_char_rate_rgb_8bpc
[23:36:57] [PASSED] drm_test_check_tmds_char_rate_rgb_10bpc
[23:36:57] [PASSED] drm_test_check_tmds_char_rate_rgb_12bpc
[23:36:57] ===== [PASSED] drm_atomic_helper_connector_hdmi_check ======
[23:36:57] === drm_atomic_helper_connector_hdmi_reset (6 subtests) ====
[23:36:57] [PASSED] drm_test_check_broadcast_rgb_value
[23:36:57] [PASSED] drm_test_check_bpc_8_value
[23:36:57] [PASSED] drm_test_check_bpc_10_value
[23:36:57] [PASSED] drm_test_check_bpc_12_value
[23:36:57] [PASSED] drm_test_check_format_value
[23:36:57] [PASSED] drm_test_check_tmds_char_value
[23:36:57] ===== [PASSED] drm_atomic_helper_connector_hdmi_reset ======
[23:36:57] = drm_atomic_helper_connector_hdmi_mode_valid (4 subtests) =
[23:36:57] [PASSED] drm_test_check_mode_valid
[23:36:57] [PASSED] drm_test_check_mode_valid_reject
[23:36:57] [PASSED] drm_test_check_mode_valid_reject_rate
[23:36:57] [PASSED] drm_test_check_mode_valid_reject_max_clock
[23:36:57] === [PASSED] drm_atomic_helper_connector_hdmi_mode_valid ===
[23:36:57] ================= drm_managed (2 subtests) =================
[23:36:57] [PASSED] drm_test_managed_release_action
[23:36:57] [PASSED] drm_test_managed_run_action
[23:36:57] =================== [PASSED] drm_managed ===================
[23:36:57] =================== drm_mm (6 subtests) ====================
[23:36:57] [PASSED] drm_test_mm_init
[23:36:57] [PASSED] drm_test_mm_debug
[23:36:57] [PASSED] drm_test_mm_align32
[23:36:57] [PASSED] drm_test_mm_align64
[23:36:57] [PASSED] drm_test_mm_lowest
[23:36:57] [PASSED] drm_test_mm_highest
[23:36:57] ===================== [PASSED] drm_mm ======================
[23:36:57] ============= drm_modes_analog_tv (5 subtests) =============
[23:36:57] [PASSED] drm_test_modes_analog_tv_mono_576i
[23:36:57] [PASSED] drm_test_modes_analog_tv_ntsc_480i
[23:36:57] [PASSED] drm_test_modes_analog_tv_ntsc_480i_inlined
[23:36:57] [PASSED] drm_test_modes_analog_tv_pal_576i
[23:36:57] [PASSED] drm_test_modes_analog_tv_pal_576i_inlined
[23:36:57] =============== [PASSED] drm_modes_analog_tv ===============
[23:36:57] ============== drm_plane_helper (2 subtests) ===============
[23:36:57] =============== drm_test_check_plane_state ================
[23:36:57] [PASSED] clipping_simple
[23:36:57] [PASSED] clipping_rotate_reflect
[23:36:57] [PASSED] positioning_simple
[23:36:57] [PASSED] upscaling
[23:36:57] [PASSED] downscaling
[23:36:57] [PASSED] rounding1
[23:36:57] [PASSED] rounding2
[23:36:57] [PASSED] rounding3
[23:36:57] [PASSED] rounding4
[23:36:57] =========== [PASSED] drm_test_check_plane_state ============
[23:36:57] =========== drm_test_check_invalid_plane_state ============
[23:36:57] [PASSED] positioning_invalid
[23:36:57] [PASSED] upscaling_invalid
[23:36:57] [PASSED] downscaling_invalid
[23:36:57] ======= [PASSED] drm_test_check_invalid_plane_state ========
[23:36:57] ================ [PASSED] drm_plane_helper =================
[23:36:57] ====== drm_connector_helper_tv_get_modes (1 subtest) =======
[23:36:57] ====== drm_test_connector_helper_tv_get_modes_check =======
[23:36:57] [PASSED] None
[23:36:57] [PASSED] PAL
[23:36:57] [PASSED] NTSC
[23:36:57] [PASSED] Both, NTSC Default
[23:36:57] [PASSED] Both, PAL Default
[23:36:57] [PASSED] Both, NTSC Default, with PAL on command-line
[23:36:57] [PASSED] Both, PAL Default, with NTSC on command-line
[23:36:57] == [PASSED] drm_test_connector_helper_tv_get_modes_check ===
[23:36:57] ======== [PASSED] drm_connector_helper_tv_get_modes ========
[23:36:57] ================== drm_rect (9 subtests) ===================
[23:36:57] [PASSED] drm_test_rect_clip_scaled_div_by_zero
[23:36:57] [PASSED] drm_test_rect_clip_scaled_not_clipped
[23:36:57] [PASSED] drm_test_rect_clip_scaled_clipped
[23:36:57] [PASSED] drm_test_rect_clip_scaled_signed_vs_unsigned
[23:36:57] ================= drm_test_rect_intersect =================
[23:36:57] [PASSED] top-left x bottom-right: 2x2+1+1 x 2x2+0+0
[23:36:57] [PASSED] top-right x bottom-left: 2x2+0+0 x 2x2+1-1
[23:36:57] [PASSED] bottom-left x top-right: 2x2+1-1 x 2x2+0+0
[23:36:57] [PASSED] bottom-right x top-left: 2x2+0+0 x 2x2+1+1
[23:36:57] [PASSED] right x left: 2x1+0+0 x 3x1+1+0
[23:36:57] [PASSED] left x right: 3x1+1+0 x 2x1+0+0
[23:36:57] [PASSED] up x bottom: 1x2+0+0 x 1x3+0-1
[23:36:57] [PASSED] bottom x up: 1x3+0-1 x 1x2+0+0
[23:36:57] [PASSED] touching corner: 1x1+0+0 x 2x2+1+1
[23:36:57] [PASSED] touching side: 1x1+0+0 x 1x1+1+0
[23:36:57] [PASSED] equal rects: 2x2+0+0 x 2x2+0+0
[23:36:57] [PASSED] inside another: 2x2+0+0 x 1x1+1+1
[23:36:57] [PASSED] far away: 1x1+0+0 x 1x1+3+6
[23:36:57] [PASSED] points intersecting: 0x0+5+10 x 0x0+5+10
[23:36:57] [PASSED] points not intersecting: 0x0+0+0 x 0x0+5+10
[23:36:57] ============= [PASSED] drm_test_rect_intersect =============
[23:36:57] ================ drm_test_rect_calc_hscale ================
[23:36:57] [PASSED] normal use
[23:36:57] [PASSED] out of max range
[23:36:57] [PASSED] out of min range
[23:36:57] [PASSED] zero dst
[23:36:57] [PASSED] negative src
[23:36:57] [PASSED] negative dst
[23:36:57] ============ [PASSED] drm_test_rect_calc_hscale ============
[23:36:57] ================ drm_test_rect_calc_vscale ================
[23:36:57] [PASSED] normal use
stty: 'standard input': Inappropriate ioctl for device
[23:36:57] [PASSED] out of max range
[23:36:57] [PASSED] out of min range
[23:36:57] [PASSED] zero dst
[23:36:57] [PASSED] negative src
[23:36:57] [PASSED] negative dst
[23:36:57] ============ [PASSED] drm_test_rect_calc_vscale ============
[23:36:57] ================== drm_test_rect_rotate ===================
[23:36:57] [PASSED] reflect-x
[23:36:57] [PASSED] reflect-y
[23:36:57] [PASSED] rotate-0
[23:36:57] [PASSED] rotate-90
[23:36:57] [PASSED] rotate-180
[23:36:57] [PASSED] rotate-270
[23:36:57] ============== [PASSED] drm_test_rect_rotate ===============
[23:36:57] ================ drm_test_rect_rotate_inv =================
[23:36:57] [PASSED] reflect-x
[23:36:57] [PASSED] reflect-y
[23:36:57] [PASSED] rotate-0
[23:36:57] [PASSED] rotate-90
[23:36:57] [PASSED] rotate-180
[23:36:57] [PASSED] rotate-270
[23:36:57] ============ [PASSED] drm_test_rect_rotate_inv =============
[23:36:57] ==================== [PASSED] drm_rect =====================
[23:36:57] ============ drm_sysfb_modeset_test (1 subtest) ============
[23:36:57] ============ drm_test_sysfb_build_fourcc_list =============
[23:36:57] [PASSED] no native formats
[23:36:57] [PASSED] XRGB8888 as native format
[23:36:57] [PASSED] remove duplicates
[23:36:57] [PASSED] convert alpha formats
[23:36:57] [PASSED] random formats
[23:36:57] ======== [PASSED] drm_test_sysfb_build_fourcc_list =========
[23:36:57] ============= [PASSED] drm_sysfb_modeset_test ==============
[23:36:57] ================== drm_fixp (2 subtests) ===================
[23:36:57] [PASSED] drm_test_int2fixp
[23:36:57] [PASSED] drm_test_sm2fixp
[23:36:57] ==================== [PASSED] drm_fixp =====================
[23:36:57] ============================================================
[23:36:57] Testing complete. Ran 624 tests: passed: 624
[23:36:57] Elapsed time: 27.672s total, 1.678s configuring, 25.573s building, 0.374s running
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig
[23:36:57] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[23:36:59] 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
[23:37:08] Starting KUnit Kernel (1/1)...
[23:37:08] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[23:37:08] ================= ttm_device (5 subtests) ==================
[23:37:08] [PASSED] ttm_device_init_basic
[23:37:08] [PASSED] ttm_device_init_multiple
[23:37:08] [PASSED] ttm_device_fini_basic
[23:37:08] [PASSED] ttm_device_init_no_vma_man
[23:37:08] ================== ttm_device_init_pools ==================
[23:37:08] [PASSED] No DMA allocations, no DMA32 required
[23:37:08] [PASSED] DMA allocations, DMA32 required
[23:37:08] [PASSED] No DMA allocations, DMA32 required
[23:37:08] [PASSED] DMA allocations, no DMA32 required
[23:37:08] ============== [PASSED] ttm_device_init_pools ==============
[23:37:08] =================== [PASSED] ttm_device ====================
[23:37:08] ================== ttm_pool (8 subtests) ===================
[23:37:08] ================== ttm_pool_alloc_basic ===================
[23:37:08] [PASSED] One page
[23:37:08] [PASSED] More than one page
[23:37:08] [PASSED] Above the allocation limit
[23:37:08] [PASSED] One page, with coherent DMA mappings enabled
[23:37:08] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[23:37:08] ============== [PASSED] ttm_pool_alloc_basic ===============
[23:37:08] ============== ttm_pool_alloc_basic_dma_addr ==============
[23:37:08] [PASSED] One page
[23:37:08] [PASSED] More than one page
[23:37:08] [PASSED] Above the allocation limit
[23:37:08] [PASSED] One page, with coherent DMA mappings enabled
[23:37:08] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[23:37:08] ========== [PASSED] ttm_pool_alloc_basic_dma_addr ==========
[23:37:08] [PASSED] ttm_pool_alloc_order_caching_match
[23:37:08] [PASSED] ttm_pool_alloc_caching_mismatch
[23:37:08] [PASSED] ttm_pool_alloc_order_mismatch
[23:37:08] [PASSED] ttm_pool_free_dma_alloc
[23:37:08] [PASSED] ttm_pool_free_no_dma_alloc
[23:37:08] [PASSED] ttm_pool_fini_basic
[23:37:08] ==================== [PASSED] ttm_pool =====================
[23:37:08] ================ ttm_resource (8 subtests) =================
[23:37:08] ================= ttm_resource_init_basic =================
[23:37:08] [PASSED] Init resource in TTM_PL_SYSTEM
[23:37:08] [PASSED] Init resource in TTM_PL_VRAM
[23:37:08] [PASSED] Init resource in a private placement
[23:37:08] [PASSED] Init resource in TTM_PL_SYSTEM, set placement flags
[23:37:08] ============= [PASSED] ttm_resource_init_basic =============
[23:37:08] [PASSED] ttm_resource_init_pinned
[23:37:08] [PASSED] ttm_resource_fini_basic
[23:37:08] [PASSED] ttm_resource_manager_init_basic
[23:37:08] [PASSED] ttm_resource_manager_usage_basic
[23:37:08] [PASSED] ttm_resource_manager_set_used_basic
[23:37:08] [PASSED] ttm_sys_man_alloc_basic
[23:37:08] [PASSED] ttm_sys_man_free_basic
[23:37:08] ================== [PASSED] ttm_resource ===================
[23:37:08] =================== ttm_tt (15 subtests) ===================
[23:37:08] ==================== ttm_tt_init_basic ====================
[23:37:08] [PASSED] Page-aligned size
[23:37:08] [PASSED] Extra pages requested
[23:37:08] ================ [PASSED] ttm_tt_init_basic ================
[23:37:08] [PASSED] ttm_tt_init_misaligned
[23:37:08] [PASSED] ttm_tt_fini_basic
[23:37:08] [PASSED] ttm_tt_fini_sg
[23:37:08] [PASSED] ttm_tt_fini_shmem
[23:37:08] [PASSED] ttm_tt_create_basic
[23:37:08] [PASSED] ttm_tt_create_invalid_bo_type
[23:37:08] [PASSED] ttm_tt_create_ttm_exists
[23:37:08] [PASSED] ttm_tt_create_failed
[23:37:08] [PASSED] ttm_tt_destroy_basic
[23:37:08] [PASSED] ttm_tt_populate_null_ttm
[23:37:08] [PASSED] ttm_tt_populate_populated_ttm
[23:37:08] [PASSED] ttm_tt_unpopulate_basic
[23:37:08] [PASSED] ttm_tt_unpopulate_empty_ttm
[23:37:08] [PASSED] ttm_tt_swapin_basic
[23:37:08] ===================== [PASSED] ttm_tt ======================
[23:37:08] =================== ttm_bo (14 subtests) ===================
[23:37:08] =========== ttm_bo_reserve_optimistic_no_ticket ===========
[23:37:08] [PASSED] Cannot be interrupted and sleeps
[23:37:08] [PASSED] Cannot be interrupted, locks straight away
[23:37:08] [PASSED] Can be interrupted, sleeps
[23:37:08] ======= [PASSED] ttm_bo_reserve_optimistic_no_ticket =======
[23:37:08] [PASSED] ttm_bo_reserve_locked_no_sleep
[23:37:08] [PASSED] ttm_bo_reserve_no_wait_ticket
[23:37:08] [PASSED] ttm_bo_reserve_double_resv
[23:37:08] [PASSED] ttm_bo_reserve_interrupted
[23:37:08] [PASSED] ttm_bo_reserve_deadlock
[23:37:08] [PASSED] ttm_bo_unreserve_basic
[23:37:08] [PASSED] ttm_bo_unreserve_pinned
[23:37:08] [PASSED] ttm_bo_unreserve_bulk
[23:37:08] [PASSED] ttm_bo_fini_basic
[23:37:08] [PASSED] ttm_bo_fini_shared_resv
[23:37:08] [PASSED] ttm_bo_pin_basic
[23:37:08] [PASSED] ttm_bo_pin_unpin_resource
[23:37:08] [PASSED] ttm_bo_multiple_pin_one_unpin
[23:37:08] ===================== [PASSED] ttm_bo ======================
[23:37:08] ============== ttm_bo_validate (21 subtests) ===============
[23:37:08] ============== ttm_bo_init_reserved_sys_man ===============
[23:37:08] [PASSED] Buffer object for userspace
[23:37:08] [PASSED] Kernel buffer object
[23:37:08] [PASSED] Shared buffer object
[23:37:08] ========== [PASSED] ttm_bo_init_reserved_sys_man ===========
[23:37:08] ============== ttm_bo_init_reserved_mock_man ==============
[23:37:08] [PASSED] Buffer object for userspace
[23:37:08] [PASSED] Kernel buffer object
[23:37:08] [PASSED] Shared buffer object
[23:37:08] ========== [PASSED] ttm_bo_init_reserved_mock_man ==========
[23:37:08] [PASSED] ttm_bo_init_reserved_resv
[23:37:08] ================== ttm_bo_validate_basic ==================
[23:37:08] [PASSED] Buffer object for userspace
[23:37:08] [PASSED] Kernel buffer object
[23:37:08] [PASSED] Shared buffer object
[23:37:08] ============== [PASSED] ttm_bo_validate_basic ==============
[23:37:08] [PASSED] ttm_bo_validate_invalid_placement
[23:37:08] ============= ttm_bo_validate_same_placement ==============
[23:37:08] [PASSED] System manager
[23:37:08] [PASSED] VRAM manager
[23:37:08] ========= [PASSED] ttm_bo_validate_same_placement ==========
[23:37:08] [PASSED] ttm_bo_validate_failed_alloc
[23:37:08] [PASSED] ttm_bo_validate_pinned
[23:37:08] [PASSED] ttm_bo_validate_busy_placement
[23:37:08] ================ ttm_bo_validate_multihop =================
[23:37:08] [PASSED] Buffer object for userspace
[23:37:08] [PASSED] Kernel buffer object
[23:37:08] [PASSED] Shared buffer object
[23:37:08] ============ [PASSED] ttm_bo_validate_multihop =============
[23:37:08] ========== ttm_bo_validate_no_placement_signaled ==========
[23:37:08] [PASSED] Buffer object in system domain, no page vector
[23:37:08] [PASSED] Buffer object in system domain with an existing page vector
[23:37:08] ====== [PASSED] ttm_bo_validate_no_placement_signaled ======
[23:37:08] ======== ttm_bo_validate_no_placement_not_signaled ========
[23:37:08] [PASSED] Buffer object for userspace
[23:37:08] [PASSED] Kernel buffer object
[23:37:08] [PASSED] Shared buffer object
[23:37:08] ==== [PASSED] ttm_bo_validate_no_placement_not_signaled ====
[23:37:08] [PASSED] ttm_bo_validate_move_fence_signaled
[23:37:08] ========= ttm_bo_validate_move_fence_not_signaled =========
[23:37:08] [PASSED] Waits for GPU
[23:37:08] [PASSED] Tries to lock straight away
[23:37:08] ===== [PASSED] ttm_bo_validate_move_fence_not_signaled =====
[23:37:08] [PASSED] ttm_bo_validate_happy_evict
[23:37:08] [PASSED] ttm_bo_validate_all_pinned_evict
[23:37:08] [PASSED] ttm_bo_validate_allowed_only_evict
[23:37:08] [PASSED] ttm_bo_validate_deleted_evict
[23:37:08] [PASSED] ttm_bo_validate_busy_domain_evict
[23:37:08] [PASSED] ttm_bo_validate_evict_gutting
[23:37:08] [PASSED] ttm_bo_validate_recrusive_evict
stty: 'standard input': Inappropriate ioctl for device
[23:37:08] ================= [PASSED] ttm_bo_validate =================
[23:37:08] ============================================================
[23:37:08] Testing complete. Ran 101 tests: passed: 101
[23:37:08] Elapsed time: 11.187s total, 1.653s configuring, 9.317s building, 0.180s running
+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel
^ permalink raw reply [flat|nested] 24+ messages in thread* ✗ Xe.CI.BAT: failure for Context based TLB invalidations (rev3)
2026-01-12 23:27 [PATCH v3 00/11] Context based TLB invalidations Matthew Brost
` (11 preceding siblings ...)
2026-01-12 23:37 ` ✓ CI.KUnit: success for Context based TLB invalidations (rev3) Patchwork
@ 2026-01-13 0:17 ` Patchwork
12 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2026-01-13 0:17 UTC (permalink / raw)
To: Matthew Brost; +Cc: intel-xe
[-- Attachment #1: Type: text/plain, Size: 2525 bytes --]
== Series Details ==
Series: Context based TLB invalidations (rev3)
URL : https://patchwork.freedesktop.org/series/156874/
State : failure
== Summary ==
CI Bug Log - changes from xe-4373-7907558010710b0829258fc6a7bbcbb8783b8aa5_BAT -> xe-pw-156874v3_BAT
====================================================
Summary
-------
**FAILURE**
Serious unknown changes coming with xe-pw-156874v3_BAT absolutely need to be
verified manually.
If you think the reported changes have nothing to do with the changes
introduced in xe-pw-156874v3_BAT, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
to document this new failure mode, which will reduce false positives in CI.
Participating hosts (12 -> 12)
------------------------------
No changes in participating hosts
Possible new issues
-------------------
Here are the unknown changes that may have been introduced in xe-pw-156874v3_BAT:
### IGT changes ###
#### Possible regressions ####
* igt@xe_exec_basic@multigpu-many-execqueues-many-vm-bindexecqueue-userptr-invalidate:
- bat-bmg-3: [PASS][1] -> [ABORT][2]
[1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4373-7907558010710b0829258fc6a7bbcbb8783b8aa5/bat-bmg-3/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-bindexecqueue-userptr-invalidate.html
[2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156874v3/bat-bmg-3/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-bindexecqueue-userptr-invalidate.html
Known issues
------------
Here are the changes found in xe-pw-156874v3_BAT that come from known issues:
### IGT changes ###
#### Issues hit ####
* igt@xe_waitfence@abstime:
- bat-dg2-oem2: [PASS][3] -> [TIMEOUT][4] ([Intel XE#6506])
[3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4373-7907558010710b0829258fc6a7bbcbb8783b8aa5/bat-dg2-oem2/igt@xe_waitfence@abstime.html
[4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156874v3/bat-dg2-oem2/igt@xe_waitfence@abstime.html
[Intel XE#6506]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6506
Build changes
-------------
* Linux: xe-4373-7907558010710b0829258fc6a7bbcbb8783b8aa5 -> xe-pw-156874v3
IGT_8698: a631adf809d1cea93174adecc7bfbac121c7d315 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
xe-4373-7907558010710b0829258fc6a7bbcbb8783b8aa5: 7907558010710b0829258fc6a7bbcbb8783b8aa5
xe-pw-156874v3: 156874v3
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156874v3/index.html
[-- Attachment #2: Type: text/html, Size: 3131 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread