Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
* ✗ CI.checkpatch: warning for MADVISE FOR XE (rev2)
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
@ 2025-06-13 12:43 ` Patchwork
  2025-06-13 12:44 ` ✗ CI.KUnit: failure " Patchwork
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Patchwork @ 2025-06-13 12:43 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe

== Series Details ==

Series: MADVISE FOR XE (rev2)
URL   : https://patchwork.freedesktop.org/series/149550/
State : warning

== Summary ==

+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master
202708c00696422fd217223bb679a353a5936e23
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit 645ba9f69158cd54e0cca870f0e54bc822e6d101
Author: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Date:   Fri Jun 13 18:25:58 2025 +0530

    drm/xe/madvise: Skip vma invalidation if mem attr are unchanged
    
    If a VMA within the madvise input range already has the same memory
    attribute as the one requested by the user, skip PTE zapping for that
    VMA to avoid unnecessary invalidation.
    
    Suggested-by: Matthew Brost <matthew.brost@intel.com>
    Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
+ /mt/dim checkpatch cce8a9af1c6cf1776511aa69e5f4b5bef7bf5938 drm-intel
78cfd38c34de Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops
e57e1197d03a drm/xe/uapi: Add madvise interface
-:48: WARNING:LONG_LINE: line length of 113 exceeds 100 columns
#48: FILE: include/uapi/drm/xe_drm.h:122:
+#define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)

total: 0 errors, 1 warnings, 0 checks, 142 lines checked
4e22da734cb1 drm/xe/vm: Add attributes struct as member of vma
6824c9a242a9 drm/xe/vma: Move pat_index to vma attributes
7bf4fe6148b0 drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter
23955e9c0ba7 drm/gpusvm: Make drm_gpusvm_for_each_* macros public
-:225: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'range__' - possible side-effects?
#225: FILE: include/drm/drm_gpusvm.h:548:
+#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
+	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_range_next(range__);				\
+	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
+	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))

-:225: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'next__' - possible side-effects?
#225: FILE: include/drm/drm_gpusvm.h:548:
+#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
+	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_range_next(range__);				\
+	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
+	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))

-:225: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'end__' - possible side-effects?
#225: FILE: include/drm/drm_gpusvm.h:548:
+#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
+	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_range_next(range__);				\
+	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
+	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))

-:258: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'notifier__' - possible side-effects?
#258: FILE: include/drm/drm_gpusvm.h:581:
+#define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__)		\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__));	\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = __drm_gpusvm_notifier_next(notifier__))

-:258: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'end__' - possible side-effects?
#258: FILE: include/drm/drm_gpusvm.h:581:
+#define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__)		\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__));	\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = __drm_gpusvm_notifier_next(notifier__))

-:274: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'notifier__' - possible side-effects?
#274: FILE: include/drm/drm_gpusvm.h:597:
+#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))

-:274: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'next__' - possible side-effects?
#274: FILE: include/drm/drm_gpusvm.h:597:
+#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))

-:274: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'end__' - possible side-effects?
#274: FILE: include/drm/drm_gpusvm.h:597:
+#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))

total: 0 errors, 0 warnings, 8 checks, 248 lines checked
249e967cc319 drm/xe/svm: Split system allocator vma incase of madvise call
d3bb724faa8a drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping
feea7cfe0212 drm/xe: Implement madvise ioctl for xe
-:62: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#62: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 318 lines checked
6684d9bd5cf3 drm/xe/vm: Add an identifier for madvise in xe_vma_ops
647ce81cb00e drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise
ea257524b2d8 drm/xe/svm : Add svm ranges migration policy on atomic access
18404a06671a drm/xe/madvise: Update migration policy based on preferred location
6255d76a51e7 drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute
0b0bf05a1c25 drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch
3738b9650d45 drm/xe/svm: Consult madvise preferred location in prefetch
7dd0ae94dd47 drm/xe/bo: Add attributes field to xe_bo
027e9c3085c7 drm/xe/bo: Update atomic_access attribute on madvise
2aa570b0f530 drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
-:75: WARNING:LONG_LINE: line length of 103 exceeds 100 columns
#75: FILE: drivers/gpu/drm/xe/xe_vm.c:2202:
+		attrs[i].preferred_mem_loc.migration_policy = vma->attr.preferred_loc.migration_policy;

-:176: WARNING:LONG_LINE: line length of 137 exceeds 100 columns
#176: FILE: include/uapi/drm/xe_drm.h:125:
+#define DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_VMAS_ATTRS, struct drm_xe_vm_query_vmas_attr)

total: 0 errors, 2 warnings, 0 checks, 264 lines checked
645ba9f69158 drm/xe/madvise: Skip vma invalidation if mem attr are unchanged



^ permalink raw reply	[flat|nested] 68+ messages in thread

* ✗ CI.KUnit: failure for MADVISE FOR XE (rev2)
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
  2025-06-13 12:43 ` ✗ CI.checkpatch: warning for MADVISE FOR XE (rev2) Patchwork
@ 2025-06-13 12:44 ` Patchwork
  2025-06-13 12:55 ` [PATCH v4 01/20] Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops Himal Prasad Ghimiray
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Patchwork @ 2025-06-13 12:44 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe

== Series Details ==

Series: MADVISE FOR XE (rev2)
URL   : https://patchwork.freedesktop.org/series/149550/
State : failure

== Summary ==

+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
ERROR:root:../drivers/gpu/drm/xe/xe_vm_madvise.c: In function ‘xe_vm_invalidate_madvise_range’:
../drivers/gpu/drm/xe/xe_vm_madvise.c:209:16: error: implicit declaration of function ‘xe_vm_range_tilemask_tlb_invalidation’ [-Werror=implicit-function-declaration]
  209 |         return xe_vm_range_tilemask_tlb_invalidation(vm, start, end, tile_mask);
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
make[7]: *** [../scripts/Makefile.build:287: drivers/gpu/drm/xe/xe_vm_madvise.o] Error 1
make[7]: *** Waiting for unfinished jobs....
make[6]: *** [../scripts/Makefile.build:554: drivers/gpu/drm/xe] Error 2
make[5]: *** [../scripts/Makefile.build:554: drivers/gpu/drm] Error 2
make[4]: *** [../scripts/Makefile.build:554: drivers/gpu] Error 2
make[3]: *** [../scripts/Makefile.build:554: drivers] Error 2
make[2]: *** [/kernel/Makefile:2006: .] Error 2
make[1]: *** [/kernel/Makefile:248: __sub-make] Error 2
make: *** [Makefile:248: __sub-make] Error 2

[12:43:59] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[12:44:03] 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
+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH v4 00/20] MADVISE FOR XE
@ 2025-06-13 12:55 Himal Prasad Ghimiray
  2025-06-13 12:43 ` ✗ CI.checkpatch: warning for MADVISE FOR XE (rev2) Patchwork
                   ` (27 more replies)
  0 siblings, 28 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

Provides a user API to assign attributes like pat_index, atomic
operation type, and preferred location for SVM ranges.
The Kernel Mode Driver (KMD) may split existing VMAs to cover input
ranges, assign user-provided attributes, and invalidate existing PTEs so
that the next page fault/prefetch can use the new attributes.

-v4:
fix atomic policies
fix attribute copy
address review comments

Himal Prasad Ghimiray (20):
  Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops
  drm/xe/uapi: Add madvise interface
  drm/xe/vm: Add attributes struct as member of vma
  drm/xe/vma: Move pat_index to vma attributes
  drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as
    parameter
  drm/gpusvm: Make drm_gpusvm_for_each_* macros public
  drm/xe/svm: Split system allocator vma incase of madvise call
  drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping
  drm/xe: Implement madvise ioctl for xe
  drm/xe/vm: Add an identifier for madvise in xe_vma_ops
  drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for
    madvise
  drm/xe/svm : Add svm ranges migration policy on atomic access
  drm/xe/madvise: Update migration policy based on preferred location
  drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute
  drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch
  drm/xe/svm: Consult madvise preferred location in prefetch
  drm/xe/bo: Add attributes field to xe_bo
  drm/xe/bo: Update atomic_access attribute on madvise
  drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
  drm/xe/madvise: Skip vma invalidation if mem attr are unchanged

 drivers/gpu/drm/drm_gpusvm.c           | 122 ++------
 drivers/gpu/drm/drm_gpuvm.c            |  93 ++++--
 drivers/gpu/drm/nouveau/nouveau_uvmm.c |   1 +
 drivers/gpu/drm/xe/Makefile            |   1 +
 drivers/gpu/drm/xe/xe_bo.c             |  21 +-
 drivers/gpu/drm/xe/xe_bo_types.h       |   8 +
 drivers/gpu/drm/xe/xe_device.c         |   3 +
 drivers/gpu/drm/xe/xe_gt_pagefault.c   |   2 +-
 drivers/gpu/drm/xe/xe_pt.c             |  25 +-
 drivers/gpu/drm/xe/xe_svm.c            | 110 ++++++-
 drivers/gpu/drm/xe/xe_svm.h            |  22 ++
 drivers/gpu/drm/xe/xe_tile.h           |  18 ++
 drivers/gpu/drm/xe/xe_vm.c             | 295 +++++++++++++++++--
 drivers/gpu/drm/xe/xe_vm.h             |   6 +-
 drivers/gpu/drm/xe/xe_vm_madvise.c     | 389 +++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_vm_madvise.h     |  15 +
 drivers/gpu/drm/xe/xe_vm_types.h       |  38 ++-
 include/drm/drm_gpusvm.h               |  70 +++++
 include/drm/drm_gpuvm.h                |  25 +-
 include/uapi/drm/xe_drm.h              | 253 ++++++++++++++++
 20 files changed, 1368 insertions(+), 149 deletions(-)
 create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
 create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH v4 01/20] Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
  2025-06-13 12:43 ` ✗ CI.checkpatch: warning for MADVISE FOR XE (rev2) Patchwork
  2025-06-13 12:44 ` ✗ CI.KUnit: failure " Patchwork
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-13 12:55 ` [PATCH v4 02/20] drm/xe/uapi: Add madvise interface Himal Prasad Ghimiray
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe
  Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray,
	Danilo Krummrich, Boris Brezillon, dri-devel

- DRM_GPUVM_SM_MAP_NOT_MADVISE: Default sm_map operations for the input
  range.

- DRM_GPUVM_SKIP_GEM_OBJ_VA_SPLIT_MADVISE: This flag is used by
  drm_gpuvm_sm_map_ops_create to iterate over GPUVMA's in the
user-provided range and split the existing non-GEM object VMA if the
start or end of the input range lies within it. The operations can
create up to 2 REMAPS and 2 MAPs. The purpose of this operation is to be
used by the Xe driver to assign attributes to GPUVMA's within the
user-defined range. Unlike drm_gpuvm_sm_map_ops_flags in default mode,
the operation with this flag will never have UNMAPs and
merges, and can be without any final operations.

v2
- use drm_gpuvm_sm_map_ops_create with flags instead of defining new
  ops_create (Danilo)
- Add doc (Danilo)

v3
- Fix doc
- Fix unmapping check

v4
- Fix mapping for non madvise ops

Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Boris Brezillon <bbrezillon@kernel.org>
Cc: <dri-devel@lists.freedesktop.org>
Signed-off-by: Himal Prasad Ghimiray<himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/drm_gpuvm.c            | 93 ++++++++++++++++++++------
 drivers/gpu/drm/nouveau/nouveau_uvmm.c |  1 +
 drivers/gpu/drm/xe/xe_vm.c             |  1 +
 include/drm/drm_gpuvm.h                | 25 ++++++-
 4 files changed, 98 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c
index f9eb56f24bef..030f7570b8e2 100644
--- a/drivers/gpu/drm/drm_gpuvm.c
+++ b/drivers/gpu/drm/drm_gpuvm.c
@@ -2102,10 +2102,13 @@ static int
 __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 		   const struct drm_gpuvm_ops *ops, void *priv,
 		   u64 req_addr, u64 req_range,
+		   enum drm_gpuvm_sm_map_ops_flags flags,
 		   struct drm_gem_object *req_obj, u64 req_offset)
 {
 	struct drm_gpuva *va, *next;
 	u64 req_end = req_addr + req_range;
+	bool is_madvise_ops = (flags == DRM_GPUVM_SKIP_GEM_OBJ_VA_SPLIT_MADVISE);
+	bool needs_map = !is_madvise_ops;
 	int ret;
 
 	if (unlikely(!drm_gpuvm_range_valid(gpuvm, req_addr, req_range)))
@@ -2118,26 +2121,35 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 		u64 range = va->va.range;
 		u64 end = addr + range;
 		bool merge = !!va->gem.obj;
+		bool skip_madvise_ops = is_madvise_ops && merge;
 
+		needs_map = !is_madvise_ops;
 		if (addr == req_addr) {
 			merge &= obj == req_obj &&
 				 offset == req_offset;
 
 			if (end == req_end) {
-				ret = op_unmap_cb(ops, priv, va, merge);
-				if (ret)
-					return ret;
+				if (!is_madvise_ops) {
+					ret = op_unmap_cb(ops, priv, va, merge);
+					if (ret)
+						return ret;
+				}
 				break;
 			}
 
 			if (end < req_end) {
-				ret = op_unmap_cb(ops, priv, va, merge);
-				if (ret)
-					return ret;
+				if (!is_madvise_ops) {
+					ret = op_unmap_cb(ops, priv, va, merge);
+					if (ret)
+						return ret;
+				}
 				continue;
 			}
 
 			if (end > req_end) {
+				if (skip_madvise_ops)
+					break;
+
 				struct drm_gpuva_op_map n = {
 					.va.addr = req_end,
 					.va.range = range - req_range,
@@ -2152,6 +2164,9 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 				ret = op_remap_cb(ops, priv, NULL, &n, &u);
 				if (ret)
 					return ret;
+
+				if (is_madvise_ops)
+					needs_map = true;
 				break;
 			}
 		} else if (addr < req_addr) {
@@ -2169,20 +2184,42 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 			u.keep = merge;
 
 			if (end == req_end) {
+				if (skip_madvise_ops)
+					break;
+
 				ret = op_remap_cb(ops, priv, &p, NULL, &u);
 				if (ret)
 					return ret;
+
+				if (is_madvise_ops)
+					needs_map = true;
+
 				break;
 			}
 
 			if (end < req_end) {
+				if (skip_madvise_ops)
+					continue;
+
 				ret = op_remap_cb(ops, priv, &p, NULL, &u);
 				if (ret)
 					return ret;
+
+				if (is_madvise_ops) {
+					ret = op_map_cb(ops, priv, req_addr,
+							min(end - req_addr, req_end - end),
+							NULL, req_offset);
+					if (ret)
+						return ret;
+				}
+
 				continue;
 			}
 
 			if (end > req_end) {
+				if (skip_madvise_ops)
+					break;
+
 				struct drm_gpuva_op_map n = {
 					.va.addr = req_end,
 					.va.range = end - req_end,
@@ -2194,6 +2231,9 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 				ret = op_remap_cb(ops, priv, &p, &n, &u);
 				if (ret)
 					return ret;
+
+				if (is_madvise_ops)
+					needs_map = true;
 				break;
 			}
 		} else if (addr > req_addr) {
@@ -2202,20 +2242,29 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 					   (addr - req_addr);
 
 			if (end == req_end) {
-				ret = op_unmap_cb(ops, priv, va, merge);
-				if (ret)
-					return ret;
+				if (!is_madvise_ops) {
+					ret = op_unmap_cb(ops, priv, va, merge);
+					if (ret)
+						return ret;
+				}
+
 				break;
 			}
 
 			if (end < req_end) {
-				ret = op_unmap_cb(ops, priv, va, merge);
-				if (ret)
-					return ret;
+				if (!is_madvise_ops) {
+					ret = op_unmap_cb(ops, priv, va, merge);
+					if (ret)
+						return ret;
+				}
+
 				continue;
 			}
 
 			if (end > req_end) {
+				if (skip_madvise_ops)
+					break;
+
 				struct drm_gpuva_op_map n = {
 					.va.addr = req_end,
 					.va.range = end - req_end,
@@ -2230,14 +2279,16 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 				ret = op_remap_cb(ops, priv, NULL, &n, &u);
 				if (ret)
 					return ret;
+
+				if (is_madvise_ops)
+					return op_map_cb(ops, priv, addr,
+							(req_end - addr), NULL, req_offset);
 				break;
 			}
 		}
 	}
-
-	return op_map_cb(ops, priv,
-			 req_addr, req_range,
-			 req_obj, req_offset);
+	return needs_map ? op_map_cb(ops, priv, req_addr,
+			   req_range, req_obj, req_offset) : 0;
 }
 
 static int
@@ -2336,15 +2387,15 @@ drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm, void *priv,
 		 struct drm_gem_object *req_obj, u64 req_offset)
 {
 	const struct drm_gpuvm_ops *ops = gpuvm->ops;
+	enum drm_gpuvm_sm_map_ops_flags flags = DRM_GPUVM_SM_MAP_NOT_MADVISE;
 
 	if (unlikely(!(ops && ops->sm_step_map &&
 		       ops->sm_step_remap &&
 		       ops->sm_step_unmap)))
 		return -EINVAL;
 
-	return __drm_gpuvm_sm_map(gpuvm, ops, priv,
-				  req_addr, req_range,
-				  req_obj, req_offset);
+	return __drm_gpuvm_sm_map(gpuvm, ops, priv, req_addr, req_range,
+				  flags, req_obj, req_offset);
 }
 EXPORT_SYMBOL_GPL(drm_gpuvm_sm_map);
 
@@ -2486,6 +2537,7 @@ static const struct drm_gpuvm_ops gpuvm_list_ops = {
  * @gpuvm: the &drm_gpuvm representing the GPU VA space
  * @req_addr: the start address of the new mapping
  * @req_range: the range of the new mapping
+ * @drm_gpuvm_sm_map_ops_flag: ops flag determining madvise or not
  * @req_obj: the &drm_gem_object to map
  * @req_offset: the offset within the &drm_gem_object
  *
@@ -2516,6 +2568,7 @@ static const struct drm_gpuvm_ops gpuvm_list_ops = {
 struct drm_gpuva_ops *
 drm_gpuvm_sm_map_ops_create(struct drm_gpuvm *gpuvm,
 			    u64 req_addr, u64 req_range,
+			    enum drm_gpuvm_sm_map_ops_flags flags,
 			    struct drm_gem_object *req_obj, u64 req_offset)
 {
 	struct drm_gpuva_ops *ops;
@@ -2535,7 +2588,7 @@ drm_gpuvm_sm_map_ops_create(struct drm_gpuvm *gpuvm,
 	args.ops = ops;
 
 	ret = __drm_gpuvm_sm_map(gpuvm, &gpuvm_list_ops, &args,
-				 req_addr, req_range,
+				 req_addr, req_range, flags,
 				 req_obj, req_offset);
 	if (ret)
 		goto err_free_ops;
diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
index 48f105239f42..26e13fcdbdb8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
@@ -1303,6 +1303,7 @@ nouveau_uvmm_bind_job_submit(struct nouveau_job *job,
 			op->ops = drm_gpuvm_sm_map_ops_create(&uvmm->base,
 							      op->va.addr,
 							      op->va.range,
+							      DRM_GPUVM_SM_MAP_NOT_MADVISE,
 							      op->gem.obj,
 							      op->gem.offset);
 			if (IS_ERR(op->ops)) {
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 6ef8c4dab647..1af858a98082 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -2318,6 +2318,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops,
 	case DRM_XE_VM_BIND_OP_MAP:
 	case DRM_XE_VM_BIND_OP_MAP_USERPTR:
 		ops = drm_gpuvm_sm_map_ops_create(&vm->gpuvm, addr, range,
+						  DRM_GPUVM_SM_MAP_NOT_MADVISE,
 						  obj, bo_offset_or_userptr);
 		break;
 	case DRM_XE_VM_BIND_OP_UNMAP:
diff --git a/include/drm/drm_gpuvm.h b/include/drm/drm_gpuvm.h
index 2a9629377633..c589b886a4fd 100644
--- a/include/drm/drm_gpuvm.h
+++ b/include/drm/drm_gpuvm.h
@@ -211,6 +211,27 @@ enum drm_gpuvm_flags {
 	DRM_GPUVM_USERBITS = BIT(1),
 };
 
+/**
+ * enum drm_gpuvm_sm_map_ops_flags - flags for drm_gpuvm split/merge ops
+ */
+enum drm_gpuvm_sm_map_ops_flags {
+	/**
+	 * @DRM_GPUVM_SM_MAP_NOT_MADVISE: DEFAULT sm_map ops
+	 */
+	DRM_GPUVM_SM_MAP_NOT_MADVISE = 0,
+
+	/**
+	 * @DRM_GPUVM_SKIP_GEM_OBJ_VA_SPLIT_MADVISE: This flag is used by
+	 * drm_gpuvm_sm_map_ops_create to iterate over GPUVMA's in the
+	 * user-provided range and split the existing non-GEM object VMA if the
+	 * start or end of the input range lies within it. The operations can
+	 * create up to 2 REMAPS and 2 MAPs. Unlike drm_gpuvm_sm_map_ops_flags
+	 * in default mode, the operation with this flag will never have UNMAPs and
+	 * merges, and can be without any final operations.
+	 */
+	DRM_GPUVM_SKIP_GEM_OBJ_VA_SPLIT_MADVISE = BIT(0),
+};
+
 /**
  * struct drm_gpuvm - DRM GPU VA Manager
  *
@@ -1059,8 +1080,8 @@ struct drm_gpuva_ops {
 #define drm_gpuva_next_op(op) list_next_entry(op, entry)
 
 struct drm_gpuva_ops *
-drm_gpuvm_sm_map_ops_create(struct drm_gpuvm *gpuvm,
-			    u64 addr, u64 range,
+drm_gpuvm_sm_map_ops_create(struct drm_gpuvm *gpuvm, u64 addr, u64 range,
+			    enum drm_gpuvm_sm_map_ops_flags flags,
 			    struct drm_gem_object *obj, u64 offset);
 struct drm_gpuva_ops *
 drm_gpuvm_sm_unmap_ops_create(struct drm_gpuvm *gpuvm,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 02/20] drm/xe/uapi: Add madvise interface
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (2 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 01/20] Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-13 14:15   ` Souza, Jose
  2025-06-23  4:30   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 03/20] drm/xe/vm: Add attributes struct as member of vma Himal Prasad Ghimiray
                   ` (23 subsequent siblings)
  27 siblings, 2 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe
  Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray,
	José Roberto de Souza

This commit introduces a new madvise interface to support
driver-specific ioctl operations. The madvise interface allows for more
efficient memory management by providing hints to the driver about the
expected memory usage and pte update policy for gpuvma.

v2 (Matthew/Thomas)
- Drop num_ops support
- Drop purgeable support
- Add kernel-docs
- IOWR/IOW

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Acked-by: José Roberto de Souza <jose.souza@intel.com>
---
 include/uapi/drm/xe_drm.h | 118 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 6a702ba7817c..b5f8d11faaa8 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -81,6 +81,7 @@ extern "C" {
  *  - &DRM_IOCTL_XE_EXEC
  *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
  *  - &DRM_IOCTL_XE_OBSERVATION
+ *  - &DRM_IOCTL_XE_MADVISE
  */
 
 /*
@@ -102,6 +103,7 @@ extern "C" {
 #define DRM_XE_EXEC			0x09
 #define DRM_XE_WAIT_USER_FENCE		0x0a
 #define DRM_XE_OBSERVATION		0x0b
+#define DRM_XE_MADVISE			0x0c
 
 /* Must be kept compact -- no holes */
 
@@ -117,6 +119,7 @@ extern "C" {
 #define DRM_IOCTL_XE_EXEC			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec)
 #define DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence)
 #define DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
+#define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
 
 /**
  * DOC: Xe IOCTL Extensions
@@ -1970,6 +1973,121 @@ struct drm_xe_query_eu_stall {
 	__u64 sampling_rates[];
 };
 
+/**
+ * struct drm_xe_madvise - Input of &DRM_IOCTL_XE_MADVISE
+ *
+ * This structure is used to set memory attributes for a virtual address range
+ * in a VM. The type of attribute is specified by @type, and the corresponding
+ * union member is used to provide additional parameters for @type.
+ *
+ * Supported attribute types:
+ * - DRM_XE_VMA_ATTR_PREFERRED_LOC: Set preferred memory location.
+ * - DRM_XE_VMA_ATTR_ATOMIC: Set atomic access policy.
+ * - DRM_XE_VMA_ATTR_PAT: Set page attribute table index.
+ *
+ * Example:
+ *
+ * .. code-block:: C
+ *
+ * struct drm_xe_madvise madvise = {
+ *          .vm_id = vm_id,
+ *          .start = 0x100000,
+ *          .range = 0x2000,
+ *          .type = DRM_XE_VMA_ATTR_ATOMIC,
+ *          .atomic_val = DRM_XE_VMA_ATOMIC_DEVICE,
+ *         };
+ *
+ * ioctl(fd, DRM_IOCTL_XE_MADVISE, &madvise);
+ *
+ */
+struct drm_xe_madvise {
+	/** @extensions: Pointer to the first extension struct, if any */
+	__u64 extensions;
+
+	/** @start: start of the virtual address range */
+	__u64 start;
+
+	/** @size: size of the virtual address range */
+	__u64 range;
+
+	/** @vm_id: vm_id of the virtual range */
+	__u32 vm_id;
+
+#define DRM_XE_VMA_ATTR_PREFERRED_LOC	0
+#define DRM_XE_VMA_ATTR_ATOMIC		1
+#define DRM_XE_VMA_ATTR_PAT		2
+	/** @type: type of attribute */
+	__u32 type;
+
+	union {
+		/**
+		 * @atomic: Atomic access policy
+		 *
+		 * Used when @type == DRM_XE_VMA_ATTR_ATOMIC.
+		 *
+		 * Supported values for @atomic.val:
+		 * - DRM_XE_VMA_ATOMIC_UNDEFINED: Undefined or default behaviour
+		 *   Support both GPU and CPU atomic operations for system allocator
+		 *   Support GPU atomic operations for normal(bo) allocator
+		 * - DRM_XE_VMA_ATOMIC_DEVICE: Support GPU atomic operations
+		 * - DRM_XE_VMA_ATOMIC_GLOBAL: Support both GPU and CPU atomic operations
+		 * - DRM_XE_VMA_ATOMIC_CPU: Support CPU atomic
+		 */
+		struct {
+#define DRM_XE_VMA_ATOMIC_UNDEFINED	0
+#define DRM_XE_VMA_ATOMIC_DEVICE	1
+#define DRM_XE_VMA_ATOMIC_GLOBAL	2
+#define DRM_XE_VMA_ATOMIC_CPU		3
+			/** @atomic.val: value of atomic operation */
+			__u32 val;
+
+			/** @atomic.reserved: Reserved */
+			__u32 reserved;
+		} atomic;
+
+		/**
+		 * @pat_index: Page attribute table index
+		 *
+		 * Used when @type == DRM_XE_VMA_ATTR_PAT.
+		 */
+		struct {
+			/** @pat_index.val: PAT index value */
+			__u32 val;
+
+			/** @pat_index.reserved: Reserved */
+			__u32 reserved;
+		} pat_index;
+
+		/**
+		 * @preferred_mem_loc: preferred memory location
+		 *
+		 * Used when @type == DRM_XE_VMA_ATTR_PREFERRED_LOC
+		 *
+		 * Supported values for @preferred_mem_loc.devmem_fd:
+		 * - DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE: set vram of faulting tile as preferred loc
+		 * - DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM: set smem as preferred loc
+		 *
+		 * Supported values for @preferred_mem_loc.migration_policy:
+		 * - DRM_XE_MIGRATE_ALL_PAGES
+		 * - DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES
+		 */
+		struct {
+#define DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE	0
+#define DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM	-1
+			/** @preferred_mem_loc.devmem_fd: fd for preferred loc */
+			__u32 devmem_fd;
+
+#define DRM_XE_MIGRATE_ALL_PAGES		0
+#define DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES	1
+			/** @preferred_mem_loc.migration_policy: Page migration policy */
+			__u32 migration_policy;
+		} preferred_mem_loc;
+	};
+
+	/** @reserved: Reserved */
+	__u64 reserved[2];
+};
+
 #if defined(__cplusplus)
 }
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 03/20] drm/xe/vm: Add attributes struct as member of vma
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (3 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 02/20] drm/xe/uapi: Add madvise interface Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23  4:18   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 04/20] drm/xe/vma: Move pat_index to vma attributes Himal Prasad Ghimiray
                   ` (22 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

The attribute of xe_vma will determine the migration policy and the
encoding of the page table entries (PTEs) for that vma.
This attribute helps manage how memory pages are moved and how their
addresses are translated. It will be used by madvise to set the
behavior of the vma.

v2 (Matthew Brost)
- Add docs

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_vm_types.h | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index bed6088e1bb3..c7663058a7e3 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -77,6 +77,27 @@ struct xe_userptr {
 #endif
 };
 
+/**
+ * struct xe_vma_mem_attr - memory attributes associated with vma
+ */
+struct xe_vma_mem_attr {
+	/** @preferred_loc: perferred memory_location*/
+	struct {
+		/** @preferred_loc.migration_policy: Policy for migration of pages */
+		u32 migration_policy;
+
+		/**
+		 * @preferred_loc.devmem_fd: used for determining pagemap_fd requested by user
+		 * DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM and DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE mean
+		 * system memory or closest device memory respectively.
+		 */
+		u32 devmem_fd;
+	} preferred_loc;
+
+	/** @atomic_access: The atomic access type for the vma */
+	u32 atomic_access;
+};
+
 struct xe_vma {
 	/** @gpuva: Base GPUVA object */
 	struct drm_gpuva gpuva;
@@ -135,6 +156,13 @@ struct xe_vma {
 	 * Needs to be signalled before UNMAP can be processed.
 	 */
 	struct xe_user_fence *ufence;
+
+	/**
+	 * @attr: The attributes of vma which determines the migration policy
+	 * and encoding of the PTEs for this vma.
+	 */
+	struct xe_vma_mem_attr attr;
+
 };
 
 /**
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 04/20] drm/xe/vma: Move pat_index to vma attributes
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (4 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 03/20] drm/xe/vm: Add attributes struct as member of vma Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-13 12:55 ` [PATCH v4 05/20] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter Himal Prasad Ghimiray
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

The PAT index determines how PTEs are encoded and can be modified by
madvise. Therefore, it is now part of the vma attributes.

Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_pt.c       |  2 +-
 drivers/gpu/drm/xe/xe_vm.c       |  6 +++---
 drivers/gpu/drm/xe/xe_vm_types.h | 11 +++++------
 3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index f39d5cc9f411..9177c571689e 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -518,7 +518,7 @@ xe_pt_stage_bind_entry(struct xe_ptw *parent, pgoff_t offset,
 {
 	struct xe_pt_stage_bind_walk *xe_walk =
 		container_of(walk, typeof(*xe_walk), base);
-	u16 pat_index = xe_walk->vma->pat_index;
+	u16 pat_index = xe_walk->vma->attr.pat_index;
 	struct xe_pt *xe_parent = container_of(parent, typeof(*xe_parent), base);
 	struct xe_vm *vm = xe_walk->vm;
 	struct xe_pt *xe_child;
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 1af858a98082..9b705526a3e3 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1223,7 +1223,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
 	if (vm->xe->info.has_atomic_enable_pte_bit)
 		vma->gpuva.flags |= XE_VMA_ATOMIC_PTE_BIT;
 
-	vma->pat_index = pat_index;
+	vma->attr.pat_index = pat_index;
 
 	if (bo) {
 		struct drm_gpuvm_bo *vm_bo;
@@ -2673,7 +2673,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
 
 			if (op->base.remap.prev) {
 				vma = new_vma(vm, op->base.remap.prev,
-					      old->pat_index, flags);
+					      old->attr.pat_index, flags);
 				if (IS_ERR(vma))
 					return PTR_ERR(vma);
 
@@ -2703,7 +2703,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
 
 			if (op->base.remap.next) {
 				vma = new_vma(vm, op->base.remap.next,
-					      old->pat_index, flags);
+					      old->attr.pat_index, flags);
 				if (IS_ERR(vma))
 					return PTR_ERR(vma);
 
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index c7663058a7e3..cde2583da303 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -96,6 +96,11 @@ struct xe_vma_mem_attr {
 
 	/** @atomic_access: The atomic access type for the vma */
 	u32 atomic_access;
+
+	/**
+	 * @pat_index: The pat index to use when encoding the PTEs for this vma.
+	 */
+	u16 pat_index;
 };
 
 struct xe_vma {
@@ -146,11 +151,6 @@ struct xe_vma {
 	/** @tile_staged: bind is staged for this VMA */
 	u8 tile_staged;
 
-	/**
-	 * @pat_index: The pat index to use when encoding the PTEs for this vma.
-	 */
-	u16 pat_index;
-
 	/**
 	 * @ufence: The user fence that was provided with MAP.
 	 * Needs to be signalled before UNMAP can be processed.
@@ -162,7 +162,6 @@ struct xe_vma {
 	 * and encoding of the PTEs for this vma.
 	 */
 	struct xe_vma_mem_attr attr;
-
 };
 
 /**
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 05/20] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (5 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 04/20] drm/xe/vma: Move pat_index to vma attributes Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23  4:38   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 06/20] drm/gpusvm: Make drm_gpusvm_for_each_* macros public Himal Prasad Ghimiray
                   ` (20 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

This change simplifies the logic by ensuring that remapped previous or
next VMAs are created with the same memory attributes as the original VMA.
By passing struct xe_vma_mem_attr as a parameter, we maintain consistency
in memory attributes.

-v2
 *dst = *src (Matthew Brost)

-v3 (Matthew Brost)
 Drop unnecessary helper
 pass attr ptr as input to new_vma and vma_create

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 9b705526a3e3..4849d4cc806a 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1168,7 +1168,8 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
 				    struct xe_bo *bo,
 				    u64 bo_offset_or_userptr,
 				    u64 start, u64 end,
-				    u16 pat_index, unsigned int flags)
+				    struct xe_vma_mem_attr *attr,
+				    unsigned int flags)
 {
 	struct xe_vma *vma;
 	struct xe_tile *tile;
@@ -1223,7 +1224,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
 	if (vm->xe->info.has_atomic_enable_pte_bit)
 		vma->gpuva.flags |= XE_VMA_ATOMIC_PTE_BIT;
 
-	vma->attr.pat_index = pat_index;
+	vma->attr = *attr;
 
 	if (bo) {
 		struct drm_gpuvm_bo *vm_bo;
@@ -2444,7 +2445,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops,
 ALLOW_ERROR_INJECTION(vm_bind_ioctl_ops_create, ERRNO);
 
 static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
-			      u16 pat_index, unsigned int flags)
+			      struct xe_vma_mem_attr *attr, unsigned int flags)
 {
 	struct xe_bo *bo = op->gem.obj ? gem_to_xe_bo(op->gem.obj) : NULL;
 	struct drm_exec exec;
@@ -2473,7 +2474,7 @@ static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
 	}
 	vma = xe_vma_create(vm, bo, op->gem.offset,
 			    op->va.addr, op->va.addr +
-			    op->va.range - 1, pat_index, flags);
+			    op->va.range - 1, attr, flags);
 	if (IS_ERR(vma))
 		goto err_unlock;
 
@@ -2616,6 +2617,15 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
 		switch (op->base.op) {
 		case DRM_GPUVA_OP_MAP:
 		{
+			struct xe_vma_mem_attr default_attr = {
+				.preferred_loc = {
+					.devmem_fd = DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE,
+					.migration_policy = DRM_XE_MIGRATE_ALL_PAGES,
+				},
+				.atomic_access = DRM_XE_VMA_ATOMIC_UNDEFINED,
+				.pat_index = op->map.pat_index,
+			};
+
 			flags |= op->map.read_only ?
 				VMA_CREATE_FLAG_READ_ONLY : 0;
 			flags |= op->map.is_null ?
@@ -2625,7 +2635,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
 			flags |= op->map.is_cpu_addr_mirror ?
 				VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR : 0;
 
-			vma = new_vma(vm, &op->base.map, op->map.pat_index,
+			vma = new_vma(vm, &op->base.map, &default_attr,
 				      flags);
 			if (IS_ERR(vma))
 				return PTR_ERR(vma);
@@ -2673,7 +2683,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
 
 			if (op->base.remap.prev) {
 				vma = new_vma(vm, op->base.remap.prev,
-					      old->attr.pat_index, flags);
+					      &old->attr, flags);
 				if (IS_ERR(vma))
 					return PTR_ERR(vma);
 
@@ -2703,7 +2713,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
 
 			if (op->base.remap.next) {
 				vma = new_vma(vm, op->base.remap.next,
-					      old->attr.pat_index, flags);
+					      &old->attr, flags);
 				if (IS_ERR(vma))
 					return PTR_ERR(vma);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 06/20] drm/gpusvm: Make drm_gpusvm_for_each_* macros public
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (6 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 05/20] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-13 12:55 ` [PATCH v4 07/20] drm/xe/svm: Split system allocator vma incase of madvise call Himal Prasad Ghimiray
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

The drm_gpusvm_for_each_notifier, drm_gpusvm_for_each_notifier_safe and
drm_gpusvm_for_each_range_safe macros are useful for locating notifiers
and ranges within a user-specified range. By making these macros public,
we enable broader access and utility for developers who need to leverage
them in their implementations.

v2 (Matthew Brost)
- drop inline __drm_gpusvm_range_find
- /s/notifier_iter_first/drm_gpusvm_notifier_find

Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/drm_gpusvm.c | 122 +++++++----------------------------
 include/drm/drm_gpusvm.h     |  70 ++++++++++++++++++++
 2 files changed, 95 insertions(+), 97 deletions(-)

diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 7ff81aa0a1ca..993485386239 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -380,107 +380,50 @@ static void drm_gpusvm_zdd_put(struct drm_gpusvm_zdd *zdd)
 }
 
 /**
- * drm_gpusvm_range_find() - Find GPU SVM range from GPU SVM notifier
- * @notifier: Pointer to the GPU SVM notifier structure.
- * @start: Start address of the range
- * @end: End address of the range
+ * drm_gpusvm_notifier_find() - Find GPU SVM notifier from GPU SVM
+ * @gpusvm: Pointer to the GPU SVM structure.
+ * @start: Start address of the notifier
+ * @end: End address of the notifier
  *
- * Return: A pointer to the drm_gpusvm_range if found or NULL
+ * Return: A pointer to the drm_gpusvm_notifier if found or NULL
  */
-struct drm_gpusvm_range *
-drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
-		      unsigned long end)
+struct drm_gpusvm_notifier *
+drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm, unsigned long start,
+			 unsigned long end)
 {
 	struct interval_tree_node *itree;
 
-	itree = interval_tree_iter_first(&notifier->root, start, end - 1);
+	itree = interval_tree_iter_first(&gpusvm->root, start, end - 1);
 
 	if (itree)
-		return container_of(itree, struct drm_gpusvm_range, itree);
+		return container_of(itree, struct drm_gpusvm_notifier, itree);
 	else
 		return NULL;
 }
-EXPORT_SYMBOL_GPL(drm_gpusvm_range_find);
+EXPORT_SYMBOL_GPL(drm_gpusvm_notifier_find);
 
 /**
- * drm_gpusvm_for_each_range_safe() - Safely iterate over GPU SVM ranges in a notifier
- * @range__: Iterator variable for the ranges
- * @next__: Iterator variable for the ranges temporay storage
- * @notifier__: Pointer to the GPU SVM notifier
- * @start__: Start address of the range
- * @end__: End address of the range
- *
- * This macro is used to iterate over GPU SVM ranges in a notifier while
- * removing ranges from it.
- */
-#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
-	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
-	     (next__) = __drm_gpusvm_range_next(range__);				\
-	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
-	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))
-
-/**
- * __drm_gpusvm_notifier_next() - get the next drm_gpusvm_notifier in the list
- * @notifier: a pointer to the current drm_gpusvm_notifier
+ * drm_gpusvm_range_find() - Find GPU SVM range from GPU SVM notifier
+ * @notifier: Pointer to the GPU SVM notifier structure.
+ * @start: Start address of the range
+ * @end: End address of the range
  *
- * Return: A pointer to the next drm_gpusvm_notifier if available, or NULL if
- *         the current notifier is the last one or if the input notifier is
- *         NULL.
+ * Return: A pointer to the drm_gpusvm_range if found or NULL
  */
-static struct drm_gpusvm_notifier *
-__drm_gpusvm_notifier_next(struct drm_gpusvm_notifier *notifier)
-{
-	if (notifier && !list_is_last(&notifier->entry,
-				      &notifier->gpusvm->notifier_list))
-		return list_next_entry(notifier, entry);
-
-	return NULL;
-}
-
-static struct drm_gpusvm_notifier *
-notifier_iter_first(struct rb_root_cached *root, unsigned long start,
-		    unsigned long last)
+struct drm_gpusvm_range *
+drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
+		      unsigned long end)
 {
 	struct interval_tree_node *itree;
 
-	itree = interval_tree_iter_first(root, start, last);
+	itree = interval_tree_iter_first(&notifier->root, start, end - 1);
 
 	if (itree)
-		return container_of(itree, struct drm_gpusvm_notifier, itree);
+		return container_of(itree, struct drm_gpusvm_range, itree);
 	else
 		return NULL;
 }
-
-/**
- * drm_gpusvm_for_each_notifier() - Iterate over GPU SVM notifiers in a gpusvm
- * @notifier__: Iterator variable for the notifiers
- * @notifier__: Pointer to the GPU SVM notifier
- * @start__: Start address of the notifier
- * @end__: End address of the notifier
- *
- * This macro is used to iterate over GPU SVM notifiers in a gpusvm.
- */
-#define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__)		\
-	for ((notifier__) = notifier_iter_first(&(gpusvm__)->root, (start__), (end__) - 1);	\
-	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
-	     (notifier__) = __drm_gpusvm_notifier_next(notifier__))
-
-/**
- * drm_gpusvm_for_each_notifier_safe() - Safely iterate over GPU SVM notifiers in a gpusvm
- * @notifier__: Iterator variable for the notifiers
- * @next__: Iterator variable for the notifiers temporay storage
- * @notifier__: Pointer to the GPU SVM notifier
- * @start__: Start address of the notifier
- * @end__: End address of the notifier
- *
- * This macro is used to iterate over GPU SVM notifiers in a gpusvm while
- * removing notifiers from it.
- */
-#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
-	for ((notifier__) = notifier_iter_first(&(gpusvm__)->root, (start__), (end__) - 1),	\
-	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
-	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
-	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))
+EXPORT_SYMBOL_GPL(drm_gpusvm_range_find);
 
 /**
  * drm_gpusvm_notifier_invalidate() - Invalidate a GPU SVM notifier.
@@ -581,22 +524,6 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
 }
 EXPORT_SYMBOL_GPL(drm_gpusvm_init);
 
-/**
- * drm_gpusvm_notifier_find() - Find GPU SVM notifier
- * @gpusvm: Pointer to the GPU SVM structure
- * @fault_addr: Fault address
- *
- * This function finds the GPU SVM notifier associated with the fault address.
- *
- * Return: Pointer to the GPU SVM notifier on success, NULL otherwise.
- */
-static struct drm_gpusvm_notifier *
-drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm,
-			 unsigned long fault_addr)
-{
-	return notifier_iter_first(&gpusvm->root, fault_addr, fault_addr + 1);
-}
-
 /**
  * to_drm_gpusvm_notifier() - retrieve the container struct for a given rbtree node
  * @node: a pointer to the rbtree node embedded within a drm_gpusvm_notifier struct
@@ -1052,7 +979,7 @@ drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm,
 	if (!mmget_not_zero(mm))
 		return ERR_PTR(-EFAULT);
 
-	notifier = drm_gpusvm_notifier_find(gpusvm, fault_addr);
+	notifier = drm_gpusvm_notifier_find(gpusvm, fault_addr, fault_addr + 1);
 	if (!notifier) {
 		notifier = drm_gpusvm_notifier_alloc(gpusvm, fault_addr);
 		if (IS_ERR(notifier)) {
@@ -1216,7 +1143,8 @@ void drm_gpusvm_range_remove(struct drm_gpusvm *gpusvm,
 	drm_gpusvm_driver_lock_held(gpusvm);
 
 	notifier = drm_gpusvm_notifier_find(gpusvm,
-					    drm_gpusvm_range_start(range));
+					    drm_gpusvm_range_start(range),
+					    drm_gpusvm_range_start(range) + 1);
 	if (WARN_ON_ONCE(!notifier))
 		return;
 
diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
index 6a5156476bf4..cdd89e5af4f8 100644
--- a/include/drm/drm_gpusvm.h
+++ b/include/drm/drm_gpusvm.h
@@ -373,6 +373,10 @@ const struct dev_pagemap_ops *drm_gpusvm_pagemap_ops_get(void);
 bool drm_gpusvm_has_mapping(struct drm_gpusvm *gpusvm, unsigned long start,
 			    unsigned long end);
 
+struct drm_gpusvm_notifier *
+drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm, unsigned long start,
+			 unsigned long end);
+
 struct drm_gpusvm_range *
 drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
 		      unsigned long end);
@@ -530,4 +534,70 @@ __drm_gpusvm_range_next(struct drm_gpusvm_range *range)
 	     (range__) && (drm_gpusvm_range_start(range__) < (end__));	\
 	     (range__) = __drm_gpusvm_range_next(range__))
 
+/**
+ * drm_gpusvm_for_each_range_safe() - Safely iterate over GPU SVM ranges in a notifier
+ * @range__: Iterator variable for the ranges
+ * @next__: Iterator variable for the ranges temporay storage
+ * @notifier__: Pointer to the GPU SVM notifier
+ * @start__: Start address of the range
+ * @end__: End address of the range
+ *
+ * This macro is used to iterate over GPU SVM ranges in a notifier while
+ * removing ranges from it.
+ */
+#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
+	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_range_next(range__);				\
+	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
+	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))
+
+/**
+ * __drm_gpusvm_notifier_next() - get the next drm_gpusvm_notifier in the list
+ * @notifier: a pointer to the current drm_gpusvm_notifier
+ *
+ * Return: A pointer to the next drm_gpusvm_notifier if available, or NULL if
+ *         the current notifier is the last one or if the input notifier is
+ *         NULL.
+ */
+static inline struct drm_gpusvm_notifier *
+__drm_gpusvm_notifier_next(struct drm_gpusvm_notifier *notifier)
+{
+	if (notifier && !list_is_last(&notifier->entry,
+				      &notifier->gpusvm->notifier_list))
+		return list_next_entry(notifier, entry);
+
+	return NULL;
+}
+
+/**
+ * drm_gpusvm_for_each_notifier() - Iterate over GPU SVM notifiers in a gpusvm
+ * @notifier__: Iterator variable for the notifiers
+ * @gpusvm__: Pointer to the GPU SVM notifier
+ * @start__: Start address of the notifier
+ * @end__: End address of the notifier
+ *
+ * This macro is used to iterate over GPU SVM notifiers in a gpusvm.
+ */
+#define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__)		\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__));	\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = __drm_gpusvm_notifier_next(notifier__))
+
+/**
+ * drm_gpusvm_for_each_notifier_safe() - Safely iterate over GPU SVM notifiers in a gpusvm
+ * @notifier__: Iterator variable for the notifiers
+ * @next__: Iterator variable for the notifiers temporay storage
+ * @gpusvm__: Pointer to the GPU SVM notifier
+ * @start__: Start address of the notifier
+ * @end__: End address of the notifier
+ *
+ * This macro is used to iterate over GPU SVM notifiers in a gpusvm while
+ * removing notifiers from it.
+ */
+#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))
+
 #endif /* __DRM_GPUSVM_H__ */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 07/20] drm/xe/svm: Split system allocator vma incase of madvise call
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (7 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 06/20] drm/gpusvm: Make drm_gpusvm_for_each_* macros public Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-13 12:55 ` [PATCH v4 08/20] drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping Himal Prasad Ghimiray
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

If the start or end of input address range lies within system allocator
vma split the vma to create new vma's as per input range.

v2 (Matthew Brost)
- Add lockdep_assert_write for vm->lock
- Remove unnecessary page aligned checks
- Add kerrnel-doc and comments
- Remove unnecessary unwind_ops and return

v3
- Fix copying of attributes

v4
- Nit fixes

Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c | 106 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_vm.h |   2 +
 2 files changed, 108 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 4849d4cc806a..f5f8de113eae 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -4172,3 +4172,109 @@ void xe_vm_snapshot_free(struct xe_vm_snapshot *snap)
 	}
 	kvfree(snap);
 }
+
+/**
+ * xe_vm_alloc_madvise_vma - Allocate VMA's with madvise ops
+ * @vm: Pointer to the xe_vm structure
+ * @start: Starting input address
+ * @range: Size of the input range
+ *
+ * This function splits existing vma to create new vma for user provided input range
+ *
+ *  Return: 0 if success
+ */
+int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t start, uint64_t range)
+{
+	struct xe_vma_ops vops;
+	struct drm_gpuva_ops *ops = NULL;
+	struct drm_gpuva_op *__op;
+	bool is_cpu_addr_mirror = false;
+	bool remap_op = false;
+	struct xe_vma_mem_attr tmp_attr;
+	int err;
+
+	vm_dbg(&vm->xe->drm, "MADVISE IN: addr=0x%016llx, size=0x%016llx", start, range);
+
+	lockdep_assert_held_write(&vm->lock);
+
+	vm_dbg(&vm->xe->drm, "MADVISE_OPS_CREATE: addr=0x%016llx, size=0x%016llx", start, range);
+	ops = drm_gpuvm_sm_map_ops_create(&vm->gpuvm, start, range,
+					  DRM_GPUVM_SKIP_GEM_OBJ_VA_SPLIT_MADVISE,
+					  NULL, start);
+	if (IS_ERR(ops))
+		return PTR_ERR(ops);
+
+	if (list_empty(&ops->list)) {
+		err = 0;
+		goto free_ops;
+	}
+
+	drm_gpuva_for_each_op(__op, ops) {
+		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
+
+		if (__op->op == DRM_GPUVA_OP_REMAP) {
+			xe_assert(vm->xe, !remap_op);
+			remap_op = true;
+
+			if (xe_vma_is_cpu_addr_mirror(gpuva_to_vma(op->base.remap.unmap->va)))
+				is_cpu_addr_mirror = true;
+			else
+				is_cpu_addr_mirror = false;
+		}
+
+		if (__op->op == DRM_GPUVA_OP_MAP) {
+			xe_assert(vm->xe, remap_op);
+			remap_op = false;
+
+			/* In case of madvise ops DRM_GPUVA_OP_MAP is always after
+			 * DRM_GPUVA_OP_REMAP, so ensure we assign op->map.is_cpu_addr_mirror true
+			 * if REMAP is for xe_vma_is_cpu_addr_mirror vma
+			 */
+			op->map.is_cpu_addr_mirror = is_cpu_addr_mirror;
+		}
+
+		print_op(vm->xe, __op);
+	}
+
+	xe_vma_ops_init(&vops, vm, NULL, NULL, 0);
+	err = vm_bind_ioctl_ops_parse(vm, ops, &vops);
+	if (err)
+		goto unwind_ops;
+
+	xe_vm_lock(vm, false);
+
+	drm_gpuva_for_each_op(__op, ops) {
+		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
+		struct xe_vma *vma;
+
+		if (__op->op == DRM_GPUVA_OP_UNMAP) {
+			/* There should be no unmap */
+			XE_WARN_ON("UNEXPECTED UNMAP");
+			xe_vma_destroy(gpuva_to_vma(op->base.unmap.va), NULL);
+		} else if (__op->op == DRM_GPUVA_OP_REMAP) {
+			vma = gpuva_to_vma(op->base.remap.unmap->va);
+			/* Store attributes for REMAP UNMAPPED VMA, so they can be assigned
+			 * to newly MAP created vma.
+			 */
+			tmp_attr = vma->attr;
+			xe_vma_destroy(gpuva_to_vma(op->base.remap.unmap->va), NULL);
+		} else if (__op->op == DRM_GPUVA_OP_MAP) {
+			vma = op->map.vma;
+			/* In case of madvise call, MAP will always be follwed by REMAP.
+			 * Therefore temp_attr will always have sane values, making it safe to
+			 * copy them to new vma.
+			 */
+			vma->attr = tmp_attr;
+		}
+	}
+
+	xe_vm_unlock(vm);
+	drm_gpuva_ops_free(&vm->gpuvm, ops);
+	return 0;
+
+unwind_ops:
+	vm_bind_ioctl_ops_unwind(vm, &ops, 1);
+free_ops:
+	drm_gpuva_ops_free(&vm->gpuvm, ops);
+	return err;
+}
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index acd3fd6c605b..66bb6babd319 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -171,6 +171,8 @@ static inline bool xe_vma_is_userptr(struct xe_vma *vma)
 
 struct xe_vma *xe_vm_find_vma_by_addr(struct xe_vm *vm, u64 page_addr);
 
+int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t addr, uint64_t size);
+
 /**
  * to_userptr_vma() - Return a pointer to an embedding userptr vma
  * @vma: Pointer to the embedded struct xe_vma
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 08/20] drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (8 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 07/20] drm/xe/svm: Split system allocator vma incase of madvise call Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23  4:56   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe Himal Prasad Ghimiray
                   ` (17 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

Introduce xe_svm_ranges_zap_ptes_in_range(), a function to zap page table
entries (PTEs) for all SVM ranges within a user-specified address range.

-v2 (Matthew Brost)
Lock should be called even for tlb_invalidation

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_pt.c  | 14 ++++++++++++-
 drivers/gpu/drm/xe/xe_svm.c | 42 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_svm.h |  7 +++++++
 3 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 9177c571689e..9a390ef10852 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -950,7 +950,19 @@ bool xe_pt_zap_ptes_range(struct xe_tile *tile, struct xe_vm *vm,
 	struct xe_pt *pt = vm->pt_root[tile->id];
 	u8 pt_mask = (range->tile_present & ~range->tile_invalidated);
 
-	xe_svm_assert_in_notifier(vm);
+	/*
+	 * Locking rules:
+	 *
+	 * - notifier_lock (write): full protection against page table changes
+	 *   and MMU notifier invalidations.
+	 *
+	 * - notifier_lock (read) + vm_lock (write): combined protection against
+	 *   invalidations and concurrent page table modifications. (e.g., madvise)
+	 *
+	 */
+	lockdep_assert(lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 0) ||
+		       (lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 1) &&
+		       lockdep_is_held_type(&vm->lock, 0)));
 
 	if (!(pt_mask & BIT(tile->id)))
 		return false;
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index 2fbbd6a604ea..19420635f1fa 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -999,6 +999,48 @@ int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range,
 	return err;
 }
 
+/**
+ * xe_svm_ranges_zap_ptes_in_range - clear ptes of svm ranges in input range
+ * @vm: Pointer to the xe_vm structure
+ * @start: Start of the input range
+ * @end: End of the input range
+ *
+ * This function removes the page table entries (PTEs) associated
+ * with the svm ranges within the given input start and end
+ *
+ * Return: tile_mask for which gt's need to be tlb invalidated.
+ */
+u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
+{
+	struct drm_gpusvm_notifier *notifier;
+	struct xe_svm_range *range;
+	u64 adj_start, adj_end;
+	struct xe_tile *tile;
+	u8 tile_mask = 0;
+	u8 id;
+
+	lockdep_assert(lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 1) &&
+		       lockdep_is_held_type(&vm->lock, 0));
+
+	drm_gpusvm_for_each_notifier(notifier, &vm->svm.gpusvm, start, end) {
+		struct drm_gpusvm_range *r = NULL;
+
+		adj_start = max(start, notifier->itree.start);
+		adj_end = min(end, notifier->itree.last + 1);
+		drm_gpusvm_for_each_range(r, notifier, adj_start, adj_end) {
+			range = to_xe_range(r);
+			for_each_tile(tile, vm->xe, id) {
+				if (xe_pt_zap_ptes_range(tile, vm, range)) {
+					tile_mask |= BIT(id);
+					range->tile_invalidated |= BIT(id);
+				}
+			}
+		}
+	}
+
+	return tile_mask;
+}
+
 #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR)
 
 static struct drm_pagemap_device_addr
diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
index 19ce4f2754a7..af8f285b6caa 100644
--- a/drivers/gpu/drm/xe/xe_svm.h
+++ b/drivers/gpu/drm/xe/xe_svm.h
@@ -91,6 +91,7 @@ bool xe_svm_range_validate(struct xe_vm *vm,
 
 u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end,  struct xe_vma *vma);
 
+u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end);
 /**
  * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping
  * @range: SVM range
@@ -305,6 +306,12 @@ u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end, struct xe_vma *vm
 	return ULONG_MAX;
 }
 
+static inline
+u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
+{
+	return 0;
+}
+
 #define xe_svm_assert_in_notifier(...) do {} while (0)
 #define xe_svm_range_has_dma_mapping(...) false
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (9 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 08/20] drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23  5:33   ` Matthew Brost
  2025-06-26  6:04   ` Lin, Shuicheng
  2025-06-13 12:55 ` [PATCH v4 10/20] drm/xe/vm: Add an identifier for madvise in xe_vma_ops Himal Prasad Ghimiray
                   ` (16 subsequent siblings)
  27 siblings, 2 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

This driver-specific ioctl enables UMDs to control the memory attributes
for GPU VMAs within a specified input range. If the start or end
addresses fall within an existing VMA, the VMA is split accordingly. The
attributes of the VMA are modified as provided by the users. The old
mappings of the VMAs are invalidated, and TLB invalidation is performed
if necessary.

v2(Matthew brost)
- xe_vm_in_fault_mode can't be enabled by Mesa, hence allow ioctl in non
fault mode too
- fix tlb invalidation skip for same ranges in multiple op
- use helper for tlb invalidation
- use xe_svm_notifier_lock/unlock helper
- s/lockdep_assert_held/lockdep_assert_held_write
- Add kernel-doc

v3(Matthew Brost)
- make vfunc fail safe
- Add sanitizing input args before vfunc

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/Makefile        |   1 +
 drivers/gpu/drm/xe/xe_device.c     |   2 +
 drivers/gpu/drm/xe/xe_vm_madvise.c | 282 +++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_vm_madvise.h |  15 ++
 4 files changed, 300 insertions(+)
 create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
 create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h

diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index f5f5775acdc0..d375b549c30f 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -117,6 +117,7 @@ xe-y += xe_bb.o \
 	xe_uc.o \
 	xe_uc_fw.o \
 	xe_vm.o \
+	xe_vm_madvise.o \
 	xe_vram.o \
 	xe_vram_freq.o \
 	xe_vsec.o \
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 7d9a31868ea9..632d3ab12392 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -61,6 +61,7 @@
 #include "xe_ttm_stolen_mgr.h"
 #include "xe_ttm_sys_mgr.h"
 #include "xe_vm.h"
+#include "xe_vm_madvise.h"
 #include "xe_vram.h"
 #include "xe_vsec.h"
 #include "xe_wait_user_fence.h"
@@ -197,6 +198,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE, xe_wait_user_fence_ioctl,
 			  DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl, DRM_RENDER_ALLOW),
 };
 
 static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
new file mode 100644
index 000000000000..ff560914ad7e
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+#include "xe_vm_madvise.h"
+
+#include <linux/nospec.h>
+#include <drm/ttm/ttm_tt.h>
+#include <drm/xe_drm.h>
+
+#include "xe_bo.h"
+#include "xe_gt_tlb_invalidation.h"
+#include "xe_pt.h"
+#include "xe_svm.h"
+
+struct xe_vmas_in_madvise_range {
+	u64 addr;
+	u64 range;
+	struct xe_vma **vmas;
+	int num_vmas;
+	bool has_svm_vmas;
+	bool has_bo_vmas;
+	bool has_userptr_vmas;
+};
+
+static int get_vmas(struct xe_vm *vm, struct xe_vmas_in_madvise_range *madvise_range)
+{
+	u64 addr = madvise_range->addr;
+	u64 range = madvise_range->range;
+
+	struct xe_vma  **__vmas;
+	struct drm_gpuva *gpuva;
+	int max_vmas = 8;
+
+	lockdep_assert_held(&vm->lock);
+
+	madvise_range->num_vmas = 0;
+	madvise_range->vmas = kmalloc_array(max_vmas, sizeof(*madvise_range->vmas), GFP_KERNEL);
+	if (!madvise_range->vmas)
+		return -ENOMEM;
+
+	vm_dbg(&vm->xe->drm, "VMA's in range: start=0x%016llx, end=0x%016llx", addr, addr + range);
+
+	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, addr, addr + range) {
+		struct xe_vma *vma = gpuva_to_vma(gpuva);
+
+		if (xe_vma_bo(vma))
+			madvise_range->has_bo_vmas = true;
+		else if (xe_vma_is_cpu_addr_mirror(vma))
+			madvise_range->has_svm_vmas = true;
+		else if (xe_vma_is_userptr(vma))
+			madvise_range->has_userptr_vmas = true;
+		else
+			XE_WARN_ON("UNEXPECTED VMA");
+
+		if (madvise_range->num_vmas == max_vmas) {
+			max_vmas <<= 1;
+			__vmas = krealloc(madvise_range->vmas,
+					  max_vmas * sizeof(*madvise_range->vmas),
+					  GFP_KERNEL);
+			if (!__vmas) {
+				kfree(madvise_range->vmas);
+				return -ENOMEM;
+			}
+			madvise_range->vmas = __vmas;
+		}
+
+		madvise_range->vmas[madvise_range->num_vmas] = vma;
+		(madvise_range->num_vmas)++;
+	}
+
+	if (!madvise_range->num_vmas)
+		kfree(madvise_range->vmas);
+
+	vm_dbg(&vm->xe->drm, "madvise_range-num_vmas = %d\n", madvise_range->num_vmas);
+
+	return 0;
+}
+
+static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm *vm,
+				      struct xe_vma **vmas, int num_vmas,
+				      struct drm_xe_madvise *op)
+{
+	/* Implementation pending */
+}
+
+static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
+			   struct xe_vma **vmas, int num_vmas,
+			   struct drm_xe_madvise *op)
+{
+	/* Implementation pending */
+}
+
+static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
+			      struct xe_vma **vmas, int num_vmas,
+			      struct drm_xe_madvise *op)
+{
+	/* Implementation pending */
+}
+
+typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
+			     struct xe_vma **vmas, int num_vmas,
+			     struct drm_xe_madvise *op);
+
+static const madvise_func madvise_funcs[] = {
+	[DRM_XE_VMA_ATTR_PREFERRED_LOC] = madvise_preferred_mem_loc,
+	[DRM_XE_VMA_ATTR_ATOMIC] = madvise_atomic,
+	[DRM_XE_VMA_ATTR_PAT] = madvise_pat_index,
+};
+
+static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start, u64 end, u8 *tile_mask)
+{
+	struct drm_gpuva *gpuva;
+	struct xe_tile *tile;
+	u8 id;
+
+	lockdep_assert_held_write(&vm->lock);
+
+	if (dma_resv_wait_timeout(xe_vm_resv(vm), DMA_RESV_USAGE_BOOKKEEP,
+				  false, MAX_SCHEDULE_TIMEOUT) <= 0)
+		XE_WARN_ON(1);
+
+	*tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
+
+	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
+		struct xe_vma *vma = gpuva_to_vma(gpuva);
+
+		if (xe_vma_is_cpu_addr_mirror(vma))
+			continue;
+
+		if (xe_vma_is_userptr(vma)) {
+			WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
+							     DMA_RESV_USAGE_BOOKKEEP));
+		}
+
+		for_each_tile(tile, vm->xe, id) {
+			if (xe_pt_zap_ptes(tile, vma)) {
+				*tile_mask |= BIT(id);
+				vma->tile_invalidated |= BIT(id);
+			}
+		}
+	}
+}
+
+static int xe_vm_invalidate_madvise_range(struct xe_vm *vm, u64 start, u64 end)
+{
+	u8 tile_mask = 0;
+
+	xe_zap_ptes_in_madvise_range(vm, start, end, &tile_mask);
+	if (!tile_mask)
+		return 0;
+
+	xe_device_wmb(vm->xe);
+
+	return xe_vm_range_tilemask_tlb_invalidation(vm, start, end, tile_mask);
+}
+
+static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const struct drm_xe_madvise *args)
+{
+	if (XE_IOCTL_DBG(xe, !args))
+		return -EINVAL;
+
+	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->start, SZ_4K)))
+		return -EINVAL;
+
+	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->range, SZ_4K)))
+		return -EINVAL;
+
+	if (XE_IOCTL_DBG(xe, args->range < SZ_4K))
+		return -EINVAL;
+
+	switch (args->type) {
+	case DRM_XE_VMA_ATTR_ATOMIC:
+		if (XE_IOCTL_DBG(xe, args->atomic.val > DRM_XE_VMA_ATOMIC_CPU))
+			return -EINVAL;
+		break;
+	case DRM_XE_VMA_ATTR_PAT:
+		/*TODO: Add valid pat check */
+		break;
+	case DRM_XE_VMA_ATTR_PREFERRED_LOC:
+		if (XE_IOCTL_DBG(xe, args->preferred_mem_loc.migration_policy >
+				     DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES))
+			return -EINVAL;
+		break;
+	default:
+		if (XE_IOCTL_DBG(xe, 1))
+			return -EINVAL;
+	}
+
+	if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * xe_vm_madvise_ioctl - Handle MADVise ioctl for a VM
+ * @dev: DRM device pointer
+ * @data: Pointer to ioctl data (drm_xe_madvise*)
+ * @file: DRM file pointer
+ *
+ * Handles the MADVISE ioctl to provide memory advice for vma's within
+ * input range.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+	struct xe_device *xe = to_xe_device(dev);
+	struct xe_file *xef = to_xe_file(file);
+	struct drm_xe_madvise *args = data;
+	struct xe_vm *vm;
+	struct xe_bo *bo;
+	struct drm_exec exec;
+	int err = 0;
+	int attr_type;
+
+	vm = xe_vm_lookup(xef, args->vm_id);
+	if (XE_IOCTL_DBG(xe, !vm))
+		return -EINVAL;
+
+	if (drm_xe_madvise_args_are_sane(vm->xe, args))
+		return -EINVAL;
+
+	down_write(&vm->lock);
+
+	if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
+		err = -ENOENT;
+		goto unlock_vm;
+	}
+
+	xe_vm_alloc_madvise_vma(vm, args->start, args->range);
+
+	struct xe_vmas_in_madvise_range madvise_range = {.addr = args->start,
+							 .range =  args->range, };
+	err = get_vmas(vm, &madvise_range);
+	if (err || !madvise_range.num_vmas)
+		goto unlock_vm;
+
+	if (madvise_range.has_bo_vmas) {
+		drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
+		drm_exec_until_all_locked(&exec) {
+			for (int i = 0; i < madvise_range.num_vmas; i++) {
+				bo = xe_vma_bo(madvise_range.vmas[i]);
+				if (!bo)
+					continue;
+				err = drm_exec_lock_obj(&exec, &bo->ttm.base);
+				drm_exec_retry_on_contention(&exec);
+				if (err)
+					goto err_fini;
+			}
+		}
+	}
+
+	if (madvise_range.has_userptr_vmas)
+		down_read(&vm->userptr.notifier_lock);
+
+	if (madvise_range.has_svm_vmas)
+		xe_svm_notifier_lock(vm);
+
+	attr_type = array_index_nospec(args->type, ARRAY_SIZE(madvise_funcs));
+	madvise_funcs[attr_type](xe, vm, madvise_range.vmas, madvise_range.num_vmas, args);
+
+	kfree(madvise_range.vmas);
+	madvise_range.vmas = NULL;
+
+	err = xe_vm_invalidate_madvise_range(vm, args->start, args->start + args->range);
+
+	if (madvise_range.has_svm_vmas)
+		xe_svm_notifier_unlock(vm);
+
+	if (madvise_range.has_userptr_vmas)
+		up_read(&vm->userptr.notifier_lock);
+err_fini:
+	if (madvise_range.has_bo_vmas)
+		drm_exec_fini(&exec);
+unlock_vm:
+	up_write(&vm->lock);
+	xe_vm_put(vm);
+	return err;
+}
diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.h b/drivers/gpu/drm/xe/xe_vm_madvise.h
new file mode 100644
index 000000000000..b0e1fc445f23
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+#ifndef _XE_VM_MADVISE_H_
+#define _XE_VM_MADVISE_H_
+
+struct drm_device;
+struct drm_file;
+
+int xe_vm_madvise_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file);
+
+#endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 10/20] drm/xe/vm: Add an identifier for madvise in xe_vma_ops
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (10 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23  5:38   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise Himal Prasad Ghimiray
                   ` (15 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

The flag XE_VMA_OPS_FLAG_MADVISE is introduced to  determine whether
xe_vma_ops is initialized by madvise operation on not.

Suggested-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c       | 1 +
 drivers/gpu/drm/xe/xe_vm_types.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index f5f8de113eae..e059d9810d26 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -4237,6 +4237,7 @@ int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t start, uint64_t range)
 	}
 
 	xe_vma_ops_init(&vops, vm, NULL, NULL, 0);
+	vops.flags |= XE_VMA_OPS_FLAG_MADVISE;
 	err = vm_bind_ioctl_ops_parse(vm, ops, &vops);
 	if (err)
 		goto unwind_ops;
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index cde2583da303..c7156f8e2ed2 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -489,6 +489,7 @@ struct xe_vma_ops {
 	struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE];
 	/** @flag: signify the properties within xe_vma_ops*/
 #define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0)
+#define XE_VMA_OPS_FLAG_MADVISE          BIT(1)
 	u32 flags;
 #ifdef TEST_VM_OPS_ERROR
 	/** @inject_error: inject error to test error handling */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (11 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 10/20] drm/xe/vm: Add an identifier for madvise in xe_vma_ops Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-14  4:31   ` kernel test robot
  2025-06-23  5:52   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 12/20] drm/xe/svm : Add svm ranges migration policy on atomic access Himal Prasad Ghimiray
                   ` (14 subsequent siblings)
  27 siblings, 2 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

In the case of the MADVISE ioctl, if the start or end addresses fall
within a VMA and existing SVM ranges are present, remove the existing
SVM mappings. Then, continue with ops_parse to create new VMAs by REMAP
unmapping of old one.

v2 (Matthew Brost)
- Use vops flag to call unmapping of ranges in vm_bind_ioctl_ops_parse
- Rename the function

Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_svm.c | 27 +++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_svm.h |  8 ++++++++
 drivers/gpu/drm/xe/xe_vm.c  |  8 ++++++--
 3 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index 19420635f1fa..df6992ee2e2d 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -935,6 +935,33 @@ bool xe_svm_has_mapping(struct xe_vm *vm, u64 start, u64 end)
 	return drm_gpusvm_has_mapping(&vm->svm.gpusvm, start, end);
 }
 
+/**
+ * xe_svm_unmap_address_range - UNMAP SVM mappings and ranges
+ * @start: start addr
+ * @end: end addr
+ *
+ * This function UNMAPS svm ranges if start or end address are inside them.
+ */
+void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end)
+{
+	struct drm_gpusvm_notifier *notifier, *next;
+
+	lockdep_assert_held_write(&vm->lock);
+
+	drm_gpusvm_for_each_notifier_safe(notifier, next, &vm->svm.gpusvm, start, end) {
+		struct drm_gpusvm_range *range, *__next;
+
+		drm_gpusvm_for_each_range_safe(range, __next, notifier, start, end) {
+			if (start > drm_gpusvm_range_start(range) ||
+			    end < drm_gpusvm_range_end(range)) {
+				if (IS_DGFX(vm->xe) && xe_svm_range_in_vram(to_xe_range(range)))
+					drm_gpusvm_range_evict(&vm->svm.gpusvm, range);
+				__xe_svm_garbage_collector(vm, to_xe_range(range));
+			}
+		}
+	}
+}
+
 /**
  * xe_svm_bo_evict() - SVM evict BO to system memory
  * @bo: BO to evict
diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
index af8f285b6caa..4e5d42323679 100644
--- a/drivers/gpu/drm/xe/xe_svm.h
+++ b/drivers/gpu/drm/xe/xe_svm.h
@@ -92,6 +92,9 @@ bool xe_svm_range_validate(struct xe_vm *vm,
 u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end,  struct xe_vma *vma);
 
 u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end);
+
+void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end);
+
 /**
  * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping
  * @range: SVM range
@@ -312,6 +315,11 @@ u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
 	return 0;
 }
 
+static inline
+void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end)
+{
+}
+
 #define xe_svm_assert_in_notifier(...) do {} while (0)
 #define xe_svm_range_has_dma_mapping(...) false
 
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index e059d9810d26..0872df8d0b15 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -2663,8 +2663,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
 				end = op->base.remap.next->va.addr;
 
 			if (xe_vma_is_cpu_addr_mirror(old) &&
-			    xe_svm_has_mapping(vm, start, end))
-				return -EBUSY;
+			    xe_svm_has_mapping(vm, start, end)) {
+				if (vops->flags & XE_VMA_OPS_FLAG_MADVISE)
+					xe_svm_unmap_address_range(vm, start, end);
+				else
+					return -EBUSY;
+			}
 
 			op->remap.start = xe_vma_start(old);
 			op->remap.range = xe_vma_size(old);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 12/20] drm/xe/svm : Add svm ranges migration policy on atomic access
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (12 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23 16:32   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location Himal Prasad Ghimiray
                   ` (13 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

If the platform does not support atomic access on system memory, and the
ranges are in system memory, but the user requires atomic accesses on
the VMA, then migrate the ranges to VRAM. Apply this policy for prefetch
operations as well.

v2
- Drop unnecessary vm_dbg

v3 (Matthew Brost)
- fix atomic policy
- prefetch shouldn't have any impact of atomic
- bo can be accessed from vma, avoid duplicate parameter

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_pt.c         |  9 ++++++--
 drivers/gpu/drm/xe/xe_svm.c        |  2 +-
 drivers/gpu/drm/xe/xe_vm.c         | 36 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_vm.h         |  2 ++
 drivers/gpu/drm/xe/xe_vm_madvise.c |  9 +++++++-
 5 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 9a390ef10852..9dd286853654 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -645,13 +645,18 @@ static bool xe_atomic_for_vram(struct xe_vm *vm)
 	return true;
 }
 
-static bool xe_atomic_for_system(struct xe_vm *vm, struct xe_bo *bo)
+static bool xe_atomic_for_system(struct xe_vm *vm,
+				 struct xe_vma *vma)
 {
 	struct xe_device *xe = vm->xe;
+	struct xe_bo *bo = xe_vma_bo(vma);
 
 	if (!xe->info.has_device_atomics_on_smem)
 		return false;
 
+	if (vma->attr.atomic_access == DRM_XE_VMA_ATOMIC_DEVICE)
+		return true;
+
 	/*
 	 * If a SMEM+LMEM allocation is backed by SMEM, a device
 	 * atomics will cause a gpu page fault and which then
@@ -745,7 +750,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
 
 	if (vma->gpuva.flags & XE_VMA_ATOMIC_PTE_BIT) {
 		xe_walk.default_vram_pte = xe_atomic_for_vram(vm) ? XE_USM_PPGTT_PTE_AE : 0;
-		xe_walk.default_system_pte = xe_atomic_for_system(vm, bo) ?
+		xe_walk.default_system_pte = xe_atomic_for_system(vm, vma) ?
 			XE_USM_PPGTT_PTE_AE : 0;
 	}
 
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index df6992ee2e2d..003aae9a0d82 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -815,7 +815,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma,
 			IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR),
 		.check_pages_threshold = IS_DGFX(vm->xe) &&
 			IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? SZ_64K : 0,
-		.devmem_only = atomic && IS_DGFX(vm->xe) &&
+		.devmem_only = xe_vma_need_vram_for_atomic(vm->xe, vma, atomic) &&
 			IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR),
 		.timeslice_ms = atomic && IS_DGFX(vm->xe) &&
 			IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ?
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 0872df8d0b15..6dd1f868942d 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -4177,6 +4177,42 @@ void xe_vm_snapshot_free(struct xe_vm_snapshot *snap)
 	kvfree(snap);
 }
 
+/**
+ * xe_vma_need_vram_for_atomic - Check if VMA needs VRAM migration for atomic operations
+ * @xe: Pointer to the XE device structure
+ * @vma: Pointer to the virtual memory area (VMA) structure
+ * @is_atomic: In pagefault path and atomic operation
+ *
+ * This function determines whether the given VMA needs to be migrated to
+ * VRAM in order to do atomic GPU operation.
+ *
+ * Return: true if migration to VRAM is required, false otherwise.
+ */
+bool xe_vma_need_vram_for_atomic(struct xe_device *xe, struct xe_vma *vma, bool is_atomic)
+{
+	if (!IS_DGFX(xe))
+		return false;
+
+	/* Note: The checks implemented here are platform-specific. For instance,
+	 * on a device supporting CXL atomics, these would ideally work universally
+	 * without additional handling.
+	 */
+	switch (vma->attr.atomic_access) {
+	case DRM_XE_VMA_ATOMIC_DEVICE:
+		return !xe->info.has_device_atomics_on_smem;
+
+	case DRM_XE_VMA_ATOMIC_CPU:
+	case DRM_XE_VMA_ATOMIC_UNDEFINED:
+		return is_atomic;
+
+	case DRM_XE_VMA_ATOMIC_GLOBAL:
+		return true;
+
+	default:
+		return is_atomic;
+	}
+}
+
 /**
  * xe_vm_alloc_madvise_vma - Allocate VMA's with madvise ops
  * @vm: Pointer to the xe_vm structure
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index 66bb6babd319..1fb639a33ffb 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -171,6 +171,8 @@ static inline bool xe_vma_is_userptr(struct xe_vma *vma)
 
 struct xe_vma *xe_vm_find_vma_by_addr(struct xe_vm *vm, u64 page_addr);
 
+bool xe_vma_need_vram_for_atomic(struct xe_device *xe, struct xe_vma *vma, bool is_atomic);
+
 int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t addr, uint64_t size);
 
 /**
diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
index ff560914ad7e..403337d79ea6 100644
--- a/drivers/gpu/drm/xe/xe_vm_madvise.c
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
@@ -89,7 +89,14 @@ static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
 			   struct xe_vma **vmas, int num_vmas,
 			   struct drm_xe_madvise *op)
 {
-	/* Implementation pending */
+	int i;
+
+	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_ATOMIC);
+	xe_assert(vm->xe, op->atomic.val <= DRM_XE_VMA_ATOMIC_CPU);
+
+	for (i = 0; i < num_vmas; i++)
+		vmas[i]->attr.atomic_access = op->atomic.val;
+	/*TODO: handle bo backed vmas */
 }
 
 static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (13 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 12/20] drm/xe/svm : Add svm ranges migration policy on atomic access Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-13 23:31   ` kernel test robot
  2025-06-14  5:33   ` kernel test robot
  2025-06-13 12:55 ` [PATCH v4 14/20] drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute Himal Prasad Ghimiray
                   ` (12 subsequent siblings)
  27 siblings, 2 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

When the user sets the valid devmem_fd as a preferred location, GPU fault
will trigger migration to tile of device associated with devmem_fd.

If the user sets an invalid devmem_fd the preferred location is current
placement(smem) only.

v2(Matthew Brost)
- Default should be faulting tile
- remove devmem_fd used as region

v3 (Matthew Brost)
- Add migration_policy
- Fix return condition
- fix migrate condition

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_svm.c        | 39 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/xe/xe_svm.h        |  8 ++++++
 drivers/gpu/drm/xe/xe_vm_madvise.c | 19 ++++++++++++++-
 3 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index 003aae9a0d82..8cbf6a6f1cf4 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -792,6 +792,37 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm
 	return true;
 }
 
+/**
+ * xe_vma_resolve_pagemap - Resolve the appropriate DRM pagemap for a VMA
+ * @vma: Pointer to the xe_vma structure containing memory attributes
+ * @tile: Pointer to the xe_tile structure used as fallback for VRAM mapping
+ *
+ * This function determines the correct DRM pagemap to use for a given VMA.
+ * It first checks if a valid devmem_fd is provided in the VMA's preferred
+ * location. If the devmem_fd is negative, it returns NULL, indicating no
+ * pagemap is available and smem to be used as preferred location.
+ * If the devmem_fd is equal to the default faulting
+ * GT identifier, it returns the VRAM pagemap associated with the tile.
+ *
+ * Future support for multi-device configurations may use drm_pagemap_from_fd()
+ * to resolve pagemaps from arbitrary file descriptors.
+ *
+ * Return: A pointer to the resolved drm_pagemap, or NULL if none is applicable.
+ */
+struct drm_pagemap *xe_vma_resolve_pagemap(struct xe_vma *vma, struct xe_tile *tile)
+{
+	s32 fd = (s32)vma->attr.preferred_loc.devmem_fd;
+
+	if (fd == DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM)
+		return NULL;
+
+	if (fd == DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE)
+		return IS_DGFX(tile_to_xe(tile)) ? &tile->mem.vram.dpagemap : NULL;
+
+	/* TODO: Support multi-device with drm_pagemap_from_fd(fd) */
+	return NULL;
+}
+
 /**
  * xe_svm_handle_pagefault() - SVM handle page fault
  * @vm: The VM.
@@ -823,6 +854,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma,
 	};
 	struct xe_svm_range *range;
 	struct dma_fence *fence;
+	struct drm_pagemap *dpagemap;
 	struct xe_tile *tile = gt_to_tile(gt);
 	int migrate_try_count = ctx.devmem_only ? 3 : 1;
 	ktime_t end = 0;
@@ -852,8 +884,13 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma,
 
 	range_debug(range, "PAGE FAULT");
 
+	dpagemap = xe_vma_resolve_pagemap(vma, tile);
 	if (--migrate_try_count >= 0 &&
-	    xe_svm_range_needs_migrate_to_vram(range, vma, IS_DGFX(vm->xe))) {
+	    xe_svm_range_needs_migrate_to_vram(range, vma, !!dpagemap || ctx.devmem_only)) {
+		/* TODO : For multi-device dpagemap will be used to find the remote tile
+		 * and remote device. Will need to modify xe_svm_alloc_vram to use dpagemap
+		 * for future multi-device support.
+		 */
 		err = xe_svm_alloc_vram(vm, tile, range, &ctx);
 		ctx.timeslice_ms <<= 1;	/* Double timeslice if we have to retry */
 		if (err) {
diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
index 4e5d42323679..900a5883951f 100644
--- a/drivers/gpu/drm/xe/xe_svm.h
+++ b/drivers/gpu/drm/xe/xe_svm.h
@@ -95,6 +95,8 @@ u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end);
 
 void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end);
 
+struct drm_pagemap *xe_vma_resolve_pagemap(struct xe_vma *vma, struct xe_tile *tile);
+
 /**
  * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping
  * @range: SVM range
@@ -320,6 +322,12 @@ void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end)
 {
 }
 
+static inline
+struct drm_pagemap *xe_vma_resolve_pagemap(struct xe_vma *vma, struct xe_tile *tile)
+{
+	return NULL;
+}
+
 #define xe_svm_assert_in_notifier(...) do {} while (0)
 #define xe_svm_range_has_dma_mapping(...) false
 
diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
index 403337d79ea6..64352fbebd25 100644
--- a/drivers/gpu/drm/xe/xe_vm_madvise.c
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
@@ -82,7 +82,19 @@ static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm *vm,
 				      struct xe_vma **vmas, int num_vmas,
 				      struct drm_xe_madvise *op)
 {
-	/* Implementation pending */
+	int i;
+
+	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_PREFERRED_LOC);
+
+	for (i = 0; i < num_vmas; i++) {
+		vmas[i]->attr.preferred_loc.devmem_fd = op->preferred_mem_loc.devmem_fd;
+
+		/* Till multi-device support is not added migration_policy
+		 * is of no use and can be ignored.
+		 */
+		vmas[i]->attr.preferred_loc.migration_policy =
+						op->preferred_mem_loc.migration_policy;
+	}
 }
 
 static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
@@ -186,6 +198,11 @@ static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const struct drm_x
 		/*TODO: Add valid pat check */
 		break;
 	case DRM_XE_VMA_ATTR_PREFERRED_LOC:
+		s32 fd = (s32)args->preferred_mem_loc.devmem_fd;
+
+		if (XE_IOCTL_DBG(xe, fd < DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM))
+			return -EINVAL;
+
 		if (XE_IOCTL_DBG(xe, args->preferred_mem_loc.migration_policy >
 				     DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES))
 			return -EINVAL;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 14/20] drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (14 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23 16:34   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 15/20] drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch Himal Prasad Ghimiray
                   ` (11 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

This attributes sets the pat_index for the svm used vma range, which is
utilized to ascertain the coherence.

v2 (Matthew Brost)
- Pat index sanity check

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_vm_madvise.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
index 64352fbebd25..973627edb23c 100644
--- a/drivers/gpu/drm/xe/xe_vm_madvise.c
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
@@ -11,6 +11,7 @@
 
 #include "xe_bo.h"
 #include "xe_gt_tlb_invalidation.h"
+#include "xe_pat.h"
 #include "xe_pt.h"
 #include "xe_svm.h"
 
@@ -115,7 +116,13 @@ static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
 			      struct xe_vma **vmas, int num_vmas,
 			      struct drm_xe_madvise *op)
 {
-	/* Implementation pending */
+	int i;
+
+	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_PAT);
+
+	for (i = 0; i < num_vmas; i++)
+		vmas[i]->attr.pat_index = op->pat_index.val;
+
 }
 
 typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
@@ -195,7 +202,13 @@ static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const struct drm_x
 			return -EINVAL;
 		break;
 	case DRM_XE_VMA_ATTR_PAT:
-		/*TODO: Add valid pat check */
+		u16 coh_mode = xe_pat_index_get_coh_mode(xe, args->pat_index.val);
+
+		if (XE_IOCTL_DBG(xe, !coh_mode))
+			return -EINVAL;
+
+		if (XE_WARN_ON(coh_mode > XE_COH_AT_LEAST_1WAY))
+			return -EINVAL;
 		break;
 	case DRM_XE_VMA_ATTR_PREFERRED_LOC:
 		s32 fd = (s32)args->preferred_mem_loc.devmem_fd;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 15/20] drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (15 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 14/20] drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23 16:36   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 16/20] drm/xe/svm: Consult madvise preferred location in prefetch Himal Prasad Ghimiray
                   ` (10 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

Introduce flag DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC to ensure prefetching
in madvise-advised memory regions

v2 (Matthew Brost)
- Add kernel-doc

v3 (Matthew Brost)
- Fix kernel-doc

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 include/uapi/drm/xe_drm.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index b5f8d11faaa8..81e90270313d 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -1006,6 +1006,10 @@ struct drm_xe_vm_destroy {
  *    valid on VMs with DRM_XE_VM_CREATE_FLAG_FAULT_MODE set. The CPU address
  *    mirror flag are only valid for DRM_XE_VM_BIND_OP_MAP operations, the BO
  *    handle MBZ, and the BO offset MBZ.
+ *
+ * The @prefetch_mem_region_instance for %DRM_XE_VM_BIND_OP_PREFETCH can also be:
+ *  - %DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC, which ensures prefetching occurs in
+ *    the memory region advised by madvise.
  */
 struct drm_xe_vm_bind_op {
 	/** @extensions: Pointer to the first extension struct, if any */
@@ -1111,6 +1115,7 @@ struct drm_xe_vm_bind_op {
 	/** @flags: Bind flags */
 	__u32 flags;
 
+#define DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC	-1
 	/**
 	 * @prefetch_mem_region_instance: Memory region to prefetch VMA to.
 	 * It is a region instance, not a mask.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 16/20] drm/xe/svm: Consult madvise preferred location in prefetch
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (16 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 15/20] drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23 22:07   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 17/20] drm/xe/bo: Add attributes field to xe_bo Himal Prasad Ghimiray
                   ` (9 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

When prefetch region is DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC, prefetch svm
ranges to preferred location provided by madvise.

v2 (Matthew Brost)
- Fix region, devmem_fd usages
- consult madvise is applicable for other vma's too.

v3
- Fix atomic handling

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_svm.h  |  1 -
 drivers/gpu/drm/xe/xe_tile.h | 18 ++++++++++++++++++
 drivers/gpu/drm/xe/xe_vm.c   | 26 ++++++++++++++++++--------
 3 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
index 900a5883951f..1658e28f3773 100644
--- a/drivers/gpu/drm/xe/xe_svm.h
+++ b/drivers/gpu/drm/xe/xe_svm.h
@@ -327,7 +327,6 @@ struct drm_pagemap *xe_vma_resolve_pagemap(struct xe_vma *vma, struct xe_tile *t
 {
 	return NULL;
 }
-
 #define xe_svm_assert_in_notifier(...) do {} while (0)
 #define xe_svm_range_has_dma_mapping(...) false
 
diff --git a/drivers/gpu/drm/xe/xe_tile.h b/drivers/gpu/drm/xe/xe_tile.h
index eb939316d55b..142ed5cf654b 100644
--- a/drivers/gpu/drm/xe/xe_tile.h
+++ b/drivers/gpu/drm/xe/xe_tile.h
@@ -10,6 +10,24 @@
 
 struct xe_tile;
 
+#if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR)
+/**
+ * xe_tile_from_dpagemap - Find xe_tile from drm_pagemap
+ * @dpagemap: pointer to struct drm_pagemap
+ *
+ * Return: Pointer to xe_tile
+ */
+static inline struct xe_tile *xe_tile_from_dpagemap(struct drm_pagemap *dpagemap)
+{
+	return container_of(dpagemap, struct xe_tile, mem.vram.dpagemap);
+}
+
+#else
+static inline  struct xe_tile *xe_tile_from_dpagemap(struct drm_pagemap *dpagemap)
+{
+	return NULL;
+}
+#endif
 int xe_tile_init_early(struct xe_tile *tile, struct xe_device *xe, u8 id);
 int xe_tile_init_noalloc(struct xe_tile *tile);
 int xe_tile_init(struct xe_tile *tile);
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 6dd1f868942d..0dd9f9e11030 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -38,6 +38,7 @@
 #include "xe_res_cursor.h"
 #include "xe_svm.h"
 #include "xe_sync.h"
+#include "xe_tile.h"
 #include "xe_trace_bo.h"
 #include "xe_wa.h"
 #include "xe_hmm.h"
@@ -2907,15 +2908,24 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op)
 	int err = 0;
 
 	struct xe_svm_range *svm_range;
+	struct drm_pagemap *dpagemap;
 	struct drm_gpusvm_ctx ctx = {};
-	struct xe_tile *tile;
+	struct xe_tile *tile = NULL;
 	unsigned long i;
 	u32 region;
 
 	if (!xe_vma_is_cpu_addr_mirror(vma))
 		return 0;
 
-	region = op->prefetch_range.region;
+	if (op->prefetch_range.region == DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC) {
+		dpagemap = xe_vma_resolve_pagemap(vma, xe_device_get_root_tile(vm->xe));
+		if (dpagemap)
+			tile = xe_tile_from_dpagemap(dpagemap);
+	} else {
+		region = op->prefetch_range.region;
+		if (region)
+			tile = &vm->xe->tiles[region_to_mem_type[region] - XE_PL_VRAM0];
+	}
 
 	ctx.read_only = xe_vma_read_only(vma);
 	ctx.devmem_possible = devmem_possible;
@@ -2923,11 +2933,10 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op)
 
 	/* TODO: Threading the migration */
 	xa_for_each(&op->prefetch_range.range, i, svm_range) {
-		if (!region)
+		if (!tile)
 			xe_svm_range_migrate_to_smem(vm, svm_range);
 
-		if (xe_svm_range_needs_migrate_to_vram(svm_range, vma, region)) {
-			tile = &vm->xe->tiles[region_to_mem_type[region] - XE_PL_VRAM0];
+		if (xe_svm_range_needs_migrate_to_vram(svm_range, vma, !!tile)) {
 			err = xe_svm_alloc_vram(vm, tile, svm_range, &ctx);
 			if (err) {
 				drm_dbg(&vm->xe->drm, "VRAM allocation failed, retry from userspace, asid=%u, gpusvm=%p, errno=%pe\n",
@@ -2995,7 +3004,8 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
 		else
 			region = op->prefetch.region;
 
-		xe_assert(vm->xe, region <= ARRAY_SIZE(region_to_mem_type));
+		xe_assert(vm->xe, region == DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC ||
+			  region <= ARRAY_SIZE(region_to_mem_type));
 
 		err = vma_lock_and_validate(exec,
 					    gpuva_to_vma(op->base.prefetch.va),
@@ -3413,8 +3423,8 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm,
 				 op == DRM_XE_VM_BIND_OP_PREFETCH) ||
 		    XE_IOCTL_DBG(xe, prefetch_region &&
 				 op != DRM_XE_VM_BIND_OP_PREFETCH) ||
-		    XE_IOCTL_DBG(xe, !(BIT(prefetch_region) &
-				       xe->info.mem_region_mask)) ||
+		    XE_IOCTL_DBG(xe,  (prefetch_region != DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC &&
+				       !(BIT(prefetch_region) & xe->info.mem_region_mask))) ||
 		    XE_IOCTL_DBG(xe, obj &&
 				 op == DRM_XE_VM_BIND_OP_UNMAP)) {
 			err = -EINVAL;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 17/20] drm/xe/bo: Add attributes field to xe_bo
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (17 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 16/20] drm/xe/svm: Consult madvise preferred location in prefetch Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-13 12:55 ` [PATCH v4 18/20] drm/xe/bo: Update atomic_access attribute on madvise Himal Prasad Ghimiray
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

A single BO can be linked to multiple VMAs, making VMA attributes
insufficient for determining the placement and PTE update attributes
of the BO. To address this, an attributes field has been added to the
BO.

Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_bo_types.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h
index eb5e83c5f233..2a5273f745f7 100644
--- a/drivers/gpu/drm/xe/xe_bo_types.h
+++ b/drivers/gpu/drm/xe/xe_bo_types.h
@@ -62,6 +62,14 @@ struct xe_bo {
 	 */
 	struct list_head client_link;
 #endif
+	/** @attr: User controlled attributes for bo */
+	struct {
+		/**
+		 * @atomic_access: type of atomic access bo needs
+		 * protected by bo dma-resv lock
+		 */
+		u32 atomic_access;
+	} attr;
 	/**
 	 * @pxp_key_instance: PXP key instance this BO was created against. A
 	 * 0 in this variable indicates that the BO does not use PXP encryption.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 18/20] drm/xe/bo: Update atomic_access attribute on madvise
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (18 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 17/20] drm/xe/bo: Add attributes field to xe_bo Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23 16:19   ` Matthew Brost
  2025-06-13 12:55 ` [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes Himal Prasad Ghimiray
                   ` (7 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

Update the bo_atomic_access based on user-provided input and determine
the migration to smem during a CPU fault

v2 (Matthew Brost)
- Avoid cpu unmapping if bo is already in smem
- check atomics on smem too for ioctl
- Add comments

v3
- Avoid migration in prefetch

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_bo.c           | 21 ++++++++--
 drivers/gpu/drm/xe/xe_gt_pagefault.c |  2 +-
 drivers/gpu/drm/xe/xe_vm.c           |  5 ++-
 drivers/gpu/drm/xe/xe_vm_madvise.c   | 61 +++++++++++++++++++++++++++-
 4 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 4e39188a021a..82b33dfc5515 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -1667,6 +1667,12 @@ static void xe_gem_object_close(struct drm_gem_object *obj,
 	}
 }
 
+static bool should_migrate_to_smem(struct xe_bo *bo)
+{
+	return bo->attr.atomic_access == DRM_XE_VMA_ATOMIC_GLOBAL ||
+	       bo->attr.atomic_access == DRM_XE_VMA_ATOMIC_CPU;
+}
+
 static vm_fault_t xe_gem_fault(struct vm_fault *vmf)
 {
 	struct ttm_buffer_object *tbo = vmf->vma->vm_private_data;
@@ -1675,7 +1681,7 @@ static vm_fault_t xe_gem_fault(struct vm_fault *vmf)
 	struct xe_bo *bo = ttm_to_xe_bo(tbo);
 	bool needs_rpm = bo->flags & XE_BO_FLAG_VRAM_MASK;
 	vm_fault_t ret;
-	int idx;
+	int idx, r = 0;
 
 	if (needs_rpm)
 		xe_pm_runtime_get(xe);
@@ -1687,8 +1693,17 @@ static vm_fault_t xe_gem_fault(struct vm_fault *vmf)
 	if (drm_dev_enter(ddev, &idx)) {
 		trace_xe_bo_cpu_fault(bo);
 
-		ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
-					       TTM_BO_VM_NUM_PREFAULT);
+		if (should_migrate_to_smem(bo)) {
+			r = xe_bo_migrate(bo, XE_PL_TT);
+			if (r == -EBUSY || r == -ERESTARTSYS || r == -EINTR)
+				ret = VM_FAULT_NOPAGE;
+			else if (r)
+				ret = VM_FAULT_SIGBUS;
+		}
+		if (!ret)
+			ret = ttm_bo_vm_fault_reserved(vmf,
+						       vmf->vma->vm_page_prot,
+						       TTM_BO_VM_NUM_PREFAULT);
 		drm_dev_exit(idx);
 	} else {
 		ret = ttm_bo_vm_dummy_page(vmf, vmf->vma->vm_page_prot);
diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
index e2d975b2fddb..1335c5fc0e10 100644
--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
@@ -89,7 +89,7 @@ static int xe_pf_begin(struct drm_exec *exec, struct xe_vma *vma,
 	if (err)
 		return err;
 
-	if (atomic && IS_DGFX(vm->xe)) {
+	if (xe_vma_need_vram_for_atomic(vm->xe, vma, atomic)) {
 		if (xe_vma_is_userptr(vma)) {
 			err = -EACCES;
 			return err;
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 0dd9f9e11030..14e554f3f4d5 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -4200,6 +4200,9 @@ void xe_vm_snapshot_free(struct xe_vm_snapshot *snap)
  */
 bool xe_vma_need_vram_for_atomic(struct xe_device *xe, struct xe_vma *vma, bool is_atomic)
 {
+	u32 atomic_access = xe_vma_bo(vma) ? xe_vma_bo(vma)->attr.atomic_access :
+					     vma->attr.atomic_access;
+
 	if (!IS_DGFX(xe))
 		return false;
 
@@ -4207,7 +4210,7 @@ bool xe_vma_need_vram_for_atomic(struct xe_device *xe, struct xe_vma *vma, bool
 	 * on a device supporting CXL atomics, these would ideally work universally
 	 * without additional handling.
 	 */
-	switch (vma->attr.atomic_access) {
+	switch (atomic_access) {
 	case DRM_XE_VMA_ATOMIC_DEVICE:
 		return !xe->info.has_device_atomics_on_smem;
 
diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
index 973627edb23c..5b96c8fc73a5 100644
--- a/drivers/gpu/drm/xe/xe_vm_madvise.c
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
@@ -102,14 +102,28 @@ static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
 			   struct xe_vma **vmas, int num_vmas,
 			   struct drm_xe_madvise *op)
 {
+	struct xe_bo *bo;
 	int i;
 
 	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_ATOMIC);
 	xe_assert(vm->xe, op->atomic.val <= DRM_XE_VMA_ATOMIC_CPU);
 
-	for (i = 0; i < num_vmas; i++)
+	for (i = 0; i < num_vmas; i++) {
 		vmas[i]->attr.atomic_access = op->atomic.val;
-	/*TODO: handle bo backed vmas */
+
+		bo = xe_vma_bo(vmas[i]);
+		if (!bo)
+			continue;
+
+		xe_bo_assert_held(bo);
+		bo->attr.atomic_access = op->atomic.val;
+
+		/* Invalidate cpu page table, so bo can migrate to smem in next access */
+		if (xe_bo_is_vram(bo) &&
+		    (bo->attr.atomic_access == DRM_XE_VMA_ATOMIC_CPU ||
+		     bo->attr.atomic_access == DRM_XE_VMA_ATOMIC_GLOBAL))
+			ttm_bo_unmap_virtual(&bo->ttm);
+	}
 }
 
 static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
@@ -231,6 +245,41 @@ static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const struct drm_x
 	return 0;
 }
 
+static int check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas,
+				  int num_vmas, u32 atomic_val)
+{
+	struct xe_device *xe = vm->xe;
+	struct xe_bo *bo;
+	int i;
+
+	for (i = 0; i < num_vmas; i++) {
+		bo = xe_vma_bo(vmas[i]);
+		if (!bo)
+			continue;
+
+		if (XE_IOCTL_DBG(xe, atomic_val == DRM_XE_VMA_ATOMIC_CPU &&
+				 !(bo->flags & XE_BO_FLAG_SYSTEM)))
+			return -EINVAL;
+
+		/* NOTE: The following atomic checks are platform-specific. For example,
+		 * if a device supports CXL atomics, these may not be necessary or
+		 * may behave differently.
+		 */
+		if (XE_IOCTL_DBG(xe, atomic_val == DRM_XE_VMA_ATOMIC_DEVICE &&
+				 !(bo->flags & XE_BO_FLAG_VRAM0) &&
+				 !(bo->flags & XE_BO_FLAG_VRAM1) &&
+				 !(bo->flags & XE_BO_FLAG_SYSTEM &&
+				   xe->info.has_device_atomics_on_smem)))
+			return -EINVAL;
+
+		if (XE_IOCTL_DBG(xe, atomic_val == DRM_XE_VMA_ATOMIC_GLOBAL &&
+				 (!(bo->flags & XE_BO_FLAG_SYSTEM) ||
+				  (!(bo->flags & XE_BO_FLAG_VRAM0) &&
+				   !(bo->flags & XE_BO_FLAG_VRAM1)))))
+			return -EINVAL;
+	}
+	return 0;
+}
 /**
  * xe_vm_madvise_ioctl - Handle MADVise ioctl for a VM
  * @dev: DRM device pointer
@@ -276,6 +325,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
 		goto unlock_vm;
 
 	if (madvise_range.has_bo_vmas) {
+		if (args->type == DRM_XE_VMA_ATTR_ATOMIC) {
+			err = check_bo_args_are_sane(vm, madvise_range.vmas,
+						     madvise_range.num_vmas,
+						     args->atomic.val);
+			if (err)
+				goto unlock_vm;
+		}
+
 		drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
 		drm_exec_until_all_locked(&exec) {
 			for (int i = 0; i < madvise_range.num_vmas; i++) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (19 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 18/20] drm/xe/bo: Update atomic_access attribute on madvise Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23 22:43   ` Matthew Brost
                     ` (2 more replies)
  2025-06-13 12:55 ` [PATCH v4 20/20] drm/xe/madvise: Skip vma invalidation if mem attr are unchanged Himal Prasad Ghimiray
                   ` (6 subsequent siblings)
  27 siblings, 3 replies; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

Introduce the DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl to allow userspace
to query memory attributes of VMAs within a specified virtual address
range.
If num_vmas == 0 and vector_of_vma_mem_attr == NULL, the ioctl returns
the number of VMAs in the specified range.
If num_vmas > 0 and a valid user pointer is provided in
vector_of_vma_mem_attr, the ioctl fills the buffer with memory
attributes for each VMA.
This two-step interface allows userspace to first query the required
buffer size, then retrieve detailed attributes efficiently.

v2 (Matthew Brost)
- Use same ioctl to overload functionality

v3
- Add kernel-doc

Cc: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_device.c |   1 +
 drivers/gpu/drm/xe/xe_vm.c     |  89 ++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_vm.h     |   2 +-
 include/uapi/drm/xe_drm.h      | 130 +++++++++++++++++++++++++++++++++
 4 files changed, 221 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 632d3ab12392..1f9969acbcd9 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -199,6 +199,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
 			  DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(XE_VM_QUERY_VMAS_ATTRS, xe_vm_query_vmas_attrs_ioctl, DRM_RENDER_ALLOW),
 };
 
 static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 14e554f3f4d5..d9ce25f3abf4 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -2171,6 +2171,95 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data,
 	return err;
 }
 
+static void xe_vm_query_vmas(struct xe_vm *vm, u32 *num_vmas, u64 start, u64 end)
+{
+	struct drm_gpuva *gpuva;
+
+	lockdep_assert_held(&vm->lock);
+	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end)
+		(*num_vmas)++;
+}
+
+static int get_mem_attrs(struct xe_vm *vm, u32 *num_vmas, u64 start,
+			 u64 end, struct drm_xe_vma_mem_attr *attrs)
+{
+	struct drm_gpuva *gpuva;
+	int i = 0;
+
+	lockdep_assert_held(&vm->lock);
+
+	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
+		struct xe_vma *vma = gpuva_to_vma(gpuva);
+
+		if (i == *num_vmas)
+			return -EINVAL;
+
+		attrs[i].start = xe_vma_start(vma);
+		attrs[i].end = xe_vma_end(vma);
+		attrs[i].atomic.val = vma->attr.atomic_access;
+		attrs[i].pat_index.val = vma->attr.pat_index;
+		attrs[i].preferred_mem_loc.devmem_fd = vma->attr.preferred_loc.devmem_fd;
+		attrs[i].preferred_mem_loc.migration_policy = vma->attr.preferred_loc.migration_policy;
+
+		i++;
+	}
+
+	if (i <  (*num_vmas - 1))
+		*num_vmas = i;
+	return 0;
+}
+
+int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+	struct xe_device *xe = to_xe_device(dev);
+	struct xe_file *xef = to_xe_file(file);
+	struct drm_xe_vma_mem_attr *mem_attrs;
+	struct drm_xe_vm_query_vmas_attr *args = data;
+	u64 __user *attrs_user = u64_to_user_ptr(args->vector_of_vma_mem_attr);
+	struct xe_vm *vm;
+	int err = 0;
+
+	if (XE_IOCTL_DBG(xe,
+			 (args->num_vmas == 0 && attrs_user) ||
+			(args->num_vmas > 0 && !attrs_user)))
+		return -EINVAL;
+
+	vm = xe_vm_lookup(xef, args->vm_id);
+	if (XE_IOCTL_DBG(xe, !vm))
+		return -EINVAL;
+
+	down_read(&vm->lock);
+
+	attrs_user = u64_to_user_ptr(args->vector_of_vma_mem_attr);
+
+	if (args->num_vmas == 0 && !attrs_user) {
+		xe_vm_query_vmas(vm, &args->num_vmas, args->start, args->start + args->range);
+		goto unlock_vm;
+	}
+
+	mem_attrs = kvmalloc_array(args->num_vmas, sizeof(struct drm_xe_vma_mem_attr),
+				   GFP_KERNEL | __GFP_ACCOUNT |
+				   __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
+	if (!mem_attrs) {
+		err = args->num_vmas > 1 ? -ENOBUFS : -ENOMEM;
+		goto unlock_vm;
+	}
+
+	err = get_mem_attrs(vm, &args->num_vmas, args->start,
+			    args->start + args->range, mem_attrs);
+	if (err)
+		goto free_mem_attrs;
+
+	err = __copy_to_user(attrs_user, mem_attrs,
+			     sizeof(struct drm_xe_vma_mem_attr) * args->num_vmas);
+
+free_mem_attrs:
+	kvfree(mem_attrs);
+unlock_vm:
+	up_read(&vm->lock);
+	return err;
+}
+
 static bool vma_matches(struct xe_vma *vma, u64 page_addr)
 {
 	if (page_addr > xe_vma_end(vma) - 1 ||
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index 1fb639a33ffb..e4a601a3583f 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -195,7 +195,7 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file);
 int xe_vm_bind_ioctl(struct drm_device *dev, void *data,
 		     struct drm_file *file);
-
+int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
 void xe_vm_close_and_put(struct xe_vm *vm);
 
 static inline bool xe_vm_in_fault_mode(struct xe_vm *vm)
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 81e90270313d..c0aa7c19870e 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -82,6 +82,7 @@ extern "C" {
  *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
  *  - &DRM_IOCTL_XE_OBSERVATION
  *  - &DRM_IOCTL_XE_MADVISE
+ *  - &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
  */
 
 /*
@@ -104,6 +105,7 @@ extern "C" {
 #define DRM_XE_WAIT_USER_FENCE		0x0a
 #define DRM_XE_OBSERVATION		0x0b
 #define DRM_XE_MADVISE			0x0c
+#define DRM_XE_VM_QUERY_VMAS_ATTRS	0x0d
 
 /* Must be kept compact -- no holes */
 
@@ -120,6 +122,7 @@ extern "C" {
 #define DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence)
 #define DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
 #define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
+#define DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_VMAS_ATTRS, struct drm_xe_vm_query_vmas_attr)
 
 /**
  * DOC: Xe IOCTL Extensions
@@ -2093,6 +2096,133 @@ struct drm_xe_madvise {
 	__u64 reserved[2];
 };
 
+/**
+ * struct drm_xe_vma_mem_attr - Output of &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
+ *
+ * This structure is provided by userspace and filled by KMD in response to the
+ * DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl. It describes memory attributes of
+ * a VMA within a specified address range in a VM.
+ *
+ * The structure includes information such as atomic access policy, purgeable
+ * state, page attribute table (PAT) index, and preferred memory location.
+ * Userspace allocates an array of these structures and passes a pointer to the
+ * ioctl to retrieve attributes for each VMA
+ *
+ * @extensions: Pointer to the first extension struct, if any
+ * @start: Start address of the virtual memory area
+ * @end: End address of the virtual memory area
+ *
+ * @atomic.val: Value of atomic operation policy
+ * @atomic.reserved: Reserved, must be zero
+ *
+ * @purge_state_val.val: Value for DRM_XE_VMA_ATTR_PURGEABLE_STATE
+ * @purge_state_val.reserved: Reserved, must be zero
+ *
+ * @pat_index.val: Page Attribute Table (PAT) index
+ * @pat_index.reserved: Reserved, must be zero
+ *
+ * @preferred_mem_loc.devmem_fd: File descriptor for preferred device memory
+ * @preferred_mem_loc.migration_policy: Migration policy for memory placement
+ *
+ */
+struct drm_xe_vma_mem_attr {
+	 /** @extensions: Pointer to the first extension struct, if any */
+	__u64 extensions;
+
+	/** @start: start of the vma */
+	__u64 start;
+
+	/** @end: end of the vma */
+	__u64 end;
+
+	struct {
+		struct {
+		/** @atomic.val: atomic attribute for vma*/
+			__u32 val;
+
+		/** @atomic.reserved: Reserved */
+			__u32 reserved;
+		} atomic;
+
+		struct {
+			/** @pat_index.val: PAT index of vma */
+			__u32 val;
+
+			/** @pat_index.reserved: Reserved */
+			__u32 reserved;
+		} pat_index;
+
+		/** @preferred_mem_loc: preferred memory location */
+		struct {
+			/** @preferred_mem_loc.devmem_fd: fd for preferred loc */
+			__u32 devmem_fd;
+
+			/** @preferred_mem_loc.migration_policy: Page migration policy */
+			__u32 migration_policy;
+		} preferred_mem_loc;
+	};
+
+	 /** @reserved: Reserved */
+	__u64 reserved[2];
+};
+
+/**
+ * struct drm_xe_vm_query_vmas_attr - Input of &DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES
+ *
+ * This structure is used to query memory attributes of virtual memory areas
+ * (VMAs) within a specified address range in a VM. It provides detailed
+ * information about each VMA, including atomic access policy, purgeable state,
+ * page attribute table (PAT) index, and preferred memory location.
+ *
+ * Userspace first calls the ioctl with @num_vmas = 0 and
+ * @vector_of_vma_mem_attr = NULL to retrieve the number of VMAs in the range.
+ * Then, it allocates a buffer of that size and calls the ioctl again to fill
+ * the buffer with VMA attributes.
+ *
+ * Example:
+ *
+ * .. code-block:: C
+ *
+ *     struct drm_xe_vma_mem_attr *attrs;
+ *     __u32 num_vmas;
+ *
+ *     // First call to get number of VMAs
+ *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
+ *     num_vmas = query.num_vmas;
+ *
+ *     // Allocate and query attributes
+ *     attrs = malloc(num_vmas, sizeof(*attrs));
+ *     query.vector_of_vma_mem_attr = (__u64)(uintptr_t)attrs;
+ *     query.num_vmas = num_vmas;
+ *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
+ */
+struct drm_xe_vm_query_vmas_attr {
+	/** @extensions: Pointer to the first extension struct, if any */
+	__u64 extensions;
+
+	/** @vm_id: vm_id of the virtual range */
+	__u32 vm_id;
+
+	/** @num_vmas: number of vmas in range */
+	__u32 num_vmas;
+
+	/** @start: start of the virtual address range */
+	__u64 start;
+
+	/** @size: size of the virtual address range */
+	__u64 range;
+
+	/**
+	 * @vector_of_ops: userptr to array of struct
+	 * drm_xe_vma_mem_attr
+	 */
+	__u64 vector_of_vma_mem_attr;
+
+	/** @reserved: Reserved */
+	__u64 reserved[2];
+
+};
+
 #if defined(__cplusplus)
 }
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v4 20/20] drm/xe/madvise: Skip vma invalidation if mem attr are unchanged
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (20 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes Himal Prasad Ghimiray
@ 2025-06-13 12:55 ` Himal Prasad Ghimiray
  2025-06-23 22:28   ` Matthew Brost
  2025-06-16  4:30 ` ✗ CI.checkpatch: warning for MADVISE FOR XE (rev3) Patchwork
                   ` (5 subsequent siblings)
  27 siblings, 1 reply; 68+ messages in thread
From: Himal Prasad Ghimiray @ 2025-06-13 12:55 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost, thomas.hellstrom, Himal Prasad Ghimiray

If a VMA within the madvise input range already has the same memory
attribute as the one requested by the user, skip PTE zapping for that
VMA to avoid unnecessary invalidation.

Suggested-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
 drivers/gpu/drm/xe/xe_vm.c         |  1 +
 drivers/gpu/drm/xe/xe_vm_madvise.c | 57 ++++++++++++++++++------------
 drivers/gpu/drm/xe/xe_vm_types.h   |  6 ++++
 3 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index d9ce25f3abf4..56d6c286e3d3 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1226,6 +1226,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
 		vma->gpuva.flags |= XE_VMA_ATOMIC_PTE_BIT;
 
 	vma->attr = *attr;
+	vma->skip_invalidation = 0;
 
 	if (bo) {
 		struct drm_gpuvm_bo *vm_bo;
diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
index 5b96c8fc73a5..06e40ab0970e 100644
--- a/drivers/gpu/drm/xe/xe_vm_madvise.c
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
@@ -88,13 +88,18 @@ static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm *vm,
 	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_PREFERRED_LOC);
 
 	for (i = 0; i < num_vmas; i++) {
-		vmas[i]->attr.preferred_loc.devmem_fd = op->preferred_mem_loc.devmem_fd;
-
-		/* Till multi-device support is not added migration_policy
-		 * is of no use and can be ignored.
-		 */
-		vmas[i]->attr.preferred_loc.migration_policy =
+		if (vmas[i]->attr.preferred_loc.devmem_fd == op->preferred_mem_loc.devmem_fd &&
+		    vmas[i]->attr.preferred_loc.migration_policy ==
+		    op->preferred_mem_loc.migration_policy) {
+			vmas[i]->skip_invalidation = 1;
+		} else {
+			vmas[i]->attr.preferred_loc.devmem_fd = op->preferred_mem_loc.devmem_fd;
+			/* Till multi-device support is not added migration_policy
+			 * is of no use and can be ignored.
+			 */
+			vmas[i]->attr.preferred_loc.migration_policy =
 						op->preferred_mem_loc.migration_policy;
+		}
 	}
 }
 
@@ -109,7 +114,10 @@ static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
 	xe_assert(vm->xe, op->atomic.val <= DRM_XE_VMA_ATOMIC_CPU);
 
 	for (i = 0; i < num_vmas; i++) {
-		vmas[i]->attr.atomic_access = op->atomic.val;
+		if (vmas[i]->attr.atomic_access == op->atomic.val)
+			vmas[i]->skip_invalidation = 1;
+		else
+			vmas[i]->attr.atomic_access = op->atomic.val;
 
 		bo = xe_vma_bo(vmas[i]);
 		if (!bo)
@@ -134,9 +142,12 @@ static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
 
 	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_PAT);
 
-	for (i = 0; i < num_vmas; i++)
-		vmas[i]->attr.pat_index = op->pat_index.val;
-
+	for (i = 0; i < num_vmas; i++) {
+		if (vmas[i]->attr.pat_index == op->pat_index.val)
+			vmas[i]->skip_invalidation = 1;
+		else
+			vmas[i]->attr.pat_index = op->pat_index.val;
+	}
 }
 
 typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
@@ -161,23 +172,25 @@ static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start, u64 end, u
 				  false, MAX_SCHEDULE_TIMEOUT) <= 0)
 		XE_WARN_ON(1);
 
-	*tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
-
 	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
 		struct xe_vma *vma = gpuva_to_vma(gpuva);
 
-		if (xe_vma_is_cpu_addr_mirror(vma))
+		if (vma->skip_invalidation)
 			continue;
 
-		if (xe_vma_is_userptr(vma)) {
-			WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
-							     DMA_RESV_USAGE_BOOKKEEP));
-		}
-
-		for_each_tile(tile, vm->xe, id) {
-			if (xe_pt_zap_ptes(tile, vma)) {
-				*tile_mask |= BIT(id);
-				vma->tile_invalidated |= BIT(id);
+		if (xe_vma_is_cpu_addr_mirror(vma)) {
+			*tile_mask |= xe_svm_ranges_zap_ptes_in_range(vm,
+								      xe_vma_start(vma),
+								      xe_vma_end(vma));
+		} else {
+			if (xe_vma_is_userptr(vma))
+				WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
+								     DMA_RESV_USAGE_BOOKKEEP));
+			for_each_tile(tile, vm->xe, id) {
+				if (xe_pt_zap_ptes(tile, vma)) {
+					*tile_mask |= BIT(id);
+					vma->tile_invalidated |= BIT(id);
+				}
 			}
 		}
 	}
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index c7156f8e2ed2..3b3019ecbfab 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -151,6 +151,12 @@ struct xe_vma {
 	/** @tile_staged: bind is staged for this VMA */
 	u8 tile_staged;
 
+	/**
+	 * @skip_invalidation: Used in madvise to avoid invalidation
+	 * if mem attributes doesn't change
+	 */
+	u32 skip_invalidation;
+
 	/**
 	 * @ufence: The user fence that was provided with MAP.
 	 * Needs to be signalled before UNMAP can be processed.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 02/20] drm/xe/uapi: Add madvise interface
  2025-06-13 12:55 ` [PATCH v4 02/20] drm/xe/uapi: Add madvise interface Himal Prasad Ghimiray
@ 2025-06-13 14:15   ` Souza, Jose
  2025-06-23  4:30   ` Matthew Brost
  1 sibling, 0 replies; 68+ messages in thread
From: Souza, Jose @ 2025-06-13 14:15 UTC (permalink / raw)
  To: intel-xe@lists.freedesktop.org, Ghimiray, Himal Prasad
  Cc: Brost, Matthew, thomas.hellstrom@linux.intel.com

On Fri, 2025-06-13 at 18:25 +0530, Himal Prasad Ghimiray wrote:
> This commit introduces a new madvise interface to support
> driver-specific ioctl operations. The madvise interface allows for more
> efficient memory management by providing hints to the driver about the
> expected memory usage and pte update policy for gpuvma.
> 
> v2 (Matthew/Thomas)
> - Drop num_ops support
> - Drop purgeable support
> - Add kernel-docs
> - IOWR/IOW
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> Acked-by: José Roberto de Souza <jose.souza@intel.com>

removing my ack, I gave ack just to the purgeable part.
That is the only part that Mesa can make use, and now that is dropped so no part of this patch has my ack.

> ---
>  include/uapi/drm/xe_drm.h | 118 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 118 insertions(+)
> 
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index 6a702ba7817c..b5f8d11faaa8 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -81,6 +81,7 @@ extern "C" {
>   *  - &DRM_IOCTL_XE_EXEC
>   *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
>   *  - &DRM_IOCTL_XE_OBSERVATION
> + *  - &DRM_IOCTL_XE_MADVISE
>   */
>  
>  /*
> @@ -102,6 +103,7 @@ extern "C" {
>  #define DRM_XE_EXEC			0x09
>  #define DRM_XE_WAIT_USER_FENCE		0x0a
>  #define DRM_XE_OBSERVATION		0x0b
> +#define DRM_XE_MADVISE			0x0c
>  
>  /* Must be kept compact -- no holes */
>  
> @@ -117,6 +119,7 @@ extern "C" {
>  #define DRM_IOCTL_XE_EXEC			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec)
>  #define DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence)
>  #define DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
> +#define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
>  
>  /**
>   * DOC: Xe IOCTL Extensions
> @@ -1970,6 +1973,121 @@ struct drm_xe_query_eu_stall {
>  	__u64 sampling_rates[];
>  };
>  
> +/**
> + * struct drm_xe_madvise - Input of &DRM_IOCTL_XE_MADVISE
> + *
> + * This structure is used to set memory attributes for a virtual address range
> + * in a VM. The type of attribute is specified by @type, and the corresponding
> + * union member is used to provide additional parameters for @type.
> + *
> + * Supported attribute types:
> + * - DRM_XE_VMA_ATTR_PREFERRED_LOC: Set preferred memory location.
> + * - DRM_XE_VMA_ATTR_ATOMIC: Set atomic access policy.
> + * - DRM_XE_VMA_ATTR_PAT: Set page attribute table index.
> + *
> + * Example:
> + *
> + * .. code-block:: C
> + *
> + * struct drm_xe_madvise madvise = {
> + *          .vm_id = vm_id,
> + *          .start = 0x100000,
> + *          .range = 0x2000,
> + *          .type = DRM_XE_VMA_ATTR_ATOMIC,
> + *          .atomic_val = DRM_XE_VMA_ATOMIC_DEVICE,
> + *         };
> + *
> + * ioctl(fd, DRM_IOCTL_XE_MADVISE, &madvise);
> + *
> + */
> +struct drm_xe_madvise {
> +	/** @extensions: Pointer to the first extension struct, if any */
> +	__u64 extensions;
> +
> +	/** @start: start of the virtual address range */
> +	__u64 start;
> +
> +	/** @size: size of the virtual address range */
> +	__u64 range;
> +
> +	/** @vm_id: vm_id of the virtual range */
> +	__u32 vm_id;
> +
> +#define DRM_XE_VMA_ATTR_PREFERRED_LOC	0
> +#define DRM_XE_VMA_ATTR_ATOMIC		1
> +#define DRM_XE_VMA_ATTR_PAT		2
> +	/** @type: type of attribute */
> +	__u32 type;
> +
> +	union {
> +		/**
> +		 * @atomic: Atomic access policy
> +		 *
> +		 * Used when @type == DRM_XE_VMA_ATTR_ATOMIC.
> +		 *
> +		 * Supported values for @atomic.val:
> +		 * - DRM_XE_VMA_ATOMIC_UNDEFINED: Undefined or default behaviour
> +		 *   Support both GPU and CPU atomic operations for system allocator
> +		 *   Support GPU atomic operations for normal(bo) allocator
> +		 * - DRM_XE_VMA_ATOMIC_DEVICE: Support GPU atomic operations
> +		 * - DRM_XE_VMA_ATOMIC_GLOBAL: Support both GPU and CPU atomic operations
> +		 * - DRM_XE_VMA_ATOMIC_CPU: Support CPU atomic
> +		 */
> +		struct {
> +#define DRM_XE_VMA_ATOMIC_UNDEFINED	0
> +#define DRM_XE_VMA_ATOMIC_DEVICE	1
> +#define DRM_XE_VMA_ATOMIC_GLOBAL	2
> +#define DRM_XE_VMA_ATOMIC_CPU		3
> +			/** @atomic.val: value of atomic operation */
> +			__u32 val;
> +
> +			/** @atomic.reserved: Reserved */
> +			__u32 reserved;
> +		} atomic;
> +
> +		/**
> +		 * @pat_index: Page attribute table index
> +		 *
> +		 * Used when @type == DRM_XE_VMA_ATTR_PAT.
> +		 */
> +		struct {
> +			/** @pat_index.val: PAT index value */
> +			__u32 val;
> +
> +			/** @pat_index.reserved: Reserved */
> +			__u32 reserved;
> +		} pat_index;
> +
> +		/**
> +		 * @preferred_mem_loc: preferred memory location
> +		 *
> +		 * Used when @type == DRM_XE_VMA_ATTR_PREFERRED_LOC
> +		 *
> +		 * Supported values for @preferred_mem_loc.devmem_fd:
> +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE: set vram of faulting tile as preferred loc
> +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM: set smem as preferred loc
> +		 *
> +		 * Supported values for @preferred_mem_loc.migration_policy:
> +		 * - DRM_XE_MIGRATE_ALL_PAGES
> +		 * - DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES
> +		 */
> +		struct {
> +#define DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE	0
> +#define DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM	-1
> +			/** @preferred_mem_loc.devmem_fd: fd for preferred loc */
> +			__u32 devmem_fd;
> +
> +#define DRM_XE_MIGRATE_ALL_PAGES		0
> +#define DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES	1
> +			/** @preferred_mem_loc.migration_policy: Page migration policy */
> +			__u32 migration_policy;
> +		} preferred_mem_loc;
> +	};
> +
> +	/** @reserved: Reserved */
> +	__u64 reserved[2];
> +};
> +
>  #if defined(__cplusplus)
>  }
>  #endif

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location
  2025-06-13 12:55 ` [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location Himal Prasad Ghimiray
@ 2025-06-13 23:31   ` kernel test robot
  2025-06-14  5:33   ` kernel test robot
  1 sibling, 0 replies; 68+ messages in thread
From: kernel test robot @ 2025-06-13 23:31 UTC (permalink / raw)
  To: Himal Prasad Ghimiray, intel-xe
  Cc: llvm, oe-kbuild-all, matthew.brost, thomas.hellstrom,
	Himal Prasad Ghimiray

Hi Himal,

kernel test robot noticed the following build warnings:

[auto build test WARNING on drm-xe/drm-xe-next]
[also build test WARNING on next-20250613]
[cannot apply to linus/master v6.16-rc1]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Himal-Prasad-Ghimiray/Introduce-drm_gpuvm_sm_map_ops_flags-enums-for-sm_map_ops/20250614-003138
base:   https://gitlab.freedesktop.org/drm/xe/kernel.git drm-xe-next
patch link:    https://lore.kernel.org/r/20250613125558.2607665-14-himal.prasad.ghimiray%40intel.com
patch subject: [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location
config: s390-allmodconfig (https://download.01.org/0day-ci/archive/20250614/202506140711.9Ogt4vi6-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250614/202506140711.9Ogt4vi6-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506140711.9Ogt4vi6-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/xe/xe_vm_madvise.c:201:3: warning: label followed by a declaration is a C23 extension [-Wc23-extensions]
     201 |                 s32 fd = (s32)args->preferred_mem_loc.devmem_fd;
         |                 ^
   1 warning generated.


vim +201 drivers/gpu/drm/xe/xe_vm_madvise.c

   177	
   178	static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const struct drm_xe_madvise *args)
   179	{
   180		if (XE_IOCTL_DBG(xe, !args))
   181			return -EINVAL;
   182	
   183		if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->start, SZ_4K)))
   184			return -EINVAL;
   185	
   186		if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->range, SZ_4K)))
   187			return -EINVAL;
   188	
   189		if (XE_IOCTL_DBG(xe, args->range < SZ_4K))
   190			return -EINVAL;
   191	
   192		switch (args->type) {
   193		case DRM_XE_VMA_ATTR_ATOMIC:
   194			if (XE_IOCTL_DBG(xe, args->atomic.val > DRM_XE_VMA_ATOMIC_CPU))
   195				return -EINVAL;
   196			break;
   197		case DRM_XE_VMA_ATTR_PAT:
   198			/*TODO: Add valid pat check */
   199			break;
   200		case DRM_XE_VMA_ATTR_PREFERRED_LOC:
 > 201			s32 fd = (s32)args->preferred_mem_loc.devmem_fd;
   202	
   203			if (XE_IOCTL_DBG(xe, fd < DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM))
   204				return -EINVAL;
   205	
   206			if (XE_IOCTL_DBG(xe, args->preferred_mem_loc.migration_policy >
   207					     DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES))
   208				return -EINVAL;
   209			break;
   210		default:
   211			if (XE_IOCTL_DBG(xe, 1))
   212				return -EINVAL;
   213		}
   214	
   215		if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
   216			return -EINVAL;
   217	
   218		return 0;
   219	}
   220	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise
  2025-06-13 12:55 ` [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise Himal Prasad Ghimiray
@ 2025-06-14  4:31   ` kernel test robot
  2025-06-23  5:52   ` Matthew Brost
  1 sibling, 0 replies; 68+ messages in thread
From: kernel test robot @ 2025-06-14  4:31 UTC (permalink / raw)
  To: Himal Prasad Ghimiray, intel-xe
  Cc: oe-kbuild-all, matthew.brost, thomas.hellstrom,
	Himal Prasad Ghimiray

Hi Himal,

kernel test robot noticed the following build warnings:

[auto build test WARNING on drm-xe/drm-xe-next]
[also build test WARNING on next-20250613]
[cannot apply to linus/master v6.16-rc1]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Himal-Prasad-Ghimiray/Introduce-drm_gpuvm_sm_map_ops_flags-enums-for-sm_map_ops/20250614-003138
base:   https://gitlab.freedesktop.org/drm/xe/kernel.git drm-xe-next
patch link:    https://lore.kernel.org/r/20250613125558.2607665-12-himal.prasad.ghimiray%40intel.com
patch subject: [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise
config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20250614/202506141250.wwQhe2P0-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250614/202506141250.wwQhe2P0-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506141250.wwQhe2P0-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> Warning: drivers/gpu/drm/xe/xe_svm.c:945 function parameter 'vm' not described in 'xe_svm_unmap_address_range'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location
  2025-06-13 12:55 ` [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location Himal Prasad Ghimiray
  2025-06-13 23:31   ` kernel test robot
@ 2025-06-14  5:33   ` kernel test robot
  1 sibling, 0 replies; 68+ messages in thread
From: kernel test robot @ 2025-06-14  5:33 UTC (permalink / raw)
  To: Himal Prasad Ghimiray, intel-xe
  Cc: llvm, oe-kbuild-all, matthew.brost, thomas.hellstrom,
	Himal Prasad Ghimiray

Hi Himal,

kernel test robot noticed the following build errors:

[auto build test ERROR on drm-xe/drm-xe-next]
[also build test ERROR on next-20250613]
[cannot apply to linus/master v6.16-rc1]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Himal-Prasad-Ghimiray/Introduce-drm_gpuvm_sm_map_ops_flags-enums-for-sm_map_ops/20250614-003138
base:   https://gitlab.freedesktop.org/drm/xe/kernel.git drm-xe-next
patch link:    https://lore.kernel.org/r/20250613125558.2607665-14-himal.prasad.ghimiray%40intel.com
patch subject: [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location
config: i386-randconfig-016-20250614 (https://download.01.org/0day-ci/archive/20250614/202506141309.LKujADbP-lkp@intel.com/config)
compiler: clang version 20.1.2 (https://github.com/llvm/llvm-project 58df0ef89dd64126512e4ee27b4ac3fd8ddf6247)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250614/202506141309.LKujADbP-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506141309.LKujADbP-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/xe/xe_vm_madvise.c:201:3: error: label followed by a declaration is a C23 extension [-Werror,-Wc23-extensions]
     201 |                 s32 fd = (s32)args->preferred_mem_loc.devmem_fd;
         |                 ^
   1 error generated.


vim +201 drivers/gpu/drm/xe/xe_vm_madvise.c

   177	
   178	static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const struct drm_xe_madvise *args)
   179	{
   180		if (XE_IOCTL_DBG(xe, !args))
   181			return -EINVAL;
   182	
   183		if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->start, SZ_4K)))
   184			return -EINVAL;
   185	
   186		if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->range, SZ_4K)))
   187			return -EINVAL;
   188	
   189		if (XE_IOCTL_DBG(xe, args->range < SZ_4K))
   190			return -EINVAL;
   191	
   192		switch (args->type) {
   193		case DRM_XE_VMA_ATTR_ATOMIC:
   194			if (XE_IOCTL_DBG(xe, args->atomic.val > DRM_XE_VMA_ATOMIC_CPU))
   195				return -EINVAL;
   196			break;
   197		case DRM_XE_VMA_ATTR_PAT:
   198			/*TODO: Add valid pat check */
   199			break;
   200		case DRM_XE_VMA_ATTR_PREFERRED_LOC:
 > 201			s32 fd = (s32)args->preferred_mem_loc.devmem_fd;
   202	
   203			if (XE_IOCTL_DBG(xe, fd < DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM))
   204				return -EINVAL;
   205	
   206			if (XE_IOCTL_DBG(xe, args->preferred_mem_loc.migration_policy >
   207					     DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES))
   208				return -EINVAL;
   209			break;
   210		default:
   211			if (XE_IOCTL_DBG(xe, 1))
   212				return -EINVAL;
   213		}
   214	
   215		if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
   216			return -EINVAL;
   217	
   218		return 0;
   219	}
   220	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 68+ messages in thread

* ✗ CI.checkpatch: warning for MADVISE FOR XE (rev3)
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (21 preceding siblings ...)
  2025-06-13 12:55 ` [PATCH v4 20/20] drm/xe/madvise: Skip vma invalidation if mem attr are unchanged Himal Prasad Ghimiray
@ 2025-06-16  4:30 ` Patchwork
  2025-06-16  4:31 ` ✓ CI.KUnit: success " Patchwork
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Patchwork @ 2025-06-16  4:30 UTC (permalink / raw)
  To: Ghimiray, Himal Prasad; +Cc: intel-xe

== Series Details ==

Series: MADVISE FOR XE (rev3)
URL   : https://patchwork.freedesktop.org/series/149550/
State : warning

== Summary ==

+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master
f8ff75ae1d2127635239b134695774ed4045d05b
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit d11b1cb6b2c43207511eb2af864afc4444df0a93
Author: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Date:   Fri Jun 13 18:25:58 2025 +0530

    drm/xe/madvise: Skip vma invalidation if mem attr are unchanged
    
    If a VMA within the madvise input range already has the same memory
    attribute as the one requested by the user, skip PTE zapping for that
    VMA to avoid unnecessary invalidation.
    
    Suggested-by: Matthew Brost <matthew.brost@intel.com>
    Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
+ /mt/dim checkpatch 707bd88d5b799c00ff5be9634b2f4e4ece79d889 drm-intel
69acd4df69ec Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops
7ca49bfe336e drm/xe/uapi: Add madvise interface
-:48: WARNING:LONG_LINE: line length of 113 exceeds 100 columns
#48: FILE: include/uapi/drm/xe_drm.h:122:
+#define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)

total: 0 errors, 1 warnings, 0 checks, 142 lines checked
4ab8907f7f8b drm/xe/vm: Add attributes struct as member of vma
ebbdc97cf1b7 drm/xe/vma: Move pat_index to vma attributes
44aa69597e5e drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter
f8006675ae3d drm/gpusvm: Make drm_gpusvm_for_each_* macros public
-:225: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'range__' - possible side-effects?
#225: FILE: include/drm/drm_gpusvm.h:548:
+#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
+	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_range_next(range__);				\
+	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
+	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))

-:225: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'next__' - possible side-effects?
#225: FILE: include/drm/drm_gpusvm.h:548:
+#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
+	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_range_next(range__);				\
+	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
+	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))

-:225: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'end__' - possible side-effects?
#225: FILE: include/drm/drm_gpusvm.h:548:
+#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
+	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_range_next(range__);				\
+	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
+	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))

-:258: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'notifier__' - possible side-effects?
#258: FILE: include/drm/drm_gpusvm.h:581:
+#define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__)		\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__));	\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = __drm_gpusvm_notifier_next(notifier__))

-:258: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'end__' - possible side-effects?
#258: FILE: include/drm/drm_gpusvm.h:581:
+#define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__)		\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__));	\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = __drm_gpusvm_notifier_next(notifier__))

-:274: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'notifier__' - possible side-effects?
#274: FILE: include/drm/drm_gpusvm.h:597:
+#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))

-:274: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'next__' - possible side-effects?
#274: FILE: include/drm/drm_gpusvm.h:597:
+#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))

-:274: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'end__' - possible side-effects?
#274: FILE: include/drm/drm_gpusvm.h:597:
+#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
+	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)),	\
+	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
+	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
+	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))

total: 0 errors, 0 warnings, 8 checks, 248 lines checked
544ffccf9ed1 drm/xe/svm: Split system allocator vma incase of madvise call
2af6b18578f4 drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping
2040359a95db drm/xe: Implement madvise ioctl for xe
-:62: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#62: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 318 lines checked
e239c38c2bd9 drm/xe/vm: Add an identifier for madvise in xe_vma_ops
c0b09c69ae5d drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise
15ae01892e22 drm/xe/svm : Add svm ranges migration policy on atomic access
42e1acd71be9 drm/xe/madvise: Update migration policy based on preferred location
04655902e967 drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute
d3503ab692cb drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch
2ffd7a98f0e5 drm/xe/svm: Consult madvise preferred location in prefetch
3863896574dc drm/xe/bo: Add attributes field to xe_bo
66a21aef1437 drm/xe/bo: Update atomic_access attribute on madvise
fe19a3443b62 drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
-:75: WARNING:LONG_LINE: line length of 103 exceeds 100 columns
#75: FILE: drivers/gpu/drm/xe/xe_vm.c:2202:
+		attrs[i].preferred_mem_loc.migration_policy = vma->attr.preferred_loc.migration_policy;

-:176: WARNING:LONG_LINE: line length of 137 exceeds 100 columns
#176: FILE: include/uapi/drm/xe_drm.h:125:
+#define DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_VMAS_ATTRS, struct drm_xe_vm_query_vmas_attr)

total: 0 errors, 2 warnings, 0 checks, 264 lines checked
d11b1cb6b2c4 drm/xe/madvise: Skip vma invalidation if mem attr are unchanged



^ permalink raw reply	[flat|nested] 68+ messages in thread

* ✓ CI.KUnit: success for MADVISE FOR XE (rev3)
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (22 preceding siblings ...)
  2025-06-16  4:30 ` ✗ CI.checkpatch: warning for MADVISE FOR XE (rev3) Patchwork
@ 2025-06-16  4:31 ` Patchwork
  2025-06-16  4:45 ` ✗ CI.checksparse: warning " Patchwork
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Patchwork @ 2025-06-16  4:31 UTC (permalink / raw)
  To: Ghimiray, Himal Prasad; +Cc: intel-xe

== Series Details ==

Series: MADVISE FOR XE (rev3)
URL   : https://patchwork.freedesktop.org/series/149550/
State : success

== Summary ==

+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
[04:30:13] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[04:30:17] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[04:30:44] Starting KUnit Kernel (1/1)...
[04:30:44] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[04:30:44] ================== guc_buf (11 subtests) ===================
[04:30:44] [PASSED] test_smallest
[04:30:44] [PASSED] test_largest
[04:30:44] [PASSED] test_granular
[04:30:44] [PASSED] test_unique
[04:30:44] [PASSED] test_overlap
[04:30:44] [PASSED] test_reusable
[04:30:44] [PASSED] test_too_big
[04:30:44] [PASSED] test_flush
[04:30:44] [PASSED] test_lookup
[04:30:44] [PASSED] test_data
[04:30:44] [PASSED] test_class
[04:30:44] ===================== [PASSED] guc_buf =====================
[04:30:44] =================== guc_dbm (7 subtests) ===================
[04:30:44] [PASSED] test_empty
[04:30:44] [PASSED] test_default
[04:30:44] ======================== test_size  ========================
[04:30:44] [PASSED] 4
[04:30:44] [PASSED] 8
[04:30:44] [PASSED] 32
[04:30:44] [PASSED] 256
[04:30:44] ==================== [PASSED] test_size ====================
[04:30:44] ======================= test_reuse  ========================
[04:30:44] [PASSED] 4
[04:30:44] [PASSED] 8
[04:30:44] [PASSED] 32
[04:30:44] [PASSED] 256
[04:30:44] =================== [PASSED] test_reuse ====================
[04:30:44] =================== test_range_overlap  ====================
[04:30:44] [PASSED] 4
[04:30:44] [PASSED] 8
[04:30:44] [PASSED] 32
[04:30:44] [PASSED] 256
[04:30:44] =============== [PASSED] test_range_overlap ================
[04:30:44] =================== test_range_compact  ====================
[04:30:44] [PASSED] 4
[04:30:44] [PASSED] 8
[04:30:44] [PASSED] 32
[04:30:44] [PASSED] 256
[04:30:44] =============== [PASSED] test_range_compact ================
[04:30:44] ==================== test_range_spare  =====================
[04:30:44] [PASSED] 4
[04:30:44] [PASSED] 8
[04:30:44] [PASSED] 32
[04:30:44] [PASSED] 256
[04:30:44] ================ [PASSED] test_range_spare =================
[04:30:44] ===================== [PASSED] guc_dbm =====================
[04:30:44] =================== guc_idm (6 subtests) ===================
[04:30:44] [PASSED] bad_init
[04:30:44] [PASSED] no_init
[04:30:44] [PASSED] init_fini
[04:30:44] [PASSED] check_used
[04:30:44] [PASSED] check_quota
[04:30:44] [PASSED] check_all
[04:30:44] ===================== [PASSED] guc_idm =====================
[04:30:44] ================== no_relay (3 subtests) ===================
[04:30:44] [PASSED] xe_drops_guc2pf_if_not_ready
[04:30:44] [PASSED] xe_drops_guc2vf_if_not_ready
[04:30:44] [PASSED] xe_rejects_send_if_not_ready
[04:30:45] ==================== [PASSED] no_relay =====================
[04:30:45] ================== pf_relay (14 subtests) ==================
[04:30:45] [PASSED] pf_rejects_guc2pf_too_short
[04:30:45] [PASSED] pf_rejects_guc2pf_too_long
[04:30:45] [PASSED] pf_rejects_guc2pf_no_payload
[04:30:45] [PASSED] pf_fails_no_payload
[04:30:45] [PASSED] pf_fails_bad_origin
[04:30:45] [PASSED] pf_fails_bad_type
[04:30:45] [PASSED] pf_txn_reports_error
[04:30:45] [PASSED] pf_txn_sends_pf2guc
[04:30:45] [PASSED] pf_sends_pf2guc
[04:30:45] [SKIPPED] pf_loopback_nop
[04:30:45] [SKIPPED] pf_loopback_echo
[04:30:45] [SKIPPED] pf_loopback_fail
[04:30:45] [SKIPPED] pf_loopback_busy
[04:30:45] [SKIPPED] pf_loopback_retry
[04:30:45] ==================== [PASSED] pf_relay =====================
[04:30:45] ================== vf_relay (3 subtests) ===================
[04:30:45] [PASSED] vf_rejects_guc2vf_too_short
[04:30:45] [PASSED] vf_rejects_guc2vf_too_long
[04:30:45] [PASSED] vf_rejects_guc2vf_no_payload
[04:30:45] ==================== [PASSED] vf_relay =====================
[04:30:45] ================= pf_service (11 subtests) =================
[04:30:45] [PASSED] pf_negotiate_any
[04:30:45] [PASSED] pf_negotiate_base_match
[04:30:45] [PASSED] pf_negotiate_base_newer
[04:30:45] [PASSED] pf_negotiate_base_next
[04:30:45] [SKIPPED] pf_negotiate_base_older
[04:30:45] [PASSED] pf_negotiate_base_prev
[04:30:45] [PASSED] pf_negotiate_latest_match
[04:30:45] [PASSED] pf_negotiate_latest_newer
[04:30:45] [PASSED] pf_negotiate_latest_next
[04:30:45] [SKIPPED] pf_negotiate_latest_older
[04:30:45] [SKIPPED] pf_negotiate_latest_prev
[04:30:45] =================== [PASSED] pf_service ====================
[04:30:45] ===================== lmtt (1 subtest) =====================
[04:30:45] ======================== test_ops  =========================
[04:30:45] [PASSED] 2-level
[04:30:45] [PASSED] multi-level
[04:30:45] ==================== [PASSED] test_ops =====================
[04:30:45] ====================== [PASSED] lmtt =======================
[04:30:45] =================== xe_mocs (2 subtests) ===================
[04:30:45] ================ xe_live_mocs_kernel_kunit  ================
[04:30:45] =========== [SKIPPED] xe_live_mocs_kernel_kunit ============
[04:30:45] ================ xe_live_mocs_reset_kunit  =================
[04:30:45] ============ [SKIPPED] xe_live_mocs_reset_kunit ============
[04:30:45] ==================== [SKIPPED] xe_mocs =====================
[04:30:45] ================= xe_migrate (2 subtests) ==================
[04:30:45] ================= xe_migrate_sanity_kunit  =================
[04:30:45] ============ [SKIPPED] xe_migrate_sanity_kunit =============
[04:30:45] ================== xe_validate_ccs_kunit  ==================
[04:30:45] ============= [SKIPPED] xe_validate_ccs_kunit ==============
[04:30:45] =================== [SKIPPED] xe_migrate ===================
[04:30:45] ================== xe_dma_buf (1 subtest) ==================
[04:30:45] ==================== xe_dma_buf_kunit  =====================
[04:30:45] ================ [SKIPPED] xe_dma_buf_kunit ================
[04:30:45] =================== [SKIPPED] xe_dma_buf ===================
[04:30:45] ================= xe_bo_shrink (1 subtest) =================
[04:30:45] =================== xe_bo_shrink_kunit  ====================
[04:30:45] =============== [SKIPPED] xe_bo_shrink_kunit ===============
[04:30:45] ================== [SKIPPED] xe_bo_shrink ==================
[04:30:45] ==================== xe_bo (2 subtests) ====================
[04:30:45] ================== xe_ccs_migrate_kunit  ===================
[04:30:45] ============== [SKIPPED] xe_ccs_migrate_kunit ==============
[04:30:45] ==================== xe_bo_evict_kunit  ====================
[04:30:45] =============== [SKIPPED] xe_bo_evict_kunit ================
[04:30:45] ===================== [SKIPPED] xe_bo ======================
[04:30:45] ==================== args (11 subtests) ====================
[04:30:45] [PASSED] count_args_test
[04:30:45] [PASSED] call_args_example
[04:30:45] [PASSED] call_args_test
[04:30:45] [PASSED] drop_first_arg_example
[04:30:45] [PASSED] drop_first_arg_test
[04:30:45] [PASSED] first_arg_example
[04:30:45] [PASSED] first_arg_test
[04:30:45] [PASSED] last_arg_example
[04:30:45] [PASSED] last_arg_test
[04:30:45] [PASSED] pick_arg_example
[04:30:45] [PASSED] sep_comma_example
[04:30:45] ====================== [PASSED] args =======================
[04:30:45] =================== xe_pci (2 subtests) ====================
[04:30:45] [PASSED] xe_gmdid_graphics_ip
[04:30:45] [PASSED] xe_gmdid_media_ip
[04:30:45] ===================== [PASSED] xe_pci ======================
[04:30:45] =================== xe_rtp (2 subtests) ====================
[04:30:45] =============== xe_rtp_process_to_sr_tests  ================
[04:30:45] [PASSED] coalesce-same-reg
[04:30:45] [PASSED] no-match-no-add
[04:30:45] [PASSED] match-or
[04:30:45] [PASSED] match-or-xfail
[04:30:45] [PASSED] no-match-no-add-multiple-rules
[04:30:45] [PASSED] two-regs-two-entries
[04:30:45] [PASSED] clr-one-set-other
[04:30:45] [PASSED] set-field
[04:30:45] [PASSED] conflict-duplicate
[04:30:45] [PASSED] conflict-not-disjoint
stty: 'standard input': Inappropriate ioctl for device
[04:30:45] [PASSED] conflict-reg-type
[04:30:45] =========== [PASSED] xe_rtp_process_to_sr_tests ============
[04:30:45] ================== xe_rtp_process_tests  ===================
[04:30:45] [PASSED] active1
[04:30:45] [PASSED] active2
[04:30:45] [PASSED] active-inactive
[04:30:45] [PASSED] inactive-active
[04:30:45] [PASSED] inactive-1st_or_active-inactive
[04:30:45] [PASSED] inactive-2nd_or_active-inactive
[04:30:45] [PASSED] inactive-last_or_active-inactive
[04:30:45] [PASSED] inactive-no_or_active-inactive
[04:30:45] ============== [PASSED] xe_rtp_process_tests ===============
[04:30:45] ===================== [PASSED] xe_rtp ======================
[04:30:45] ==================== xe_wa (1 subtest) =====================
[04:30:45] ======================== xe_wa_gt  =========================
[04:30:45] [PASSED] TIGERLAKE (B0)
[04:30:45] [PASSED] DG1 (A0)
[04:30:45] [PASSED] DG1 (B0)
[04:30:45] [PASSED] ALDERLAKE_S (A0)
[04:30:45] [PASSED] ALDERLAKE_S (B0)
[04:30:45] [PASSED] ALDERLAKE_S (C0)
[04:30:45] [PASSED] ALDERLAKE_S (D0)
[04:30:45] [PASSED] ALDERLAKE_P (A0)
[04:30:45] [PASSED] ALDERLAKE_P (B0)
[04:30:45] [PASSED] ALDERLAKE_P (C0)
[04:30:45] [PASSED] ALDERLAKE_S_RPLS (D0)
[04:30:45] [PASSED] ALDERLAKE_P_RPLU (E0)
[04:30:45] [PASSED] DG2_G10 (C0)
[04:30:45] [PASSED] DG2_G11 (B1)
[04:30:45] [PASSED] DG2_G12 (A1)
[04:30:45] [PASSED] METEORLAKE (g:A0, m:A0)
[04:30:45] [PASSED] METEORLAKE (g:A0, m:A0)
[04:30:45] [PASSED] METEORLAKE (g:A0, m:A0)
[04:30:45] [PASSED] LUNARLAKE (g:A0, m:A0)
[04:30:45] [PASSED] LUNARLAKE (g:B0, m:A0)
[04:30:45] [PASSED] BATTLEMAGE (g:A0, m:A1)
[04:30:45] ==================== [PASSED] xe_wa_gt =====================
[04:30:45] ====================== [PASSED] xe_wa ======================
[04:30:45] ============================================================
[04:30:45] Testing complete. Ran 133 tests: passed: 117, skipped: 16
[04:30:45] Elapsed time: 31.593s total, 4.147s configuring, 27.129s building, 0.292s running

+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/tests/.kunitconfig
[04:30:45] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[04:30:46] 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
[04:31:08] Starting KUnit Kernel (1/1)...
[04:31:08] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[04:31:08] == drm_test_atomic_get_connector_for_encoder (1 subtest) ===
[04:31:08] [PASSED] drm_test_drm_atomic_get_connector_for_encoder
[04:31:08] ==== [PASSED] drm_test_atomic_get_connector_for_encoder ====
[04:31:08] =========== drm_validate_clone_mode (2 subtests) ===========
[04:31:08] ============== drm_test_check_in_clone_mode  ===============
[04:31:08] [PASSED] in_clone_mode
[04:31:08] [PASSED] not_in_clone_mode
[04:31:08] ========== [PASSED] drm_test_check_in_clone_mode ===========
[04:31:08] =============== drm_test_check_valid_clones  ===============
[04:31:08] [PASSED] not_in_clone_mode
[04:31:08] [PASSED] valid_clone
[04:31:08] [PASSED] invalid_clone
[04:31:08] =========== [PASSED] drm_test_check_valid_clones ===========
[04:31:08] ============= [PASSED] drm_validate_clone_mode =============
[04:31:08] ============= drm_validate_modeset (1 subtest) =============
[04:31:08] [PASSED] drm_test_check_connector_changed_modeset
[04:31:08] ============== [PASSED] drm_validate_modeset ===============
[04:31:08] ====== drm_test_bridge_get_current_state (2 subtests) ======
[04:31:08] [PASSED] drm_test_drm_bridge_get_current_state_atomic
[04:31:08] [PASSED] drm_test_drm_bridge_get_current_state_legacy
[04:31:08] ======== [PASSED] drm_test_bridge_get_current_state ========
[04:31:08] ====== drm_test_bridge_helper_reset_crtc (3 subtests) ======
[04:31:08] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic
[04:31:08] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic_disabled
[04:31:08] [PASSED] drm_test_drm_bridge_helper_reset_crtc_legacy
[04:31:08] ======== [PASSED] drm_test_bridge_helper_reset_crtc ========
[04:31:08] ============== drm_bridge_alloc (2 subtests) ===============
[04:31:08] [PASSED] drm_test_drm_bridge_alloc_basic
[04:31:08] [PASSED] drm_test_drm_bridge_alloc_get_put
[04:31:08] ================ [PASSED] drm_bridge_alloc =================
[04:31:08] ================== drm_buddy (7 subtests) ==================
[04:31:08] [PASSED] drm_test_buddy_alloc_limit
[04:31:08] [PASSED] drm_test_buddy_alloc_optimistic
[04:31:08] [PASSED] drm_test_buddy_alloc_pessimistic
[04:31:08] [PASSED] drm_test_buddy_alloc_pathological
[04:31:08] [PASSED] drm_test_buddy_alloc_contiguous
[04:31:08] [PASSED] drm_test_buddy_alloc_clear
[04:31:08] [PASSED] drm_test_buddy_alloc_range_bias
[04:31:08] ==================== [PASSED] drm_buddy ====================
[04:31:08] ============= drm_cmdline_parser (40 subtests) =============
[04:31:08] [PASSED] drm_test_cmdline_force_d_only
[04:31:08] [PASSED] drm_test_cmdline_force_D_only_dvi
[04:31:08] [PASSED] drm_test_cmdline_force_D_only_hdmi
[04:31:08] [PASSED] drm_test_cmdline_force_D_only_not_digital
[04:31:08] [PASSED] drm_test_cmdline_force_e_only
[04:31:08] [PASSED] drm_test_cmdline_res
[04:31:08] [PASSED] drm_test_cmdline_res_vesa
[04:31:08] [PASSED] drm_test_cmdline_res_vesa_rblank
[04:31:08] [PASSED] drm_test_cmdline_res_rblank
[04:31:08] [PASSED] drm_test_cmdline_res_bpp
[04:31:08] [PASSED] drm_test_cmdline_res_refresh
[04:31:08] [PASSED] drm_test_cmdline_res_bpp_refresh
[04:31:08] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced
[04:31:08] [PASSED] drm_test_cmdline_res_bpp_refresh_margins
[04:31:08] [PASSED] drm_test_cmdline_res_bpp_refresh_force_off
[04:31:08] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on
[04:31:08] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_analog
[04:31:08] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_digital
[04:31:08] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on
[04:31:08] [PASSED] drm_test_cmdline_res_margins_force_on
[04:31:08] [PASSED] drm_test_cmdline_res_vesa_margins
[04:31:08] [PASSED] drm_test_cmdline_name
[04:31:08] [PASSED] drm_test_cmdline_name_bpp
[04:31:08] [PASSED] drm_test_cmdline_name_option
[04:31:08] [PASSED] drm_test_cmdline_name_bpp_option
[04:31:08] [PASSED] drm_test_cmdline_rotate_0
[04:31:08] [PASSED] drm_test_cmdline_rotate_90
[04:31:08] [PASSED] drm_test_cmdline_rotate_180
[04:31:08] [PASSED] drm_test_cmdline_rotate_270
[04:31:08] [PASSED] drm_test_cmdline_hmirror
[04:31:08] [PASSED] drm_test_cmdline_vmirror
[04:31:08] [PASSED] drm_test_cmdline_margin_options
[04:31:08] [PASSED] drm_test_cmdline_multiple_options
[04:31:08] [PASSED] drm_test_cmdline_bpp_extra_and_option
[04:31:08] [PASSED] drm_test_cmdline_extra_and_option
[04:31:08] [PASSED] drm_test_cmdline_freestanding_options
[04:31:08] [PASSED] drm_test_cmdline_freestanding_force_e_and_options
[04:31:08] [PASSED] drm_test_cmdline_panel_orientation
[04:31:08] ================ drm_test_cmdline_invalid  =================
[04:31:08] [PASSED] margin_only
[04:31:08] [PASSED] interlace_only
[04:31:08] [PASSED] res_missing_x
[04:31:08] [PASSED] res_missing_y
[04:31:08] [PASSED] res_bad_y
[04:31:08] [PASSED] res_missing_y_bpp
[04:31:08] [PASSED] res_bad_bpp
[04:31:08] [PASSED] res_bad_refresh
[04:31:08] [PASSED] res_bpp_refresh_force_on_off
[04:31:08] [PASSED] res_invalid_mode
[04:31:08] [PASSED] res_bpp_wrong_place_mode
[04:31:08] [PASSED] name_bpp_refresh
[04:31:08] [PASSED] name_refresh
[04:31:08] [PASSED] name_refresh_wrong_mode
[04:31:08] [PASSED] name_refresh_invalid_mode
[04:31:08] [PASSED] rotate_multiple
[04:31:08] [PASSED] rotate_invalid_val
[04:31:08] [PASSED] rotate_truncated
[04:31:08] [PASSED] invalid_option
[04:31:08] [PASSED] invalid_tv_option
[04:31:08] [PASSED] truncated_tv_option
[04:31:08] ============ [PASSED] drm_test_cmdline_invalid =============
[04:31:08] =============== drm_test_cmdline_tv_options  ===============
[04:31:08] [PASSED] NTSC
[04:31:08] [PASSED] NTSC_443
[04:31:08] [PASSED] NTSC_J
[04:31:08] [PASSED] PAL
[04:31:08] [PASSED] PAL_M
[04:31:08] [PASSED] PAL_N
[04:31:08] [PASSED] SECAM
[04:31:08] [PASSED] MONO_525
[04:31:08] [PASSED] MONO_625
[04:31:08] =========== [PASSED] drm_test_cmdline_tv_options ===========
[04:31:08] =============== [PASSED] drm_cmdline_parser ================
[04:31:08] ========== drmm_connector_hdmi_init (20 subtests) ==========
[04:31:08] [PASSED] drm_test_connector_hdmi_init_valid
[04:31:08] [PASSED] drm_test_connector_hdmi_init_bpc_8
[04:31:08] [PASSED] drm_test_connector_hdmi_init_bpc_10
[04:31:08] [PASSED] drm_test_connector_hdmi_init_bpc_12
[04:31:08] [PASSED] drm_test_connector_hdmi_init_bpc_invalid
[04:31:08] [PASSED] drm_test_connector_hdmi_init_bpc_null
[04:31:08] [PASSED] drm_test_connector_hdmi_init_formats_empty
[04:31:08] [PASSED] drm_test_connector_hdmi_init_formats_no_rgb
[04:31:08] === drm_test_connector_hdmi_init_formats_yuv420_allowed  ===
[04:31:08] [PASSED] supported_formats=0x9 yuv420_allowed=1
[04:31:08] [PASSED] supported_formats=0x9 yuv420_allowed=0
[04:31:08] [PASSED] supported_formats=0x3 yuv420_allowed=1
[04:31:08] [PASSED] supported_formats=0x3 yuv420_allowed=0
[04:31:08] === [PASSED] drm_test_connector_hdmi_init_formats_yuv420_allowed ===
[04:31:08] [PASSED] drm_test_connector_hdmi_init_null_ddc
[04:31:08] [PASSED] drm_test_connector_hdmi_init_null_product
[04:31:08] [PASSED] drm_test_connector_hdmi_init_null_vendor
[04:31:08] [PASSED] drm_test_connector_hdmi_init_product_length_exact
[04:31:08] [PASSED] drm_test_connector_hdmi_init_product_length_too_long
[04:31:08] [PASSED] drm_test_connector_hdmi_init_product_valid
[04:31:08] [PASSED] drm_test_connector_hdmi_init_vendor_length_exact
[04:31:08] [PASSED] drm_test_connector_hdmi_init_vendor_length_too_long
[04:31:08] [PASSED] drm_test_connector_hdmi_init_vendor_valid
[04:31:08] ========= drm_test_connector_hdmi_init_type_valid  =========
[04:31:08] [PASSED] HDMI-A
[04:31:08] [PASSED] HDMI-B
[04:31:08] ===== [PASSED] drm_test_connector_hdmi_init_type_valid =====
[04:31:08] ======== drm_test_connector_hdmi_init_type_invalid  ========
[04:31:08] [PASSED] Unknown
[04:31:08] [PASSED] VGA
[04:31:08] [PASSED] DVI-I
[04:31:08] [PASSED] DVI-D
[04:31:08] [PASSED] DVI-A
[04:31:08] [PASSED] Composite
[04:31:08] [PASSED] SVIDEO
[04:31:08] [PASSED] LVDS
[04:31:08] [PASSED] Component
[04:31:08] [PASSED] DIN
[04:31:08] [PASSED] DP
[04:31:08] [PASSED] TV
[04:31:08] [PASSED] eDP
[04:31:08] [PASSED] Virtual
[04:31:08] [PASSED] DSI
[04:31:08] [PASSED] DPI
[04:31:08] [PASSED] Writeback
[04:31:08] [PASSED] SPI
[04:31:08] [PASSED] USB
[04:31:08] ==== [PASSED] drm_test_connector_hdmi_init_type_invalid ====
[04:31:08] ============ [PASSED] drmm_connector_hdmi_init =============
[04:31:08] ============= drmm_connector_init (3 subtests) =============
[04:31:08] [PASSED] drm_test_drmm_connector_init
[04:31:08] [PASSED] drm_test_drmm_connector_init_null_ddc
[04:31:08] ========= drm_test_drmm_connector_init_type_valid  =========
[04:31:08] [PASSED] Unknown
[04:31:08] [PASSED] VGA
[04:31:08] [PASSED] DVI-I
[04:31:08] [PASSED] DVI-D
[04:31:08] [PASSED] DVI-A
[04:31:08] [PASSED] Composite
[04:31:08] [PASSED] SVIDEO
[04:31:08] [PASSED] LVDS
[04:31:08] [PASSED] Component
[04:31:08] [PASSED] DIN
[04:31:08] [PASSED] DP
[04:31:08] [PASSED] HDMI-A
[04:31:08] [PASSED] HDMI-B
[04:31:08] [PASSED] TV
[04:31:08] [PASSED] eDP
[04:31:08] [PASSED] Virtual
[04:31:08] [PASSED] DSI
[04:31:08] [PASSED] DPI
[04:31:08] [PASSED] Writeback
[04:31:08] [PASSED] SPI
[04:31:08] [PASSED] USB
[04:31:08] ===== [PASSED] drm_test_drmm_connector_init_type_valid =====
[04:31:08] =============== [PASSED] drmm_connector_init ===============
[04:31:08] ========= drm_connector_dynamic_init (6 subtests) ==========
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_init
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_init_null_ddc
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_init_not_added
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_init_properties
[04:31:08] ===== drm_test_drm_connector_dynamic_init_type_valid  ======
[04:31:08] [PASSED] Unknown
[04:31:08] [PASSED] VGA
[04:31:08] [PASSED] DVI-I
[04:31:08] [PASSED] DVI-D
[04:31:08] [PASSED] DVI-A
[04:31:08] [PASSED] Composite
[04:31:08] [PASSED] SVIDEO
[04:31:08] [PASSED] LVDS
[04:31:08] [PASSED] Component
[04:31:08] [PASSED] DIN
[04:31:08] [PASSED] DP
[04:31:08] [PASSED] HDMI-A
[04:31:08] [PASSED] HDMI-B
[04:31:08] [PASSED] TV
[04:31:08] [PASSED] eDP
[04:31:08] [PASSED] Virtual
[04:31:08] [PASSED] DSI
[04:31:08] [PASSED] DPI
[04:31:08] [PASSED] Writeback
[04:31:08] [PASSED] SPI
[04:31:08] [PASSED] USB
[04:31:08] = [PASSED] drm_test_drm_connector_dynamic_init_type_valid ==
[04:31:08] ======== drm_test_drm_connector_dynamic_init_name  =========
[04:31:08] [PASSED] Unknown
[04:31:08] [PASSED] VGA
[04:31:08] [PASSED] DVI-I
[04:31:08] [PASSED] DVI-D
[04:31:08] [PASSED] DVI-A
[04:31:08] [PASSED] Composite
[04:31:08] [PASSED] SVIDEO
[04:31:08] [PASSED] LVDS
[04:31:08] [PASSED] Component
[04:31:08] [PASSED] DIN
[04:31:08] [PASSED] DP
[04:31:08] [PASSED] HDMI-A
[04:31:08] [PASSED] HDMI-B
[04:31:08] [PASSED] TV
[04:31:08] [PASSED] eDP
[04:31:08] [PASSED] Virtual
[04:31:08] [PASSED] DSI
[04:31:08] [PASSED] DPI
[04:31:08] [PASSED] Writeback
[04:31:08] [PASSED] SPI
[04:31:08] [PASSED] USB
[04:31:08] ==== [PASSED] drm_test_drm_connector_dynamic_init_name =====
[04:31:08] =========== [PASSED] drm_connector_dynamic_init ============
[04:31:08] ==== drm_connector_dynamic_register_early (4 subtests) =====
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_early_on_list
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_early_defer
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_early_no_init
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_early_no_mode_object
[04:31:08] ====== [PASSED] drm_connector_dynamic_register_early =======
[04:31:08] ======= drm_connector_dynamic_register (7 subtests) ========
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_on_list
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_no_defer
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_no_init
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_mode_object
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_sysfs
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_sysfs_name
[04:31:08] [PASSED] drm_test_drm_connector_dynamic_register_debugfs
[04:31:08] ========= [PASSED] drm_connector_dynamic_register ==========
[04:31:08] = drm_connector_attach_broadcast_rgb_property (2 subtests) =
[04:31:08] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property
[04:31:08] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector
[04:31:08] === [PASSED] drm_connector_attach_broadcast_rgb_property ===
[04:31:08] ========== drm_get_tv_mode_from_name (2 subtests) ==========
[04:31:08] ========== drm_test_get_tv_mode_from_name_valid  ===========
[04:31:08] [PASSED] NTSC
[04:31:08] [PASSED] NTSC-443
[04:31:08] [PASSED] NTSC-J
[04:31:08] [PASSED] PAL
[04:31:08] [PASSED] PAL-M
[04:31:08] [PASSED] PAL-N
[04:31:08] [PASSED] SECAM
[04:31:08] [PASSED] Mono
[04:31:08] ====== [PASSED] drm_test_get_tv_mode_from_name_valid =======
[04:31:08] [PASSED] drm_test_get_tv_mode_from_name_truncated
[04:31:08] ============ [PASSED] drm_get_tv_mode_from_name ============
[04:31:08] = drm_test_connector_hdmi_compute_mode_clock (12 subtests) =
[04:31:08] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb
[04:31:08] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc
[04:31:08] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1
[04:31:08] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc
[04:31:08] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1
[04:31:08] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_double
[04:31:08] = drm_test_connector_hdmi_compute_mode_clock_yuv420_valid  =
[04:31:08] [PASSED] VIC 96
[04:31:08] [PASSED] VIC 97
[04:31:08] [PASSED] VIC 101
[04:31:08] [PASSED] VIC 102
[04:31:08] [PASSED] VIC 106
[04:31:08] [PASSED] VIC 107
[04:31:08] === [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_valid ===
[04:31:08] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc
[04:31:08] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc
[04:31:08] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc
[04:31:08] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc
[04:31:08] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc
[04:31:08] === [PASSED] drm_test_connector_hdmi_compute_mode_clock ====
[04:31:08] == drm_hdmi_connector_get_broadcast_rgb_name (2 subtests) ==
[04:31:08] === drm_test_drm_hdmi_connector_get_broadcast_rgb_name  ====
[04:31:08] [PASSED] Automatic
[04:31:08] [PASSED] Full
[04:31:08] [PASSED] Limited 16:235
[04:31:08] === [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name ===
[04:31:08] [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid
[04:31:08] ==== [PASSED] drm_hdmi_connector_get_broadcast_rgb_name ====
[04:31:08] == drm_hdmi_connector_get_output_format_name (2 subtests) ==
[04:31:08] === drm_test_drm_hdmi_connector_get_output_format_name  ====
[04:31:08] [PASSED] RGB
[04:31:08] [PASSED] YUV 4:2:0
[04:31:08] [PASSED] YUV 4:2:2
[04:31:08] [PASSED] YUV 4:4:4
[04:31:08] === [PASSED] drm_test_drm_hdmi_connector_get_output_format_name ===
[04:31:08] [PASSED] drm_test_drm_hdmi_connector_get_output_format_name_invalid
[04:31:08] ==== [PASSED] drm_hdmi_connector_get_output_format_name ====
[04:31:08] ============= drm_damage_helper (21 subtests) ==============
[04:31:08] [PASSED] drm_test_damage_iter_no_damage
[04:31:08] [PASSED] drm_test_damage_iter_no_damage_fractional_src
[04:31:08] [PASSED] drm_test_damage_iter_no_damage_src_moved
[04:31:08] [PASSED] drm_test_damage_iter_no_damage_fractional_src_moved
[04:31:08] [PASSED] drm_test_damage_iter_no_damage_not_visible
[04:31:08] [PASSED] drm_test_damage_iter_no_damage_no_crtc
[04:31:08] [PASSED] drm_test_damage_iter_no_damage_no_fb
[04:31:08] [PASSED] drm_test_damage_iter_simple_damage
[04:31:08] [PASSED] drm_test_damage_iter_single_damage
[04:31:08] [PASSED] drm_test_damage_iter_single_damage_intersect_src
[04:31:08] [PASSED] drm_test_damage_iter_single_damage_outside_src
[04:31:08] [PASSED] drm_test_damage_iter_single_damage_fractional_src
[04:31:08] [PASSED] drm_test_damage_iter_single_damage_intersect_fractional_src
[04:31:08] [PASSED] drm_test_damage_iter_single_damage_outside_fractional_src
[04:31:08] [PASSED] drm_test_damage_iter_single_damage_src_moved
[04:31:08] [PASSED] drm_test_damage_iter_single_damage_fractional_src_moved
[04:31:08] [PASSED] drm_test_damage_iter_damage
[04:31:08] [PASSED] drm_test_damage_iter_damage_one_intersect
[04:31:08] [PASSED] drm_test_damage_iter_damage_one_outside
[04:31:08] [PASSED] drm_test_damage_iter_damage_src_moved
[04:31:08] [PASSED] drm_test_damage_iter_damage_not_visible
[04:31:08] ================ [PASSED] drm_damage_helper ================
[04:31:08] ============== drm_dp_mst_helper (3 subtests) ==============
[04:31:08] ============== drm_test_dp_mst_calc_pbn_mode  ==============
[04:31:08] [PASSED] Clock 154000 BPP 30 DSC disabled
[04:31:08] [PASSED] Clock 234000 BPP 30 DSC disabled
[04:31:08] [PASSED] Clock 297000 BPP 24 DSC disabled
[04:31:08] [PASSED] Clock 332880 BPP 24 DSC enabled
[04:31:08] [PASSED] Clock 324540 BPP 24 DSC enabled
[04:31:08] ========== [PASSED] drm_test_dp_mst_calc_pbn_mode ==========
[04:31:08] ============== drm_test_dp_mst_calc_pbn_div  ===============
[04:31:08] [PASSED] Link rate 2000000 lane count 4
[04:31:08] [PASSED] Link rate 2000000 lane count 2
[04:31:08] [PASSED] Link rate 2000000 lane count 1
[04:31:08] [PASSED] Link rate 1350000 lane count 4
[04:31:08] [PASSED] Link rate 1350000 lane count 2
[04:31:08] [PASSED] Link rate 1350000 lane count 1
[04:31:08] [PASSED] Link rate 1000000 lane count 4
[04:31:08] [PASSED] Link rate 1000000 lane count 2
[04:31:08] [PASSED] Link rate 1000000 lane count 1
[04:31:08] [PASSED] Link rate 810000 lane count 4
[04:31:08] [PASSED] Link rate 810000 lane count 2
[04:31:08] [PASSED] Link rate 810000 lane count 1
[04:31:08] [PASSED] Link rate 540000 lane count 4
[04:31:08] [PASSED] Link rate 540000 lane count 2
[04:31:08] [PASSED] Link rate 540000 lane count 1
[04:31:08] [PASSED] Link rate 270000 lane count 4
[04:31:08] [PASSED] Link rate 270000 lane count 2
[04:31:08] [PASSED] Link rate 270000 lane count 1
[04:31:08] [PASSED] Link rate 162000 lane count 4
[04:31:08] [PASSED] Link rate 162000 lane count 2
[04:31:08] [PASSED] Link rate 162000 lane count 1
[04:31:08] ========== [PASSED] drm_test_dp_mst_calc_pbn_div ===========
[04:31:08] ========= drm_test_dp_mst_sideband_msg_req_decode  =========
[04:31:08] [PASSED] DP_ENUM_PATH_RESOURCES with port number
[04:31:08] [PASSED] DP_POWER_UP_PHY with port number
[04:31:08] [PASSED] DP_POWER_DOWN_PHY with port number
[04:31:08] [PASSED] DP_ALLOCATE_PAYLOAD with SDP stream sinks
[04:31:08] [PASSED] DP_ALLOCATE_PAYLOAD with port number
[04:31:08] [PASSED] DP_ALLOCATE_PAYLOAD with VCPI
[04:31:08] [PASSED] DP_ALLOCATE_PAYLOAD with PBN
[04:31:08] [PASSED] DP_QUERY_PAYLOAD with port number
[04:31:08] [PASSED] DP_QUERY_PAYLOAD with VCPI
[04:31:08] [PASSED] DP_REMOTE_DPCD_READ with port number
[04:31:08] [PASSED] DP_REMOTE_DPCD_READ with DPCD address
[04:31:08] [PASSED] DP_REMOTE_DPCD_READ with max number of bytes
[04:31:08] [PASSED] DP_REMOTE_DPCD_WRITE with port number
[04:31:08] [PASSED] DP_REMOTE_DPCD_WRITE with DPCD address
[04:31:08] [PASSED] DP_REMOTE_DPCD_WRITE with data array
[04:31:08] [PASSED] DP_REMOTE_I2C_READ with port number
[04:31:08] [PASSED] DP_REMOTE_I2C_READ with I2C device ID
[04:31:08] [PASSED] DP_REMOTE_I2C_READ with transactions array
[04:31:08] [PASSED] DP_REMOTE_I2C_WRITE with port number
[04:31:08] [PASSED] DP_REMOTE_I2C_WRITE with I2C device ID
[04:31:08] [PASSED] DP_REMOTE_I2C_WRITE with data array
[04:31:08] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream ID
[04:31:08] [PASSED] DP_QUERY_STREAM_ENC_STATUS with client ID
[04:31:08] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream event
[04:31:08] [PASSED] DP_QUERY_STREAM_ENC_STATUS with valid stream event
[04:31:08] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream behavior
[04:31:08] [PASSED] DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior
[04:31:08] ===== [PASSED] drm_test_dp_mst_sideband_msg_req_decode =====
[04:31:08] ================ [PASSED] drm_dp_mst_helper ================
[04:31:08] ================== drm_exec (7 subtests) ===================
[04:31:08] [PASSED] sanitycheck
[04:31:08] [PASSED] test_lock
[04:31:08] [PASSED] test_lock_unlock
[04:31:08] [PASSED] test_duplicates
[04:31:08] [PASSED] test_prepare
[04:31:08] [PASSED] test_prepare_array
[04:31:08] [PASSED] test_multiple_loops
[04:31:08] ==================== [PASSED] drm_exec =====================
[04:31:08] =========== drm_format_helper_test (18 subtests) ===========
[04:31:08] ============== drm_test_fb_xrgb8888_to_gray8  ==============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ========== [PASSED] drm_test_fb_xrgb8888_to_gray8 ==========
[04:31:08] ============= drm_test_fb_xrgb8888_to_rgb332  ==============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb332 ==========
[04:31:08] ============= drm_test_fb_xrgb8888_to_rgb565  ==============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb565 ==========
[04:31:08] ============ drm_test_fb_xrgb8888_to_xrgb1555  =============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ======== [PASSED] drm_test_fb_xrgb8888_to_xrgb1555 =========
[04:31:08] ============ drm_test_fb_xrgb8888_to_argb1555  =============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ======== [PASSED] drm_test_fb_xrgb8888_to_argb1555 =========
[04:31:08] ============ drm_test_fb_xrgb8888_to_rgba5551  =============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ======== [PASSED] drm_test_fb_xrgb8888_to_rgba5551 =========
[04:31:08] ============= drm_test_fb_xrgb8888_to_rgb888  ==============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb888 ==========
[04:31:08] ============= drm_test_fb_xrgb8888_to_bgr888  ==============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ========= [PASSED] drm_test_fb_xrgb8888_to_bgr888 ==========
[04:31:08] ============ drm_test_fb_xrgb8888_to_argb8888  =============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ======== [PASSED] drm_test_fb_xrgb8888_to_argb8888 =========
[04:31:08] =========== drm_test_fb_xrgb8888_to_xrgb2101010  ===========
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ======= [PASSED] drm_test_fb_xrgb8888_to_xrgb2101010 =======
[04:31:08] =========== drm_test_fb_xrgb8888_to_argb2101010  ===========
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ======= [PASSED] drm_test_fb_xrgb8888_to_argb2101010 =======
[04:31:08] ============== drm_test_fb_xrgb8888_to_mono  ===============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ========== [PASSED] drm_test_fb_xrgb8888_to_mono ===========
[04:31:08] ==================== drm_test_fb_swab  =====================
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ================ [PASSED] drm_test_fb_swab =================
[04:31:08] ============ drm_test_fb_xrgb8888_to_xbgr8888  =============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ======== [PASSED] drm_test_fb_xrgb8888_to_xbgr8888 =========
[04:31:08] ============ drm_test_fb_xrgb8888_to_abgr8888  =============
[04:31:08] [PASSED] single_pixel_source_buffer
[04:31:08] [PASSED] single_pixel_clip_rectangle
[04:31:08] [PASSED] well_known_colors
[04:31:08] [PASSED] destination_pitch
[04:31:08] ======== [PASSED] drm_test_fb_xrgb8888_to_abgr8888 =========
[04:31:08] ================= drm_test_fb_clip_offset  =================
[04:31:08] [PASSED] pass through
[04:31:08] [PASSED] horizontal offset
[04:31:08] [PASSED] vertical offset
[04:31:08] [PASSED] horizontal and vertical offset
[04:31:08] [PASSED] horizontal offset (custom pitch)
[04:31:08] [PASSED] vertical offset (custom pitch)
[04:31:08] [PASSED] horizontal and vertical offset (custom pitch)
[04:31:08] ============= [PASSED] drm_test_fb_clip_offset =============
[04:31:08] ============== drm_test_fb_build_fourcc_list  ==============
[04:31:08] [PASSED] no native formats
[04:31:08] [PASSED] XRGB8888 as native format
[04:31:08] [PASSED] remove duplicates
[04:31:08] [PASSED] convert alpha formats
[04:31:08] [PASSED] random formats
[04:31:08] ========== [PASSED] drm_test_fb_build_fourcc_list ==========
[04:31:08] =================== drm_test_fb_memcpy  ====================
[04:31:08] [PASSED] single_pixel_source_buffer: XR24 little-endian (0x34325258)
[04:31:08] [PASSED] single_pixel_source_buffer: XRA8 little-endian (0x38415258)
[04:31:08] [PASSED] single_pixel_source_buffer: YU24 little-endian (0x34325559)
[04:31:08] [PASSED] single_pixel_clip_rectangle: XB24 little-endian (0x34324258)
[04:31:08] [PASSED] single_pixel_clip_rectangle: XRA8 little-endian (0x38415258)
[04:31:08] [PASSED] single_pixel_clip_rectangle: YU24 little-endian (0x34325559)
[04:31:08] [PASSED] well_known_colors: XB24 little-endian (0x34324258)
[04:31:08] [PASSED] well_known_colors: XRA8 little-endian (0x38415258)
[04:31:08] [PASSED] well_known_colors: YU24 little-endian (0x34325559)
[04:31:08] [PASSED] destination_pitch: XB24 little-endian (0x34324258)
[04:31:08] [PASSED] destination_pitch: XRA8 little-endian (0x38415258)
[04:31:08] [PASSED] destination_pitch: YU24 little-endian (0x34325559)
[04:31:08] =============== [PASSED] drm_test_fb_memcpy ================
[04:31:08] ============= [PASSED] drm_format_helper_test ==============
[04:31:08] ================= drm_format (18 subtests) =================
[04:31:08] [PASSED] drm_test_format_block_width_invalid
[04:31:08] [PASSED] drm_test_format_block_width_one_plane
[04:31:08] [PASSED] drm_test_format_block_width_two_plane
[04:31:08] [PASSED] drm_test_format_block_width_three_plane
[04:31:08] [PASSED] drm_test_format_block_width_tiled
[04:31:08] [PASSED] drm_test_format_block_height_invalid
[04:31:08] [PASSED] drm_test_format_block_height_one_plane
[04:31:08] [PASSED] drm_test_format_block_height_two_plane
[04:31:08] [PASSED] drm_test_format_block_height_three_plane
[04:31:08] [PASSED] drm_test_format_block_height_tiled
[04:31:08] [PASSED] drm_test_format_min_pitch_invalid
[04:31:08] [PASSED] drm_test_format_min_pitch_one_plane_8bpp
[04:31:08] [PASSED] drm_test_format_min_pitch_one_plane_16bpp
[04:31:08] [PASSED] drm_test_format_min_pitch_one_plane_24bpp
[04:31:08] [PASSED] drm_test_format_min_pitch_one_plane_32bpp
[04:31:08] [PASSED] drm_test_format_min_pitch_two_plane
[04:31:08] [PASSED] drm_test_format_min_pitch_three_plane_8bpp
[04:31:08] [PASSED] drm_test_format_min_pitch_tiled
[04:31:08] =================== [PASSED] drm_format ====================
[04:31:08] ============== drm_framebuffer (10 subtests) ===============
[04:31:08] ========== drm_test_framebuffer_check_src_coords  ==========
[04:31:08] [PASSED] Success: source fits into fb
[04:31:08] [PASSED] Fail: overflowing fb with x-axis coordinate
[04:31:08] [PASSED] Fail: overflowing fb with y-axis coordinate
[04:31:08] [PASSED] Fail: overflowing fb with source width
[04:31:08] [PASSED] Fail: overflowing fb with source height
[04:31:08] ====== [PASSED] drm_test_framebuffer_check_src_coords ======
[04:31:08] [PASSED] drm_test_framebuffer_cleanup
[04:31:08] =============== drm_test_framebuffer_create  ===============
[04:31:08] [PASSED] ABGR8888 normal sizes
[04:31:08] [PASSED] ABGR8888 max sizes
[04:31:08] [PASSED] ABGR8888 pitch greater than min required
[04:31:08] [PASSED] ABGR8888 pitch less than min required
[04:31:08] [PASSED] ABGR8888 Invalid width
[04:31:08] [PASSED] ABGR8888 Invalid buffer handle
[04:31:08] [PASSED] No pixel format
[04:31:08] [PASSED] ABGR8888 Width 0
[04:31:08] [PASSED] ABGR8888 Height 0
[04:31:08] [PASSED] ABGR8888 Out of bound height * pitch combination
[04:31:08] [PASSED] ABGR8888 Large buffer offset
[04:31:08] [PASSED] ABGR8888 Buffer offset for inexistent plane
[04:31:08] [PASSED] ABGR8888 Invalid flag
[04:31:08] [PASSED] ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers
[04:31:08] [PASSED] ABGR8888 Valid buffer modifier
[04:31:08] [PASSED] ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
[04:31:08] [PASSED] ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS
[04:31:08] [PASSED] ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS
[04:31:08] [PASSED] NV12 Normal sizes
[04:31:08] [PASSED] NV12 Max sizes
[04:31:08] [PASSED] NV12 Invalid pitch
[04:31:08] [PASSED] NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag
[04:31:08] [PASSED] NV12 different  modifier per-plane
[04:31:08] [PASSED] NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
[04:31:08] [PASSED] NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS
[04:31:08] [PASSED] NV12 Modifier for inexistent plane
[04:31:08] [PASSED] NV12 Handle for inexistent plane
[04:31:08] [PASSED] NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS
[04:31:08] [PASSED] YVU420 DRM_MODE_FB_MODIFIERS set without modifier
[04:31:08] [PASSED] YVU420 Normal sizes
[04:31:08] [PASSED] YVU420 Max sizes
[04:31:08] [PASSED] YVU420 Invalid pitch
[04:31:08] [PASSED] YVU420 Different pitches
[04:31:08] [PASSED] YVU420 Different buffer offsets/pitches
[04:31:08] [PASSED] YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS
[04:31:08] [PASSED] YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS
[04:31:08] [PASSED] YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS
[04:31:08] [PASSED] YVU420 Valid modifier
[04:31:08] [PASSED] YVU420 Different modifiers per plane
[04:31:08] [PASSED] YVU420 Modifier for inexistent plane
[04:31:08] [PASSED] YUV420_10BIT Invalid modifier(DRM_FORMAT_MOD_LINEAR)
[04:31:08] [PASSED] X0L2 Normal sizes
[04:31:08] [PASSED] X0L2 Max sizes
[04:31:08] [PASSED] X0L2 Invalid pitch
[04:31:08] [PASSED] X0L2 Pitch greater than minimum required
[04:31:08] [PASSED] X0L2 Handle for inexistent plane
[04:31:08] [PASSED] X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set
[04:31:08] [PASSED] X0L2 Modifier without DRM_MODE_FB_MODIFIERS set
[04:31:08] [PASSED] X0L2 Valid modifier
[04:31:08] [PASSED] X0L2 Modifier for inexistent plane
[04:31:08] =========== [PASSED] drm_test_framebuffer_create ===========
[04:31:08] [PASSED] drm_test_framebuffer_free
[04:31:08] [PASSED] drm_test_framebuffer_init
[04:31:08] [PASSED] drm_test_framebuffer_init_bad_format
[04:31:08] [PASSED] drm_test_framebuffer_init_dev_mismatch
[04:31:08] [PASSED] drm_test_framebuffer_lookup
[04:31:08] [PASSED] drm_test_framebuffer_lookup_inexistent
[04:31:08] [PASSED] drm_test_framebuffer_modifiers_not_supported
[04:31:08] ================= [PASSED] drm_framebuffer =================
[04:31:08] ================ drm_gem_shmem (8 subtests) ================
[04:31:08] [PASSED] drm_gem_shmem_test_obj_create
[04:31:08] [PASSED] drm_gem_shmem_test_obj_create_private
[04:31:08] [PASSED] drm_gem_shmem_test_pin_pages
[04:31:08] [PASSED] drm_gem_shmem_test_vmap
[04:31:08] [PASSED] drm_gem_shmem_test_get_pages_sgt
[04:31:08] [PASSED] drm_gem_shmem_test_get_sg_table
[04:31:08] [PASSED] drm_gem_shmem_test_madvise
[04:31:08] [PASSED] drm_gem_shmem_test_purge
[04:31:08] ================== [PASSED] drm_gem_shmem ==================
[04:31:08] === drm_atomic_helper_connector_hdmi_check (27 subtests) ===
[04:31:08] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode
[04:31:08] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode_vic_1
[04:31:08] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode
[04:31:08] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode_vic_1
[04:31:08] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode
[04:31:08] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode_vic_1
[04:31:08] ====== drm_test_check_broadcast_rgb_cea_mode_yuv420  =======
[04:31:08] [PASSED] Automatic
[04:31:08] [PASSED] Full
[04:31:08] [PASSED] Limited 16:235
[04:31:08] == [PASSED] drm_test_check_broadcast_rgb_cea_mode_yuv420 ===
[04:31:08] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_changed
[04:31:08] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_not_changed
[04:31:08] [PASSED] drm_test_check_disable_connector
[04:31:08] [PASSED] drm_test_check_hdmi_funcs_reject_rate
[04:31:08] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_rgb
[04:31:08] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_yuv420
[04:31:08] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422
[04:31:08] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420
[04:31:08] [PASSED] drm_test_check_driver_unsupported_fallback_yuv420
[04:31:08] [PASSED] drm_test_check_output_bpc_crtc_mode_changed
[04:31:08] [PASSED] drm_test_check_output_bpc_crtc_mode_not_changed
[04:31:08] [PASSED] drm_test_check_output_bpc_dvi
[04:31:08] [PASSED] drm_test_check_output_bpc_format_vic_1
[04:31:08] [PASSED] drm_test_check_output_bpc_format_display_8bpc_only
[04:31:08] [PASSED] drm_test_check_output_bpc_format_display_rgb_only
[04:31:08] [PASSED] drm_test_check_output_bpc_format_driver_8bpc_only
[04:31:08] [PASSED] drm_test_check_output_bpc_format_driver_rgb_only
[04:31:08] [PASSED] drm_test_check_tmds_char_rate_rgb_8bpc
[04:31:08] [PASSED] drm_test_check_tmds_char_rate_rgb_10bpc
[04:31:08] [PASSED] drm_test_check_tmds_char_rate_rgb_12bpc
[04:31:08] ===== [PASSED] drm_atomic_helper_connector_hdmi_check ======
[04:31:08] === drm_atomic_helper_connector_hdmi_reset (6 subtests) ====
[04:31:08] [PASSED] drm_test_check_broadcast_rgb_value
[04:31:08] [PASSED] drm_test_check_bpc_8_value
[04:31:08] [PASSED] drm_test_check_bpc_10_value
[04:31:08] [PASSED] drm_test_check_bpc_12_value
[04:31:08] [PASSED] drm_test_check_format_value
[04:31:08] [PASSED] drm_test_check_tmds_char_value
[04:31:08] ===== [PASSED] drm_atomic_helper_connector_hdmi_reset ======
[04:31:08] = drm_atomic_helper_connector_hdmi_mode_valid (4 subtests) =
[04:31:08] [PASSED] drm_test_check_mode_valid
[04:31:08] [PASSED] drm_test_check_mode_valid_reject
[04:31:08] [PASSED] drm_test_check_mode_valid_reject_rate
[04:31:08] [PASSED] drm_test_check_mode_valid_reject_max_clock
[04:31:08] === [PASSED] drm_atomic_helper_connector_hdmi_mode_valid ===
[04:31:08] ================= drm_managed (2 subtests) =================
[04:31:08] [PASSED] drm_test_managed_release_action
[04:31:08] [PASSED] drm_test_managed_run_action
[04:31:08] =================== [PASSED] drm_managed ===================
[04:31:08] =================== drm_mm (6 subtests) ====================
[04:31:08] [PASSED] drm_test_mm_init
[04:31:08] [PASSED] drm_test_mm_debug
[04:31:08] [PASSED] drm_test_mm_align32
[04:31:08] [PASSED] drm_test_mm_align64
[04:31:08] [PASSED] drm_test_mm_lowest
[04:31:08] [PASSED] drm_test_mm_highest
[04:31:08] ===================== [PASSED] drm_mm ======================
[04:31:08] ============= drm_modes_analog_tv (5 subtests) =============
[04:31:08] [PASSED] drm_test_modes_analog_tv_mono_576i
[04:31:08] [PASSED] drm_test_modes_analog_tv_ntsc_480i
[04:31:08] [PASSED] drm_test_modes_analog_tv_ntsc_480i_inlined
[04:31:08] [PASSED] drm_test_modes_analog_tv_pal_576i
[04:31:08] [PASSED] drm_test_modes_analog_tv_pal_576i_inlined
[04:31:08] =============== [PASSED] drm_modes_analog_tv ===============
[04:31:08] ============== drm_plane_helper (2 subtests) ===============
[04:31:08] =============== drm_test_check_plane_state  ================
[04:31:08] [PASSED] clipping_simple
[04:31:08] [PASSED] clipping_rotate_reflect
[04:31:08] [PASSED] positioning_simple
[04:31:08] [PASSED] upscaling
[04:31:08] [PASSED] downscaling
[04:31:08] [PASSED] rounding1
[04:31:08] [PASSED] rounding2
[04:31:08] [PASSED] rounding3
[04:31:08] [PASSED] rounding4
[04:31:08] =========== [PASSED] drm_test_check_plane_state ============
[04:31:08] =========== drm_test_check_invalid_plane_state  ============
[04:31:08] [PASSED] positioning_invalid
[04:31:08] [PASSED] upscaling_invalid
[04:31:08] [PASSED] downscaling_invalid
[04:31:08] ======= [PASSED] drm_test_check_invalid_plane_state ========
[04:31:08] ================ [PASSED] drm_plane_helper =================
[04:31:08] ====== drm_connector_helper_tv_get_modes (1 subtest) =======
[04:31:08] ====== drm_test_connector_helper_tv_get_modes_check  =======
[04:31:08] [PASSED] None
[04:31:08] [PASSED] PAL
[04:31:08] [PASSED] NTSC
[04:31:08] [PASSED] Both, NTSC Default
[04:31:08] [PASSED] Both, PAL Default
[04:31:08] [PASSED] Both, NTSC Default, with PAL on command-line
[04:31:08] [PASSED] Both, PAL Default, with NTSC on command-line
[04:31:08] == [PASSED] drm_test_connector_helper_tv_get_modes_check ===
[04:31:08] ======== [PASSED] drm_connector_helper_tv_get_modes ========
[04:31:08] ================== drm_rect (9 subtests) ===================
[04:31:08] [PASSED] drm_test_rect_clip_scaled_div_by_zero
[04:31:08] [PASSED] drm_test_rect_clip_scaled_not_clipped
[04:31:08] [PASSED] drm_test_rect_clip_scaled_clipped
[04:31:08] [PASSED] drm_test_rect_clip_scaled_signed_vs_unsigned
[04:31:08] ================= drm_test_rect_intersect  =================
[04:31:08] [PASSED] top-left x bottom-right: 2x2+1+1 x 2x2+0+0
[04:31:08] [PASSED] top-right x bottom-left: 2x2+0+0 x 2x2+1-1
[04:31:08] [PASSED] bottom-left x top-right: 2x2+1-1 x 2x2+0+0
[04:31:08] [PASSED] bottom-right x top-left: 2x2+0+0 x 2x2+1+1
[04:31:08] [PASSED] right x left: 2x1+0+0 x 3x1+1+0
[04:31:08] [PASSED] left x right: 3x1+1+0 x 2x1+0+0
[04:31:08] [PASSED] up x bottom: 1x2+0+0 x 1x3+0-1
[04:31:08] [PASSED] bottom x up: 1x3+0-1 x 1x2+0+0
[04:31:08] [PASSED] touching corner: 1x1+0+0 x 2x2+1+1
[04:31:08] [PASSED] touching side: 1x1+0+0 x 1x1+1+0
[04:31:08] [PASSED] equal rects: 2x2+0+0 x 2x2+0+0
[04:31:08] [PASSED] inside another: 2x2+0+0 x 1x1+1+1
[04:31:08] [PASSED] far away: 1x1+0+0 x 1x1+3+6
[04:31:08] [PASSED] points intersecting: 0x0+5+10 x 0x0+5+10
[04:31:08] [PASSED] points not intersecting: 0x0+0+0 x 0x0+5+10
[04:31:08] ============= [PASSED] drm_test_rect_intersect =============
[04:31:08] ================ drm_test_rect_calc_hscale  ================
[04:31:08] [PASSED] normal use
[04:31:08] [PASSED] out of max range
[04:31:08] [PASSED] out of min range
[04:31:08] [PASSED] zero dst
[04:31:08] [PASSED] negative src
[04:31:08] [PASSED] negative dst
[04:31:08] ============ [PASSED] drm_test_rect_calc_hscale ============
[04:31:08] ================ drm_test_rect_calc_vscale  ================
[04:31:08] [PASSED] normal use
[04:31:08] [PASSED] out of max range
[04:31:08] [PASSED] out of min range
[04:31:08] [PASSED] zero dst
[04:31:08] [PASSED] negative src
[04:31:08] [PASSED] negative dst
stty: 'standard input': Inappropriate ioctl for device
[04:31:08] ============ [PASSED] drm_test_rect_calc_vscale ============
[04:31:08] ================== drm_test_rect_rotate  ===================
[04:31:08] [PASSED] reflect-x
[04:31:08] [PASSED] reflect-y
[04:31:08] [PASSED] rotate-0
[04:31:08] [PASSED] rotate-90
[04:31:08] [PASSED] rotate-180
[04:31:08] [PASSED] rotate-270
[04:31:08] ============== [PASSED] drm_test_rect_rotate ===============
[04:31:08] ================ drm_test_rect_rotate_inv  =================
[04:31:08] [PASSED] reflect-x
[04:31:08] [PASSED] reflect-y
[04:31:08] [PASSED] rotate-0
[04:31:08] [PASSED] rotate-90
[04:31:08] [PASSED] rotate-180
[04:31:08] [PASSED] rotate-270
[04:31:08] ============ [PASSED] drm_test_rect_rotate_inv =============
[04:31:08] ==================== [PASSED] drm_rect =====================
[04:31:08] ============================================================
[04:31:08] Testing complete. Ran 616 tests: passed: 616
[04:31:08] Elapsed time: 23.778s total, 1.668s configuring, 21.941s building, 0.132s running

+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig
[04:31:09] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[04:31:10] 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
[04:31:18] Starting KUnit Kernel (1/1)...
[04:31:18] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[04:31:18] ================= ttm_device (5 subtests) ==================
[04:31:18] [PASSED] ttm_device_init_basic
[04:31:18] [PASSED] ttm_device_init_multiple
[04:31:18] [PASSED] ttm_device_fini_basic
[04:31:18] [PASSED] ttm_device_init_no_vma_man
[04:31:18] ================== ttm_device_init_pools  ==================
[04:31:18] [PASSED] No DMA allocations, no DMA32 required
[04:31:18] [PASSED] DMA allocations, DMA32 required
[04:31:18] [PASSED] No DMA allocations, DMA32 required
[04:31:18] [PASSED] DMA allocations, no DMA32 required
[04:31:18] ============== [PASSED] ttm_device_init_pools ==============
[04:31:18] =================== [PASSED] ttm_device ====================
[04:31:18] ================== ttm_pool (8 subtests) ===================
[04:31:18] ================== ttm_pool_alloc_basic  ===================
[04:31:18] [PASSED] One page
[04:31:18] [PASSED] More than one page
[04:31:18] [PASSED] Above the allocation limit
[04:31:18] [PASSED] One page, with coherent DMA mappings enabled
[04:31:18] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[04:31:18] ============== [PASSED] ttm_pool_alloc_basic ===============
[04:31:18] ============== ttm_pool_alloc_basic_dma_addr  ==============
[04:31:18] [PASSED] One page
[04:31:18] [PASSED] More than one page
[04:31:18] [PASSED] Above the allocation limit
[04:31:18] [PASSED] One page, with coherent DMA mappings enabled
[04:31:18] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[04:31:18] ========== [PASSED] ttm_pool_alloc_basic_dma_addr ==========
[04:31:18] [PASSED] ttm_pool_alloc_order_caching_match
[04:31:18] [PASSED] ttm_pool_alloc_caching_mismatch
[04:31:18] [PASSED] ttm_pool_alloc_order_mismatch
[04:31:18] [PASSED] ttm_pool_free_dma_alloc
[04:31:18] [PASSED] ttm_pool_free_no_dma_alloc
[04:31:18] [PASSED] ttm_pool_fini_basic
[04:31:18] ==================== [PASSED] ttm_pool =====================
[04:31:18] ================ ttm_resource (8 subtests) =================
[04:31:18] ================= ttm_resource_init_basic  =================
[04:31:18] [PASSED] Init resource in TTM_PL_SYSTEM
[04:31:18] [PASSED] Init resource in TTM_PL_VRAM
[04:31:18] [PASSED] Init resource in a private placement
[04:31:18] [PASSED] Init resource in TTM_PL_SYSTEM, set placement flags
[04:31:18] ============= [PASSED] ttm_resource_init_basic =============
[04:31:18] [PASSED] ttm_resource_init_pinned
[04:31:18] [PASSED] ttm_resource_fini_basic
[04:31:18] [PASSED] ttm_resource_manager_init_basic
[04:31:18] [PASSED] ttm_resource_manager_usage_basic
[04:31:18] [PASSED] ttm_resource_manager_set_used_basic
[04:31:18] [PASSED] ttm_sys_man_alloc_basic
[04:31:18] [PASSED] ttm_sys_man_free_basic
[04:31:18] ================== [PASSED] ttm_resource ===================
[04:31:18] =================== ttm_tt (15 subtests) ===================
[04:31:18] ==================== ttm_tt_init_basic  ====================
[04:31:18] [PASSED] Page-aligned size
[04:31:18] [PASSED] Extra pages requested
[04:31:18] ================ [PASSED] ttm_tt_init_basic ================
[04:31:18] [PASSED] ttm_tt_init_misaligned
[04:31:18] [PASSED] ttm_tt_fini_basic
[04:31:18] [PASSED] ttm_tt_fini_sg
[04:31:18] [PASSED] ttm_tt_fini_shmem
[04:31:18] [PASSED] ttm_tt_create_basic
[04:31:18] [PASSED] ttm_tt_create_invalid_bo_type
[04:31:18] [PASSED] ttm_tt_create_ttm_exists
[04:31:18] [PASSED] ttm_tt_create_failed
[04:31:18] [PASSED] ttm_tt_destroy_basic
[04:31:18] [PASSED] ttm_tt_populate_null_ttm
[04:31:18] [PASSED] ttm_tt_populate_populated_ttm
[04:31:18] [PASSED] ttm_tt_unpopulate_basic
[04:31:18] [PASSED] ttm_tt_unpopulate_empty_ttm
[04:31:18] [PASSED] ttm_tt_swapin_basic
[04:31:18] ===================== [PASSED] ttm_tt ======================
[04:31:18] =================== ttm_bo (14 subtests) ===================
[04:31:18] =========== ttm_bo_reserve_optimistic_no_ticket  ===========
[04:31:18] [PASSED] Cannot be interrupted and sleeps
[04:31:18] [PASSED] Cannot be interrupted, locks straight away
[04:31:18] [PASSED] Can be interrupted, sleeps
[04:31:18] ======= [PASSED] ttm_bo_reserve_optimistic_no_ticket =======
[04:31:18] [PASSED] ttm_bo_reserve_locked_no_sleep
[04:31:18] [PASSED] ttm_bo_reserve_no_wait_ticket
[04:31:18] [PASSED] ttm_bo_reserve_double_resv
[04:31:18] [PASSED] ttm_bo_reserve_interrupted
[04:31:18] [PASSED] ttm_bo_reserve_deadlock
[04:31:18] [PASSED] ttm_bo_unreserve_basic
[04:31:18] [PASSED] ttm_bo_unreserve_pinned
[04:31:18] [PASSED] ttm_bo_unreserve_bulk
[04:31:18] [PASSED] ttm_bo_put_basic
[04:31:18] [PASSED] ttm_bo_put_shared_resv
[04:31:18] [PASSED] ttm_bo_pin_basic
[04:31:18] [PASSED] ttm_bo_pin_unpin_resource
[04:31:18] [PASSED] ttm_bo_multiple_pin_one_unpin
[04:31:18] ===================== [PASSED] ttm_bo ======================
[04:31:18] ============== ttm_bo_validate (22 subtests) ===============
[04:31:18] ============== ttm_bo_init_reserved_sys_man  ===============
[04:31:18] [PASSED] Buffer object for userspace
[04:31:18] [PASSED] Kernel buffer object
[04:31:18] [PASSED] Shared buffer object
[04:31:18] ========== [PASSED] ttm_bo_init_reserved_sys_man ===========
[04:31:18] ============== ttm_bo_init_reserved_mock_man  ==============
[04:31:18] [PASSED] Buffer object for userspace
[04:31:18] [PASSED] Kernel buffer object
[04:31:18] [PASSED] Shared buffer object
[04:31:18] ========== [PASSED] ttm_bo_init_reserved_mock_man ==========
[04:31:18] [PASSED] ttm_bo_init_reserved_resv
[04:31:18] ================== ttm_bo_validate_basic  ==================
[04:31:18] [PASSED] Buffer object for userspace
[04:31:18] [PASSED] Kernel buffer object
[04:31:18] [PASSED] Shared buffer object
[04:31:18] ============== [PASSED] ttm_bo_validate_basic ==============
[04:31:18] [PASSED] ttm_bo_validate_invalid_placement
[04:31:18] ============= ttm_bo_validate_same_placement  ==============
[04:31:18] [PASSED] System manager
[04:31:18] [PASSED] VRAM manager
[04:31:18] ========= [PASSED] ttm_bo_validate_same_placement ==========
[04:31:18] [PASSED] ttm_bo_validate_failed_alloc
[04:31:18] [PASSED] ttm_bo_validate_pinned
[04:31:18] [PASSED] ttm_bo_validate_busy_placement
[04:31:18] ================ ttm_bo_validate_multihop  =================
[04:31:18] [PASSED] Buffer object for userspace
[04:31:18] [PASSED] Kernel buffer object
[04:31:18] [PASSED] Shared buffer object
[04:31:18] ============ [PASSED] ttm_bo_validate_multihop =============
[04:31:18] ========== ttm_bo_validate_no_placement_signaled  ==========
[04:31:18] [PASSED] Buffer object in system domain, no page vector
[04:31:18] [PASSED] Buffer object in system domain with an existing page vector
[04:31:18] ====== [PASSED] ttm_bo_validate_no_placement_signaled ======
[04:31:18] ======== ttm_bo_validate_no_placement_not_signaled  ========
[04:31:18] [PASSED] Buffer object for userspace
[04:31:18] [PASSED] Kernel buffer object
[04:31:18] [PASSED] Shared buffer object
[04:31:18] ==== [PASSED] ttm_bo_validate_no_placement_not_signaled ====
[04:31:18] [PASSED] ttm_bo_validate_move_fence_signaled
[04:31:18] ========= ttm_bo_validate_move_fence_not_signaled  =========
[04:31:18] [PASSED] Waits for GPU
[04:31:18] [PASSED] Tries to lock straight away
[04:31:19] ===== [PASSED] ttm_bo_validate_move_fence_not_signaled =====
[04:31:19] [PASSED] ttm_bo_validate_swapout
[04:31:19] [PASSED] ttm_bo_validate_happy_evict
[04:31:19] [PASSED] ttm_bo_validate_all_pinned_evict
[04:31:19] [PASSED] ttm_bo_validate_allowed_only_evict
[04:31:19] [PASSED] ttm_bo_validate_deleted_evict
[04:31:19] [PASSED] ttm_bo_validate_busy_domain_evict
[04:31:19] [PASSED] ttm_bo_validate_evict_gutting
[04:31:19] [PASSED] ttm_bo_validate_recrusive_evict
stty: 'standard input': Inappropriate ioctl for device
[04:31:19] ================= [PASSED] ttm_bo_validate =================
[04:31:19] ============================================================
[04:31:19] Testing complete. Ran 102 tests: passed: 102
[04:31:19] Elapsed time: 10.067s total, 1.634s configuring, 7.765s building, 0.574s running

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



^ permalink raw reply	[flat|nested] 68+ messages in thread

* ✗ CI.checksparse: warning for MADVISE FOR XE (rev3)
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (23 preceding siblings ...)
  2025-06-16  4:31 ` ✓ CI.KUnit: success " Patchwork
@ 2025-06-16  4:45 ` Patchwork
  2025-06-16  5:13 ` ✓ Xe.CI.BAT: success " Patchwork
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 68+ messages in thread
From: Patchwork @ 2025-06-16  4:45 UTC (permalink / raw)
  To: Ghimiray, Himal Prasad; +Cc: intel-xe

== Series Details ==

Series: MADVISE FOR XE (rev3)
URL   : https://patchwork.freedesktop.org/series/149550/
State : warning

== Summary ==

+ trap cleanup EXIT
+ KERNEL=/kernel
+ MT=/root/linux/maintainer-tools
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools /root/linux/maintainer-tools
Cloning into '/root/linux/maintainer-tools'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ make -C /root/linux/maintainer-tools
make: Entering directory '/root/linux/maintainer-tools'
cc -O2 -g -Wextra -o remap-log remap-log.c
make: Leaving directory '/root/linux/maintainer-tools'
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ /root/linux/maintainer-tools/dim sparse --fast 707bd88d5b799c00ff5be9634b2f4e4ece79d889
Sparse version: 0.6.4 (Ubuntu: 0.6.4-4ubuntu3)
Fast mode used, each commit won't be checked separately.
-
+drivers/gpu/drm/i915/display/intel_display_types.h:1995:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:1995:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_psr.c: note: in included file:

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



^ permalink raw reply	[flat|nested] 68+ messages in thread

* ✓ Xe.CI.BAT: success for MADVISE FOR XE (rev3)
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (24 preceding siblings ...)
  2025-06-16  4:45 ` ✗ CI.checksparse: warning " Patchwork
@ 2025-06-16  5:13 ` Patchwork
  2025-06-16 15:06 ` ✗ Xe.CI.Full: failure " Patchwork
  2025-07-29  4:41 ` [PATCH v4 00/20] MADVISE FOR XE Matthew Brost
  27 siblings, 0 replies; 68+ messages in thread
From: Patchwork @ 2025-06-16  5:13 UTC (permalink / raw)
  To: Ghimiray, Himal Prasad; +Cc: intel-xe

[-- Attachment #1: Type: text/plain, Size: 933 bytes --]

== Series Details ==

Series: MADVISE FOR XE (rev3)
URL   : https://patchwork.freedesktop.org/series/149550/
State : success

== Summary ==

CI Bug Log - changes from xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889_BAT -> xe-pw-149550v3_BAT
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Participating hosts (8 -> 8)
------------------------------

  No changes in participating hosts


Changes
-------

  No changes found


Build changes
-------------

  * Linux: xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889 -> xe-pw-149550v3

  IGT_8411: d5b5d2bb4f8795a98ea58376a128b74f654b7ec1 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889: 707bd88d5b799c00ff5be9634b2f4e4ece79d889
  xe-pw-149550v3: 149550v3

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/index.html

[-- Attachment #2: Type: text/html, Size: 1481 bytes --]

^ permalink raw reply	[flat|nested] 68+ messages in thread

* ✗ Xe.CI.Full: failure for MADVISE FOR XE (rev3)
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (25 preceding siblings ...)
  2025-06-16  5:13 ` ✓ Xe.CI.BAT: success " Patchwork
@ 2025-06-16 15:06 ` Patchwork
  2025-07-29  4:41 ` [PATCH v4 00/20] MADVISE FOR XE Matthew Brost
  27 siblings, 0 replies; 68+ messages in thread
From: Patchwork @ 2025-06-16 15:06 UTC (permalink / raw)
  To: Ghimiray, Himal Prasad; +Cc: intel-xe

[-- Attachment #1: Type: text/plain, Size: 60695 bytes --]

== Series Details ==

Series: MADVISE FOR XE (rev3)
URL   : https://patchwork.freedesktop.org/series/149550/
State : failure

== Summary ==

CI Bug Log - changes from xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889_FULL -> xe-pw-149550v3_FULL
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with xe-pw-149550v3_FULL absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in xe-pw-149550v3_FULL, 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 (4 -> 4)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in xe-pw-149550v3_FULL:

### IGT changes ###

#### Possible regressions ####

  * igt@core_hotunplug@hotreplug:
    - shard-dg2-set2:     [PASS][1] -> [ABORT][2]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-433/igt@core_hotunplug@hotreplug.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-463/igt@core_hotunplug@hotreplug.html

  
Known issues
------------

  Here are the changes found in xe-pw-149550v3_FULL that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@kms_async_flips@async-flip-with-page-flip-events-tiled@pipe-d-dp-2-4-mc-ccs:
    - shard-dg2-set2:     NOTRUN -> [SKIP][3] ([Intel XE#3767]) +15 other tests skip
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_async_flips@async-flip-with-page-flip-events-tiled@pipe-d-dp-2-4-mc-ccs.html

  * igt@kms_big_fb@4-tiled-64bpp-rotate-270:
    - shard-adlp:         NOTRUN -> [SKIP][4] ([Intel XE#1124]) +1 other test skip
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@kms_big_fb@4-tiled-64bpp-rotate-270.html

  * igt@kms_big_fb@linear-32bpp-rotate-90:
    - shard-dg2-set2:     NOTRUN -> [SKIP][5] ([Intel XE#316]) +1 other test skip
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_big_fb@linear-32bpp-rotate-90.html

  * igt@kms_big_fb@x-tiled-32bpp-rotate-90:
    - shard-lnl:          NOTRUN -> [SKIP][6] ([Intel XE#1407])
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_big_fb@x-tiled-32bpp-rotate-90.html

  * igt@kms_big_fb@yf-tiled-64bpp-rotate-180:
    - shard-bmg:          NOTRUN -> [SKIP][7] ([Intel XE#1124])
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_big_fb@yf-tiled-64bpp-rotate-180.html

  * igt@kms_big_fb@yf-tiled-addfb-size-overflow:
    - shard-dg2-set2:     NOTRUN -> [SKIP][8] ([Intel XE#610])
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_big_fb@yf-tiled-addfb-size-overflow.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip:
    - shard-lnl:          NOTRUN -> [SKIP][9] ([Intel XE#1124])
   [9]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip:
    - shard-dg2-set2:     NOTRUN -> [SKIP][10] ([Intel XE#1124]) +3 other tests skip
   [10]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip.html

  * igt@kms_bw@connected-linear-tiling-3-displays-1920x1080p:
    - shard-adlp:         NOTRUN -> [SKIP][11] ([Intel XE#2191])
   [11]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@kms_bw@connected-linear-tiling-3-displays-1920x1080p.html
    - shard-dg2-set2:     NOTRUN -> [SKIP][12] ([Intel XE#2191])
   [12]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_bw@connected-linear-tiling-3-displays-1920x1080p.html

  * igt@kms_bw@linear-tiling-2-displays-3840x2160p:
    - shard-bmg:          NOTRUN -> [SKIP][13] ([Intel XE#367])
   [13]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_bw@linear-tiling-2-displays-3840x2160p.html

  * igt@kms_bw@linear-tiling-3-displays-2560x1440p:
    - shard-lnl:          NOTRUN -> [SKIP][14] ([Intel XE#367])
   [14]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_bw@linear-tiling-3-displays-2560x1440p.html

  * igt@kms_bw@linear-tiling-4-displays-1920x1080p:
    - shard-dg2-set2:     NOTRUN -> [SKIP][15] ([Intel XE#367])
   [15]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_bw@linear-tiling-4-displays-1920x1080p.html

  * igt@kms_ccs@bad-pixel-format-y-tiled-gen12-rc-ccs-cc:
    - shard-bmg:          NOTRUN -> [SKIP][16] ([Intel XE#2887]) +3 other tests skip
   [16]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_ccs@bad-pixel-format-y-tiled-gen12-rc-ccs-cc.html

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs:
    - shard-lnl:          NOTRUN -> [SKIP][17] ([Intel XE#2887])
   [17]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_ccs@bad-rotation-90-yf-tiled-ccs.html

  * igt@kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc@pipe-d-dp-4:
    - shard-dg2-set2:     NOTRUN -> [SKIP][18] ([Intel XE#455] / [Intel XE#787]) +22 other tests skip
   [18]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-435/igt@kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc@pipe-d-dp-4.html

  * igt@kms_ccs@crc-primary-basic-4-tiled-bmg-ccs:
    - shard-adlp:         NOTRUN -> [SKIP][19] ([Intel XE#2907])
   [19]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@kms_ccs@crc-primary-basic-4-tiled-bmg-ccs.html

  * igt@kms_ccs@crc-primary-suspend-4-tiled-bmg-ccs:
    - shard-bmg:          [PASS][20] -> [INCOMPLETE][21] ([Intel XE#3862]) +1 other test incomplete
   [20]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-2/igt@kms_ccs@crc-primary-suspend-4-tiled-bmg-ccs.html
   [21]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-4/igt@kms_ccs@crc-primary-suspend-4-tiled-bmg-ccs.html

  * igt@kms_ccs@crc-primary-suspend-y-tiled-gen12-rc-ccs@pipe-c-hdmi-a-2:
    - shard-dg2-set2:     NOTRUN -> [SKIP][22] ([Intel XE#787]) +125 other tests skip
   [22]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_ccs@crc-primary-suspend-y-tiled-gen12-rc-ccs@pipe-c-hdmi-a-2.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-bmg-ccs:
    - shard-dg2-set2:     NOTRUN -> [SKIP][23] ([Intel XE#2907]) +2 other tests skip
   [23]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-bmg-ccs.html

  * igt@kms_cdclk@mode-transition@pipe-a-dp-2:
    - shard-dg2-set2:     NOTRUN -> [SKIP][24] ([Intel XE#4417]) +3 other tests skip
   [24]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_cdclk@mode-transition@pipe-a-dp-2.html

  * igt@kms_chamelium_color@ctm-0-25:
    - shard-bmg:          NOTRUN -> [SKIP][25] ([Intel XE#2325])
   [25]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_chamelium_color@ctm-0-25.html

  * igt@kms_chamelium_color@ctm-0-75:
    - shard-lnl:          NOTRUN -> [SKIP][26] ([Intel XE#306])
   [26]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_chamelium_color@ctm-0-75.html

  * igt@kms_chamelium_color@ctm-blue-to-red:
    - shard-dg2-set2:     NOTRUN -> [SKIP][27] ([Intel XE#306])
   [27]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_chamelium_color@ctm-blue-to-red.html

  * igt@kms_chamelium_frames@vga-frame-dump:
    - shard-dg2-set2:     NOTRUN -> [SKIP][28] ([Intel XE#373]) +1 other test skip
   [28]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_chamelium_frames@vga-frame-dump.html

  * igt@kms_chamelium_hpd@dp-hpd-storm:
    - shard-lnl:          NOTRUN -> [SKIP][29] ([Intel XE#373])
   [29]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_chamelium_hpd@dp-hpd-storm.html

  * igt@kms_chamelium_hpd@hdmi-hpd-after-suspend:
    - shard-adlp:         NOTRUN -> [SKIP][30] ([Intel XE#373])
   [30]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@kms_chamelium_hpd@hdmi-hpd-after-suspend.html

  * igt@kms_chamelium_hpd@hdmi-hpd-storm-disable:
    - shard-bmg:          NOTRUN -> [SKIP][31] ([Intel XE#2252])
   [31]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_chamelium_hpd@hdmi-hpd-storm-disable.html

  * igt@kms_content_protection@atomic:
    - shard-bmg:          NOTRUN -> [SKIP][32] ([Intel XE#2341])
   [32]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_content_protection@atomic.html

  * igt@kms_content_protection@atomic-dpms@pipe-a-dp-2:
    - shard-dg2-set2:     NOTRUN -> [FAIL][33] ([Intel XE#1178])
   [33]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_content_protection@atomic-dpms@pipe-a-dp-2.html
    - shard-bmg:          NOTRUN -> [FAIL][34] ([Intel XE#1178])
   [34]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-3/igt@kms_content_protection@atomic-dpms@pipe-a-dp-2.html

  * igt@kms_content_protection@lic-type-0@pipe-a-dp-4:
    - shard-dg2-set2:     NOTRUN -> [FAIL][35] ([Intel XE#3304])
   [35]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-463/igt@kms_content_protection@lic-type-0@pipe-a-dp-4.html

  * igt@kms_cursor_crc@cursor-sliding-max-size:
    - shard-bmg:          NOTRUN -> [SKIP][36] ([Intel XE#2320])
   [36]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_cursor_crc@cursor-sliding-max-size.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions-varying-size:
    - shard-bmg:          [PASS][37] -> [SKIP][38] ([Intel XE#2291]) +3 other tests skip
   [37]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-6/igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions-varying-size.html
   [38]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions-varying-size.html

  * igt@kms_cursor_legacy@cursorb-vs-flipa-legacy:
    - shard-bmg:          NOTRUN -> [SKIP][39] ([Intel XE#2291]) +1 other test skip
   [39]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_cursor_legacy@cursorb-vs-flipa-legacy.html

  * igt@kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions-varying-size:
    - shard-dg2-set2:     NOTRUN -> [SKIP][40] ([Intel XE#323]) +1 other test skip
   [40]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions-varying-size.html

  * igt@kms_dither@fb-8bpc-vs-panel-6bpc:
    - shard-bmg:          [PASS][41] -> [SKIP][42] ([Intel XE#1340])
   [41]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-6/igt@kms_dither@fb-8bpc-vs-panel-6bpc.html
   [42]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_dither@fb-8bpc-vs-panel-6bpc.html

  * igt@kms_dp_aux_dev:
    - shard-bmg:          [PASS][43] -> [SKIP][44] ([Intel XE#3009])
   [43]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-6/igt@kms_dp_aux_dev.html
   [44]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_dp_aux_dev.html

  * igt@kms_dp_link_training@non-uhbr-sst:
    - shard-bmg:          [PASS][45] -> [SKIP][46] ([Intel XE#4354])
   [45]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-1/igt@kms_dp_link_training@non-uhbr-sst.html
   [46]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-5/igt@kms_dp_link_training@non-uhbr-sst.html

  * igt@kms_fbcon_fbt@psr:
    - shard-dg2-set2:     NOTRUN -> [SKIP][47] ([Intel XE#776])
   [47]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_fbcon_fbt@psr.html

  * igt@kms_feature_discovery@display-3x:
    - shard-bmg:          NOTRUN -> [SKIP][48] ([Intel XE#2373])
   [48]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_feature_discovery@display-3x.html

  * igt@kms_flip@2x-flip-vs-absolute-wf_vblank:
    - shard-dg2-set2:     [PASS][49] -> [FAIL][50] ([Intel XE#886])
   [49]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-464/igt@kms_flip@2x-flip-vs-absolute-wf_vblank.html
   [50]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_flip@2x-flip-vs-absolute-wf_vblank.html

  * igt@kms_flip@2x-flip-vs-absolute-wf_vblank@ab-hdmi-a2-dp2:
    - shard-dg2-set2:     NOTRUN -> [FAIL][51] ([Intel XE#886])
   [51]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_flip@2x-flip-vs-absolute-wf_vblank@ab-hdmi-a2-dp2.html

  * igt@kms_flip@2x-flip-vs-dpms-on-nop-interruptible:
    - shard-bmg:          [PASS][52] -> [SKIP][53] ([Intel XE#2316]) +5 other tests skip
   [52]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-8/igt@kms_flip@2x-flip-vs-dpms-on-nop-interruptible.html
   [53]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-5/igt@kms_flip@2x-flip-vs-dpms-on-nop-interruptible.html

  * igt@kms_flip@2x-plain-flip-fb-recreate-interruptible:
    - shard-lnl:          NOTRUN -> [SKIP][54] ([Intel XE#1421])
   [54]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_flip@2x-plain-flip-fb-recreate-interruptible.html

  * igt@kms_flip@flip-vs-absolute-wf_vblank:
    - shard-lnl:          [PASS][55] -> [FAIL][56] ([Intel XE#886]) +1 other test fail
   [55]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-lnl-5/igt@kms_flip@flip-vs-absolute-wf_vblank.html
   [56]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-7/igt@kms_flip@flip-vs-absolute-wf_vblank.html

  * igt@kms_flip@flip-vs-absolute-wf_vblank@a-hdmi-a1:
    - shard-adlp:         [PASS][57] -> [FAIL][58] ([Intel XE#2882]) +2 other tests fail
   [57]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-adlp-9/igt@kms_flip@flip-vs-absolute-wf_vblank@a-hdmi-a1.html
   [58]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@kms_flip@flip-vs-absolute-wf_vblank@a-hdmi-a1.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@b-dp4:
    - shard-dg2-set2:     [PASS][59] -> [FAIL][60] ([Intel XE#301])
   [59]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-466/igt@kms_flip@flip-vs-expired-vblank-interruptible@b-dp4.html
   [60]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-466/igt@kms_flip@flip-vs-expired-vblank-interruptible@b-dp4.html

  * igt@kms_flip@flip-vs-suspend:
    - shard-adlp:         NOTRUN -> [DMESG-WARN][61] ([Intel XE#2953] / [Intel XE#4173]) +1 other test dmesg-warn
   [61]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@kms_flip@flip-vs-suspend.html

  * igt@kms_flip@flip-vs-suspend-interruptible:
    - shard-bmg:          [PASS][62] -> [INCOMPLETE][63] ([Intel XE#2049] / [Intel XE#2597]) +1 other test incomplete
   [62]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-3/igt@kms_flip@flip-vs-suspend-interruptible.html
   [63]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-4/igt@kms_flip@flip-vs-suspend-interruptible.html
    - shard-dg2-set2:     [PASS][64] -> [INCOMPLETE][65] ([Intel XE#2049] / [Intel XE#2597]) +1 other test incomplete
   [64]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-433/igt@kms_flip@flip-vs-suspend-interruptible.html
   [65]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-433/igt@kms_flip@flip-vs-suspend-interruptible.html

  * igt@kms_flip@flip-vs-suspend@d-dp4:
    - shard-dg2-set2:     NOTRUN -> [INCOMPLETE][66] ([Intel XE#2049] / [Intel XE#2597]) +1 other test incomplete
   [66]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_flip@flip-vs-suspend@d-dp4.html

  * igt@kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling:
    - shard-lnl:          NOTRUN -> [SKIP][67] ([Intel XE#1401] / [Intel XE#1745]) +1 other test skip
   [67]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-upscaling@pipe-a-default-mode:
    - shard-lnl:          NOTRUN -> [SKIP][68] ([Intel XE#1401]) +1 other test skip
   [68]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-upscaling@pipe-a-default-mode.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling:
    - shard-dg2-set2:     NOTRUN -> [SKIP][69] ([Intel XE#455]) +9 other tests skip
   [69]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-upscaling:
    - shard-adlp:         NOTRUN -> [SKIP][70] ([Intel XE#455]) +2 other tests skip
   [70]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling:
    - shard-bmg:          NOTRUN -> [SKIP][71] ([Intel XE#2293] / [Intel XE#2380])
   [71]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling@pipe-a-valid-mode:
    - shard-bmg:          NOTRUN -> [SKIP][72] ([Intel XE#2293])
   [72]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling@pipe-a-valid-mode.html

  * igt@kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-onoff:
    - shard-dg2-set2:     NOTRUN -> [SKIP][73] ([Intel XE#651]) +12 other tests skip
   [73]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-onoff.html

  * igt@kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-mmap-wc:
    - shard-bmg:          NOTRUN -> [SKIP][74] ([Intel XE#2312]) +9 other tests skip
   [74]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@drrs-rgb101010-draw-blt:
    - shard-bmg:          NOTRUN -> [SKIP][75] ([Intel XE#2311]) +2 other tests skip
   [75]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_frontbuffer_tracking@drrs-rgb101010-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-pgflip-blt:
    - shard-bmg:          NOTRUN -> [SKIP][76] ([Intel XE#4141]) +1 other test skip
   [76]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-pgflip-blt.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-mmap-wc:
    - shard-adlp:         NOTRUN -> [SKIP][77] ([Intel XE#656])
   [77]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-fullscreen:
    - shard-lnl:          NOTRUN -> [SKIP][78] ([Intel XE#656]) +4 other tests skip
   [78]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-fullscreen.html

  * igt@kms_frontbuffer_tracking@fbcpsr-suspend:
    - shard-bmg:          NOTRUN -> [SKIP][79] ([Intel XE#2313])
   [79]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_frontbuffer_tracking@fbcpsr-suspend.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-msflip-blt:
    - shard-dg2-set2:     NOTRUN -> [SKIP][80] ([Intel XE#653]) +11 other tests skip
   [80]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-msflip-blt.html

  * igt@kms_getfb@getfb2-accept-ccs:
    - shard-lnl:          NOTRUN -> [SKIP][81] ([Intel XE#2340])
   [81]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_getfb@getfb2-accept-ccs.html

  * igt@kms_joiner@invalid-modeset-force-ultra-joiner:
    - shard-dg2-set2:     NOTRUN -> [SKIP][82] ([Intel XE#2925])
   [82]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_joiner@invalid-modeset-force-ultra-joiner.html

  * igt@kms_plane_cursor@primary@pipe-a-hdmi-a-2-size-256:
    - shard-dg2-set2:     NOTRUN -> [FAIL][83] ([Intel XE#616]) +2 other tests fail
   [83]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_plane_cursor@primary@pipe-a-hdmi-a-2-size-256.html

  * igt@kms_plane_multiple@2x-tiling-none:
    - shard-bmg:          [PASS][84] -> [SKIP][85] ([Intel XE#4596])
   [84]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-7/igt@kms_plane_multiple@2x-tiling-none.html
   [85]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_plane_multiple@2x-tiling-none.html

  * igt@kms_plane_scaling@2x-scaler-multi-pipe:
    - shard-bmg:          [PASS][86] -> [SKIP][87] ([Intel XE#2571])
   [86]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-7/igt@kms_plane_scaling@2x-scaler-multi-pipe.html
   [87]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_plane_scaling@2x-scaler-multi-pipe.html

  * igt@kms_pm_dc@dc5-retention-flops:
    - shard-dg2-set2:     NOTRUN -> [SKIP][88] ([Intel XE#3309])
   [88]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_pm_dc@dc5-retention-flops.html

  * igt@kms_psr2_sf@fbc-psr2-overlay-plane-update-sf-dmg-area:
    - shard-bmg:          NOTRUN -> [SKIP][89] ([Intel XE#1489]) +1 other test skip
   [89]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_psr2_sf@fbc-psr2-overlay-plane-update-sf-dmg-area.html

  * igt@kms_psr2_sf@fbc-psr2-primary-plane-update-sf-dmg-area:
    - shard-dg2-set2:     NOTRUN -> [SKIP][90] ([Intel XE#1489]) +2 other tests skip
   [90]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_psr2_sf@fbc-psr2-primary-plane-update-sf-dmg-area.html

  * igt@kms_psr2_sf@pr-primary-plane-update-sf-dmg-area:
    - shard-lnl:          NOTRUN -> [SKIP][91] ([Intel XE#2893])
   [91]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@kms_psr2_sf@pr-primary-plane-update-sf-dmg-area.html

  * igt@kms_psr@fbc-psr2-sprite-plane-move:
    - shard-dg2-set2:     NOTRUN -> [SKIP][92] ([Intel XE#2850] / [Intel XE#929]) +6 other tests skip
   [92]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_psr@fbc-psr2-sprite-plane-move.html

  * igt@kms_psr@psr-cursor-plane-move:
    - shard-bmg:          NOTRUN -> [SKIP][93] ([Intel XE#2234] / [Intel XE#2850]) +2 other tests skip
   [93]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_psr@psr-cursor-plane-move.html

  * igt@kms_rotation_crc@multiplane-rotation-cropping-bottom:
    - shard-adlp:         NOTRUN -> [FAIL][94] ([Intel XE#1874])
   [94]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@kms_rotation_crc@multiplane-rotation-cropping-bottom.html

  * igt@kms_rotation_crc@primary-y-tiled-reflect-x-90:
    - shard-bmg:          NOTRUN -> [SKIP][95] ([Intel XE#3414] / [Intel XE#3904])
   [95]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_rotation_crc@primary-y-tiled-reflect-x-90.html

  * igt@kms_rotation_crc@primary-yf-tiled-reflect-x-180:
    - shard-bmg:          NOTRUN -> [SKIP][96] ([Intel XE#2330])
   [96]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-180.html

  * igt@kms_setmode@basic@pipe-b-hdmi-a-2-pipe-a-dp-2:
    - shard-dg2-set2:     NOTRUN -> [FAIL][97] ([Intel XE#2883]) +3 other tests fail
   [97]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_setmode@basic@pipe-b-hdmi-a-2-pipe-a-dp-2.html

  * igt@xe_copy_basic@mem-set-linear-0xfffe:
    - shard-dg2-set2:     NOTRUN -> [SKIP][98] ([Intel XE#1126])
   [98]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_copy_basic@mem-set-linear-0xfffe.html

  * igt@xe_create@create-big-vram:
    - shard-lnl:          NOTRUN -> [SKIP][99] ([Intel XE#1062])
   [99]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@xe_create@create-big-vram.html

  * igt@xe_eudebug@basic-vm-bind-discovery:
    - shard-lnl:          NOTRUN -> [SKIP][100] ([Intel XE#4837])
   [100]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@xe_eudebug@basic-vm-bind-discovery.html

  * igt@xe_eudebug@discovery-empty-clients:
    - shard-bmg:          NOTRUN -> [SKIP][101] ([Intel XE#4837]) +1 other test skip
   [101]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@xe_eudebug@discovery-empty-clients.html

  * igt@xe_eudebug_online@resume-dss:
    - shard-dg2-set2:     NOTRUN -> [SKIP][102] ([Intel XE#4837]) +5 other tests skip
   [102]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_eudebug_online@resume-dss.html

  * igt@xe_eudebug_sriov@deny-sriov:
    - shard-bmg:          NOTRUN -> [SKIP][103] ([Intel XE#4518])
   [103]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@xe_eudebug_sriov@deny-sriov.html

  * igt@xe_exec_basic@multigpu-many-execqueues-many-vm-basic-defer-bind:
    - shard-lnl:          NOTRUN -> [SKIP][104] ([Intel XE#1392]) +1 other test skip
   [104]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-basic-defer-bind.html

  * igt@xe_exec_basic@multigpu-many-execqueues-many-vm-null-defer-mmap:
    - shard-adlp:         NOTRUN -> [SKIP][105] ([Intel XE#1392])
   [105]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-null-defer-mmap.html

  * igt@xe_exec_basic@multigpu-no-exec-null-rebind:
    - shard-bmg:          NOTRUN -> [SKIP][106] ([Intel XE#2322]) +2 other tests skip
   [106]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@xe_exec_basic@multigpu-no-exec-null-rebind.html

  * igt@xe_exec_basic@multigpu-no-exec-userptr-invalidate-race:
    - shard-dg2-set2:     [PASS][107] -> [SKIP][108] ([Intel XE#1392]) +5 other tests skip
   [107]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-463/igt@xe_exec_basic@multigpu-no-exec-userptr-invalidate-race.html
   [108]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_exec_basic@multigpu-no-exec-userptr-invalidate-race.html

  * igt@xe_exec_fault_mode@many-execqueues-bindexecqueue-rebind-imm:
    - shard-dg2-set2:     NOTRUN -> [SKIP][109] ([Intel XE#288]) +9 other tests skip
   [109]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_exec_fault_mode@many-execqueues-bindexecqueue-rebind-imm.html

  * igt@xe_exec_fault_mode@many-execqueues-userptr-rebind:
    - shard-adlp:         NOTRUN -> [SKIP][110] ([Intel XE#288])
   [110]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@xe_exec_fault_mode@many-execqueues-userptr-rebind.html

  * igt@xe_exec_system_allocator@many-execqueues-mmap-new-huge:
    - shard-dg2-set2:     NOTRUN -> [SKIP][111] ([Intel XE#4915]) +110 other tests skip
   [111]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_exec_system_allocator@many-execqueues-mmap-new-huge.html

  * igt@xe_exec_system_allocator@many-execqueues-mmap-new-huge-nomemset:
    - shard-lnl:          NOTRUN -> [SKIP][112] ([Intel XE#4943])
   [112]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@xe_exec_system_allocator@many-execqueues-mmap-new-huge-nomemset.html

  * igt@xe_exec_system_allocator@threads-many-mmap-huge:
    - shard-bmg:          NOTRUN -> [SKIP][113] ([Intel XE#4943]) +5 other tests skip
   [113]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@xe_exec_system_allocator@threads-many-mmap-huge.html

  * igt@xe_exec_system_allocator@twice-large-malloc-race-nomemset:
    - shard-adlp:         NOTRUN -> [SKIP][114] ([Intel XE#4915]) +4 other tests skip
   [114]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@xe_exec_system_allocator@twice-large-malloc-race-nomemset.html

  * igt@xe_fault_injection@inject-fault-probe-function-xe_add_hw_engine_class_defaults:
    - shard-lnl:          NOTRUN -> [ABORT][115] ([Intel XE#4757])
   [115]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@xe_fault_injection@inject-fault-probe-function-xe_add_hw_engine_class_defaults.html

  * igt@xe_module_load@load:
    - shard-dg2-set2:     ([PASS][116], [PASS][117], [PASS][118], [PASS][119], [PASS][120], [PASS][121], [PASS][122], [PASS][123], [PASS][124], [PASS][125], [PASS][126], [PASS][127], [PASS][128], [PASS][129], [PASS][130], [PASS][131], [PASS][132], [PASS][133], [PASS][134], [PASS][135], [PASS][136], [PASS][137], [PASS][138], [PASS][139], [PASS][140]) -> ([PASS][141], [PASS][142], [PASS][143], [PASS][144], [PASS][145], [PASS][146], [PASS][147], [SKIP][148], [PASS][149], [PASS][150], [PASS][151], [PASS][152], [PASS][153], [PASS][154], [PASS][155], [PASS][156], [PASS][157], [PASS][158], [PASS][159], [PASS][160], [PASS][161], [PASS][162], [PASS][163], [PASS][164], [PASS][165]) ([Intel XE#378])
   [116]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-463/igt@xe_module_load@load.html
   [117]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-435/igt@xe_module_load@load.html
   [118]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-432/igt@xe_module_load@load.html
   [119]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-436/igt@xe_module_load@load.html
   [120]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-466/igt@xe_module_load@load.html
   [121]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-466/igt@xe_module_load@load.html
   [122]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-463/igt@xe_module_load@load.html
   [123]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-433/igt@xe_module_load@load.html
   [124]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-436/igt@xe_module_load@load.html
   [125]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-435/igt@xe_module_load@load.html
   [126]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-464/igt@xe_module_load@load.html
   [127]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-464/igt@xe_module_load@load.html
   [128]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-464/igt@xe_module_load@load.html
   [129]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-435/igt@xe_module_load@load.html
   [130]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-434/igt@xe_module_load@load.html
   [131]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-434/igt@xe_module_load@load.html
   [132]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-463/igt@xe_module_load@load.html
   [133]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-433/igt@xe_module_load@load.html
   [134]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-433/igt@xe_module_load@load.html
   [135]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-463/igt@xe_module_load@load.html
   [136]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-434/igt@xe_module_load@load.html
   [137]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-434/igt@xe_module_load@load.html
   [138]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-466/igt@xe_module_load@load.html
   [139]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-432/igt@xe_module_load@load.html
   [140]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-432/igt@xe_module_load@load.html
   [141]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-435/igt@xe_module_load@load.html
   [142]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-435/igt@xe_module_load@load.html
   [143]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-463/igt@xe_module_load@load.html
   [144]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-463/igt@xe_module_load@load.html
   [145]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@xe_module_load@load.html
   [146]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@xe_module_load@load.html
   [147]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-464/igt@xe_module_load@load.html
   [148]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_module_load@load.html
   [149]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_module_load@load.html
   [150]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-433/igt@xe_module_load@load.html
   [151]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-433/igt@xe_module_load@load.html
   [152]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-436/igt@xe_module_load@load.html
   [153]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-464/igt@xe_module_load@load.html
   [154]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-466/igt@xe_module_load@load.html
   [155]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_module_load@load.html
   [156]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_module_load@load.html
   [157]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-463/igt@xe_module_load@load.html
   [158]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-433/igt@xe_module_load@load.html
   [159]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-433/igt@xe_module_load@load.html
   [160]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-464/igt@xe_module_load@load.html
   [161]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-435/igt@xe_module_load@load.html
   [162]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-436/igt@xe_module_load@load.html
   [163]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-436/igt@xe_module_load@load.html
   [164]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-436/igt@xe_module_load@load.html
   [165]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@xe_module_load@load.html

  * igt@xe_oa@non-privileged-map-oa-buffer:
    - shard-dg2-set2:     NOTRUN -> [SKIP][166] ([Intel XE#2541] / [Intel XE#3573]) +2 other tests skip
   [166]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_oa@non-privileged-map-oa-buffer.html

  * igt@xe_pm@s4-basic-exec:
    - shard-lnl:          [PASS][167] -> [ABORT][168] ([Intel XE#1794])
   [167]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-lnl-1/igt@xe_pm@s4-basic-exec.html
   [168]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-2/igt@xe_pm@s4-basic-exec.html

  * igt@xe_pm@s4-multiple-execs:
    - shard-adlp:         [PASS][169] -> [ABORT][170] ([Intel XE#1794])
   [169]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-adlp-2/igt@xe_pm@s4-multiple-execs.html
   [170]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-9/igt@xe_pm@s4-multiple-execs.html

  * igt@xe_pm@s4-vm-bind-userptr:
    - shard-bmg:          [PASS][171] -> [ABORT][172] ([Intel XE#5255])
   [171]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-6/igt@xe_pm@s4-vm-bind-userptr.html
   [172]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@xe_pm@s4-vm-bind-userptr.html

  * igt@xe_pxp@pxp-termination-key-update-post-suspend:
    - shard-dg2-set2:     NOTRUN -> [SKIP][173] ([Intel XE#4733]) +2 other tests skip
   [173]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@xe_pxp@pxp-termination-key-update-post-suspend.html

  * igt@xe_query@multigpu-query-invalid-cs-cycles:
    - shard-bmg:          NOTRUN -> [SKIP][174] ([Intel XE#944])
   [174]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@xe_query@multigpu-query-invalid-cs-cycles.html

  * igt@xe_spin_batch@spin-mem-copy:
    - shard-dg2-set2:     NOTRUN -> [SKIP][175] ([Intel XE#4821])
   [175]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_spin_batch@spin-mem-copy.html

  
#### Possible fixes ####

  * igt@kms_atomic_transition@plane-toggle-modeset-transition:
    - shard-adlp:         [FAIL][176] ([Intel XE#3908]) -> [PASS][177] +1 other test pass
   [176]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-adlp-4/igt@kms_atomic_transition@plane-toggle-modeset-transition.html
   [177]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-3/igt@kms_atomic_transition@plane-toggle-modeset-transition.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs:
    - shard-dg2-set2:     [INCOMPLETE][178] ([Intel XE#1727] / [Intel XE#3113] / [Intel XE#3124] / [Intel XE#4345]) -> [PASS][179]
   [178]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-436/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs.html
   [179]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs@pipe-b-hdmi-a-6:
    - shard-dg2-set2:     [INCOMPLETE][180] ([Intel XE#1727] / [Intel XE#3113] / [Intel XE#3124]) -> [PASS][181] +1 other test pass
   [180]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-464/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs@pipe-b-hdmi-a-6.html
   [181]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs@pipe-b-hdmi-a-6.html

  * igt@kms_cursor_crc@cursor-suspend:
    - shard-bmg:          [SKIP][182] ([Intel XE#2320] / [Intel XE#5042]) -> [PASS][183]
   [182]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-6/igt@kms_cursor_crc@cursor-suspend.html
   [183]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_cursor_crc@cursor-suspend.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-legacy:
    - shard-bmg:          [SKIP][184] ([Intel XE#2291]) -> [PASS][185] +1 other test pass
   [184]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-5/igt@kms_cursor_legacy@cursora-vs-flipb-legacy.html
   [185]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-3/igt@kms_cursor_legacy@cursora-vs-flipb-legacy.html

  * igt@kms_flip@2x-flip-vs-blocking-wf-vblank@ab-hdmi-a6-dp4:
    - shard-dg2-set2:     [FAIL][186] ([Intel XE#886]) -> [PASS][187] +1 other test pass
   [186]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-433/igt@kms_flip@2x-flip-vs-blocking-wf-vblank@ab-hdmi-a6-dp4.html
   [187]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-434/igt@kms_flip@2x-flip-vs-blocking-wf-vblank@ab-hdmi-a6-dp4.html

  * igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset:
    - shard-bmg:          [SKIP][188] ([Intel XE#2316]) -> [PASS][189] +3 other tests pass
   [188]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-5/igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset.html
   [189]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-3/igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset.html

  * igt@kms_plane_scaling@plane-downscale-factor-0-5-with-modifiers@pipe-d:
    - shard-adlp:         [DMESG-WARN][190] ([Intel XE#2953] / [Intel XE#4173]) -> [PASS][191] +1 other test pass
   [190]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-adlp-6/igt@kms_plane_scaling@plane-downscale-factor-0-5-with-modifiers@pipe-d.html
   [191]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-2/igt@kms_plane_scaling@plane-downscale-factor-0-5-with-modifiers@pipe-d.html

  * igt@kms_pm_rpm@basic-rte:
    - shard-bmg:          [DMESG-WARN][192] ([Intel XE#3428]) -> [PASS][193] +2 other tests pass
   [192]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-6/igt@kms_pm_rpm@basic-rte.html
   [193]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_pm_rpm@basic-rte.html

  * igt@kms_vrr@cmrr@pipe-a-edp-1:
    - shard-lnl:          [FAIL][194] ([Intel XE#4459]) -> [PASS][195] +1 other test pass
   [194]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-lnl-3/igt@kms_vrr@cmrr@pipe-a-edp-1.html
   [195]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-1/igt@kms_vrr@cmrr@pipe-a-edp-1.html

  * igt@xe_ccs@suspend-resume@linear-compressed-compfmt0-system-vram01:
    - shard-dg2-set2:     [INCOMPLETE][196] ([Intel XE#4358]) -> [PASS][197] +1 other test pass
   [196]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-463/igt@xe_ccs@suspend-resume@linear-compressed-compfmt0-system-vram01.html
   [197]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_ccs@suspend-resume@linear-compressed-compfmt0-system-vram01.html

  * igt@xe_exec_basic@multigpu-once-basic-defer-mmap:
    - shard-dg2-set2:     [SKIP][198] ([Intel XE#1392]) -> [PASS][199] +4 other tests pass
   [198]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-432/igt@xe_exec_basic@multigpu-once-basic-defer-mmap.html
   [199]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-435/igt@xe_exec_basic@multigpu-once-basic-defer-mmap.html

  * igt@xe_exec_threads@threads-hang-fd-userptr-rebind:
    - shard-dg2-set2:     [DMESG-WARN][200] ([Intel XE#3876]) -> [PASS][201]
   [200]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-434/igt@xe_exec_threads@threads-hang-fd-userptr-rebind.html
   [201]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-436/igt@xe_exec_threads@threads-hang-fd-userptr-rebind.html

  * igt@xe_pm@s4-multiple-execs:
    - shard-lnl:          [ABORT][202] ([Intel XE#1794]) -> [PASS][203]
   [202]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-lnl-2/igt@xe_pm@s4-multiple-execs.html
   [203]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-8/igt@xe_pm@s4-multiple-execs.html

  * igt@xe_pm@s4-vm-bind-userptr:
    - shard-adlp:         [ABORT][204] ([Intel XE#1794]) -> [PASS][205]
   [204]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-adlp-9/igt@xe_pm@s4-vm-bind-userptr.html
   [205]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-1/igt@xe_pm@s4-vm-bind-userptr.html

  * igt@xe_pmu@gt-frequency:
    - shard-dg2-set2:     [FAIL][206] ([Intel XE#4819]) -> [PASS][207] +1 other test pass
   [206]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-434/igt@xe_pmu@gt-frequency.html
   [207]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-436/igt@xe_pmu@gt-frequency.html

  
#### Warnings ####

  * igt@kms_content_protection@atomic-dpms:
    - shard-bmg:          [SKIP][208] ([Intel XE#2341]) -> [FAIL][209] ([Intel XE#1178])
   [208]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-5/igt@kms_content_protection@atomic-dpms.html
   [209]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-3/igt@kms_content_protection@atomic-dpms.html

  * igt@kms_content_protection@uevent:
    - shard-bmg:          [FAIL][210] ([Intel XE#1188]) -> [SKIP][211] ([Intel XE#2341])
   [210]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-1/igt@kms_content_protection@uevent.html
   [211]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-5/igt@kms_content_protection@uevent.html

  * igt@kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-mmap-wc:
    - shard-bmg:          [SKIP][212] ([Intel XE#2312]) -> [SKIP][213] ([Intel XE#2311]) +6 other tests skip
   [212]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-5/igt@kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-mmap-wc.html
   [213]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-3/igt@kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render:
    - shard-bmg:          [SKIP][214] ([Intel XE#4141]) -> [SKIP][215] ([Intel XE#2312]) +4 other tests skip
   [214]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-6/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render.html
   [215]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-render:
    - shard-bmg:          [SKIP][216] ([Intel XE#2312]) -> [SKIP][217] ([Intel XE#4141]) +3 other tests skip
   [216]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-5/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-render.html
   [217]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-3/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-render:
    - shard-bmg:          [SKIP][218] ([Intel XE#2311]) -> [SKIP][219] ([Intel XE#2312]) +14 other tests skip
   [218]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-1/igt@kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-render.html
   [219]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-5/igt@kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-indfb-plflip-blt:
    - shard-bmg:          [SKIP][220] ([Intel XE#2312]) -> [SKIP][221] ([Intel XE#2313]) +5 other tests skip
   [220]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-5/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-indfb-plflip-blt.html
   [221]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-3/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-indfb-plflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-indfb-plflip-blt:
    - shard-bmg:          [SKIP][222] ([Intel XE#2313]) -> [SKIP][223] ([Intel XE#2312]) +17 other tests skip
   [222]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-bmg-6/igt@kms_frontbuffer_tracking@psr-2p-primscrn-indfb-plflip-blt.html
   [223]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-bmg-6/igt@kms_frontbuffer_tracking@psr-2p-primscrn-indfb-plflip-blt.html

  * igt@xe_exec_system_allocator@threads-shared-vm-many-large-new-bo-map-nomemset:
    - shard-lnl:          [FAIL][224] ([Intel XE#5018]) -> [FAIL][225] ([Intel XE#4937] / [Intel XE#5018])
   [224]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-lnl-3/igt@xe_exec_system_allocator@threads-shared-vm-many-large-new-bo-map-nomemset.html
   [225]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-lnl-1/igt@xe_exec_system_allocator@threads-shared-vm-many-large-new-bo-map-nomemset.html

  * igt@xe_peer2peer@write:
    - shard-dg2-set2:     [FAIL][226] ([Intel XE#1173]) -> [SKIP][227] ([Intel XE#1061])
   [226]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-dg2-436/igt@xe_peer2peer@write.html
   [227]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-dg2-432/igt@xe_peer2peer@write.html

  * igt@xe_pmu@engine-activity-all-load:
    - shard-adlp:         [ABORT][228] ([Intel XE#5214]) -> [DMESG-WARN][229] ([Intel XE#5214])
   [228]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-adlp-6/igt@xe_pmu@engine-activity-all-load.html
   [229]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-2/igt@xe_pmu@engine-activity-all-load.html

  * igt@xe_pmu@engine-activity-load:
    - shard-adlp:         [DMESG-WARN][230] ([Intel XE#5214]) -> [ABORT][231] ([Intel XE#5214]) +1 other test abort
   [230]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-adlp-1/igt@xe_pmu@engine-activity-load.html
   [231]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-8/igt@xe_pmu@engine-activity-load.html

  * igt@xe_sriov_scheduling@equal-throughput:
    - shard-adlp:         [ABORT][232] ([Intel XE#5214]) -> [INCOMPLETE][233] ([Intel XE#5214]) +2 other tests incomplete
   [232]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889/shard-adlp-1/igt@xe_sriov_scheduling@equal-throughput.html
   [233]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/shard-adlp-2/igt@xe_sriov_scheduling@equal-throughput.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [Intel XE#1061]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1061
  [Intel XE#1062]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1062
  [Intel XE#1124]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1124
  [Intel XE#1126]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1126
  [Intel XE#1173]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1173
  [Intel XE#1178]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1178
  [Intel XE#1188]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1188
  [Intel XE#1340]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1340
  [Intel XE#1392]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1392
  [Intel XE#1401]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1401
  [Intel XE#1407]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1407
  [Intel XE#1421]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1421
  [Intel XE#1489]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1489
  [Intel XE#1727]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1727
  [Intel XE#1745]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1745
  [Intel XE#1794]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1794
  [Intel XE#1874]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1874
  [Intel XE#2049]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2049
  [Intel XE#2191]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2191
  [Intel XE#2234]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2234
  [Intel XE#2252]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2252
  [Intel XE#2291]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2291
  [Intel XE#2293]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2293
  [Intel XE#2311]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2311
  [Intel XE#2312]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2312
  [Intel XE#2313]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2313
  [Intel XE#2316]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2316
  [Intel XE#2320]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2320
  [Intel XE#2322]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2322
  [Intel XE#2325]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2325
  [Intel XE#2330]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2330
  [Intel XE#2340]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2340
  [Intel XE#2341]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2341
  [Intel XE#2373]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2373
  [Intel XE#2380]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2380
  [Intel XE#2541]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2541
  [Intel XE#2571]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2571
  [Intel XE#2597]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2597
  [Intel XE#2850]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2850
  [Intel XE#288]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/288
  [Intel XE#2882]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2882
  [Intel XE#2883]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2883
  [Intel XE#2887]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2887
  [Intel XE#2893]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2893
  [Intel XE#2907]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2907
  [Intel XE#2925]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2925
  [Intel XE#2953]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2953
  [Intel XE#3009]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3009
  [Intel XE#301]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/301
  [Intel XE#306]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/306
  [Intel XE#3113]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3113
  [Intel XE#3124]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3124
  [Intel XE#316]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/316
  [Intel XE#323]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/323
  [Intel XE#3304]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3304
  [Intel XE#3309]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3309
  [Intel XE#3414]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3414
  [Intel XE#3428]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3428
  [Intel XE#3573]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3573
  [Intel XE#367]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/367
  [Intel XE#373]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/373
  [Intel XE#3767]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3767
  [Intel XE#378]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/378
  [Intel XE#3862]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3862
  [Intel XE#3876]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3876
  [Intel XE#3904]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3904
  [Intel XE#3908]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3908
  [Intel XE#4141]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4141
  [Intel XE#4173]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4173
  [Intel XE#4345]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4345
  [Intel XE#4354]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4354
  [Intel XE#4358]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4358
  [Intel XE#4417]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4417
  [Intel XE#4459]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4459
  [Intel XE#4518]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4518
  [Intel XE#455]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/455
  [Intel XE#4596]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4596
  [Intel XE#4733]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4733
  [Intel XE#4757]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4757
  [Intel XE#4819]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4819
  [Intel XE#4821]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4821
  [Intel XE#4837]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4837
  [Intel XE#4915]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4915
  [Intel XE#4937]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4937
  [Intel XE#4943]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4943
  [Intel XE#5018]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5018
  [Intel XE#5042]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5042
  [Intel XE#5172]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5172
  [Intel XE#5214]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5214
  [Intel XE#5255]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5255
  [Intel XE#610]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/610
  [Intel XE#616]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/616
  [Intel XE#651]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/651
  [Intel XE#653]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/653
  [Intel XE#656]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/656
  [Intel XE#776]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/776
  [Intel XE#787]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/787
  [Intel XE#886]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/886
  [Intel XE#929]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/929
  [Intel XE#944]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/944


Build changes
-------------

  * Linux: xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889 -> xe-pw-149550v3

  IGT_8411: d5b5d2bb4f8795a98ea58376a128b74f654b7ec1 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  xe-3253-707bd88d5b799c00ff5be9634b2f4e4ece79d889: 707bd88d5b799c00ff5be9634b2f4e4ece79d889
  xe-pw-149550v3: 149550v3

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-149550v3/index.html

[-- Attachment #2: Type: text/html, Size: 69592 bytes --]

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 03/20] drm/xe/vm: Add attributes struct as member of vma
  2025-06-13 12:55 ` [PATCH v4 03/20] drm/xe/vm: Add attributes struct as member of vma Himal Prasad Ghimiray
@ 2025-06-23  4:18   ` Matthew Brost
  2025-06-23  6:21     ` Ghimiray, Himal Prasad
  2025-06-27 14:32     ` Thomas Hellström
  0 siblings, 2 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23  4:18 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:41PM +0530, Himal Prasad Ghimiray wrote:
> The attribute of xe_vma will determine the migration policy and the
> encoding of the page table entries (PTEs) for that vma.
> This attribute helps manage how memory pages are moved and how their
> addresses are translated. It will be used by madvise to set the
> behavior of the vma.
> 
> v2 (Matthew Brost)
> - Add docs
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm_types.h | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
> index bed6088e1bb3..c7663058a7e3 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -77,6 +77,27 @@ struct xe_userptr {
>  #endif
>  };
>  
> +/**
> + * struct xe_vma_mem_attr - memory attributes associated with vma
> + */
> +struct xe_vma_mem_attr {
> +	/** @preferred_loc: perferred memory_location*/
> +	struct {
> +		/** @preferred_loc.migration_policy: Policy for migration of pages */
> +		u32 migration_policy;
> +
> +		/**
> +		 * @preferred_loc.devmem_fd: used for determining pagemap_fd requested by user
> +		 * DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM and DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE mean
> +		 * system memory or closest device memory respectively.

Nit, I generally prefer 80 character line wraps. I know checkpatch
allows 100 but in general I think Xe generally wraps at 80 unless it is
an odd case with nested code and an 80 character wrap makes the code
unreadable.

80 generally allows 2 windows split vertically in vi on a typical laptop
which makes navigating the code a bit easier.

> +		 */
> +		u32 devmem_fd;
> +	} preferred_loc;
> +
> +	/** @atomic_access: The atomic access type for the vma */

I'd reference the uAPI here. e.g., DRM_XE_VMA_ATOMIC_*

With the minor nits fixed:
Reviewed-by: Matthew Brost <matthew.brost@intel.com>

Matt

> +	u32 atomic_access;
> +};
> +
>  struct xe_vma {
>  	/** @gpuva: Base GPUVA object */
>  	struct drm_gpuva gpuva;
> @@ -135,6 +156,13 @@ struct xe_vma {
>  	 * Needs to be signalled before UNMAP can be processed.
>  	 */
>  	struct xe_user_fence *ufence;
> +
> +	/**
> +	 * @attr: The attributes of vma which determines the migration policy
> +	 * and encoding of the PTEs for this vma.
> +	 */
> +	struct xe_vma_mem_attr attr;
> +
>  };
>  
>  /**
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 02/20] drm/xe/uapi: Add madvise interface
  2025-06-13 12:55 ` [PATCH v4 02/20] drm/xe/uapi: Add madvise interface Himal Prasad Ghimiray
  2025-06-13 14:15   ` Souza, Jose
@ 2025-06-23  4:30   ` Matthew Brost
  2025-06-23  6:20     ` Ghimiray, Himal Prasad
  2025-06-27 14:29     ` Thomas Hellström
  1 sibling, 2 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23  4:30 UTC (permalink / raw)
  To: Himal Prasad Ghimiray
  Cc: intel-xe, thomas.hellstrom, José Roberto de Souza

On Fri, Jun 13, 2025 at 06:25:40PM +0530, Himal Prasad Ghimiray wrote:
> This commit introduces a new madvise interface to support
> driver-specific ioctl operations. The madvise interface allows for more
> efficient memory management by providing hints to the driver about the
> expected memory usage and pte update policy for gpuvma.
> 
> v2 (Matthew/Thomas)
> - Drop num_ops support
> - Drop purgeable support
> - Add kernel-docs
> - IOWR/IOW
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> Acked-by: José Roberto de Souza <jose.souza@intel.com>
> ---
>  include/uapi/drm/xe_drm.h | 118 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 118 insertions(+)
> 
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index 6a702ba7817c..b5f8d11faaa8 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -81,6 +81,7 @@ extern "C" {
>   *  - &DRM_IOCTL_XE_EXEC
>   *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
>   *  - &DRM_IOCTL_XE_OBSERVATION
> + *  - &DRM_IOCTL_XE_MADVISE
>   */
>  
>  /*
> @@ -102,6 +103,7 @@ extern "C" {
>  #define DRM_XE_EXEC			0x09
>  #define DRM_XE_WAIT_USER_FENCE		0x0a
>  #define DRM_XE_OBSERVATION		0x0b
> +#define DRM_XE_MADVISE			0x0c
>  
>  /* Must be kept compact -- no holes */
>  
> @@ -117,6 +119,7 @@ extern "C" {
>  #define DRM_IOCTL_XE_EXEC			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec)
>  #define DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence)
>  #define DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
> +#define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
>  
>  /**
>   * DOC: Xe IOCTL Extensions
> @@ -1970,6 +1973,121 @@ struct drm_xe_query_eu_stall {
>  	__u64 sampling_rates[];
>  };
>  
> +/**
> + * struct drm_xe_madvise - Input of &DRM_IOCTL_XE_MADVISE
> + *
> + * This structure is used to set memory attributes for a virtual address range
> + * in a VM. The type of attribute is specified by @type, and the corresponding
> + * union member is used to provide additional parameters for @type.
> + *
> + * Supported attribute types:
> + * - DRM_XE_VMA_ATTR_PREFERRED_LOC: Set preferred memory location.
> + * - DRM_XE_VMA_ATTR_ATOMIC: Set atomic access policy.
> + * - DRM_XE_VMA_ATTR_PAT: Set page attribute table index.
> + *
> + * Example:
> + *
> + * .. code-block:: C
> + *
> + * struct drm_xe_madvise madvise = {
> + *          .vm_id = vm_id,
> + *          .start = 0x100000,
> + *          .range = 0x2000,
> + *          .type = DRM_XE_VMA_ATTR_ATOMIC,
> + *          .atomic_val = DRM_XE_VMA_ATOMIC_DEVICE,
> + *         };
> + *
> + * ioctl(fd, DRM_IOCTL_XE_MADVISE, &madvise);
> + *
> + */
> +struct drm_xe_madvise {
> +	/** @extensions: Pointer to the first extension struct, if any */
> +	__u64 extensions;
> +
> +	/** @start: start of the virtual address range */
> +	__u64 start;
> +
> +	/** @size: size of the virtual address range */
> +	__u64 range;
> +
> +	/** @vm_id: vm_id of the virtual range */
> +	__u32 vm_id;
> +
> +#define DRM_XE_VMA_ATTR_PREFERRED_LOC	0
> +#define DRM_XE_VMA_ATTR_ATOMIC		1
> +#define DRM_XE_VMA_ATTR_PAT		2
> +	/** @type: type of attribute */
> +	__u32 type;
> +
> +	union {

Nit: I'd make this union is same order as the defines (e.g., preferred location
first, atomic second, pat third).

> +		/**
> +		 * @atomic: Atomic access policy
> +		 *
> +		 * Used when @type == DRM_XE_VMA_ATTR_ATOMIC.
> +		 *
> +		 * Supported values for @atomic.val:
> +		 * - DRM_XE_VMA_ATOMIC_UNDEFINED: Undefined or default behaviour
> +		 *   Support both GPU and CPU atomic operations for system allocator
> +		 *   Support GPU atomic operations for normal(bo) allocator
> +		 * - DRM_XE_VMA_ATOMIC_DEVICE: Support GPU atomic operations
> +		 * - DRM_XE_VMA_ATOMIC_GLOBAL: Support both GPU and CPU atomic operations
> +		 * - DRM_XE_VMA_ATOMIC_CPU: Support CPU atomic
> +		 */
> +		struct {
> +#define DRM_XE_VMA_ATOMIC_UNDEFINED	0
> +#define DRM_XE_VMA_ATOMIC_DEVICE	1
> +#define DRM_XE_VMA_ATOMIC_GLOBAL	2
> +#define DRM_XE_VMA_ATOMIC_CPU		3
> +			/** @atomic.val: value of atomic operation */
> +			__u32 val;
> +
> +			/** @atomic.reserved: Reserved */
> +			__u32 reserved;
> +		} atomic;
> +
> +		/**
> +		 * @pat_index: Page attribute table index
> +		 *
> +		 * Used when @type == DRM_XE_VMA_ATTR_PAT.
> +		 */
> +		struct {
> +			/** @pat_index.val: PAT index value */
> +			__u32 val;
> +
> +			/** @pat_index.reserved: Reserved */
> +			__u32 reserved;
> +		} pat_index;
> +
> +		/**
> +		 * @preferred_mem_loc: preferred memory location
> +		 *
> +		 * Used when @type == DRM_XE_VMA_ATTR_PREFERRED_LOC
> +		 *
> +		 * Supported values for @preferred_mem_loc.devmem_fd:
> +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE: set vram of faulting tile as preferred loc
> +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM: set smem as preferred loc
> +		 *
> +		 * Supported values for @preferred_mem_loc.migration_policy:
> +		 * - DRM_XE_MIGRATE_ALL_PAGES
> +		 * - DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES
> +		 */
> +		struct {
> +#define DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE	0
> +#define DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM	-1
> +			/** @preferred_mem_loc.devmem_fd: fd for preferred loc */
> +			__u32 devmem_fd;
> +
> +#define DRM_XE_MIGRATE_ALL_PAGES		0
> +#define DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES	1

I'd double check with Thomas / maintainers if they want this (migration_policy)
to be included in this version as still more or less unused in this series.

> +			/** @preferred_mem_loc.migration_policy: Page migration policy */
> +			__u32 migration_policy;

Could we future proof a little, maybe migration_policy is a __u16 (or __u8?) and
stick a reserved __u16 in here?

Matt

> +		} preferred_mem_loc;
> +	};
> +
> +	/** @reserved: Reserved */
> +	__u64 reserved[2];
> +};
> +
>  #if defined(__cplusplus)
>  }
>  #endif
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 05/20] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter
  2025-06-13 12:55 ` [PATCH v4 05/20] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter Himal Prasad Ghimiray
@ 2025-06-23  4:38   ` Matthew Brost
  2025-06-23 16:21     ` Matthew Brost
  0 siblings, 1 reply; 68+ messages in thread
From: Matthew Brost @ 2025-06-23  4:38 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:43PM +0530, Himal Prasad Ghimiray wrote:
> This change simplifies the logic by ensuring that remapped previous or
> next VMAs are created with the same memory attributes as the original VMA.
> By passing struct xe_vma_mem_attr as a parameter, we maintain consistency
> in memory attributes.
> 
> -v2
>  *dst = *src (Matthew Brost)
> 
> -v3 (Matthew Brost)
>  Drop unnecessary helper
>  pass attr ptr as input to new_vma and vma_create
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c | 24 +++++++++++++++++-------
>  1 file changed, 17 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 9b705526a3e3..4849d4cc806a 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1168,7 +1168,8 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
>  				    struct xe_bo *bo,
>  				    u64 bo_offset_or_userptr,
>  				    u64 start, u64 end,
> -				    u16 pat_index, unsigned int flags)
> +				    struct xe_vma_mem_attr *attr,
> +				    unsigned int flags)
>  {
>  	struct xe_vma *vma;
>  	struct xe_tile *tile;
> @@ -1223,7 +1224,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
>  	if (vm->xe->info.has_atomic_enable_pte_bit)
>  		vma->gpuva.flags |= XE_VMA_ATOMIC_PTE_BIT;
>  
> -	vma->attr.pat_index = pat_index;
> +	vma->attr = *attr;
>  
>  	if (bo) {
>  		struct drm_gpuvm_bo *vm_bo;
> @@ -2444,7 +2445,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops,
>  ALLOW_ERROR_INJECTION(vm_bind_ioctl_ops_create, ERRNO);
>  
>  static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
> -			      u16 pat_index, unsigned int flags)
> +			      struct xe_vma_mem_attr *attr, unsigned int flags)
>  {
>  	struct xe_bo *bo = op->gem.obj ? gem_to_xe_bo(op->gem.obj) : NULL;
>  	struct drm_exec exec;
> @@ -2473,7 +2474,7 @@ static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
>  	}
>  	vma = xe_vma_create(vm, bo, op->gem.offset,
>  			    op->va.addr, op->va.addr +
> -			    op->va.range - 1, pat_index, flags);
> +			    op->va.range - 1, attr, flags);
>  	if (IS_ERR(vma))
>  		goto err_unlock;
>  
> @@ -2616,6 +2617,15 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
>  		switch (op->base.op) {
>  		case DRM_GPUVA_OP_MAP:
>  		{
> +			struct xe_vma_mem_attr default_attr = {
> +				.preferred_loc = {
> +					.devmem_fd = DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE,
> +					.migration_policy = DRM_XE_MIGRATE_ALL_PAGES,
> +				},
> +				.atomic_access = DRM_XE_VMA_ATOMIC_UNDEFINED,

We need to double-check with the UMD team here — there are ongoing discussions
in our internal repo where we might need to set the default behavior for BOs to
enable global/CPU atomics on BOs with SRAM/VRAM placements. If that is the case,
then if this is a faulting VM, I believe the default should be
DRM_XE_VMA_ATOMIC_GLOBAL. See VLK-66541.

This would be behavior change too, so perhaps the maintainers can comment if
this is allowed or if we need add a query indicating the behavior change.

Let’s close on this before I put an RB here. Everything else LGTM.

Matt

> +				.pat_index = op->map.pat_index,
> +			};
> +
>  			flags |= op->map.read_only ?
>  				VMA_CREATE_FLAG_READ_ONLY : 0;
>  			flags |= op->map.is_null ?
> @@ -2625,7 +2635,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
>  			flags |= op->map.is_cpu_addr_mirror ?
>  				VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR : 0;
>  
> -			vma = new_vma(vm, &op->base.map, op->map.pat_index,
> +			vma = new_vma(vm, &op->base.map, &default_attr,
>  				      flags);
>  			if (IS_ERR(vma))
>  				return PTR_ERR(vma);
> @@ -2673,7 +2683,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
>  
>  			if (op->base.remap.prev) {
>  				vma = new_vma(vm, op->base.remap.prev,
> -					      old->attr.pat_index, flags);
> +					      &old->attr, flags);
>  				if (IS_ERR(vma))
>  					return PTR_ERR(vma);
>  
> @@ -2703,7 +2713,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
>  
>  			if (op->base.remap.next) {
>  				vma = new_vma(vm, op->base.remap.next,
> -					      old->attr.pat_index, flags);
> +					      &old->attr, flags);
>  				if (IS_ERR(vma))
>  					return PTR_ERR(vma);
>  
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 08/20] drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping
  2025-06-13 12:55 ` [PATCH v4 08/20] drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping Himal Prasad Ghimiray
@ 2025-06-23  4:56   ` Matthew Brost
  2025-06-23  6:25     ` Ghimiray, Himal Prasad
  0 siblings, 1 reply; 68+ messages in thread
From: Matthew Brost @ 2025-06-23  4:56 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:46PM +0530, Himal Prasad Ghimiray wrote:
> Introduce xe_svm_ranges_zap_ptes_in_range(), a function to zap page table
> entries (PTEs) for all SVM ranges within a user-specified address range.
> 
> -v2 (Matthew Brost)
> Lock should be called even for tlb_invalidation
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_pt.c  | 14 ++++++++++++-
>  drivers/gpu/drm/xe/xe_svm.c | 42 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_svm.h |  7 +++++++
>  3 files changed, 62 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index 9177c571689e..9a390ef10852 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -950,7 +950,19 @@ bool xe_pt_zap_ptes_range(struct xe_tile *tile, struct xe_vm *vm,
>  	struct xe_pt *pt = vm->pt_root[tile->id];
>  	u8 pt_mask = (range->tile_present & ~range->tile_invalidated);
>  
> -	xe_svm_assert_in_notifier(vm);
> +	/*
> +	 * Locking rules:
> +	 *
> +	 * - notifier_lock (write): full protection against page table changes
> +	 *   and MMU notifier invalidations.
> +	 *
> +	 * - notifier_lock (read) + vm_lock (write): combined protection against
> +	 *   invalidations and concurrent page table modifications. (e.g., madvise)
> +	 *
> +	 */
> +	lockdep_assert(lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 0) ||
> +		       (lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 1) &&
> +		       lockdep_is_held_type(&vm->lock, 0)));
>  
>  	if (!(pt_mask & BIT(tile->id)))
>  		return false;
> diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
> index 2fbbd6a604ea..19420635f1fa 100644
> --- a/drivers/gpu/drm/xe/xe_svm.c
> +++ b/drivers/gpu/drm/xe/xe_svm.c
> @@ -999,6 +999,48 @@ int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range,
>  	return err;
>  }
>  
> +/**
> + * xe_svm_ranges_zap_ptes_in_range - clear ptes of svm ranges in input range
> + * @vm: Pointer to the xe_vm structure
> + * @start: Start of the input range
> + * @end: End of the input range
> + *
> + * This function removes the page table entries (PTEs) associated
> + * with the svm ranges within the given input start and end
> + *
> + * Return: tile_mask for which gt's need to be tlb invalidated.
> + */
> +u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
> +{
> +	struct drm_gpusvm_notifier *notifier;
> +	struct xe_svm_range *range;
> +	u64 adj_start, adj_end;
> +	struct xe_tile *tile;
> +	u8 tile_mask = 0;
> +	u8 id;
> +
> +	lockdep_assert(lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 1) &&
> +		       lockdep_is_held_type(&vm->lock, 0));
> +
> +	drm_gpusvm_for_each_notifier(notifier, &vm->svm.gpusvm, start, end) {
> +		struct drm_gpusvm_range *r = NULL;
> +
> +		adj_start = max(start, notifier->itree.start);

s/notifier->itree.start/drm_gpusvm_notifier_start

> +		adj_end = min(end, notifier->itree.last + 1);

s/notifier->itree.last + 1/drm_gpusvm_notifier_end

> +		drm_gpusvm_for_each_range(r, notifier, adj_start, adj_end) {
> +			range = to_xe_range(r);
> +			for_each_tile(tile, vm->xe, id) {
> +				if (xe_pt_zap_ptes_range(tile, vm, range)) {
> +					tile_mask |= BIT(id);
> +					range->tile_invalidated |= BIT(id);

/* WRITE_ONCE pairs with READ_ONCE in xe_vm_has_valid_gpu_mapping() */
WRITE_ONCE(range->tile_invalidated, range->tile_invalidated | BIT(id));

Also, we need to be careful here. If we can fail after this point but
before the TLB invalidation completes, we could break the notifier, as
the notifier would skip the TLB invalidation. The code, as written, can
only fail if the CT channel is down — in that case, all bets are off and
we are issuing a GT reset. So, I think the code as written is okay, but
I’d add a comment here indicating that there must be no failure points
between setting tile_invalidated and issuing the TLB invalidation.

Matt

> +				}
> +			}
> +		}
> +	}
> +
> +	return tile_mask;
> +}
> +
>  #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR)
>  
>  static struct drm_pagemap_device_addr
> diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
> index 19ce4f2754a7..af8f285b6caa 100644
> --- a/drivers/gpu/drm/xe/xe_svm.h
> +++ b/drivers/gpu/drm/xe/xe_svm.h
> @@ -91,6 +91,7 @@ bool xe_svm_range_validate(struct xe_vm *vm,
>  
>  u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end,  struct xe_vma *vma);
>  
> +u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end);
>  /**
>   * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping
>   * @range: SVM range
> @@ -305,6 +306,12 @@ u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end, struct xe_vma *vm
>  	return ULONG_MAX;
>  }
>  
> +static inline
> +u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
> +{
> +	return 0;
> +}
> +
>  #define xe_svm_assert_in_notifier(...) do {} while (0)
>  #define xe_svm_range_has_dma_mapping(...) false
>  
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe
  2025-06-13 12:55 ` [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe Himal Prasad Ghimiray
@ 2025-06-23  5:33   ` Matthew Brost
  2025-06-26  6:04   ` Lin, Shuicheng
  1 sibling, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23  5:33 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:47PM +0530, Himal Prasad Ghimiray wrote:
> This driver-specific ioctl enables UMDs to control the memory attributes
> for GPU VMAs within a specified input range. If the start or end
> addresses fall within an existing VMA, the VMA is split accordingly. The
> attributes of the VMA are modified as provided by the users. The old
> mappings of the VMAs are invalidated, and TLB invalidation is performed
> if necessary.
> 
> v2(Matthew brost)
> - xe_vm_in_fault_mode can't be enabled by Mesa, hence allow ioctl in non
> fault mode too
> - fix tlb invalidation skip for same ranges in multiple op
> - use helper for tlb invalidation
> - use xe_svm_notifier_lock/unlock helper
> - s/lockdep_assert_held/lockdep_assert_held_write
> - Add kernel-doc
> 
> v3(Matthew Brost)
> - make vfunc fail safe
> - Add sanitizing input args before vfunc
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/Makefile        |   1 +
>  drivers/gpu/drm/xe/xe_device.c     |   2 +
>  drivers/gpu/drm/xe/xe_vm_madvise.c | 282 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_vm_madvise.h |  15 ++
>  4 files changed, 300 insertions(+)
>  create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
>  create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h
> 
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> index f5f5775acdc0..d375b549c30f 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -117,6 +117,7 @@ xe-y += xe_bb.o \
>  	xe_uc.o \
>  	xe_uc_fw.o \
>  	xe_vm.o \
> +	xe_vm_madvise.o \
>  	xe_vram.o \
>  	xe_vram_freq.o \
>  	xe_vsec.o \
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 7d9a31868ea9..632d3ab12392 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -61,6 +61,7 @@
>  #include "xe_ttm_stolen_mgr.h"
>  #include "xe_ttm_sys_mgr.h"
>  #include "xe_vm.h"
> +#include "xe_vm_madvise.h"
>  #include "xe_vram.h"
>  #include "xe_vsec.h"
>  #include "xe_wait_user_fence.h"
> @@ -197,6 +198,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
>  	DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE, xe_wait_user_fence_ioctl,
>  			  DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl, DRM_RENDER_ALLOW),

I'd make this change the last patch in the series once the
implementation is complete.

>  };
>  
>  static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
> new file mode 100644
> index 000000000000..ff560914ad7e
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
> @@ -0,0 +1,282 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#include "xe_vm_madvise.h"
> +
> +#include <linux/nospec.h>
> +#include <drm/ttm/ttm_tt.h>

Why do you need the ttm_tt include?

> +#include <drm/xe_drm.h>
> +
> +#include "xe_bo.h"
> +#include "xe_gt_tlb_invalidation.h"

I don't this you need the xe_gt_tlb_invalidation include.

> +#include "xe_pt.h"
> +#include "xe_svm.h"
> +
> +struct xe_vmas_in_madvise_range {
> +	u64 addr;
> +	u64 range;
> +	struct xe_vma **vmas;
> +	int num_vmas;
> +	bool has_svm_vmas;
> +	bool has_bo_vmas;
> +	bool has_userptr_vmas;
> +};
> +
> +static int get_vmas(struct xe_vm *vm, struct xe_vmas_in_madvise_range *madvise_range)
> +{
> +	u64 addr = madvise_range->addr;
> +	u64 range = madvise_range->range;
> +
> +	struct xe_vma  **__vmas;
> +	struct drm_gpuva *gpuva;
> +	int max_vmas = 8;
> +
> +	lockdep_assert_held(&vm->lock);
> +
> +	madvise_range->num_vmas = 0;
> +	madvise_range->vmas = kmalloc_array(max_vmas, sizeof(*madvise_range->vmas), GFP_KERNEL);
> +	if (!madvise_range->vmas)
> +		return -ENOMEM;
> +
> +	vm_dbg(&vm->xe->drm, "VMA's in range: start=0x%016llx, end=0x%016llx", addr, addr + range);
> +
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, addr, addr + range) {
> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> +
> +		if (xe_vma_bo(vma))
> +			madvise_range->has_bo_vmas = true;
> +		else if (xe_vma_is_cpu_addr_mirror(vma))
> +			madvise_range->has_svm_vmas = true;
> +		else if (xe_vma_is_userptr(vma))
> +			madvise_range->has_userptr_vmas = true;
> +		else
> +			XE_WARN_ON("UNEXPECTED VMA");

A NULL range would be odd to set madvise for but I don't think it
warrents a WARN_ON, rather just ingore it.

> +
> +		if (madvise_range->num_vmas == max_vmas) {
> +			max_vmas <<= 1;
> +			__vmas = krealloc(madvise_range->vmas,
> +					  max_vmas * sizeof(*madvise_range->vmas),
> +					  GFP_KERNEL);
> +			if (!__vmas) {
> +				kfree(madvise_range->vmas);
> +				return -ENOMEM;
> +			}
> +			madvise_range->vmas = __vmas;
> +		}
> +
> +		madvise_range->vmas[madvise_range->num_vmas] = vma;
> +		(madvise_range->num_vmas)++;
> +	}
> +
> +	if (!madvise_range->num_vmas)
> +		kfree(madvise_range->vmas);
> +
> +	vm_dbg(&vm->xe->drm, "madvise_range-num_vmas = %d\n", madvise_range->num_vmas);
> +
> +	return 0;
> +}
> +
> +static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm *vm,
> +				      struct xe_vma **vmas, int num_vmas,
> +				      struct drm_xe_madvise *op)
> +{
> +	/* Implementation pending */
> +}
> +
> +static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
> +			   struct xe_vma **vmas, int num_vmas,
> +			   struct drm_xe_madvise *op)
> +{
> +	/* Implementation pending */
> +}
> +
> +static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
> +			      struct xe_vma **vmas, int num_vmas,
> +			      struct drm_xe_madvise *op)
> +{
> +	/* Implementation pending */
> +}
> +
> +typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
> +			     struct xe_vma **vmas, int num_vmas,
> +			     struct drm_xe_madvise *op);
> +
> +static const madvise_func madvise_funcs[] = {
> +	[DRM_XE_VMA_ATTR_PREFERRED_LOC] = madvise_preferred_mem_loc,
> +	[DRM_XE_VMA_ATTR_ATOMIC] = madvise_atomic,
> +	[DRM_XE_VMA_ATTR_PAT] = madvise_pat_index,
> +};
> +
> +static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start, u64 end, u8 *tile_mask)

Return a tile_mask?

> +{
> +	struct drm_gpuva *gpuva;
> +	struct xe_tile *tile;
> +	u8 id;
> +
> +	lockdep_assert_held_write(&vm->lock);
> +

/* Wait for pending binds */

> +	if (dma_resv_wait_timeout(xe_vm_resv(vm), DMA_RESV_USAGE_BOOKKEEP,
> +				  false, MAX_SCHEDULE_TIMEOUT) <= 0)
> +		XE_WARN_ON(1);
> +
> +	*tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
> +
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> +
> +		if (xe_vma_is_cpu_addr_mirror(vma))
> +			continue;
> +
> +		if (xe_vma_is_userptr(vma)) {
> +			WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
> +							     DMA_RESV_USAGE_BOOKKEEP));
> +		}

You don't need brackets.

Also I think BO move could make this pop. So this might be incorrect in
xe_vm_invalidate_vma too. Maybe let's check with Thomas on this as he
added this to xe_vm_invalidate_vma originally.

> +
> +		for_each_tile(tile, vm->xe, id) {
> +			if (xe_pt_zap_ptes(tile, vma)) {
> +				*tile_mask |= BIT(id);
> +				vma->tile_invalidated |= BIT(id);

WRITE_ONCE /w pairs with comment.

> +			}
> +		}
> +	}
> +}
> +
> +static int xe_vm_invalidate_madvise_range(struct xe_vm *vm, u64 start, u64 end)
> +{
> +	u8 tile_mask = 0;
> +
> +	xe_zap_ptes_in_madvise_range(vm, start, end, &tile_mask);
> +	if (!tile_mask)
> +		return 0;
> +
> +	xe_device_wmb(vm->xe);
> +
> +	return xe_vm_range_tilemask_tlb_invalidation(vm, start, end, tile_mask);
> +}
> +
> +static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const struct drm_xe_madvise *args)
> +{
> +	if (XE_IOCTL_DBG(xe, !args))
> +		return -EINVAL;
> +
> +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->start, SZ_4K)))
> +		return -EINVAL;
> +
> +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->range, SZ_4K)))
> +		return -EINVAL;
> +
> +	if (XE_IOCTL_DBG(xe, args->range < SZ_4K))
> +		return -EINVAL;
> +
> +	switch (args->type) {
> +	case DRM_XE_VMA_ATTR_ATOMIC:
> +		if (XE_IOCTL_DBG(xe, args->atomic.val > DRM_XE_VMA_ATOMIC_CPU))
> +			return -EINVAL;

Ensure atomic.reserved is zero.

> +		break;
> +	case DRM_XE_VMA_ATTR_PAT:
> +		/*TODO: Add valid pat check */
> +		break;
> +	case DRM_XE_VMA_ATTR_PREFERRED_LOC:
> +		if (XE_IOCTL_DBG(xe, args->preferred_mem_loc.migration_policy >
> +				     DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES))
> +			return -EINVAL;
> +		break;
> +	default:
> +		if (XE_IOCTL_DBG(xe, 1))
> +			return -EINVAL;
> +	}
> +
> +	if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +/**
> + * xe_vm_madvise_ioctl - Handle MADVise ioctl for a VM
> + * @dev: DRM device pointer
> + * @data: Pointer to ioctl data (drm_xe_madvise*)
> + * @file: DRM file pointer
> + *
> + * Handles the MADVISE ioctl to provide memory advice for vma's within
> + * input range.
> + *
> + * Return: 0 on success or a negative error code on failure.
> + */
> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
> +{
> +	struct xe_device *xe = to_xe_device(dev);
> +	struct xe_file *xef = to_xe_file(file);
> +	struct drm_xe_madvise *args = data;
> +	struct xe_vm *vm;
> +	struct xe_bo *bo;
> +	struct drm_exec exec;
> +	int err = 0;
> +	int attr_type;
> +
> +	vm = xe_vm_lookup(xef, args->vm_id);
> +	if (XE_IOCTL_DBG(xe, !vm))
> +		return -EINVAL;
> +
> +	if (drm_xe_madvise_args_are_sane(vm->xe, args))
> +		return -EINVAL;
> +
> +	down_write(&vm->lock);

down_write_killable + error check.

> +
> +	if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
> +		err = -ENOENT;
> +		goto unlock_vm;
> +	}
> +
> +	xe_vm_alloc_madvise_vma(vm, args->start, args->range);

This function has a return value, any reason you are not checking the
return value and erroring out on failure? 

> +
> +	struct xe_vmas_in_madvise_range madvise_range = {.addr = args->start,
> +							 .range =  args->range, };
> +	err = get_vmas(vm, &madvise_range);
> +	if (err || !madvise_range.num_vmas)
> +		goto unlock_vm;
> +
> +	if (madvise_range.has_bo_vmas) {
> +		drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);

| DRM_EXEC_INTERRUPTIBLE_WAIT

> +		drm_exec_until_all_locked(&exec) {
> +			for (int i = 0; i < madvise_range.num_vmas; i++) {
> +				bo = xe_vma_bo(madvise_range.vmas[i]);

Since BO is local, struct xe_bo *bo =...

Then delete struct xe_bo at the top of the function.

> +				if (!bo)
> +					continue;
> +				err = drm_exec_lock_obj(&exec, &bo->ttm.base);
> +				drm_exec_retry_on_contention(&exec);
> +				if (err)
> +					goto err_fini;
> +			}
> +		}
> +	}
> +
> +	if (madvise_range.has_userptr_vmas)
> +		down_read(&vm->userptr.notifier_lock);
> +
> +	if (madvise_range.has_svm_vmas)
> +		xe_svm_notifier_lock(vm);

These likely should be interruptable locks too... 

> +
> +	attr_type = array_index_nospec(args->type, ARRAY_SIZE(madvise_funcs));
> +	madvise_funcs[attr_type](xe, vm, madvise_range.vmas, madvise_range.num_vmas, args);
> +
> +	kfree(madvise_range.vmas);
> +	madvise_range.vmas = NULL;
> +
> +	err = xe_vm_invalidate_madvise_range(vm, args->start, args->start + args->range);
> +
> +	if (madvise_range.has_svm_vmas)
> +		xe_svm_notifier_unlock(vm);
> +
> +	if (madvise_range.has_userptr_vmas)
> +		up_read(&vm->userptr.notifier_lock);
> +err_fini:

The error handling is wrong here. You'd leak madvise_range.vmas on this
error path.

Matt

> +	if (madvise_range.has_bo_vmas)
> +		drm_exec_fini(&exec);
> +unlock_vm:
> +	up_write(&vm->lock);
> +	xe_vm_put(vm);
> +	return err;
> +}
> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.h b/drivers/gpu/drm/xe/xe_vm_madvise.h
> new file mode 100644
> index 000000000000..b0e1fc445f23
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#ifndef _XE_VM_MADVISE_H_
> +#define _XE_VM_MADVISE_H_
> +
> +struct drm_device;
> +struct drm_file;
> +
> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data,
> +			struct drm_file *file);
> +
> +#endif
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 10/20] drm/xe/vm: Add an identifier for madvise in xe_vma_ops
  2025-06-13 12:55 ` [PATCH v4 10/20] drm/xe/vm: Add an identifier for madvise in xe_vma_ops Himal Prasad Ghimiray
@ 2025-06-23  5:38   ` Matthew Brost
  2025-06-23  6:28     ` Ghimiray, Himal Prasad
  0 siblings, 1 reply; 68+ messages in thread
From: Matthew Brost @ 2025-06-23  5:38 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:48PM +0530, Himal Prasad Ghimiray wrote:
> The flag XE_VMA_OPS_FLAG_MADVISE is introduced to  determine whether
> xe_vma_ops is initialized by madvise operation on not.
> 

I'd just squash this into patch #7.

Then move patch #11 directly after patch #7 to tell a coherent story.

Matt

> Suggested-by: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c       | 1 +
>  drivers/gpu/drm/xe/xe_vm_types.h | 1 +
>  2 files changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index f5f8de113eae..e059d9810d26 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -4237,6 +4237,7 @@ int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t start, uint64_t range)
>  	}
>  
>  	xe_vma_ops_init(&vops, vm, NULL, NULL, 0);
> +	vops.flags |= XE_VMA_OPS_FLAG_MADVISE;
>  	err = vm_bind_ioctl_ops_parse(vm, ops, &vops);
>  	if (err)
>  		goto unwind_ops;
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
> index cde2583da303..c7156f8e2ed2 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -489,6 +489,7 @@ struct xe_vma_ops {
>  	struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE];
>  	/** @flag: signify the properties within xe_vma_ops*/
>  #define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0)
> +#define XE_VMA_OPS_FLAG_MADVISE          BIT(1)
>  	u32 flags;
>  #ifdef TEST_VM_OPS_ERROR
>  	/** @inject_error: inject error to test error handling */
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise
  2025-06-13 12:55 ` [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise Himal Prasad Ghimiray
  2025-06-14  4:31   ` kernel test robot
@ 2025-06-23  5:52   ` Matthew Brost
  2025-06-23  6:18     ` Ghimiray, Himal Prasad
  1 sibling, 1 reply; 68+ messages in thread
From: Matthew Brost @ 2025-06-23  5:52 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:49PM +0530, Himal Prasad Ghimiray wrote:
> In the case of the MADVISE ioctl, if the start or end addresses fall
> within a VMA and existing SVM ranges are present, remove the existing
> SVM mappings. Then, continue with ops_parse to create new VMAs by REMAP
> unmapping of old one.
> 
> v2 (Matthew Brost)
> - Use vops flag to call unmapping of ranges in vm_bind_ioctl_ops_parse
> - Rename the function
> 
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_svm.c | 27 +++++++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_svm.h |  8 ++++++++
>  drivers/gpu/drm/xe/xe_vm.c  |  8 ++++++--
>  3 files changed, 41 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
> index 19420635f1fa..df6992ee2e2d 100644
> --- a/drivers/gpu/drm/xe/xe_svm.c
> +++ b/drivers/gpu/drm/xe/xe_svm.c
> @@ -935,6 +935,33 @@ bool xe_svm_has_mapping(struct xe_vm *vm, u64 start, u64 end)
>  	return drm_gpusvm_has_mapping(&vm->svm.gpusvm, start, end);
>  }
>  
> +/**
> + * xe_svm_unmap_address_range - UNMAP SVM mappings and ranges
> + * @start: start addr
> + * @end: end addr
> + *
> + * This function UNMAPS svm ranges if start or end address are inside them.
> + */
> +void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end)
> +{
> +	struct drm_gpusvm_notifier *notifier, *next;
> +
> +	lockdep_assert_held_write(&vm->lock);
> +
> +	drm_gpusvm_for_each_notifier_safe(notifier, next, &vm->svm.gpusvm, start, end) {
> +		struct drm_gpusvm_range *range, *__next;
> +
> +		drm_gpusvm_for_each_range_safe(range, __next, notifier, start, end) {
> +			if (start > drm_gpusvm_range_start(range) ||
> +			    end < drm_gpusvm_range_end(range)) {
> +				if (IS_DGFX(vm->xe) && xe_svm_range_in_vram(to_xe_range(range)))
> +					drm_gpusvm_range_evict(&vm->svm.gpusvm, range);

I think you could use xe_svm_range_migrate_to_smem here but also I don't
eviction is strickly required here either. This akin to a partial unmap
and we don't evict there. Any reason that I'm missing here?

Matt

> +				__xe_svm_garbage_collector(vm, to_xe_range(range));
> +			}
> +		}
> +	}
> +}
> +
>  /**
>   * xe_svm_bo_evict() - SVM evict BO to system memory
>   * @bo: BO to evict
> diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
> index af8f285b6caa..4e5d42323679 100644
> --- a/drivers/gpu/drm/xe/xe_svm.h
> +++ b/drivers/gpu/drm/xe/xe_svm.h
> @@ -92,6 +92,9 @@ bool xe_svm_range_validate(struct xe_vm *vm,
>  u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end,  struct xe_vma *vma);
>  
>  u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end);
> +
> +void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end);
> +
>  /**
>   * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping
>   * @range: SVM range
> @@ -312,6 +315,11 @@ u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
>  	return 0;
>  }
>  
> +static inline
> +void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end)
> +{
> +}
> +
>  #define xe_svm_assert_in_notifier(...) do {} while (0)
>  #define xe_svm_range_has_dma_mapping(...) false
>  
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index e059d9810d26..0872df8d0b15 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -2663,8 +2663,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
>  				end = op->base.remap.next->va.addr;
>  
>  			if (xe_vma_is_cpu_addr_mirror(old) &&
> -			    xe_svm_has_mapping(vm, start, end))
> -				return -EBUSY;
> +			    xe_svm_has_mapping(vm, start, end)) {
> +				if (vops->flags & XE_VMA_OPS_FLAG_MADVISE)
> +					xe_svm_unmap_address_range(vm, start, end);
> +				else
> +					return -EBUSY;
> +			}
>  
>  			op->remap.start = xe_vma_start(old);
>  			op->remap.range = xe_vma_size(old);
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise
  2025-06-23  5:52   ` Matthew Brost
@ 2025-06-23  6:18     ` Ghimiray, Himal Prasad
  2025-06-23 11:45       ` Matthew Brost
  0 siblings, 1 reply; 68+ messages in thread
From: Ghimiray, Himal Prasad @ 2025-06-23  6:18 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe, thomas.hellstrom



On 23-06-2025 11:22, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:49PM +0530, Himal Prasad Ghimiray wrote:
>> In the case of the MADVISE ioctl, if the start or end addresses fall
>> within a VMA and existing SVM ranges are present, remove the existing
>> SVM mappings. Then, continue with ops_parse to create new VMAs by REMAP
>> unmapping of old one.
>>
>> v2 (Matthew Brost)
>> - Use vops flag to call unmapping of ranges in vm_bind_ioctl_ops_parse
>> - Rename the function
>>
>> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_svm.c | 27 +++++++++++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_svm.h |  8 ++++++++
>>   drivers/gpu/drm/xe/xe_vm.c  |  8 ++++++--
>>   3 files changed, 41 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
>> index 19420635f1fa..df6992ee2e2d 100644
>> --- a/drivers/gpu/drm/xe/xe_svm.c
>> +++ b/drivers/gpu/drm/xe/xe_svm.c
>> @@ -935,6 +935,33 @@ bool xe_svm_has_mapping(struct xe_vm *vm, u64 start, u64 end)
>>   	return drm_gpusvm_has_mapping(&vm->svm.gpusvm, start, end);
>>   }
>>   
>> +/**
>> + * xe_svm_unmap_address_range - UNMAP SVM mappings and ranges
>> + * @start: start addr
>> + * @end: end addr
>> + *
>> + * This function UNMAPS svm ranges if start or end address are inside them.
>> + */
>> +void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end)
>> +{
>> +	struct drm_gpusvm_notifier *notifier, *next;
>> +
>> +	lockdep_assert_held_write(&vm->lock);
>> +
>> +	drm_gpusvm_for_each_notifier_safe(notifier, next, &vm->svm.gpusvm, start, end) {
>> +		struct drm_gpusvm_range *range, *__next;
>> +
>> +		drm_gpusvm_for_each_range_safe(range, __next, notifier, start, end) {
>> +			if (start > drm_gpusvm_range_start(range) ||
>> +			    end < drm_gpusvm_range_end(range)) {
>> +				if (IS_DGFX(vm->xe) && xe_svm_range_in_vram(to_xe_range(range)))
>> +					drm_gpusvm_range_evict(&vm->svm.gpusvm, range);
> 
> I think you could use xe_svm_range_migrate_to_smem here but also I don't
> eviction is strickly required here either. This akin to a partial unmap
> and we don't evict there. Any reason that I'm missing here?

If previous ranges had devmem pages allocated, and eviction did not 
occur, subsequent VRAM allocations for smaller ranges were failing.

Scenario:

A 2 MiB range existed with VRAM allocation.
A madvise call triggered a split, invoking xe_svm_unmap_address_range.
Without eviction, the 64 KiB sub-ranges failed to allocate VRAM during 
subsequent page faults.
As a result, bindings were being forced from system memory (SMEM) 
instead of VRAM.
  >
> Matt
> 
>> +				__xe_svm_garbage_collector(vm, to_xe_range(range));
>> +			}
>> +		}
>> +	}
>> +}
>> +
>>   /**
>>    * xe_svm_bo_evict() - SVM evict BO to system memory
>>    * @bo: BO to evict
>> diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
>> index af8f285b6caa..4e5d42323679 100644
>> --- a/drivers/gpu/drm/xe/xe_svm.h
>> +++ b/drivers/gpu/drm/xe/xe_svm.h
>> @@ -92,6 +92,9 @@ bool xe_svm_range_validate(struct xe_vm *vm,
>>   u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end,  struct xe_vma *vma);
>>   
>>   u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end);
>> +
>> +void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end);
>> +
>>   /**
>>    * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping
>>    * @range: SVM range
>> @@ -312,6 +315,11 @@ u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
>>   	return 0;
>>   }
>>   
>> +static inline
>> +void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end)
>> +{
>> +}
>> +
>>   #define xe_svm_assert_in_notifier(...) do {} while (0)
>>   #define xe_svm_range_has_dma_mapping(...) false
>>   
>> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
>> index e059d9810d26..0872df8d0b15 100644
>> --- a/drivers/gpu/drm/xe/xe_vm.c
>> +++ b/drivers/gpu/drm/xe/xe_vm.c
>> @@ -2663,8 +2663,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
>>   				end = op->base.remap.next->va.addr;
>>   
>>   			if (xe_vma_is_cpu_addr_mirror(old) &&
>> -			    xe_svm_has_mapping(vm, start, end))
>> -				return -EBUSY;
>> +			    xe_svm_has_mapping(vm, start, end)) {
>> +				if (vops->flags & XE_VMA_OPS_FLAG_MADVISE)
>> +					xe_svm_unmap_address_range(vm, start, end);
>> +				else
>> +					return -EBUSY;
>> +			}
>>   
>>   			op->remap.start = xe_vma_start(old);
>>   			op->remap.range = xe_vma_size(old);
>> -- 
>> 2.34.1
>>


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 02/20] drm/xe/uapi: Add madvise interface
  2025-06-23  4:30   ` Matthew Brost
@ 2025-06-23  6:20     ` Ghimiray, Himal Prasad
  2025-06-27 13:47       ` Thomas Hellström
  2025-06-27 14:29     ` Thomas Hellström
  1 sibling, 1 reply; 68+ messages in thread
From: Ghimiray, Himal Prasad @ 2025-06-23  6:20 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe, thomas.hellstrom, José Roberto de Souza



On 23-06-2025 10:00, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:40PM +0530, Himal Prasad Ghimiray wrote:
>> This commit introduces a new madvise interface to support
>> driver-specific ioctl operations. The madvise interface allows for more
>> efficient memory management by providing hints to the driver about the
>> expected memory usage and pte update policy for gpuvma.
>>
>> v2 (Matthew/Thomas)
>> - Drop num_ops support
>> - Drop purgeable support
>> - Add kernel-docs
>> - IOWR/IOW
>>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> Acked-by: José Roberto de Souza <jose.souza@intel.com>
>> ---
>>   include/uapi/drm/xe_drm.h | 118 ++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 118 insertions(+)
>>
>> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
>> index 6a702ba7817c..b5f8d11faaa8 100644
>> --- a/include/uapi/drm/xe_drm.h
>> +++ b/include/uapi/drm/xe_drm.h
>> @@ -81,6 +81,7 @@ extern "C" {
>>    *  - &DRM_IOCTL_XE_EXEC
>>    *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
>>    *  - &DRM_IOCTL_XE_OBSERVATION
>> + *  - &DRM_IOCTL_XE_MADVISE
>>    */
>>   
>>   /*
>> @@ -102,6 +103,7 @@ extern "C" {
>>   #define DRM_XE_EXEC			0x09
>>   #define DRM_XE_WAIT_USER_FENCE		0x0a
>>   #define DRM_XE_OBSERVATION		0x0b
>> +#define DRM_XE_MADVISE			0x0c
>>   
>>   /* Must be kept compact -- no holes */
>>   
>> @@ -117,6 +119,7 @@ extern "C" {
>>   #define DRM_IOCTL_XE_EXEC			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec)
>>   #define DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence)
>>   #define DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
>> +#define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
>>   
>>   /**
>>    * DOC: Xe IOCTL Extensions
>> @@ -1970,6 +1973,121 @@ struct drm_xe_query_eu_stall {
>>   	__u64 sampling_rates[];
>>   };
>>   
>> +/**
>> + * struct drm_xe_madvise - Input of &DRM_IOCTL_XE_MADVISE
>> + *
>> + * This structure is used to set memory attributes for a virtual address range
>> + * in a VM. The type of attribute is specified by @type, and the corresponding
>> + * union member is used to provide additional parameters for @type.
>> + *
>> + * Supported attribute types:
>> + * - DRM_XE_VMA_ATTR_PREFERRED_LOC: Set preferred memory location.
>> + * - DRM_XE_VMA_ATTR_ATOMIC: Set atomic access policy.
>> + * - DRM_XE_VMA_ATTR_PAT: Set page attribute table index.
>> + *
>> + * Example:
>> + *
>> + * .. code-block:: C
>> + *
>> + * struct drm_xe_madvise madvise = {
>> + *          .vm_id = vm_id,
>> + *          .start = 0x100000,
>> + *          .range = 0x2000,
>> + *          .type = DRM_XE_VMA_ATTR_ATOMIC,
>> + *          .atomic_val = DRM_XE_VMA_ATOMIC_DEVICE,
>> + *         };
>> + *
>> + * ioctl(fd, DRM_IOCTL_XE_MADVISE, &madvise);
>> + *
>> + */
>> +struct drm_xe_madvise {
>> +	/** @extensions: Pointer to the first extension struct, if any */
>> +	__u64 extensions;
>> +
>> +	/** @start: start of the virtual address range */
>> +	__u64 start;
>> +
>> +	/** @size: size of the virtual address range */
>> +	__u64 range;
>> +
>> +	/** @vm_id: vm_id of the virtual range */
>> +	__u32 vm_id;
>> +
>> +#define DRM_XE_VMA_ATTR_PREFERRED_LOC	0
>> +#define DRM_XE_VMA_ATTR_ATOMIC		1
>> +#define DRM_XE_VMA_ATTR_PAT		2
>> +	/** @type: type of attribute */
>> +	__u32 type;
>> +
>> +	union {
> 
> Nit: I'd make this union is same order as the defines (e.g., preferred location
> first, atomic second, pat third).

sure

> 
>> +		/**
>> +		 * @atomic: Atomic access policy
>> +		 *
>> +		 * Used when @type == DRM_XE_VMA_ATTR_ATOMIC.
>> +		 *
>> +		 * Supported values for @atomic.val:
>> +		 * - DRM_XE_VMA_ATOMIC_UNDEFINED: Undefined or default behaviour
>> +		 *   Support both GPU and CPU atomic operations for system allocator
>> +		 *   Support GPU atomic operations for normal(bo) allocator
>> +		 * - DRM_XE_VMA_ATOMIC_DEVICE: Support GPU atomic operations
>> +		 * - DRM_XE_VMA_ATOMIC_GLOBAL: Support both GPU and CPU atomic operations
>> +		 * - DRM_XE_VMA_ATOMIC_CPU: Support CPU atomic
>> +		 */
>> +		struct {
>> +#define DRM_XE_VMA_ATOMIC_UNDEFINED	0
>> +#define DRM_XE_VMA_ATOMIC_DEVICE	1
>> +#define DRM_XE_VMA_ATOMIC_GLOBAL	2
>> +#define DRM_XE_VMA_ATOMIC_CPU		3
>> +			/** @atomic.val: value of atomic operation */
>> +			__u32 val;
>> +
>> +			/** @atomic.reserved: Reserved */
>> +			__u32 reserved;
>> +		} atomic;
>> +
>> +		/**
>> +		 * @pat_index: Page attribute table index
>> +		 *
>> +		 * Used when @type == DRM_XE_VMA_ATTR_PAT.
>> +		 */
>> +		struct {
>> +			/** @pat_index.val: PAT index value */
>> +			__u32 val;
>> +
>> +			/** @pat_index.reserved: Reserved */
>> +			__u32 reserved;
>> +		} pat_index;
>> +
>> +		/**
>> +		 * @preferred_mem_loc: preferred memory location
>> +		 *
>> +		 * Used when @type == DRM_XE_VMA_ATTR_PREFERRED_LOC
>> +		 *
>> +		 * Supported values for @preferred_mem_loc.devmem_fd:
>> +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE: set vram of faulting tile as preferred loc
>> +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM: set smem as preferred loc
>> +		 *
>> +		 * Supported values for @preferred_mem_loc.migration_policy:
>> +		 * - DRM_XE_MIGRATE_ALL_PAGES
>> +		 * - DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES
>> +		 */
>> +		struct {
>> +#define DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE	0
>> +#define DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM	-1
>> +			/** @preferred_mem_loc.devmem_fd: fd for preferred loc */
>> +			__u32 devmem_fd;
>> +
>> +#define DRM_XE_MIGRATE_ALL_PAGES		0
>> +#define DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES	1
> 
> I'd double check with Thomas / maintainers if they want this (migration_policy)
> to be included in this version as still more or less unused in this series.

Sure

> 
>> +			/** @preferred_mem_loc.migration_policy: Page migration policy */
>> +			__u32 migration_policy;
> 
> Could we future proof a little, maybe migration_policy is a __u16 (or __u8?) and
> stick a reserved __u16 in here?

OK

> 
> Matt
> 
>> +		} preferred_mem_loc;
>> +	};
>> +
>> +	/** @reserved: Reserved */
>> +	__u64 reserved[2];
>> +};
>> +
>>   #if defined(__cplusplus)
>>   }
>>   #endif
>> -- 
>> 2.34.1
>>



^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 03/20] drm/xe/vm: Add attributes struct as member of vma
  2025-06-23  4:18   ` Matthew Brost
@ 2025-06-23  6:21     ` Ghimiray, Himal Prasad
  2025-06-27 14:32     ` Thomas Hellström
  1 sibling, 0 replies; 68+ messages in thread
From: Ghimiray, Himal Prasad @ 2025-06-23  6:21 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe, thomas.hellstrom



On 23-06-2025 09:48, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:41PM +0530, Himal Prasad Ghimiray wrote:
>> The attribute of xe_vma will determine the migration policy and the
>> encoding of the page table entries (PTEs) for that vma.
>> This attribute helps manage how memory pages are moved and how their
>> addresses are translated. It will be used by madvise to set the
>> behavior of the vma.
>>
>> v2 (Matthew Brost)
>> - Add docs
>>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_vm_types.h | 28 ++++++++++++++++++++++++++++
>>   1 file changed, 28 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
>> index bed6088e1bb3..c7663058a7e3 100644
>> --- a/drivers/gpu/drm/xe/xe_vm_types.h
>> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
>> @@ -77,6 +77,27 @@ struct xe_userptr {
>>   #endif
>>   };
>>   
>> +/**
>> + * struct xe_vma_mem_attr - memory attributes associated with vma
>> + */
>> +struct xe_vma_mem_attr {
>> +	/** @preferred_loc: perferred memory_location*/
>> +	struct {
>> +		/** @preferred_loc.migration_policy: Policy for migration of pages */
>> +		u32 migration_policy;
>> +
>> +		/**
>> +		 * @preferred_loc.devmem_fd: used for determining pagemap_fd requested by user
>> +		 * DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM and DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE mean
>> +		 * system memory or closest device memory respectively.
> 
> Nit, I generally prefer 80 character line wraps. I know checkpatch
> allows 100 but in general I think Xe generally wraps at 80 unless it is
> an odd case with nested code and an 80 character wrap makes the code
> unreadable.
> 
> 80 generally allows 2 windows split vertically in vi on a typical laptop
> which makes navigating the code a bit easier.

Noted. Will address it in next version.

> 
>> +		 */
>> +		u32 devmem_fd;
>> +	} preferred_loc;
>> +
>> +	/** @atomic_access: The atomic access type for the vma */
> 
> I'd reference the uAPI here. e.g., DRM_XE_VMA_ATOMIC_*

Sure

> 
> With the minor nits fixed:
> Reviewed-by: Matthew Brost <matthew.brost@intel.com>

Thanks

> 
> Matt
> 
>> +	u32 atomic_access;
>> +};
>> +
>>   struct xe_vma {
>>   	/** @gpuva: Base GPUVA object */
>>   	struct drm_gpuva gpuva;
>> @@ -135,6 +156,13 @@ struct xe_vma {
>>   	 * Needs to be signalled before UNMAP can be processed.
>>   	 */
>>   	struct xe_user_fence *ufence;
>> +
>> +	/**
>> +	 * @attr: The attributes of vma which determines the migration policy
>> +	 * and encoding of the PTEs for this vma.
>> +	 */
>> +	struct xe_vma_mem_attr attr;
>> +
>>   };
>>   
>>   /**
>> -- 
>> 2.34.1
>>


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 08/20] drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping
  2025-06-23  4:56   ` Matthew Brost
@ 2025-06-23  6:25     ` Ghimiray, Himal Prasad
  0 siblings, 0 replies; 68+ messages in thread
From: Ghimiray, Himal Prasad @ 2025-06-23  6:25 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe, thomas.hellstrom



On 23-06-2025 10:26, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:46PM +0530, Himal Prasad Ghimiray wrote:
>> Introduce xe_svm_ranges_zap_ptes_in_range(), a function to zap page table
>> entries (PTEs) for all SVM ranges within a user-specified address range.
>>
>> -v2 (Matthew Brost)
>> Lock should be called even for tlb_invalidation
>>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_pt.c  | 14 ++++++++++++-
>>   drivers/gpu/drm/xe/xe_svm.c | 42 +++++++++++++++++++++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_svm.h |  7 +++++++
>>   3 files changed, 62 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
>> index 9177c571689e..9a390ef10852 100644
>> --- a/drivers/gpu/drm/xe/xe_pt.c
>> +++ b/drivers/gpu/drm/xe/xe_pt.c
>> @@ -950,7 +950,19 @@ bool xe_pt_zap_ptes_range(struct xe_tile *tile, struct xe_vm *vm,
>>   	struct xe_pt *pt = vm->pt_root[tile->id];
>>   	u8 pt_mask = (range->tile_present & ~range->tile_invalidated);
>>   
>> -	xe_svm_assert_in_notifier(vm);
>> +	/*
>> +	 * Locking rules:
>> +	 *
>> +	 * - notifier_lock (write): full protection against page table changes
>> +	 *   and MMU notifier invalidations.
>> +	 *
>> +	 * - notifier_lock (read) + vm_lock (write): combined protection against
>> +	 *   invalidations and concurrent page table modifications. (e.g., madvise)
>> +	 *
>> +	 */
>> +	lockdep_assert(lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 0) ||
>> +		       (lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 1) &&
>> +		       lockdep_is_held_type(&vm->lock, 0)));
>>   
>>   	if (!(pt_mask & BIT(tile->id)))
>>   		return false;
>> diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
>> index 2fbbd6a604ea..19420635f1fa 100644
>> --- a/drivers/gpu/drm/xe/xe_svm.c
>> +++ b/drivers/gpu/drm/xe/xe_svm.c
>> @@ -999,6 +999,48 @@ int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range,
>>   	return err;
>>   }
>>   
>> +/**
>> + * xe_svm_ranges_zap_ptes_in_range - clear ptes of svm ranges in input range
>> + * @vm: Pointer to the xe_vm structure
>> + * @start: Start of the input range
>> + * @end: End of the input range
>> + *
>> + * This function removes the page table entries (PTEs) associated
>> + * with the svm ranges within the given input start and end
>> + *
>> + * Return: tile_mask for which gt's need to be tlb invalidated.
>> + */
>> +u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
>> +{
>> +	struct drm_gpusvm_notifier *notifier;
>> +	struct xe_svm_range *range;
>> +	u64 adj_start, adj_end;
>> +	struct xe_tile *tile;
>> +	u8 tile_mask = 0;
>> +	u8 id;
>> +
>> +	lockdep_assert(lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 1) &&
>> +		       lockdep_is_held_type(&vm->lock, 0));
>> +
>> +	drm_gpusvm_for_each_notifier(notifier, &vm->svm.gpusvm, start, end) {
>> +		struct drm_gpusvm_range *r = NULL;
>> +
>> +		adj_start = max(start, notifier->itree.start);
> 
> s/notifier->itree.start/drm_gpusvm_notifier_start
> 
>> +		adj_end = min(end, notifier->itree.last + 1);
> 
> s/notifier->itree.last + 1/drm_gpusvm_notifier_end
> 
>> +		drm_gpusvm_for_each_range(r, notifier, adj_start, adj_end) {
>> +			range = to_xe_range(r);
>> +			for_each_tile(tile, vm->xe, id) {
>> +				if (xe_pt_zap_ptes_range(tile, vm, range)) {
>> +					tile_mask |= BIT(id);
>> +					range->tile_invalidated |= BIT(id);
> 
> /* WRITE_ONCE pairs with READ_ONCE in xe_vm_has_valid_gpu_mapping() */
> WRITE_ONCE(range->tile_invalidated, range->tile_invalidated | BIT(id));

Sure

> 
> Also, we need to be careful here. If we can fail after this point but
> before the TLB invalidation completes, we could break the notifier, as
> the notifier would skip the TLB invalidation. The code, as written, can
> only fail if the CT channel is down — in that case, all bets are off and
> we are issuing a GT reset. So, I think the code as written is okay, but
> I’d add a comment here indicating that there must be no failure points
> between setting tile_invalidated and issuing the TLB invalidation.

Will add a comment.

> 
> Matt
> 
>> +				}
>> +			}
>> +		}
>> +	}
>> +
>> +	return tile_mask;
>> +}
>> +
>>   #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR)
>>   
>>   static struct drm_pagemap_device_addr
>> diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
>> index 19ce4f2754a7..af8f285b6caa 100644
>> --- a/drivers/gpu/drm/xe/xe_svm.h
>> +++ b/drivers/gpu/drm/xe/xe_svm.h
>> @@ -91,6 +91,7 @@ bool xe_svm_range_validate(struct xe_vm *vm,
>>   
>>   u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end,  struct xe_vma *vma);
>>   
>> +u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end);
>>   /**
>>    * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping
>>    * @range: SVM range
>> @@ -305,6 +306,12 @@ u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end, struct xe_vma *vm
>>   	return ULONG_MAX;
>>   }
>>   
>> +static inline
>> +u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
>> +{
>> +	return 0;
>> +}
>> +
>>   #define xe_svm_assert_in_notifier(...) do {} while (0)
>>   #define xe_svm_range_has_dma_mapping(...) false
>>   
>> -- 
>> 2.34.1
>>



^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 10/20] drm/xe/vm: Add an identifier for madvise in xe_vma_ops
  2025-06-23  5:38   ` Matthew Brost
@ 2025-06-23  6:28     ` Ghimiray, Himal Prasad
  0 siblings, 0 replies; 68+ messages in thread
From: Ghimiray, Himal Prasad @ 2025-06-23  6:28 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe, thomas.hellstrom



On 23-06-2025 11:08, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:48PM +0530, Himal Prasad Ghimiray wrote:
>> The flag XE_VMA_OPS_FLAG_MADVISE is introduced to  determine whether
>> xe_vma_ops is initialized by madvise operation on not.
>>
> 
> I'd just squash this into patch #7.
> 
> Then move patch #11 directly after patch #7 to tell a coherent story.

Makes sense, will modify in next version.
Thanks for review.

> 
> Matt
> 
>> Suggested-by: Matthew Brost <matthew.brost@intel.com>
>> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_vm.c       | 1 +
>>   drivers/gpu/drm/xe/xe_vm_types.h | 1 +
>>   2 files changed, 2 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
>> index f5f8de113eae..e059d9810d26 100644
>> --- a/drivers/gpu/drm/xe/xe_vm.c
>> +++ b/drivers/gpu/drm/xe/xe_vm.c
>> @@ -4237,6 +4237,7 @@ int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t start, uint64_t range)
>>   	}
>>   
>>   	xe_vma_ops_init(&vops, vm, NULL, NULL, 0);
>> +	vops.flags |= XE_VMA_OPS_FLAG_MADVISE;
>>   	err = vm_bind_ioctl_ops_parse(vm, ops, &vops);
>>   	if (err)
>>   		goto unwind_ops;
>> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
>> index cde2583da303..c7156f8e2ed2 100644
>> --- a/drivers/gpu/drm/xe/xe_vm_types.h
>> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
>> @@ -489,6 +489,7 @@ struct xe_vma_ops {
>>   	struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE];
>>   	/** @flag: signify the properties within xe_vma_ops*/
>>   #define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0)
>> +#define XE_VMA_OPS_FLAG_MADVISE          BIT(1)
>>   	u32 flags;
>>   #ifdef TEST_VM_OPS_ERROR
>>   	/** @inject_error: inject error to test error handling */
>> -- 
>> 2.34.1
>>


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise
  2025-06-23  6:18     ` Ghimiray, Himal Prasad
@ 2025-06-23 11:45       ` Matthew Brost
  0 siblings, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23 11:45 UTC (permalink / raw)
  To: Ghimiray, Himal Prasad; +Cc: intel-xe, thomas.hellstrom

On Mon, Jun 23, 2025 at 11:48:18AM +0530, Ghimiray, Himal Prasad wrote:
> 
> 
> On 23-06-2025 11:22, Matthew Brost wrote:
> > On Fri, Jun 13, 2025 at 06:25:49PM +0530, Himal Prasad Ghimiray wrote:
> > > In the case of the MADVISE ioctl, if the start or end addresses fall
> > > within a VMA and existing SVM ranges are present, remove the existing
> > > SVM mappings. Then, continue with ops_parse to create new VMAs by REMAP
> > > unmapping of old one.
> > > 
> > > v2 (Matthew Brost)
> > > - Use vops flag to call unmapping of ranges in vm_bind_ioctl_ops_parse
> > > - Rename the function
> > > 
> > > Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> > > ---
> > >   drivers/gpu/drm/xe/xe_svm.c | 27 +++++++++++++++++++++++++++
> > >   drivers/gpu/drm/xe/xe_svm.h |  8 ++++++++
> > >   drivers/gpu/drm/xe/xe_vm.c  |  8 ++++++--
> > >   3 files changed, 41 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
> > > index 19420635f1fa..df6992ee2e2d 100644
> > > --- a/drivers/gpu/drm/xe/xe_svm.c
> > > +++ b/drivers/gpu/drm/xe/xe_svm.c
> > > @@ -935,6 +935,33 @@ bool xe_svm_has_mapping(struct xe_vm *vm, u64 start, u64 end)
> > >   	return drm_gpusvm_has_mapping(&vm->svm.gpusvm, start, end);
> > >   }
> > > +/**
> > > + * xe_svm_unmap_address_range - UNMAP SVM mappings and ranges
> > > + * @start: start addr
> > > + * @end: end addr
> > > + *
> > > + * This function UNMAPS svm ranges if start or end address are inside them.
> > > + */
> > > +void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end)
> > > +{
> > > +	struct drm_gpusvm_notifier *notifier, *next;
> > > +
> > > +	lockdep_assert_held_write(&vm->lock);
> > > +
> > > +	drm_gpusvm_for_each_notifier_safe(notifier, next, &vm->svm.gpusvm, start, end) {
> > > +		struct drm_gpusvm_range *range, *__next;
> > > +
> > > +		drm_gpusvm_for_each_range_safe(range, __next, notifier, start, end) {
> > > +			if (start > drm_gpusvm_range_start(range) ||
> > > +			    end < drm_gpusvm_range_end(range)) {
> > > +				if (IS_DGFX(vm->xe) && xe_svm_range_in_vram(to_xe_range(range)))
> > > +					drm_gpusvm_range_evict(&vm->svm.gpusvm, range);
> > 
> > I think you could use xe_svm_range_migrate_to_smem here but also I don't
> > eviction is strickly required here either. This akin to a partial unmap
> > and we don't evict there. Any reason that I'm missing here?
> 
> If previous ranges had devmem pages allocated, and eviction did not occur,
> subsequent VRAM allocations for smaller ranges were failing.
> 
> Scenario:
> 
> A 2 MiB range existed with VRAM allocation.
> A madvise call triggered a split, invoking xe_svm_unmap_address_range.
> Without eviction, the 64 KiB sub-ranges failed to allocate VRAM during
> subsequent page faults.
> As a result, bindings were being forced from system memory (SMEM) instead of
> VRAM.

Right. But would allocate xe_svm_alloc_vram but not fail (on
!migrate.cpages in drm_gpusvm_migrate_to_devmem) and the subsequent
get_pages not find the old VRAM pages still in place? I guess I'm
looking now and our error handling in the fault handler / prefetch
doesn't handle this scenario correctly but I think it could. Let me try
to tweak these paths today and get back to you - if we can fix that then
I believe this could avoided. For now, yea I think this is correct.

Matt

>  >
> > Matt
> > 
> > > +				__xe_svm_garbage_collector(vm, to_xe_range(range));
> > > +			}
> > > +		}
> > > +	}
> > > +}
> > > +
> > >   /**
> > >    * xe_svm_bo_evict() - SVM evict BO to system memory
> > >    * @bo: BO to evict
> > > diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
> > > index af8f285b6caa..4e5d42323679 100644
> > > --- a/drivers/gpu/drm/xe/xe_svm.h
> > > +++ b/drivers/gpu/drm/xe/xe_svm.h
> > > @@ -92,6 +92,9 @@ bool xe_svm_range_validate(struct xe_vm *vm,
> > >   u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end,  struct xe_vma *vma);
> > >   u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end);
> > > +
> > > +void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end);
> > > +
> > >   /**
> > >    * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping
> > >    * @range: SVM range
> > > @@ -312,6 +315,11 @@ u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end)
> > >   	return 0;
> > >   }
> > > +static inline
> > > +void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end)
> > > +{
> > > +}
> > > +
> > >   #define xe_svm_assert_in_notifier(...) do {} while (0)
> > >   #define xe_svm_range_has_dma_mapping(...) false
> > > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > > index e059d9810d26..0872df8d0b15 100644
> > > --- a/drivers/gpu/drm/xe/xe_vm.c
> > > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > > @@ -2663,8 +2663,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
> > >   				end = op->base.remap.next->va.addr;
> > >   			if (xe_vma_is_cpu_addr_mirror(old) &&
> > > -			    xe_svm_has_mapping(vm, start, end))
> > > -				return -EBUSY;
> > > +			    xe_svm_has_mapping(vm, start, end)) {
> > > +				if (vops->flags & XE_VMA_OPS_FLAG_MADVISE)
> > > +					xe_svm_unmap_address_range(vm, start, end);
> > > +				else
> > > +					return -EBUSY;
> > > +			}
> > >   			op->remap.start = xe_vma_start(old);
> > >   			op->remap.range = xe_vma_size(old);
> > > -- 
> > > 2.34.1
> > > 
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 18/20] drm/xe/bo: Update atomic_access attribute on madvise
  2025-06-13 12:55 ` [PATCH v4 18/20] drm/xe/bo: Update atomic_access attribute on madvise Himal Prasad Ghimiray
@ 2025-06-23 16:19   ` Matthew Brost
  0 siblings, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23 16:19 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:56PM +0530, Himal Prasad Ghimiray wrote:
> Update the bo_atomic_access based on user-provided input and determine
> the migration to smem during a CPU fault
> 
> v2 (Matthew Brost)
> - Avoid cpu unmapping if bo is already in smem
> - check atomics on smem too for ioctl
> - Add comments
> 
> v3
> - Avoid migration in prefetch
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_bo.c           | 21 ++++++++--
>  drivers/gpu/drm/xe/xe_gt_pagefault.c |  2 +-
>  drivers/gpu/drm/xe/xe_vm.c           |  5 ++-
>  drivers/gpu/drm/xe/xe_vm_madvise.c   | 61 +++++++++++++++++++++++++++-
>  4 files changed, 82 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
> index 4e39188a021a..82b33dfc5515 100644
> --- a/drivers/gpu/drm/xe/xe_bo.c
> +++ b/drivers/gpu/drm/xe/xe_bo.c
> @@ -1667,6 +1667,12 @@ static void xe_gem_object_close(struct drm_gem_object *obj,
>  	}
>  }
>  
> +static bool should_migrate_to_smem(struct xe_bo *bo)
> +{

Again maybe a quick platform specfic comment here so we remember to fix
this on different platforms.

> +	return bo->attr.atomic_access == DRM_XE_VMA_ATOMIC_GLOBAL ||
> +	       bo->attr.atomic_access == DRM_XE_VMA_ATOMIC_CPU;
> +}
> +
>  static vm_fault_t xe_gem_fault(struct vm_fault *vmf)
>  {
>  	struct ttm_buffer_object *tbo = vmf->vma->vm_private_data;
> @@ -1675,7 +1681,7 @@ static vm_fault_t xe_gem_fault(struct vm_fault *vmf)
>  	struct xe_bo *bo = ttm_to_xe_bo(tbo);
>  	bool needs_rpm = bo->flags & XE_BO_FLAG_VRAM_MASK;
>  	vm_fault_t ret;
> -	int idx;
> +	int idx, r = 0;
>  
>  	if (needs_rpm)
>  		xe_pm_runtime_get(xe);
> @@ -1687,8 +1693,17 @@ static vm_fault_t xe_gem_fault(struct vm_fault *vmf)
>  	if (drm_dev_enter(ddev, &idx)) {
>  		trace_xe_bo_cpu_fault(bo);
>  
> -		ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
> -					       TTM_BO_VM_NUM_PREFAULT);
> +		if (should_migrate_to_smem(bo)) {

Maybe assert here that a BO has system placements to ensure our
sanitization of madvise IOCTLs is correct.

> +			r = xe_bo_migrate(bo, XE_PL_TT);
> +			if (r == -EBUSY || r == -ERESTARTSYS || r == -EINTR)
> +				ret = VM_FAULT_NOPAGE;
> +			else if (r)
> +				ret = VM_FAULT_SIGBUS;
> +		}
> +		if (!ret)
> +			ret = ttm_bo_vm_fault_reserved(vmf,
> +						       vmf->vma->vm_page_prot,
> +						       TTM_BO_VM_NUM_PREFAULT);
>  		drm_dev_exit(idx);
>  	} else {
>  		ret = ttm_bo_vm_dummy_page(vmf, vmf->vma->vm_page_prot);
> diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> index e2d975b2fddb..1335c5fc0e10 100644
> --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
> +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> @@ -89,7 +89,7 @@ static int xe_pf_begin(struct drm_exec *exec, struct xe_vma *vma,
>  	if (err)
>  		return err;
>  
> -	if (atomic && IS_DGFX(vm->xe)) {
> +	if (xe_vma_need_vram_for_atomic(vm->xe, vma, atomic)) {
>  		if (xe_vma_is_userptr(vma)) {
>  			err = -EACCES;
>  			return err;
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 0dd9f9e11030..14e554f3f4d5 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -4200,6 +4200,9 @@ void xe_vm_snapshot_free(struct xe_vm_snapshot *snap)
>   */
>  bool xe_vma_need_vram_for_atomic(struct xe_device *xe, struct xe_vma *vma, bool is_atomic)
>  {
> +	u32 atomic_access = xe_vma_bo(vma) ? xe_vma_bo(vma)->attr.atomic_access :
> +					     vma->attr.atomic_access;
> +
>  	if (!IS_DGFX(xe))
>  		return false;
>  
> @@ -4207,7 +4210,7 @@ bool xe_vma_need_vram_for_atomic(struct xe_device *xe, struct xe_vma *vma, bool
>  	 * on a device supporting CXL atomics, these would ideally work universally
>  	 * without additional handling.
>  	 */
> -	switch (vma->attr.atomic_access) {
> +	switch (atomic_access) {
>  	case DRM_XE_VMA_ATOMIC_DEVICE:
>  		return !xe->info.has_device_atomics_on_smem;
>  
> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
> index 973627edb23c..5b96c8fc73a5 100644
> --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
> @@ -102,14 +102,28 @@ static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
>  			   struct xe_vma **vmas, int num_vmas,
>  			   struct drm_xe_madvise *op)
>  {
> +	struct xe_bo *bo;
>  	int i;
>  
>  	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_ATOMIC);
>  	xe_assert(vm->xe, op->atomic.val <= DRM_XE_VMA_ATOMIC_CPU);
>  
> -	for (i = 0; i < num_vmas; i++)
> +	for (i = 0; i < num_vmas; i++) {
>  		vmas[i]->attr.atomic_access = op->atomic.val;
> -	/*TODO: handle bo backed vmas */
> +
> +		bo = xe_vma_bo(vmas[i]);
> +		if (!bo)
> +			continue;
> +
> +		xe_bo_assert_held(bo);
> +		bo->attr.atomic_access = op->atomic.val;
> +
> +		/* Invalidate cpu page table, so bo can migrate to smem in next access */
> +		if (xe_bo_is_vram(bo) &&
> +		    (bo->attr.atomic_access == DRM_XE_VMA_ATOMIC_CPU ||
> +		     bo->attr.atomic_access == DRM_XE_VMA_ATOMIC_GLOBAL))
> +			ttm_bo_unmap_virtual(&bo->ttm);
> +	}
>  }
>  
>  static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
> @@ -231,6 +245,41 @@ static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const struct drm_x
>  	return 0;
>  }
>  
> +static int check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas,
> +				  int num_vmas, u32 atomic_val)
> +{
> +	struct xe_device *xe = vm->xe;
> +	struct xe_bo *bo;
> +	int i;
> +
> +	for (i = 0; i < num_vmas; i++) {
> +		bo = xe_vma_bo(vmas[i]);
> +		if (!bo)
> +			continue;
> +
> +		if (XE_IOCTL_DBG(xe, atomic_val == DRM_XE_VMA_ATOMIC_CPU &&
> +				 !(bo->flags & XE_BO_FLAG_SYSTEM)))
> +			return -EINVAL;
> +
> +		/* NOTE: The following atomic checks are platform-specific. For example,
> +		 * if a device supports CXL atomics, these may not be necessary or
> +		 * may behave differently.
> +		 */

/*
 * NOTE:

I believe above is the style and IIRC checkpatch will complain about the
way you have it.

Also this comment could be at the top of the function or at least above
the first check.

Nits aside, patch LGTM.

Matt

> +		if (XE_IOCTL_DBG(xe, atomic_val == DRM_XE_VMA_ATOMIC_DEVICE &&
> +				 !(bo->flags & XE_BO_FLAG_VRAM0) &&
> +				 !(bo->flags & XE_BO_FLAG_VRAM1) &&
> +				 !(bo->flags & XE_BO_FLAG_SYSTEM &&
> +				   xe->info.has_device_atomics_on_smem)))
> +			return -EINVAL;
> +
> +		if (XE_IOCTL_DBG(xe, atomic_val == DRM_XE_VMA_ATOMIC_GLOBAL &&
> +				 (!(bo->flags & XE_BO_FLAG_SYSTEM) ||
> +				  (!(bo->flags & XE_BO_FLAG_VRAM0) &&
> +				   !(bo->flags & XE_BO_FLAG_VRAM1)))))
> +			return -EINVAL;
> +	}
> +	return 0;
> +}
>  /**
>   * xe_vm_madvise_ioctl - Handle MADVise ioctl for a VM
>   * @dev: DRM device pointer
> @@ -276,6 +325,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
>  		goto unlock_vm;
>  
>  	if (madvise_range.has_bo_vmas) {
> +		if (args->type == DRM_XE_VMA_ATTR_ATOMIC) {
> +			err = check_bo_args_are_sane(vm, madvise_range.vmas,
> +						     madvise_range.num_vmas,
> +						     args->atomic.val);
> +			if (err)
> +				goto unlock_vm;
> +		}
> +
>  		drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
>  		drm_exec_until_all_locked(&exec) {
>  			for (int i = 0; i < madvise_range.num_vmas; i++) {
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 05/20] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter
  2025-06-23  4:38   ` Matthew Brost
@ 2025-06-23 16:21     ` Matthew Brost
  0 siblings, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23 16:21 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Sun, Jun 22, 2025 at 09:38:30PM -0700, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:43PM +0530, Himal Prasad Ghimiray wrote:
> > This change simplifies the logic by ensuring that remapped previous or
> > next VMAs are created with the same memory attributes as the original VMA.
> > By passing struct xe_vma_mem_attr as a parameter, we maintain consistency
> > in memory attributes.
> > 
> > -v2
> >  *dst = *src (Matthew Brost)
> > 
> > -v3 (Matthew Brost)
> >  Drop unnecessary helper
> >  pass attr ptr as input to new_vma and vma_create
> > 
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm.c | 24 +++++++++++++++++-------
> >  1 file changed, 17 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> > index 9b705526a3e3..4849d4cc806a 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -1168,7 +1168,8 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
> >  				    struct xe_bo *bo,
> >  				    u64 bo_offset_or_userptr,
> >  				    u64 start, u64 end,
> > -				    u16 pat_index, unsigned int flags)
> > +				    struct xe_vma_mem_attr *attr,
> > +				    unsigned int flags)
> >  {
> >  	struct xe_vma *vma;
> >  	struct xe_tile *tile;
> > @@ -1223,7 +1224,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
> >  	if (vm->xe->info.has_atomic_enable_pte_bit)
> >  		vma->gpuva.flags |= XE_VMA_ATOMIC_PTE_BIT;
> >  
> > -	vma->attr.pat_index = pat_index;
> > +	vma->attr = *attr;
> >  
> >  	if (bo) {
> >  		struct drm_gpuvm_bo *vm_bo;
> > @@ -2444,7 +2445,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops,
> >  ALLOW_ERROR_INJECTION(vm_bind_ioctl_ops_create, ERRNO);
> >  
> >  static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
> > -			      u16 pat_index, unsigned int flags)
> > +			      struct xe_vma_mem_attr *attr, unsigned int flags)
> >  {
> >  	struct xe_bo *bo = op->gem.obj ? gem_to_xe_bo(op->gem.obj) : NULL;
> >  	struct drm_exec exec;
> > @@ -2473,7 +2474,7 @@ static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
> >  	}
> >  	vma = xe_vma_create(vm, bo, op->gem.offset,
> >  			    op->va.addr, op->va.addr +
> > -			    op->va.range - 1, pat_index, flags);
> > +			    op->va.range - 1, attr, flags);
> >  	if (IS_ERR(vma))
> >  		goto err_unlock;
> >  
> > @@ -2616,6 +2617,15 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
> >  		switch (op->base.op) {
> >  		case DRM_GPUVA_OP_MAP:
> >  		{
> > +			struct xe_vma_mem_attr default_attr = {
> > +				.preferred_loc = {
> > +					.devmem_fd = DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE,
> > +					.migration_policy = DRM_XE_MIGRATE_ALL_PAGES,
> > +				},
> > +				.atomic_access = DRM_XE_VMA_ATOMIC_UNDEFINED,
> 
> We need to double-check with the UMD team here — there are ongoing discussions
> in our internal repo where we might need to set the default behavior for BOs to
> enable global/CPU atomics on BOs with SRAM/VRAM placements. If that is the case,
> then if this is a faulting VM, I believe the default should be
> DRM_XE_VMA_ATOMIC_GLOBAL. See VLK-66541.
> 
> This would be behavior change too, so perhaps the maintainers can comment if
> this is allowed or if we need add a query indicating the behavior change.
> 
> Let’s close on this before I put an RB here. Everything else LGTM.
> 

We resolved this question after some internal discussion. Patch is good as is.

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> Matt
> 
> > +				.pat_index = op->map.pat_index,
> > +			};
> > +
> >  			flags |= op->map.read_only ?
> >  				VMA_CREATE_FLAG_READ_ONLY : 0;
> >  			flags |= op->map.is_null ?
> > @@ -2625,7 +2635,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
> >  			flags |= op->map.is_cpu_addr_mirror ?
> >  				VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR : 0;
> >  
> > -			vma = new_vma(vm, &op->base.map, op->map.pat_index,
> > +			vma = new_vma(vm, &op->base.map, &default_attr,
> >  				      flags);
> >  			if (IS_ERR(vma))
> >  				return PTR_ERR(vma);
> > @@ -2673,7 +2683,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
> >  
> >  			if (op->base.remap.prev) {
> >  				vma = new_vma(vm, op->base.remap.prev,
> > -					      old->attr.pat_index, flags);
> > +					      &old->attr, flags);
> >  				if (IS_ERR(vma))
> >  					return PTR_ERR(vma);
> >  
> > @@ -2703,7 +2713,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops,
> >  
> >  			if (op->base.remap.next) {
> >  				vma = new_vma(vm, op->base.remap.next,
> > -					      old->attr.pat_index, flags);
> > +					      &old->attr, flags);
> >  				if (IS_ERR(vma))
> >  					return PTR_ERR(vma);
> >  
> > -- 
> > 2.34.1
> > 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 12/20] drm/xe/svm : Add svm ranges migration policy on atomic access
  2025-06-13 12:55 ` [PATCH v4 12/20] drm/xe/svm : Add svm ranges migration policy on atomic access Himal Prasad Ghimiray
@ 2025-06-23 16:32   ` Matthew Brost
  0 siblings, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23 16:32 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:50PM +0530, Himal Prasad Ghimiray wrote:
> If the platform does not support atomic access on system memory, and the
> ranges are in system memory, but the user requires atomic accesses on
> the VMA, then migrate the ranges to VRAM. Apply this policy for prefetch
> operations as well.
> 
> v2
> - Drop unnecessary vm_dbg
> 
> v3 (Matthew Brost)
> - fix atomic policy
> - prefetch shouldn't have any impact of atomic
> - bo can be accessed from vma, avoid duplicate parameter
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_pt.c         |  9 ++++++--
>  drivers/gpu/drm/xe/xe_svm.c        |  2 +-
>  drivers/gpu/drm/xe/xe_vm.c         | 36 ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_vm.h         |  2 ++
>  drivers/gpu/drm/xe/xe_vm_madvise.c |  9 +++++++-
>  5 files changed, 54 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index 9a390ef10852..9dd286853654 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -645,13 +645,18 @@ static bool xe_atomic_for_vram(struct xe_vm *vm)
>  	return true;
>  }
>  
> -static bool xe_atomic_for_system(struct xe_vm *vm, struct xe_bo *bo)
> +static bool xe_atomic_for_system(struct xe_vm *vm,
> +				 struct xe_vma *vma)
>  {
>  	struct xe_device *xe = vm->xe;
> +	struct xe_bo *bo = xe_vma_bo(vma);
>  
>  	if (!xe->info.has_device_atomics_on_smem)
>  		return false;
>  
> +	if (vma->attr.atomic_access == DRM_XE_VMA_ATOMIC_DEVICE)
> +		return true;

I think this addresses the TODO comment below so it can be deleted.

> +
>  	/*
>  	 * If a SMEM+LMEM allocation is backed by SMEM, a device
>  	 * atomics will cause a gpu page fault and which then
> @@ -745,7 +750,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
>  
>  	if (vma->gpuva.flags & XE_VMA_ATOMIC_PTE_BIT) {
>  		xe_walk.default_vram_pte = xe_atomic_for_vram(vm) ? XE_USM_PPGTT_PTE_AE : 0;
> -		xe_walk.default_system_pte = xe_atomic_for_system(vm, bo) ?
> +		xe_walk.default_system_pte = xe_atomic_for_system(vm, vma) ?
>  			XE_USM_PPGTT_PTE_AE : 0;
>  	}
>  
> diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
> index df6992ee2e2d..003aae9a0d82 100644
> --- a/drivers/gpu/drm/xe/xe_svm.c
> +++ b/drivers/gpu/drm/xe/xe_svm.c
> @@ -815,7 +815,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma,
>  			IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR),
>  		.check_pages_threshold = IS_DGFX(vm->xe) &&
>  			IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? SZ_64K : 0,
> -		.devmem_only = atomic && IS_DGFX(vm->xe) &&
> +		.devmem_only = xe_vma_need_vram_for_atomic(vm->xe, vma, atomic) &&
>  			IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR),
>  		.timeslice_ms = atomic && IS_DGFX(vm->xe) &&
>  			IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ?
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 0872df8d0b15..6dd1f868942d 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -4177,6 +4177,42 @@ void xe_vm_snapshot_free(struct xe_vm_snapshot *snap)
>  	kvfree(snap);
>  }
>  
> +/**
> + * xe_vma_need_vram_for_atomic - Check if VMA needs VRAM migration for atomic operations
> + * @xe: Pointer to the XE device structure
> + * @vma: Pointer to the virtual memory area (VMA) structure
> + * @is_atomic: In pagefault path and atomic operation
> + *
> + * This function determines whether the given VMA needs to be migrated to
> + * VRAM in order to do atomic GPU operation.
> + *
> + * Return: true if migration to VRAM is required, false otherwise.
> + */
> +bool xe_vma_need_vram_for_atomic(struct xe_device *xe, struct xe_vma *vma, bool is_atomic)
> +{
> +	if (!IS_DGFX(xe))
> +		return false;
> +
> +	/* Note: The checks implemented here are platform-specific. For instance,
> +	 * on a device supporting CXL atomics, these would ideally work universally
> +	 * without additional handling.

/*
 * NOTE:

See my comment in patch 18.

Patch LGTM aside from nits.

Matt

> +	 */
> +	switch (vma->attr.atomic_access) {
> +	case DRM_XE_VMA_ATOMIC_DEVICE:
> +		return !xe->info.has_device_atomics_on_smem;
> +
> +	case DRM_XE_VMA_ATOMIC_CPU:
> +	case DRM_XE_VMA_ATOMIC_UNDEFINED:
> +		return is_atomic;
> +
> +	case DRM_XE_VMA_ATOMIC_GLOBAL:
> +		return true;
> +
> +	default:
> +		return is_atomic;
> +	}
> +}
> +
>  /**
>   * xe_vm_alloc_madvise_vma - Allocate VMA's with madvise ops
>   * @vm: Pointer to the xe_vm structure
> diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
> index 66bb6babd319..1fb639a33ffb 100644
> --- a/drivers/gpu/drm/xe/xe_vm.h
> +++ b/drivers/gpu/drm/xe/xe_vm.h
> @@ -171,6 +171,8 @@ static inline bool xe_vma_is_userptr(struct xe_vma *vma)
>  
>  struct xe_vma *xe_vm_find_vma_by_addr(struct xe_vm *vm, u64 page_addr);
>  
> +bool xe_vma_need_vram_for_atomic(struct xe_device *xe, struct xe_vma *vma, bool is_atomic);
> +
>  int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t addr, uint64_t size);
>  
>  /**
> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
> index ff560914ad7e..403337d79ea6 100644
> --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
> @@ -89,7 +89,14 @@ static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
>  			   struct xe_vma **vmas, int num_vmas,
>  			   struct drm_xe_madvise *op)
>  {
> -	/* Implementation pending */
> +	int i;
> +
> +	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_ATOMIC);
> +	xe_assert(vm->xe, op->atomic.val <= DRM_XE_VMA_ATOMIC_CPU);
> +
> +	for (i = 0; i < num_vmas; i++)
> +		vmas[i]->attr.atomic_access = op->atomic.val;
> +	/*TODO: handle bo backed vmas */
>  }
>  
>  static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 14/20] drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute
  2025-06-13 12:55 ` [PATCH v4 14/20] drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute Himal Prasad Ghimiray
@ 2025-06-23 16:34   ` Matthew Brost
  0 siblings, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23 16:34 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:52PM +0530, Himal Prasad Ghimiray wrote:
> This attributes sets the pat_index for the svm used vma range, which is
> utilized to ascertain the coherence.
> 
> v2 (Matthew Brost)
> - Pat index sanity check
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> ---
>  drivers/gpu/drm/xe/xe_vm_madvise.c | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
> index 64352fbebd25..973627edb23c 100644
> --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
> @@ -11,6 +11,7 @@
>  
>  #include "xe_bo.h"
>  #include "xe_gt_tlb_invalidation.h"
> +#include "xe_pat.h"
>  #include "xe_pt.h"
>  #include "xe_svm.h"
>  
> @@ -115,7 +116,13 @@ static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
>  			      struct xe_vma **vmas, int num_vmas,
>  			      struct drm_xe_madvise *op)
>  {
> -	/* Implementation pending */
> +	int i;
> +
> +	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_PAT);
> +
> +	for (i = 0; i < num_vmas; i++)
> +		vmas[i]->attr.pat_index = op->pat_index.val;
> +
>  }
>  
>  typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
> @@ -195,7 +202,13 @@ static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const struct drm_x
>  			return -EINVAL;
>  		break;
>  	case DRM_XE_VMA_ATTR_PAT:
> -		/*TODO: Add valid pat check */
> +		u16 coh_mode = xe_pat_index_get_coh_mode(xe, args->pat_index.val);
> +
> +		if (XE_IOCTL_DBG(xe, !coh_mode))
> +			return -EINVAL;
> +
> +		if (XE_WARN_ON(coh_mode > XE_COH_AT_LEAST_1WAY))
> +			return -EINVAL;
>  		break;
>  	case DRM_XE_VMA_ATTR_PREFERRED_LOC:
>  		s32 fd = (s32)args->preferred_mem_loc.devmem_fd;
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 15/20] drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch
  2025-06-13 12:55 ` [PATCH v4 15/20] drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch Himal Prasad Ghimiray
@ 2025-06-23 16:36   ` Matthew Brost
  0 siblings, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23 16:36 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:53PM +0530, Himal Prasad Ghimiray wrote:
> Introduce flag DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC to ensure prefetching
> in madvise-advised memory regions
> 
> v2 (Matthew Brost)
> - Add kernel-doc
> 
> v3 (Matthew Brost)
> - Fix kernel-doc
> 
> Cc: Matthew Brost <matthew.brost@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  include/uapi/drm/xe_drm.h | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index b5f8d11faaa8..81e90270313d 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -1006,6 +1006,10 @@ struct drm_xe_vm_destroy {
>   *    valid on VMs with DRM_XE_VM_CREATE_FLAG_FAULT_MODE set. The CPU address
>   *    mirror flag are only valid for DRM_XE_VM_BIND_OP_MAP operations, the BO
>   *    handle MBZ, and the BO offset MBZ.
> + *
> + * The @prefetch_mem_region_instance for %DRM_XE_VM_BIND_OP_PREFETCH can also be:
> + *  - %DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC, which ensures prefetching occurs in
> + *    the memory region advised by madvise.
>   */
>  struct drm_xe_vm_bind_op {
>  	/** @extensions: Pointer to the first extension struct, if any */
> @@ -1111,6 +1115,7 @@ struct drm_xe_vm_bind_op {
>  	/** @flags: Bind flags */
>  	__u32 flags;
>  
> +#define DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC	-1
>  	/**
>  	 * @prefetch_mem_region_instance: Memory region to prefetch VMA to.
>  	 * It is a region instance, not a mask.
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 16/20] drm/xe/svm: Consult madvise preferred location in prefetch
  2025-06-13 12:55 ` [PATCH v4 16/20] drm/xe/svm: Consult madvise preferred location in prefetch Himal Prasad Ghimiray
@ 2025-06-23 22:07   ` Matthew Brost
  0 siblings, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23 22:07 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:54PM +0530, Himal Prasad Ghimiray wrote:
> When prefetch region is DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC, prefetch svm
> ranges to preferred location provided by madvise.
> 
> v2 (Matthew Brost)
> - Fix region, devmem_fd usages
> - consult madvise is applicable for other vma's too.
> 
> v3
> - Fix atomic handling
> 
> Cc: Matthew Brost <matthew.brost@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_svm.h  |  1 -
>  drivers/gpu/drm/xe/xe_tile.h | 18 ++++++++++++++++++
>  drivers/gpu/drm/xe/xe_vm.c   | 26 ++++++++++++++++++--------
>  3 files changed, 36 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
> index 900a5883951f..1658e28f3773 100644
> --- a/drivers/gpu/drm/xe/xe_svm.h
> +++ b/drivers/gpu/drm/xe/xe_svm.h
> @@ -327,7 +327,6 @@ struct drm_pagemap *xe_vma_resolve_pagemap(struct xe_vma *vma, struct xe_tile *t
>  {
>  	return NULL;
>  }
> -
>  #define xe_svm_assert_in_notifier(...) do {} while (0)
>  #define xe_svm_range_has_dma_mapping(...) false
>  
> diff --git a/drivers/gpu/drm/xe/xe_tile.h b/drivers/gpu/drm/xe/xe_tile.h
> index eb939316d55b..142ed5cf654b 100644
> --- a/drivers/gpu/drm/xe/xe_tile.h
> +++ b/drivers/gpu/drm/xe/xe_tile.h
> @@ -10,6 +10,24 @@
>  
>  struct xe_tile;
>  
> +#if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR)
> +/**
> + * xe_tile_from_dpagemap - Find xe_tile from drm_pagemap
> + * @dpagemap: pointer to struct drm_pagemap
> + *
> + * Return: Pointer to xe_tile
> + */
> +static inline struct xe_tile *xe_tile_from_dpagemap(struct drm_pagemap *dpagemap)
> +{
> +	return container_of(dpagemap, struct xe_tile, mem.vram.dpagemap);
> +}
> +
> +#else
> +static inline  struct xe_tile *xe_tile_from_dpagemap(struct drm_pagemap *dpagemap)
> +{
> +	return NULL;
> +}
> +#endif
>  int xe_tile_init_early(struct xe_tile *tile, struct xe_device *xe, u8 id);
>  int xe_tile_init_noalloc(struct xe_tile *tile);
>  int xe_tile_init(struct xe_tile *tile);
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 6dd1f868942d..0dd9f9e11030 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -38,6 +38,7 @@
>  #include "xe_res_cursor.h"
>  #include "xe_svm.h"
>  #include "xe_sync.h"
> +#include "xe_tile.h"
>  #include "xe_trace_bo.h"
>  #include "xe_wa.h"
>  #include "xe_hmm.h"
> @@ -2907,15 +2908,24 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op)
>  	int err = 0;
>  
>  	struct xe_svm_range *svm_range;
> +	struct drm_pagemap *dpagemap;
>  	struct drm_gpusvm_ctx ctx = {};
> -	struct xe_tile *tile;
> +	struct xe_tile *tile = NULL;
>  	unsigned long i;
>  	u32 region;
>  
>  	if (!xe_vma_is_cpu_addr_mirror(vma))
>  		return 0;
>  
> -	region = op->prefetch_range.region;
> +	if (op->prefetch_range.region == DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC) {
> +		dpagemap = xe_vma_resolve_pagemap(vma, xe_device_get_root_tile(vm->xe));
> +		if (dpagemap)
> +			tile = xe_tile_from_dpagemap(dpagemap);
> +	} else {
> +		region = op->prefetch_range.region;
> +		if (region)
> +			tile = &vm->xe->tiles[region_to_mem_type[region] - XE_PL_VRAM0];
> +	}
>  
>  	ctx.read_only = xe_vma_read_only(vma);
>  	ctx.devmem_possible = devmem_possible;
> @@ -2923,11 +2933,10 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op)
>  
>  	/* TODO: Threading the migration */
>  	xa_for_each(&op->prefetch_range.range, i, svm_range) {
> -		if (!region)
> +		if (!tile)
>  			xe_svm_range_migrate_to_smem(vm, svm_range);
>  
> -		if (xe_svm_range_needs_migrate_to_vram(svm_range, vma, region)) {
> -			tile = &vm->xe->tiles[region_to_mem_type[region] - XE_PL_VRAM0];
> +		if (xe_svm_range_needs_migrate_to_vram(svm_range, vma, !!tile)) {
>  			err = xe_svm_alloc_vram(vm, tile, svm_range, &ctx);
>  			if (err) {
>  				drm_dbg(&vm->xe->drm, "VRAM allocation failed, retry from userspace, asid=%u, gpusvm=%p, errno=%pe\n",
> @@ -2995,7 +3004,8 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
>  		else
>  			region = op->prefetch.region;
>  
> -		xe_assert(vm->xe, region <= ARRAY_SIZE(region_to_mem_type));
> +		xe_assert(vm->xe, region == DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC ||
> +			  region <= ARRAY_SIZE(region_to_mem_type));
>  
>  		err = vma_lock_and_validate(exec,
>  					    gpuva_to_vma(op->base.prefetch.va),
> @@ -3413,8 +3423,8 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm,
>  				 op == DRM_XE_VM_BIND_OP_PREFETCH) ||
>  		    XE_IOCTL_DBG(xe, prefetch_region &&
>  				 op != DRM_XE_VM_BIND_OP_PREFETCH) ||
> -		    XE_IOCTL_DBG(xe, !(BIT(prefetch_region) &
> -				       xe->info.mem_region_mask)) ||
> +		    XE_IOCTL_DBG(xe,  (prefetch_region != DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC &&
> +				       !(BIT(prefetch_region) & xe->info.mem_region_mask))) ||
>  		    XE_IOCTL_DBG(xe, obj &&
>  				 op == DRM_XE_VM_BIND_OP_UNMAP)) {
>  			err = -EINVAL;
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 20/20] drm/xe/madvise: Skip vma invalidation if mem attr are unchanged
  2025-06-13 12:55 ` [PATCH v4 20/20] drm/xe/madvise: Skip vma invalidation if mem attr are unchanged Himal Prasad Ghimiray
@ 2025-06-23 22:28   ` Matthew Brost
  2025-06-26  8:54     ` Ghimiray, Himal Prasad
  0 siblings, 1 reply; 68+ messages in thread
From: Matthew Brost @ 2025-06-23 22:28 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:58PM +0530, Himal Prasad Ghimiray wrote:
> If a VMA within the madvise input range already has the same memory
> attribute as the one requested by the user, skip PTE zapping for that
> VMA to avoid unnecessary invalidation.
> 
> Suggested-by: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_vm.c         |  1 +
>  drivers/gpu/drm/xe/xe_vm_madvise.c | 57 ++++++++++++++++++------------
>  drivers/gpu/drm/xe/xe_vm_types.h   |  6 ++++
>  3 files changed, 42 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index d9ce25f3abf4..56d6c286e3d3 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -1226,6 +1226,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
>  		vma->gpuva.flags |= XE_VMA_ATOMIC_PTE_BIT;
>  
>  	vma->attr = *attr;
> +	vma->skip_invalidation = 0;

This kzalloc'd so not needed.

>  
>  	if (bo) {
>  		struct drm_gpuvm_bo *vm_bo;
> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
> index 5b96c8fc73a5..06e40ab0970e 100644
> --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
> @@ -88,13 +88,18 @@ static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm *vm,
>  	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_PREFERRED_LOC);
>  
>  	for (i = 0; i < num_vmas; i++) {
> -		vmas[i]->attr.preferred_loc.devmem_fd = op->preferred_mem_loc.devmem_fd;
> -
> -		/* Till multi-device support is not added migration_policy
> -		 * is of no use and can be ignored.
> -		 */
> -		vmas[i]->attr.preferred_loc.migration_policy =
> +		if (vmas[i]->attr.preferred_loc.devmem_fd == op->preferred_mem_loc.devmem_fd &&
> +		    vmas[i]->attr.preferred_loc.migration_policy ==
> +		    op->preferred_mem_loc.migration_policy) {
> +			vmas[i]->skip_invalidation = 1;

In the else statement, you need to clear this so subsequent madvise
which change properties do issue invalidations. 

> +		} else {
> +			vmas[i]->attr.preferred_loc.devmem_fd = op->preferred_mem_loc.devmem_fd;
> +			/* Till multi-device support is not added migration_policy
> +			 * is of no use and can be ignored.
> +			 */
> +			vmas[i]->attr.preferred_loc.migration_policy =
>  						op->preferred_mem_loc.migration_policy;
> +		}
>  	}
>  }
>  
> @@ -109,7 +114,10 @@ static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
>  	xe_assert(vm->xe, op->atomic.val <= DRM_XE_VMA_ATOMIC_CPU);
>  
>  	for (i = 0; i < num_vmas; i++) {
> -		vmas[i]->attr.atomic_access = op->atomic.val;
> +		if (vmas[i]->attr.atomic_access == op->atomic.val)
> +			vmas[i]->skip_invalidation = 1;
> +		else
> +			vmas[i]->attr.atomic_access = op->atomic.val;
>  
>  		bo = xe_vma_bo(vmas[i]);
>  		if (!bo)
> @@ -134,9 +142,12 @@ static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
>  
>  	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_PAT);
>  
> -	for (i = 0; i < num_vmas; i++)
> -		vmas[i]->attr.pat_index = op->pat_index.val;
> -
> +	for (i = 0; i < num_vmas; i++) {
> +		if (vmas[i]->attr.pat_index == op->pat_index.val)
> +			vmas[i]->skip_invalidation = 1;
> +		else
> +			vmas[i]->attr.pat_index = op->pat_index.val;
> +	}
>  }
>  
>  typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
> @@ -161,23 +172,25 @@ static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start, u64 end, u
>  				  false, MAX_SCHEDULE_TIMEOUT) <= 0)
>  		XE_WARN_ON(1);
>  
> -	*tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
> -
>  	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
>  		struct xe_vma *vma = gpuva_to_vma(gpuva);
>  
> -		if (xe_vma_is_cpu_addr_mirror(vma))
> +		if (vma->skip_invalidation)
>  			continue;
>  
> -		if (xe_vma_is_userptr(vma)) {
> -			WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
> -							     DMA_RESV_USAGE_BOOKKEEP));
> -		}
> -
> -		for_each_tile(tile, vm->xe, id) {
> -			if (xe_pt_zap_ptes(tile, vma)) {
> -				*tile_mask |= BIT(id);
> -				vma->tile_invalidated |= BIT(id);
> +		if (xe_vma_is_cpu_addr_mirror(vma)) {
> +			*tile_mask |= xe_svm_ranges_zap_ptes_in_range(vm,
> +								      xe_vma_start(vma),
> +								      xe_vma_end(vma));
> +		} else {
> +			if (xe_vma_is_userptr(vma))
> +				WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
> +								     DMA_RESV_USAGE_BOOKKEEP));
> +			for_each_tile(tile, vm->xe, id) {
> +				if (xe_pt_zap_ptes(tile, vma)) {
> +					*tile_mask |= BIT(id);
> +					vma->tile_invalidated |= BIT(id);
> +				}
>  			}
>  		}
>  	}
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
> index c7156f8e2ed2..3b3019ecbfab 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -151,6 +151,12 @@ struct xe_vma {
>  	/** @tile_staged: bind is staged for this VMA */
>  	u8 tile_staged;
>  
> +	/**
> +	 * @skip_invalidation: Used in madvise to avoid invalidation
> +	 * if mem attributes doesn't change
> +	 */
> +	u32 skip_invalidation;

bool or I think you can safely stuff this into gpuva flags (e.g.,
DRM_GPUVA_USERBITS) as this only set / cleared / viewed by a single
thread and all other flags are set at init time or bind time (i.e., no
races). If you choose the latter, or regardless, we should probably
document the gpuva usage.

Matt

> +
>  	/**
>  	 * @ufence: The user fence that was provided with MAP.
>  	 * Needs to be signalled before UNMAP can be processed.
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
  2025-06-13 12:55 ` [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes Himal Prasad Ghimiray
@ 2025-06-23 22:43   ` Matthew Brost
  2025-06-24  2:18   ` Matthew Brost
  2025-06-26  3:44   ` Lin, Shuicheng
  2 siblings, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-23 22:43 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:57PM +0530, Himal Prasad Ghimiray wrote:
> Introduce the DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl to allow userspace
> to query memory attributes of VMAs within a specified virtual address
> range.
> If num_vmas == 0 and vector_of_vma_mem_attr == NULL, the ioctl returns
> the number of VMAs in the specified range.
> If num_vmas > 0 and a valid user pointer is provided in
> vector_of_vma_mem_attr, the ioctl fills the buffer with memory
> attributes for each VMA.
> This two-step interface allows userspace to first query the required
> buffer size, then retrieve detailed attributes efficiently.
> 
> v2 (Matthew Brost)
> - Use same ioctl to overload functionality
> 
> v3
> - Add kernel-doc
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_device.c |   1 +
>  drivers/gpu/drm/xe/xe_vm.c     |  89 ++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_vm.h     |   2 +-
>  include/uapi/drm/xe_drm.h      | 130 +++++++++++++++++++++++++++++++++
>  4 files changed, 221 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 632d3ab12392..1f9969acbcd9 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -199,6 +199,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
>  			  DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl, DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF_DRV(XE_VM_QUERY_VMAS_ATTRS, xe_vm_query_vmas_attrs_ioctl, DRM_RENDER_ALLOW),
>  };
>  
>  static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 14e554f3f4d5..d9ce25f3abf4 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -2171,6 +2171,95 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data,
>  	return err;
>  }
>  
> +static void xe_vm_query_vmas(struct xe_vm *vm, u32 *num_vmas, u64 start, u64 end)
> +{
> +	struct drm_gpuva *gpuva;
> +
> +	lockdep_assert_held(&vm->lock);
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end)
> +		(*num_vmas)++;

Return num_vmas rather than pass by reference?

> +}
> +
> +static int get_mem_attrs(struct xe_vm *vm, u32 *num_vmas, u64 start,
> +			 u64 end, struct drm_xe_vma_mem_attr *attrs)
> +{
> +	struct drm_gpuva *gpuva;
> +	int i = 0;
> +
> +	lockdep_assert_held(&vm->lock);
> +
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> +
> +		if (i == *num_vmas)
> +			return -EINVAL;

Hmm, if the number of num_vmas has changed behind users back (e.g.,
binds happen), I think it is fair to return an error. But I think
-ENOSPC would better and also document what this error code means (e.g.,
call the query IOCTL again with num_vmas == 0 and try again.

> +
> +		attrs[i].start = xe_vma_start(vma);
> +		attrs[i].end = xe_vma_end(vma);
> +		attrs[i].atomic.val = vma->attr.atomic_access;
> +		attrs[i].pat_index.val = vma->attr.pat_index;
> +		attrs[i].preferred_mem_loc.devmem_fd = vma->attr.preferred_loc.devmem_fd;
> +		attrs[i].preferred_mem_loc.migration_policy = vma->attr.preferred_loc.migration_policy;

You should either explictly set the reserved bits to zero or kvzalloc
the attrs.

> +
> +		i++;
> +	}
> +
> +	if (i <  (*num_vmas - 1))
> +		*num_vmas = i;
> +	return 0;
> +}
> +
> +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
> +{
> +	struct xe_device *xe = to_xe_device(dev);
> +	struct xe_file *xef = to_xe_file(file);
> +	struct drm_xe_vma_mem_attr *mem_attrs;
> +	struct drm_xe_vm_query_vmas_attr *args = data;
> +	u64 __user *attrs_user = u64_to_user_ptr(args->vector_of_vma_mem_attr);
> +	struct xe_vm *vm;
> +	int err = 0;
> +
> +	if (XE_IOCTL_DBG(xe,
> +			 (args->num_vmas == 0 && attrs_user) ||
> +			(args->num_vmas > 0 && !attrs_user)))
> +		return -EINVAL;
> +
> +	vm = xe_vm_lookup(xef, args->vm_id);
> +	if (XE_IOCTL_DBG(xe, !vm))
> +		return -EINVAL;
> +
> +	down_read(&vm->lock);

down_read_interruptable

> +
> +	attrs_user = u64_to_user_ptr(args->vector_of_vma_mem_attr);
> +
> +	if (args->num_vmas == 0 && !attrs_user) {
> +		xe_vm_query_vmas(vm, &args->num_vmas, args->start, args->start + args->range);
> +		goto unlock_vm;
> +	}
> +
> +	mem_attrs = kvmalloc_array(args->num_vmas, sizeof(struct drm_xe_vma_mem_attr),
> +				   GFP_KERNEL | __GFP_ACCOUNT |
> +				   __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
> +	if (!mem_attrs) {
> +		err = args->num_vmas > 1 ? -ENOBUFS : -ENOMEM;
> +		goto unlock_vm;
> +	}
> +
> +	err = get_mem_attrs(vm, &args->num_vmas, args->start,
> +			    args->start + args->range, mem_attrs);
> +	if (err)
> +		goto free_mem_attrs;
> +
> +	err = __copy_to_user(attrs_user, mem_attrs,

I think copy_to_user is preferred. This is fixed in a bunch of places in
Xe recently.

> +			     sizeof(struct drm_xe_vma_mem_attr) * args->num_vmas);
> +
> +free_mem_attrs:
> +	kvfree(mem_attrs);
> +unlock_vm:
> +	up_read(&vm->lock);
> +	return err;
> +}
> +
>  static bool vma_matches(struct xe_vma *vma, u64 page_addr)
>  {
>  	if (page_addr > xe_vma_end(vma) - 1 ||
> diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
> index 1fb639a33ffb..e4a601a3583f 100644
> --- a/drivers/gpu/drm/xe/xe_vm.h
> +++ b/drivers/gpu/drm/xe/xe_vm.h
> @@ -195,7 +195,7 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data,
>  			struct drm_file *file);
>  int xe_vm_bind_ioctl(struct drm_device *dev, void *data,
>  		     struct drm_file *file);
> -
> +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
>  void xe_vm_close_and_put(struct xe_vm *vm);
>  
>  static inline bool xe_vm_in_fault_mode(struct xe_vm *vm)
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index 81e90270313d..c0aa7c19870e 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -82,6 +82,7 @@ extern "C" {
>   *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
>   *  - &DRM_IOCTL_XE_OBSERVATION
>   *  - &DRM_IOCTL_XE_MADVISE
> + *  - &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
>   */
>  
>  /*
> @@ -104,6 +105,7 @@ extern "C" {
>  #define DRM_XE_WAIT_USER_FENCE		0x0a
>  #define DRM_XE_OBSERVATION		0x0b
>  #define DRM_XE_MADVISE			0x0c
> +#define DRM_XE_VM_QUERY_VMAS_ATTRS	0x0d
>  
>  /* Must be kept compact -- no holes */
>  
> @@ -120,6 +122,7 @@ extern "C" {
>  #define DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence)
>  #define DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
>  #define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
> +#define DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_VMAS_ATTRS, struct drm_xe_vm_query_vmas_attr)
>  
>  /**
>   * DOC: Xe IOCTL Extensions
> @@ -2093,6 +2096,133 @@ struct drm_xe_madvise {
>  	__u64 reserved[2];
>  };
>  
> +/**
> + * struct drm_xe_vma_mem_attr - Output of &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
> + *
> + * This structure is provided by userspace and filled by KMD in response to the
> + * DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl. It describes memory attributes of
> + * a VMA within a specified address range in a VM.
> + *
> + * The structure includes information such as atomic access policy, purgeable
> + * state, page attribute table (PAT) index, and preferred memory location.
> + * Userspace allocates an array of these structures and passes a pointer to the
> + * ioctl to retrieve attributes for each VMA
> + *
> + * @extensions: Pointer to the first extension struct, if any
> + * @start: Start address of the virtual memory area
> + * @end: End address of the virtual memory area
> + *
> + * @atomic.val: Value of atomic operation policy
> + * @atomic.reserved: Reserved, must be zero
> + *
> + * @purge_state_val.val: Value for DRM_XE_VMA_ATTR_PURGEABLE_STATE
> + * @purge_state_val.reserved: Reserved, must be zero
> + *
> + * @pat_index.val: Page Attribute Table (PAT) index
> + * @pat_index.reserved: Reserved, must be zero
> + *
> + * @preferred_mem_loc.devmem_fd: File descriptor for preferred device memory
> + * @preferred_mem_loc.migration_policy: Migration policy for memory placement

Double kernel doc for the fields?

> + *
> + */
> +struct drm_xe_vma_mem_attr {
> +	 /** @extensions: Pointer to the first extension struct, if any */
> +	__u64 extensions;
> +
> +	/** @start: start of the vma */
> +	__u64 start;
> +
> +	/** @end: end of the vma */
> +	__u64 end;
> +
> +	struct {

Same thing here, match the order of the defines for these.

Also no need for the outer struct here.

> +		struct {
> +		/** @atomic.val: atomic attribute for vma*/
> +			__u32 val;
> +
> +		/** @atomic.reserved: Reserved */

Alignment is off in my editor.

> +			__u32 reserved;
> +		} atomic;
> +
> +		struct {
> +			/** @pat_index.val: PAT index of vma */
> +			__u32 val;
> +
> +			/** @pat_index.reserved: Reserved */
> +			__u32 reserved;
> +		} pat_index;
> +
> +		/** @preferred_mem_loc: preferred memory location */
> +		struct {
> +			/** @preferred_mem_loc.devmem_fd: fd for preferred loc */
> +			__u32 devmem_fd;
> +
> +			/** @preferred_mem_loc.migration_policy: Page migration policy */
> +			__u32 migration_policy;
> +		} preferred_mem_loc;
> +	};
> +
> +	 /** @reserved: Reserved */
> +	__u64 reserved[2];
> +};
> +
> +/**
> + * struct drm_xe_vm_query_vmas_attr - Input of &DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES
> + *
> + * This structure is used to query memory attributes of virtual memory areas
> + * (VMAs) within a specified address range in a VM. It provides detailed
> + * information about each VMA, including atomic access policy, purgeable state,
> + * page attribute table (PAT) index, and preferred memory location.
> + *
> + * Userspace first calls the ioctl with @num_vmas = 0 and
> + * @vector_of_vma_mem_attr = NULL to retrieve the number of VMAs in the range.
> + * Then, it allocates a buffer of that size and calls the ioctl again to fill
> + * the buffer with VMA attributes.
> + *
> + * Example:
> + *
> + * .. code-block:: C
> + *

I'd show how query is initialized. See drm_xe_device_query kernel doc
for an example.

Matt

> + *     struct drm_xe_vma_mem_attr *attrs;
> + *     __u32 num_vmas;
> + *
> + *     // First call to get number of VMAs
> + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> + *     num_vmas = query.num_vmas;
> + *
> + *     // Allocate and query attributes
> + *     attrs = malloc(num_vmas, sizeof(*attrs));
> + *     query.vector_of_vma_mem_attr = (__u64)(uintptr_t)attrs;
> + *     query.num_vmas = num_vmas;
> + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> + */
> +struct drm_xe_vm_query_vmas_attr {
> +	/** @extensions: Pointer to the first extension struct, if any */
> +	__u64 extensions;
> +
> +	/** @vm_id: vm_id of the virtual range */
> +	__u32 vm_id;
> +
> +	/** @num_vmas: number of vmas in range */
> +	__u32 num_vmas;
> +
> +	/** @start: start of the virtual address range */
> +	__u64 start;
> +
> +	/** @size: size of the virtual address range */
> +	__u64 range;
> +
> +	/**
> +	 * @vector_of_ops: userptr to array of struct
> +	 * drm_xe_vma_mem_attr
> +	 */
> +	__u64 vector_of_vma_mem_attr;
> +
> +	/** @reserved: Reserved */
> +	__u64 reserved[2];
> +
> +};
> +
>  #if defined(__cplusplus)
>  }
>  #endif
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
  2025-06-13 12:55 ` [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes Himal Prasad Ghimiray
  2025-06-23 22:43   ` Matthew Brost
@ 2025-06-24  2:18   ` Matthew Brost
  2025-06-27 13:20     ` Thomas Hellström
  2025-06-27 13:43     ` Thomas Hellström
  2025-06-26  3:44   ` Lin, Shuicheng
  2 siblings, 2 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-24  2:18 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:57PM +0530, Himal Prasad Ghimiray wrote:
> Introduce the DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl to allow userspace
> to query memory attributes of VMAs within a specified virtual address
> range.
> If num_vmas == 0 and vector_of_vma_mem_attr == NULL, the ioctl returns
> the number of VMAs in the specified range.
> If num_vmas > 0 and a valid user pointer is provided in
> vector_of_vma_mem_attr, the ioctl fills the buffer with memory
> attributes for each VMA.
> This two-step interface allows userspace to first query the required
> buffer size, then retrieve detailed attributes efficiently.
> 
> v2 (Matthew Brost)
> - Use same ioctl to overload functionality
> 
> v3
> - Add kernel-doc
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_device.c |   1 +
>  drivers/gpu/drm/xe/xe_vm.c     |  89 ++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_vm.h     |   2 +-
>  include/uapi/drm/xe_drm.h      | 130 +++++++++++++++++++++++++++++++++
>  4 files changed, 221 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 632d3ab12392..1f9969acbcd9 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -199,6 +199,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
>  			  DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl, DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF_DRV(XE_VM_QUERY_VMAS_ATTRS, xe_vm_query_vmas_attrs_ioctl, DRM_RENDER_ALLOW),
>  };
>  
>  static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 14e554f3f4d5..d9ce25f3abf4 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -2171,6 +2171,95 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data,
>  	return err;
>  }
>  
> +static void xe_vm_query_vmas(struct xe_vm *vm, u32 *num_vmas, u64 start, u64 end)
> +{
> +	struct drm_gpuva *gpuva;
> +
> +	lockdep_assert_held(&vm->lock);
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end)
> +		(*num_vmas)++;
> +}
> +
> +static int get_mem_attrs(struct xe_vm *vm, u32 *num_vmas, u64 start,
> +			 u64 end, struct drm_xe_vma_mem_attr *attrs)
> +{
> +	struct drm_gpuva *gpuva;
> +	int i = 0;
> +
> +	lockdep_assert_held(&vm->lock);
> +
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> +
> +		if (i == *num_vmas)
> +			return -EINVAL;
> +
> +		attrs[i].start = xe_vma_start(vma);
> +		attrs[i].end = xe_vma_end(vma);
> +		attrs[i].atomic.val = vma->attr.atomic_access;
> +		attrs[i].pat_index.val = vma->attr.pat_index;
> +		attrs[i].preferred_mem_loc.devmem_fd = vma->attr.preferred_loc.devmem_fd;
> +		attrs[i].preferred_mem_loc.migration_policy = vma->attr.preferred_loc.migration_policy;
> +
> +		i++;
> +	}
> +
> +	if (i <  (*num_vmas - 1))
> +		*num_vmas = i;
> +	return 0;
> +}
> +
> +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
> +{
> +	struct xe_device *xe = to_xe_device(dev);
> +	struct xe_file *xef = to_xe_file(file);
> +	struct drm_xe_vma_mem_attr *mem_attrs;
> +	struct drm_xe_vm_query_vmas_attr *args = data;
> +	u64 __user *attrs_user = u64_to_user_ptr(args->vector_of_vma_mem_attr);
> +	struct xe_vm *vm;
> +	int err = 0;
> +
> +	if (XE_IOCTL_DBG(xe,
> +			 (args->num_vmas == 0 && attrs_user) ||
> +			(args->num_vmas > 0 && !attrs_user)))
> +		return -EINVAL;
> +
> +	vm = xe_vm_lookup(xef, args->vm_id);
> +	if (XE_IOCTL_DBG(xe, !vm))
> +		return -EINVAL;
> +
> +	down_read(&vm->lock);
> +
> +	attrs_user = u64_to_user_ptr(args->vector_of_vma_mem_attr);
> +
> +	if (args->num_vmas == 0 && !attrs_user) {
> +		xe_vm_query_vmas(vm, &args->num_vmas, args->start, args->start + args->range);
> +		goto unlock_vm;
> +	}
> +
> +	mem_attrs = kvmalloc_array(args->num_vmas, sizeof(struct drm_xe_vma_mem_attr),
> +				   GFP_KERNEL | __GFP_ACCOUNT |
> +				   __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
> +	if (!mem_attrs) {
> +		err = args->num_vmas > 1 ? -ENOBUFS : -ENOMEM;
> +		goto unlock_vm;
> +	}
> +
> +	err = get_mem_attrs(vm, &args->num_vmas, args->start,
> +			    args->start + args->range, mem_attrs);
> +	if (err)
> +		goto free_mem_attrs;
> +
> +	err = __copy_to_user(attrs_user, mem_attrs,
> +			     sizeof(struct drm_xe_vma_mem_attr) * args->num_vmas);
> +
> +free_mem_attrs:
> +	kvfree(mem_attrs);
> +unlock_vm:
> +	up_read(&vm->lock);
> +	return err;
> +}
> +
>  static bool vma_matches(struct xe_vma *vma, u64 page_addr)
>  {
>  	if (page_addr > xe_vma_end(vma) - 1 ||
> diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
> index 1fb639a33ffb..e4a601a3583f 100644
> --- a/drivers/gpu/drm/xe/xe_vm.h
> +++ b/drivers/gpu/drm/xe/xe_vm.h
> @@ -195,7 +195,7 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data,
>  			struct drm_file *file);
>  int xe_vm_bind_ioctl(struct drm_device *dev, void *data,
>  		     struct drm_file *file);
> -
> +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
>  void xe_vm_close_and_put(struct xe_vm *vm);
>  
>  static inline bool xe_vm_in_fault_mode(struct xe_vm *vm)
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index 81e90270313d..c0aa7c19870e 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -82,6 +82,7 @@ extern "C" {
>   *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
>   *  - &DRM_IOCTL_XE_OBSERVATION
>   *  - &DRM_IOCTL_XE_MADVISE
> + *  - &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
>   */
>  
>  /*
> @@ -104,6 +105,7 @@ extern "C" {
>  #define DRM_XE_WAIT_USER_FENCE		0x0a
>  #define DRM_XE_OBSERVATION		0x0b
>  #define DRM_XE_MADVISE			0x0c
> +#define DRM_XE_VM_QUERY_VMAS_ATTRS	0x0d
>  
>  /* Must be kept compact -- no holes */
>  
> @@ -120,6 +122,7 @@ extern "C" {
>  #define DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence)
>  #define DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
>  #define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
> +#define DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_VMAS_ATTRS, struct drm_xe_vm_query_vmas_attr)
>  
>  /**
>   * DOC: Xe IOCTL Extensions
> @@ -2093,6 +2096,133 @@ struct drm_xe_madvise {
>  	__u64 reserved[2];
>  };
>  
> +/**
> + * struct drm_xe_vma_mem_attr - Output of &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
> + *
> + * This structure is provided by userspace and filled by KMD in response to the
> + * DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl. It describes memory attributes of
> + * a VMA within a specified address range in a VM.
> + *
> + * The structure includes information such as atomic access policy, purgeable
> + * state, page attribute table (PAT) index, and preferred memory location.
> + * Userspace allocates an array of these structures and passes a pointer to the
> + * ioctl to retrieve attributes for each VMA
> + *
> + * @extensions: Pointer to the first extension struct, if any
> + * @start: Start address of the virtual memory area
> + * @end: End address of the virtual memory area
> + *
> + * @atomic.val: Value of atomic operation policy
> + * @atomic.reserved: Reserved, must be zero
> + *
> + * @purge_state_val.val: Value for DRM_XE_VMA_ATTR_PURGEABLE_STATE
> + * @purge_state_val.reserved: Reserved, must be zero
> + *
> + * @pat_index.val: Page Attribute Table (PAT) index
> + * @pat_index.reserved: Reserved, must be zero
> + *
> + * @preferred_mem_loc.devmem_fd: File descriptor for preferred device memory
> + * @preferred_mem_loc.migration_policy: Migration policy for memory placement
> + *
> + */
> +struct drm_xe_vma_mem_attr {
> +	 /** @extensions: Pointer to the first extension struct, if any */
> +	__u64 extensions;
> +
> +	/** @start: start of the vma */
> +	__u64 start;
> +
> +	/** @end: end of the vma */
> +	__u64 end;
> +
> +	struct {
> +		struct {
> +		/** @atomic.val: atomic attribute for vma*/
> +			__u32 val;
> +
> +		/** @atomic.reserved: Reserved */
> +			__u32 reserved;
> +		} atomic;
> +
> +		struct {
> +			/** @pat_index.val: PAT index of vma */
> +			__u32 val;
> +
> +			/** @pat_index.reserved: Reserved */
> +			__u32 reserved;
> +		} pat_index;
> +
> +		/** @preferred_mem_loc: preferred memory location */
> +		struct {
> +			/** @preferred_mem_loc.devmem_fd: fd for preferred loc */
> +			__u32 devmem_fd;
> +
> +			/** @preferred_mem_loc.migration_policy: Page migration policy */
> +			__u32 migration_policy;
> +		} preferred_mem_loc;
> +	};

I just realized this interface isn’t very future-proof. Let me give an
easy example of how this could break. Let’s say we add three more
madvise attributes at some point in the future — we wouldn’t be able to
fit those three additional attributes here.

Hmm, maybe in drm_xe_vm_query_vmas_attr we could also return the sizeof
a single struct drm_xe_vma_mem_attr entry. That would allow us to grow
individual entries indefinitely without breaking userspace, as long as
it does something like the code below, and as long as we only grow
struct drm_xe_vm_query_vmas_attr by appending new fields (i.e. we never
reorder existing ones).

struct drm_xe_vm_query_vmas_attr query = {
    .vm_id = vm,
    .start = start,
    .range = range,
};

/* First ioctl to get number of VMAs and the size of each attribute */
ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);

/* Allocate buffer for the VMA attributes */
void *ptr = malloc(query.num_vmas * query.sizeof_vma_mem_attr);

query.vector_of_vma_mem_attr = (uintptr_t)ptr;

/* Second ioctl to actually fill the VMA attributes */
ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);

/* Iterate over the returned VMA attributes */
for (unsigned int i = 0; i < query.num_vmas; ++i) {
    struct drm_xe_vma_mem_attr *vma_attr = (struct drm_xe_vma_mem_attr *)ptr;

    /* Do something with vma_attr */

    /* Move pointer by one VMA entry */
    ptr += query.sizeof_vma_mem_attr;
}

I think we need to double-check with the maintainer to see if this type
of interface is allowed, but I don’t see any reason why it wouldn’t be.

Matt

> +
> +	 /** @reserved: Reserved */
> +	__u64 reserved[2];
> +};
> +
> +/**
> + * struct drm_xe_vm_query_vmas_attr - Input of &DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES
> + *
> + * This structure is used to query memory attributes of virtual memory areas
> + * (VMAs) within a specified address range in a VM. It provides detailed
> + * information about each VMA, including atomic access policy, purgeable state,
> + * page attribute table (PAT) index, and preferred memory location.
> + *
> + * Userspace first calls the ioctl with @num_vmas = 0 and
> + * @vector_of_vma_mem_attr = NULL to retrieve the number of VMAs in the range.
> + * Then, it allocates a buffer of that size and calls the ioctl again to fill
> + * the buffer with VMA attributes.
> + *
> + * Example:
> + *
> + * .. code-block:: C
> + *
> + *     struct drm_xe_vma_mem_attr *attrs;
> + *     __u32 num_vmas;
> + *
> + *     // First call to get number of VMAs
> + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> + *     num_vmas = query.num_vmas;
> + *
> + *     // Allocate and query attributes
> + *     attrs = malloc(num_vmas, sizeof(*attrs));
> + *     query.vector_of_vma_mem_attr = (__u64)(uintptr_t)attrs;
> + *     query.num_vmas = num_vmas;
> + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> + */
> +struct drm_xe_vm_query_vmas_attr {
> +	/** @extensions: Pointer to the first extension struct, if any */
> +	__u64 extensions;
> +
> +	/** @vm_id: vm_id of the virtual range */
> +	__u32 vm_id;
> +
> +	/** @num_vmas: number of vmas in range */
> +	__u32 num_vmas;
> +
> +	/** @start: start of the virtual address range */
> +	__u64 start;
> +
> +	/** @size: size of the virtual address range */
> +	__u64 range;
> +
> +	/**
> +	 * @vector_of_ops: userptr to array of struct
> +	 * drm_xe_vma_mem_attr
> +	 */
> +	__u64 vector_of_vma_mem_attr;
> +
> +	/** @reserved: Reserved */
> +	__u64 reserved[2];
> +
> +};
> +
>  #if defined(__cplusplus)
>  }
>  #endif
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* RE: [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
  2025-06-13 12:55 ` [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes Himal Prasad Ghimiray
  2025-06-23 22:43   ` Matthew Brost
  2025-06-24  2:18   ` Matthew Brost
@ 2025-06-26  3:44   ` Lin, Shuicheng
  2 siblings, 0 replies; 68+ messages in thread
From: Lin, Shuicheng @ 2025-06-26  3:44 UTC (permalink / raw)
  To: Ghimiray, Himal Prasad, intel-xe@lists.freedesktop.org
  Cc: Brost, Matthew, thomas.hellstrom@linux.intel.com,
	Ghimiray, Himal Prasad

On Fri, June 13, 2025 8:56 PM Himal Prasad Ghimiray wrote:
> Introduce the DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl to allow
> userspace to query memory attributes of VMAs within a specified virtual address
> range.
> If num_vmas == 0 and vector_of_vma_mem_attr == NULL, the ioctl returns the
> number of VMAs in the specified range.
> If num_vmas > 0 and a valid user pointer is provided in vector_of_vma_mem_attr,
> the ioctl fills the buffer with memory attributes for each VMA.
> This two-step interface allows userspace to first query the required buffer size,
> then retrieve detailed attributes efficiently.
> 
> v2 (Matthew Brost)
> - Use same ioctl to overload functionality
> 
> v3
> - Add kernel-doc
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_device.c |   1 +
>  drivers/gpu/drm/xe/xe_vm.c     |  89 ++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_vm.h     |   2 +-
>  include/uapi/drm/xe_drm.h      | 130 +++++++++++++++++++++++++++++++++
>  4 files changed, 221 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 632d3ab12392..1f9969acbcd9 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -199,6 +199,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
>  			  DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl,
> DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl,
> DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF_DRV(XE_VM_QUERY_VMAS_ATTRS,
> +xe_vm_query_vmas_attrs_ioctl, DRM_RENDER_ALLOW),

I have not gone through the details, but it seems this query ioctl is much like the XE_DEVICE_QUERY ioctl.
Is it possible to put this query to be a sub-query of it?
Thanks.

Shuicheng

>  };
> 
>  static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) diff
> --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index
> 14e554f3f4d5..d9ce25f3abf4 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -2171,6 +2171,95 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void
> *data,
>  	return err;
>  }
> 
> +static void xe_vm_query_vmas(struct xe_vm *vm, u32 *num_vmas, u64
> +start, u64 end) {
> +	struct drm_gpuva *gpuva;
> +
> +	lockdep_assert_held(&vm->lock);
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end)
> +		(*num_vmas)++;
> +}
> +
> +static int get_mem_attrs(struct xe_vm *vm, u32 *num_vmas, u64 start,
> +			 u64 end, struct drm_xe_vma_mem_attr *attrs) {
> +	struct drm_gpuva *gpuva;
> +	int i = 0;
> +
> +	lockdep_assert_held(&vm->lock);
> +
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> +
> +		if (i == *num_vmas)
> +			return -EINVAL;
> +
> +		attrs[i].start = xe_vma_start(vma);
> +		attrs[i].end = xe_vma_end(vma);
> +		attrs[i].atomic.val = vma->attr.atomic_access;
> +		attrs[i].pat_index.val = vma->attr.pat_index;
> +		attrs[i].preferred_mem_loc.devmem_fd = vma-
> >attr.preferred_loc.devmem_fd;
> +		attrs[i].preferred_mem_loc.migration_policy =
> +vma->attr.preferred_loc.migration_policy;
> +
> +		i++;
> +	}
> +
> +	if (i <  (*num_vmas - 1))
> +		*num_vmas = i;

I am not sure this is correct or not. Should it be "i < *num_vmas"?
Thanks.

Shuicheng

> +	return 0;
> +}
> +
> +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void *data,
> +struct drm_file *file) {
> +	struct xe_device *xe = to_xe_device(dev);
> +	struct xe_file *xef = to_xe_file(file);
> +	struct drm_xe_vma_mem_attr *mem_attrs;
> +	struct drm_xe_vm_query_vmas_attr *args = data;
> +	u64 __user *attrs_user = u64_to_user_ptr(args-
> >vector_of_vma_mem_attr);
> +	struct xe_vm *vm;
> +	int err = 0;
> +
> +	if (XE_IOCTL_DBG(xe,
> +			 (args->num_vmas == 0 && attrs_user) ||
> +			(args->num_vmas > 0 && !attrs_user)))
> +		return -EINVAL;
> +
> +	vm = xe_vm_lookup(xef, args->vm_id);
> +	if (XE_IOCTL_DBG(xe, !vm))
> +		return -EINVAL;
> +

The vm returned by xe_vm_lookup() need be released by call xe_vm_put(vm) at the end of the function.
Thanks.

Shuicheng

> +	down_read(&vm->lock);
> +
> +	attrs_user = u64_to_user_ptr(args->vector_of_vma_mem_attr);
> +
> +	if (args->num_vmas == 0 && !attrs_user) {
> +		xe_vm_query_vmas(vm, &args->num_vmas, args->start, args-
> >start + args->range);
> +		goto unlock_vm;
> +	}
> +
> +	mem_attrs = kvmalloc_array(args->num_vmas, sizeof(struct
> drm_xe_vma_mem_attr),
> +				   GFP_KERNEL | __GFP_ACCOUNT |
> +				   __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
> +	if (!mem_attrs) {
> +		err = args->num_vmas > 1 ? -ENOBUFS : -ENOMEM;
> +		goto unlock_vm;
> +	}
> +
> +	err = get_mem_attrs(vm, &args->num_vmas, args->start,
> +			    args->start + args->range, mem_attrs);
> +	if (err)
> +		goto free_mem_attrs;
> +
> +	err = __copy_to_user(attrs_user, mem_attrs,
> +			     sizeof(struct drm_xe_vma_mem_attr) * args-
> >num_vmas);
> +
> +free_mem_attrs:
> +	kvfree(mem_attrs);
> +unlock_vm:
> +	up_read(&vm->lock);
> +	return err;
> +}
> +
>  static bool vma_matches(struct xe_vma *vma, u64 page_addr)  {
>  	if (page_addr > xe_vma_end(vma) - 1 || diff --git
> a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index
> 1fb639a33ffb..e4a601a3583f 100644
> --- a/drivers/gpu/drm/xe/xe_vm.h
> +++ b/drivers/gpu/drm/xe/xe_vm.h
> @@ -195,7 +195,7 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void
> *data,
>  			struct drm_file *file);
>  int xe_vm_bind_ioctl(struct drm_device *dev, void *data,
>  		     struct drm_file *file);
> -
> +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void *data,
> +struct drm_file *file);
>  void xe_vm_close_and_put(struct xe_vm *vm);
> 
>  static inline bool xe_vm_in_fault_mode(struct xe_vm *vm) diff --git
> a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index
> 81e90270313d..c0aa7c19870e 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -82,6 +82,7 @@ extern "C" {
>   *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
>   *  - &DRM_IOCTL_XE_OBSERVATION
>   *  - &DRM_IOCTL_XE_MADVISE
> + *  - &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
>   */
> 
>  /*
> @@ -104,6 +105,7 @@ extern "C" {
>  #define DRM_XE_WAIT_USER_FENCE		0x0a
>  #define DRM_XE_OBSERVATION		0x0b
>  #define DRM_XE_MADVISE			0x0c
> +#define DRM_XE_VM_QUERY_VMAS_ATTRS	0x0d
> 
>  /* Must be kept compact -- no holes */
> 
> @@ -120,6 +122,7 @@ extern "C" {
>  #define DRM_IOCTL_XE_WAIT_USER_FENCE
> 	DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE,
> struct drm_xe_wait_user_fence)
>  #define DRM_IOCTL_XE_OBSERVATION
> 	DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct
> drm_xe_observation_param)
>  #define DRM_IOCTL_XE_MADVISE
> 	DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct
> drm_xe_madvise)
> +#define DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
> 	DRM_IOWR(DRM_COMMAND_BASE +
> DRM_XE_VM_QUERY_VMAS_ATTRS, struct drm_xe_vm_query_vmas_attr)
> 
>  /**
>   * DOC: Xe IOCTL Extensions
> @@ -2093,6 +2096,133 @@ struct drm_xe_madvise {
>  	__u64 reserved[2];
>  };
> 
> +/**
> + * struct drm_xe_vma_mem_attr - Output of
> +&DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
> + *
> + * This structure is provided by userspace and filled by KMD in
> +response to the
> + * DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl. It describes memory
> +attributes of
> + * a VMA within a specified address range in a VM.
> + *
> + * The structure includes information such as atomic access policy,
> +purgeable
> + * state, page attribute table (PAT) index, and preferred memory location.
> + * Userspace allocates an array of these structures and passes a
> +pointer to the
> + * ioctl to retrieve attributes for each VMA
> + *
> + * @extensions: Pointer to the first extension struct, if any
> + * @start: Start address of the virtual memory area
> + * @end: End address of the virtual memory area
> + *
> + * @atomic.val: Value of atomic operation policy
> + * @atomic.reserved: Reserved, must be zero
> + *
> + * @purge_state_val.val: Value for DRM_XE_VMA_ATTR_PURGEABLE_STATE
> + * @purge_state_val.reserved: Reserved, must be zero
> + *
> + * @pat_index.val: Page Attribute Table (PAT) index
> + * @pat_index.reserved: Reserved, must be zero
> + *
> + * @preferred_mem_loc.devmem_fd: File descriptor for preferred device
> +memory
> + * @preferred_mem_loc.migration_policy: Migration policy for memory
> +placement
> + *
> + */
> +struct drm_xe_vma_mem_attr {
> +	 /** @extensions: Pointer to the first extension struct, if any */
> +	__u64 extensions;
> +
> +	/** @start: start of the vma */
> +	__u64 start;
> +
> +	/** @end: end of the vma */
> +	__u64 end;
> +
> +	struct {
> +		struct {
> +		/** @atomic.val: atomic attribute for vma*/
> +			__u32 val;
> +
> +		/** @atomic.reserved: Reserved */
> +			__u32 reserved;
> +		} atomic;
> +
> +		struct {
> +			/** @pat_index.val: PAT index of vma */
> +			__u32 val;
> +
> +			/** @pat_index.reserved: Reserved */
> +			__u32 reserved;
> +		} pat_index;
> +
> +		/** @preferred_mem_loc: preferred memory location */
> +		struct {
> +			/** @preferred_mem_loc.devmem_fd: fd for preferred
> loc */
> +			__u32 devmem_fd;
> +
> +			/** @preferred_mem_loc.migration_policy: Page
> migration policy */
> +			__u32 migration_policy;
> +		} preferred_mem_loc;
> +	};
> +
> +	 /** @reserved: Reserved */
> +	__u64 reserved[2];
> +};
> +
> +/**
> + * struct drm_xe_vm_query_vmas_attr - Input of
> +&DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES
> + *
> + * This structure is used to query memory attributes of virtual memory
> +areas
> + * (VMAs) within a specified address range in a VM. It provides
> +detailed
> + * information about each VMA, including atomic access policy,
> +purgeable state,
> + * page attribute table (PAT) index, and preferred memory location.
> + *
> + * Userspace first calls the ioctl with @num_vmas = 0 and
> + * @vector_of_vma_mem_attr = NULL to retrieve the number of VMAs in the
> range.
> + * Then, it allocates a buffer of that size and calls the ioctl again
> +to fill
> + * the buffer with VMA attributes.
> + *
> + * Example:
> + *
> + * .. code-block:: C
> + *
> + *     struct drm_xe_vma_mem_attr *attrs;
> + *     __u32 num_vmas;
> + *
> + *     // First call to get number of VMAs
> + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> + *     num_vmas = query.num_vmas;
> + *
> + *     // Allocate and query attributes
> + *     attrs = malloc(num_vmas, sizeof(*attrs));
> + *     query.vector_of_vma_mem_attr = (__u64)(uintptr_t)attrs;
> + *     query.num_vmas = num_vmas;
> + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);  */ struct
> +drm_xe_vm_query_vmas_attr {
> +	/** @extensions: Pointer to the first extension struct, if any */
> +	__u64 extensions;
> +
> +	/** @vm_id: vm_id of the virtual range */
> +	__u32 vm_id;
> +
> +	/** @num_vmas: number of vmas in range */
> +	__u32 num_vmas;
> +
> +	/** @start: start of the virtual address range */
> +	__u64 start;
> +
> +	/** @size: size of the virtual address range */
> +	__u64 range;
> +
> +	/**
> +	 * @vector_of_ops: userptr to array of struct
> +	 * drm_xe_vma_mem_attr
> +	 */
> +	__u64 vector_of_vma_mem_attr;
> +
> +	/** @reserved: Reserved */
> +	__u64 reserved[2];
> +
> +};
> +
>  #if defined(__cplusplus)
>  }
>  #endif
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 68+ messages in thread

* RE: [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe
  2025-06-13 12:55 ` [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe Himal Prasad Ghimiray
  2025-06-23  5:33   ` Matthew Brost
@ 2025-06-26  6:04   ` Lin, Shuicheng
  2025-06-26  6:15     ` Matthew Brost
  2025-06-26  8:34     ` Ghimiray, Himal Prasad
  1 sibling, 2 replies; 68+ messages in thread
From: Lin, Shuicheng @ 2025-06-26  6:04 UTC (permalink / raw)
  To: Ghimiray, Himal Prasad, intel-xe@lists.freedesktop.org
  Cc: Brost, Matthew, thomas.hellstrom@linux.intel.com,
	Ghimiray, Himal Prasad

On Fri, June 13, 2025 8:56 PM Himal Prasad Ghimiray wrote:
> This driver-specific ioctl enables UMDs to control the memory attributes for GPU
> VMAs within a specified input range. If the start or end addresses fall within an
> existing VMA, the VMA is split accordingly. The attributes of the VMA are
> modified as provided by the users. The old mappings of the VMAs are invalidated,
> and TLB invalidation is performed if necessary.
> 
> v2(Matthew brost)
> - xe_vm_in_fault_mode can't be enabled by Mesa, hence allow ioctl in non fault
> mode too
> - fix tlb invalidation skip for same ranges in multiple op
> - use helper for tlb invalidation
> - use xe_svm_notifier_lock/unlock helper
> - s/lockdep_assert_held/lockdep_assert_held_write
> - Add kernel-doc
> 
> v3(Matthew Brost)
> - make vfunc fail safe
> - Add sanitizing input args before vfunc
> 
> Cc: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
>  drivers/gpu/drm/xe/Makefile        |   1 +
>  drivers/gpu/drm/xe/xe_device.c     |   2 +
>  drivers/gpu/drm/xe/xe_vm_madvise.c | 282
> +++++++++++++++++++++++++++++  drivers/gpu/drm/xe/xe_vm_madvise.h |  15
> ++
>  4 files changed, 300 insertions(+)
>  create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
>  create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h
> 
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index
> f5f5775acdc0..d375b549c30f 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -117,6 +117,7 @@ xe-y += xe_bb.o \
>  	xe_uc.o \
>  	xe_uc_fw.o \
>  	xe_vm.o \
> +	xe_vm_madvise.o \
>  	xe_vram.o \
>  	xe_vram_freq.o \
>  	xe_vsec.o \
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 7d9a31868ea9..632d3ab12392 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -61,6 +61,7 @@
>  #include "xe_ttm_stolen_mgr.h"
>  #include "xe_ttm_sys_mgr.h"
>  #include "xe_vm.h"
> +#include "xe_vm_madvise.h"
>  #include "xe_vram.h"
>  #include "xe_vsec.h"
>  #include "xe_wait_user_fence.h"
> @@ -197,6 +198,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
>  	DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE,
> xe_wait_user_fence_ioctl,
>  			  DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl,
> DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl,
> DRM_RENDER_ALLOW),
>  };
> 
>  static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) diff
> --git a/drivers/gpu/drm/xe/xe_vm_madvise.c
> b/drivers/gpu/drm/xe/xe_vm_madvise.c
> new file mode 100644
> index 000000000000..ff560914ad7e
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
> @@ -0,0 +1,282 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#include "xe_vm_madvise.h"
> +
> +#include <linux/nospec.h>
> +#include <drm/ttm/ttm_tt.h>
> +#include <drm/xe_drm.h>
> +
> +#include "xe_bo.h"
> +#include "xe_gt_tlb_invalidation.h"
> +#include "xe_pt.h"
> +#include "xe_svm.h"
> +
> +struct xe_vmas_in_madvise_range {
> +	u64 addr;
> +	u64 range;
> +	struct xe_vma **vmas;
> +	int num_vmas;
> +	bool has_svm_vmas;
> +	bool has_bo_vmas;
> +	bool has_userptr_vmas;
> +};
> +
> +static int get_vmas(struct xe_vm *vm, struct xe_vmas_in_madvise_range
> +*madvise_range) {
> +	u64 addr = madvise_range->addr;
> +	u64 range = madvise_range->range;
> +
> +	struct xe_vma  **__vmas;
> +	struct drm_gpuva *gpuva;
> +	int max_vmas = 8;
> +
> +	lockdep_assert_held(&vm->lock);
> +
> +	madvise_range->num_vmas = 0;
> +	madvise_range->vmas = kmalloc_array(max_vmas,
> sizeof(*madvise_range->vmas), GFP_KERNEL);
> +	if (!madvise_range->vmas)
> +		return -ENOMEM;
> +
> +	vm_dbg(&vm->xe->drm, "VMA's in range: start=0x%016llx,
> end=0x%016llx",
> +addr, addr + range);
> +
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, addr, addr +
> range) {
> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> +
> +		if (xe_vma_bo(vma))
> +			madvise_range->has_bo_vmas = true;
> +		else if (xe_vma_is_cpu_addr_mirror(vma))
> +			madvise_range->has_svm_vmas = true;
> +		else if (xe_vma_is_userptr(vma))
> +			madvise_range->has_userptr_vmas = true;
> +		else
> +			XE_WARN_ON("UNEXPECTED VMA");
> +
> +		if (madvise_range->num_vmas == max_vmas) {
> +			max_vmas <<= 1;
> +			__vmas = krealloc(madvise_range->vmas,
> +					  max_vmas * sizeof(*madvise_range-
> >vmas),
> +					  GFP_KERNEL);
> +			if (!__vmas) {
> +				kfree(madvise_range->vmas);
> +				return -ENOMEM;
> +			}
> +			madvise_range->vmas = __vmas;
> +		}
> +
> +		madvise_range->vmas[madvise_range->num_vmas] = vma;
> +		(madvise_range->num_vmas)++;
> +	}
> +
> +	if (!madvise_range->num_vmas)
> +		kfree(madvise_range->vmas);
> +
> +	vm_dbg(&vm->xe->drm, "madvise_range-num_vmas = %d\n",
> +madvise_range->num_vmas);
> +
> +	return 0;
> +}
> +
> +static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm
> *vm,
> +				      struct xe_vma **vmas, int num_vmas,
> +				      struct drm_xe_madvise *op)
> +{
> +	/* Implementation pending */
> +}
> +
> +static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
> +			   struct xe_vma **vmas, int num_vmas,
> +			   struct drm_xe_madvise *op)
> +{
> +	/* Implementation pending */
> +}
> +
> +static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
> +			      struct xe_vma **vmas, int num_vmas,
> +			      struct drm_xe_madvise *op)
> +{
> +	/* Implementation pending */
> +}
> +
> +typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
> +			     struct xe_vma **vmas, int num_vmas,
> +			     struct drm_xe_madvise *op);
> +
> +static const madvise_func madvise_funcs[] = {
> +	[DRM_XE_VMA_ATTR_PREFERRED_LOC] =
> madvise_preferred_mem_loc,
> +	[DRM_XE_VMA_ATTR_ATOMIC] = madvise_atomic,
> +	[DRM_XE_VMA_ATTR_PAT] = madvise_pat_index, };
> +
> +static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start,
> +u64 end, u8 *tile_mask) {
> +	struct drm_gpuva *gpuva;
> +	struct xe_tile *tile;
> +	u8 id;
> +
> +	lockdep_assert_held_write(&vm->lock);
> +
> +	if (dma_resv_wait_timeout(xe_vm_resv(vm),
> DMA_RESV_USAGE_BOOKKEEP,
> +				  false, MAX_SCHEDULE_TIMEOUT) <= 0)
> +		XE_WARN_ON(1);
> +
> +	*tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
> +
> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> +
> +		if (xe_vma_is_cpu_addr_mirror(vma))
> +			continue;
> +
> +		if (xe_vma_is_userptr(vma)) {
> +
> 	WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(v
> ma)),
> +
> DMA_RESV_USAGE_BOOKKEEP));
> +		}
> +
> +		for_each_tile(tile, vm->xe, id) {
> +			if (xe_pt_zap_ptes(tile, vma)) {
> +				*tile_mask |= BIT(id);
> +				vma->tile_invalidated |= BIT(id);
> +			}
> +		}
> +	}
> +}
> +
> +static int xe_vm_invalidate_madvise_range(struct xe_vm *vm, u64 start,
> +u64 end) {
> +	u8 tile_mask = 0;
> +
> +	xe_zap_ptes_in_madvise_range(vm, start, end, &tile_mask);
> +	if (!tile_mask)
> +		return 0;
> +
> +	xe_device_wmb(vm->xe);
> +
> +	return xe_vm_range_tilemask_tlb_invalidation(vm, start, end,
> +tile_mask); }
> +
> +static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const
> +struct drm_xe_madvise *args) {
> +	if (XE_IOCTL_DBG(xe, !args))
> +		return -EINVAL;
> +
> +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->start, SZ_4K)))
> +		return -EINVAL;
> +
> +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->range, SZ_4K)))
> +		return -EINVAL;
> +
> +	if (XE_IOCTL_DBG(xe, args->range < SZ_4K))
> +		return -EINVAL;
> +
> +	switch (args->type) {
> +	case DRM_XE_VMA_ATTR_ATOMIC:
> +		if (XE_IOCTL_DBG(xe, args->atomic.val >
> DRM_XE_VMA_ATOMIC_CPU))
> +			return -EINVAL;
> +		break;
> +	case DRM_XE_VMA_ATTR_PAT:
> +		/*TODO: Add valid pat check */
> +		break;
> +	case DRM_XE_VMA_ATTR_PREFERRED_LOC:
> +		if (XE_IOCTL_DBG(xe, args-
> >preferred_mem_loc.migration_policy >
> +				     DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES))
> +			return -EINVAL;
> +		break;
> +	default:
> +		if (XE_IOCTL_DBG(xe, 1))
> +			return -EINVAL;
> +	}
> +
> +	if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +/**
> + * xe_vm_madvise_ioctl - Handle MADVise ioctl for a VM
> + * @dev: DRM device pointer
> + * @data: Pointer to ioctl data (drm_xe_madvise*)
> + * @file: DRM file pointer
> + *
> + * Handles the MADVISE ioctl to provide memory advice for vma's within
> + * input range.
> + *
> + * Return: 0 on success or a negative error code on failure.
> + */
> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct
> +drm_file *file) {
> +	struct xe_device *xe = to_xe_device(dev);
> +	struct xe_file *xef = to_xe_file(file);
> +	struct drm_xe_madvise *args = data;
> +	struct xe_vm *vm;
> +	struct xe_bo *bo;
> +	struct drm_exec exec;
> +	int err = 0;
> +	int attr_type;
> +
> +	vm = xe_vm_lookup(xef, args->vm_id);
> +	if (XE_IOCTL_DBG(xe, !vm))
> +		return -EINVAL;
> +
> +	if (drm_xe_madvise_args_are_sane(vm->xe, args))
> +		return -EINVAL;

The upper error return will miss the "xe_vm_put(vm)".
BTW, the function name drm_xe_madvise_args_are_sane is somehow a little misleading. The name looks like a boolean function, while the return value is 0 for success and error code for failure.

Shuicheng 

> +
> +	down_write(&vm->lock);
> +
> +	if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
> +		err = -ENOENT;
> +		goto unlock_vm;
> +	}
> +
> +	xe_vm_alloc_madvise_vma(vm, args->start, args->range);
> +
> +	struct xe_vmas_in_madvise_range madvise_range = {.addr = args->start,
> +							 .range =  args-
> >range, };
> +	err = get_vmas(vm, &madvise_range);
> +	if (err || !madvise_range.num_vmas)
> +		goto unlock_vm;
> +
> +	if (madvise_range.has_bo_vmas) {
> +		drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
> +		drm_exec_until_all_locked(&exec) {
> +			for (int i = 0; i < madvise_range.num_vmas; i++) {
> +				bo = xe_vma_bo(madvise_range.vmas[i]);
> +				if (!bo)
> +					continue;
> +				err = drm_exec_lock_obj(&exec, &bo-
> >ttm.base);
> +				drm_exec_retry_on_contention(&exec);
> +				if (err)
> +					goto err_fini;
> +			}
> +		}
> +	}
> +
> +	if (madvise_range.has_userptr_vmas)
> +		down_read(&vm->userptr.notifier_lock);
> +
> +	if (madvise_range.has_svm_vmas)
> +		xe_svm_notifier_lock(vm);
> +
> +	attr_type = array_index_nospec(args->type,
> ARRAY_SIZE(madvise_funcs));
> +	madvise_funcs[attr_type](xe, vm, madvise_range.vmas,
> +madvise_range.num_vmas, args);
> +
> +	kfree(madvise_range.vmas);
> +	madvise_range.vmas = NULL;
> +
> +	err = xe_vm_invalidate_madvise_range(vm, args->start, args->start +
> +args->range);
> +
> +	if (madvise_range.has_svm_vmas)
> +		xe_svm_notifier_unlock(vm);
> +
> +	if (madvise_range.has_userptr_vmas)
> +		up_read(&vm->userptr.notifier_lock);
> +err_fini:
> +	if (madvise_range.has_bo_vmas)
> +		drm_exec_fini(&exec);
> +unlock_vm:
> +	up_write(&vm->lock);
> +	xe_vm_put(vm);
> +	return err;
> +}
> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.h
> b/drivers/gpu/drm/xe/xe_vm_madvise.h
> new file mode 100644
> index 000000000000..b0e1fc445f23
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#ifndef _XE_VM_MADVISE_H_
> +#define _XE_VM_MADVISE_H_
> +
> +struct drm_device;
> +struct drm_file;
> +
> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data,
> +			struct drm_file *file);
> +
> +#endif
> --
> 2.34.1


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe
  2025-06-26  6:04   ` Lin, Shuicheng
@ 2025-06-26  6:15     ` Matthew Brost
  2025-06-26  8:36       ` Ghimiray, Himal Prasad
  2025-06-26  8:34     ` Ghimiray, Himal Prasad
  1 sibling, 1 reply; 68+ messages in thread
From: Matthew Brost @ 2025-06-26  6:15 UTC (permalink / raw)
  To: Lin, Shuicheng
  Cc: Ghimiray, Himal Prasad, intel-xe@lists.freedesktop.org,
	thomas.hellstrom@linux.intel.com

On Thu, Jun 26, 2025 at 12:04:07AM -0600, Lin, Shuicheng wrote:
> On Fri, June 13, 2025 8:56 PM Himal Prasad Ghimiray wrote:
> > This driver-specific ioctl enables UMDs to control the memory attributes for GPU
> > VMAs within a specified input range. If the start or end addresses fall within an
> > existing VMA, the VMA is split accordingly. The attributes of the VMA are
> > modified as provided by the users. The old mappings of the VMAs are invalidated,
> > and TLB invalidation is performed if necessary.
> > 
> > v2(Matthew brost)
> > - xe_vm_in_fault_mode can't be enabled by Mesa, hence allow ioctl in non fault
> > mode too
> > - fix tlb invalidation skip for same ranges in multiple op
> > - use helper for tlb invalidation
> > - use xe_svm_notifier_lock/unlock helper
> > - s/lockdep_assert_held/lockdep_assert_held_write
> > - Add kernel-doc
> > 
> > v3(Matthew Brost)
> > - make vfunc fail safe
> > - Add sanitizing input args before vfunc
> > 
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> > ---
> >  drivers/gpu/drm/xe/Makefile        |   1 +
> >  drivers/gpu/drm/xe/xe_device.c     |   2 +
> >  drivers/gpu/drm/xe/xe_vm_madvise.c | 282
> > +++++++++++++++++++++++++++++  drivers/gpu/drm/xe/xe_vm_madvise.h |  15
> > ++
> >  4 files changed, 300 insertions(+)
> >  create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
> >  create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h
> > 
> > diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index
> > f5f5775acdc0..d375b549c30f 100644
> > --- a/drivers/gpu/drm/xe/Makefile
> > +++ b/drivers/gpu/drm/xe/Makefile
> > @@ -117,6 +117,7 @@ xe-y += xe_bb.o \
> >  	xe_uc.o \
> >  	xe_uc_fw.o \
> >  	xe_vm.o \
> > +	xe_vm_madvise.o \
> >  	xe_vram.o \
> >  	xe_vram_freq.o \
> >  	xe_vsec.o \
> > diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> > index 7d9a31868ea9..632d3ab12392 100644
> > --- a/drivers/gpu/drm/xe/xe_device.c
> > +++ b/drivers/gpu/drm/xe/xe_device.c
> > @@ -61,6 +61,7 @@
> >  #include "xe_ttm_stolen_mgr.h"
> >  #include "xe_ttm_sys_mgr.h"
> >  #include "xe_vm.h"
> > +#include "xe_vm_madvise.h"
> >  #include "xe_vram.h"
> >  #include "xe_vsec.h"
> >  #include "xe_wait_user_fence.h"
> > @@ -197,6 +198,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
> >  	DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE,
> > xe_wait_user_fence_ioctl,
> >  			  DRM_RENDER_ALLOW),
> >  	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl,
> > DRM_RENDER_ALLOW),
> > +	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl,
> > DRM_RENDER_ALLOW),
> >  };
> > 
> >  static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) diff
> > --git a/drivers/gpu/drm/xe/xe_vm_madvise.c
> > b/drivers/gpu/drm/xe/xe_vm_madvise.c
> > new file mode 100644
> > index 000000000000..ff560914ad7e
> > --- /dev/null
> > +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
> > @@ -0,0 +1,282 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2025 Intel Corporation
> > + */
> > +
> > +#include "xe_vm_madvise.h"
> > +
> > +#include <linux/nospec.h>
> > +#include <drm/ttm/ttm_tt.h>
> > +#include <drm/xe_drm.h>
> > +
> > +#include "xe_bo.h"
> > +#include "xe_gt_tlb_invalidation.h"
> > +#include "xe_pt.h"
> > +#include "xe_svm.h"
> > +
> > +struct xe_vmas_in_madvise_range {
> > +	u64 addr;
> > +	u64 range;
> > +	struct xe_vma **vmas;
> > +	int num_vmas;
> > +	bool has_svm_vmas;
> > +	bool has_bo_vmas;
> > +	bool has_userptr_vmas;
> > +};
> > +
> > +static int get_vmas(struct xe_vm *vm, struct xe_vmas_in_madvise_range
> > +*madvise_range) {
> > +	u64 addr = madvise_range->addr;
> > +	u64 range = madvise_range->range;
> > +
> > +	struct xe_vma  **__vmas;
> > +	struct drm_gpuva *gpuva;
> > +	int max_vmas = 8;
> > +
> > +	lockdep_assert_held(&vm->lock);
> > +
> > +	madvise_range->num_vmas = 0;
> > +	madvise_range->vmas = kmalloc_array(max_vmas,
> > sizeof(*madvise_range->vmas), GFP_KERNEL);
> > +	if (!madvise_range->vmas)
> > +		return -ENOMEM;
> > +
> > +	vm_dbg(&vm->xe->drm, "VMA's in range: start=0x%016llx,
> > end=0x%016llx",
> > +addr, addr + range);
> > +
> > +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, addr, addr +
> > range) {
> > +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> > +
> > +		if (xe_vma_bo(vma))
> > +			madvise_range->has_bo_vmas = true;
> > +		else if (xe_vma_is_cpu_addr_mirror(vma))
> > +			madvise_range->has_svm_vmas = true;
> > +		else if (xe_vma_is_userptr(vma))
> > +			madvise_range->has_userptr_vmas = true;
> > +		else
> > +			XE_WARN_ON("UNEXPECTED VMA");
> > +
> > +		if (madvise_range->num_vmas == max_vmas) {
> > +			max_vmas <<= 1;
> > +			__vmas = krealloc(madvise_range->vmas,
> > +					  max_vmas * sizeof(*madvise_range-
> > >vmas),
> > +					  GFP_KERNEL);
> > +			if (!__vmas) {
> > +				kfree(madvise_range->vmas);
> > +				return -ENOMEM;
> > +			}
> > +			madvise_range->vmas = __vmas;
> > +		}
> > +
> > +		madvise_range->vmas[madvise_range->num_vmas] = vma;
> > +		(madvise_range->num_vmas)++;
> > +	}
> > +
> > +	if (!madvise_range->num_vmas)
> > +		kfree(madvise_range->vmas);
> > +
> > +	vm_dbg(&vm->xe->drm, "madvise_range-num_vmas = %d\n",
> > +madvise_range->num_vmas);
> > +
> > +	return 0;
> > +}
> > +
> > +static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm
> > *vm,
> > +				      struct xe_vma **vmas, int num_vmas,
> > +				      struct drm_xe_madvise *op)
> > +{
> > +	/* Implementation pending */
> > +}
> > +
> > +static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
> > +			   struct xe_vma **vmas, int num_vmas,
> > +			   struct drm_xe_madvise *op)
> > +{
> > +	/* Implementation pending */
> > +}
> > +
> > +static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
> > +			      struct xe_vma **vmas, int num_vmas,
> > +			      struct drm_xe_madvise *op)
> > +{
> > +	/* Implementation pending */
> > +}
> > +
> > +typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
> > +			     struct xe_vma **vmas, int num_vmas,
> > +			     struct drm_xe_madvise *op);
> > +
> > +static const madvise_func madvise_funcs[] = {
> > +	[DRM_XE_VMA_ATTR_PREFERRED_LOC] =
> > madvise_preferred_mem_loc,
> > +	[DRM_XE_VMA_ATTR_ATOMIC] = madvise_atomic,
> > +	[DRM_XE_VMA_ATTR_PAT] = madvise_pat_index, };
> > +
> > +static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start,
> > +u64 end, u8 *tile_mask) {
> > +	struct drm_gpuva *gpuva;
> > +	struct xe_tile *tile;
> > +	u8 id;
> > +
> > +	lockdep_assert_held_write(&vm->lock);
> > +
> > +	if (dma_resv_wait_timeout(xe_vm_resv(vm),
> > DMA_RESV_USAGE_BOOKKEEP,
> > +				  false, MAX_SCHEDULE_TIMEOUT) <= 0)
> > +		XE_WARN_ON(1);
> > +
> > +	*tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
> > +
> > +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
> > +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> > +
> > +		if (xe_vma_is_cpu_addr_mirror(vma))
> > +			continue;
> > +
> > +		if (xe_vma_is_userptr(vma)) {
> > +
> > 	WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(v
> > ma)),
> > +
> > DMA_RESV_USAGE_BOOKKEEP));
> > +		}
> > +
> > +		for_each_tile(tile, vm->xe, id) {
> > +			if (xe_pt_zap_ptes(tile, vma)) {
> > +				*tile_mask |= BIT(id);
> > +				vma->tile_invalidated |= BIT(id);
> > +			}
> > +		}
> > +	}
> > +}
> > +
> > +static int xe_vm_invalidate_madvise_range(struct xe_vm *vm, u64 start,
> > +u64 end) {
> > +	u8 tile_mask = 0;
> > +
> > +	xe_zap_ptes_in_madvise_range(vm, start, end, &tile_mask);
> > +	if (!tile_mask)
> > +		return 0;
> > +
> > +	xe_device_wmb(vm->xe);
> > +
> > +	return xe_vm_range_tilemask_tlb_invalidation(vm, start, end,
> > +tile_mask); }
> > +
> > +static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const
> > +struct drm_xe_madvise *args) {
> > +	if (XE_IOCTL_DBG(xe, !args))
> > +		return -EINVAL;
> > +
> > +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->start, SZ_4K)))
> > +		return -EINVAL;
> > +
> > +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->range, SZ_4K)))
> > +		return -EINVAL;
> > +
> > +	if (XE_IOCTL_DBG(xe, args->range < SZ_4K))
> > +		return -EINVAL;
> > +
> > +	switch (args->type) {
> > +	case DRM_XE_VMA_ATTR_ATOMIC:
> > +		if (XE_IOCTL_DBG(xe, args->atomic.val >
> > DRM_XE_VMA_ATOMIC_CPU))
> > +			return -EINVAL;
> > +		break;
> > +	case DRM_XE_VMA_ATTR_PAT:
> > +		/*TODO: Add valid pat check */
> > +		break;
> > +	case DRM_XE_VMA_ATTR_PREFERRED_LOC:
> > +		if (XE_IOCTL_DBG(xe, args-
> > >preferred_mem_loc.migration_policy >
> > +				     DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES))
> > +			return -EINVAL;
> > +		break;
> > +	default:
> > +		if (XE_IOCTL_DBG(xe, 1))
> > +			return -EINVAL;
> > +	}
> > +
> > +	if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * xe_vm_madvise_ioctl - Handle MADVise ioctl for a VM
> > + * @dev: DRM device pointer
> > + * @data: Pointer to ioctl data (drm_xe_madvise*)
> > + * @file: DRM file pointer
> > + *
> > + * Handles the MADVISE ioctl to provide memory advice for vma's within
> > + * input range.
> > + *
> > + * Return: 0 on success or a negative error code on failure.
> > + */
> > +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct
> > +drm_file *file) {
> > +	struct xe_device *xe = to_xe_device(dev);
> > +	struct xe_file *xef = to_xe_file(file);
> > +	struct drm_xe_madvise *args = data;
> > +	struct xe_vm *vm;
> > +	struct xe_bo *bo;
> > +	struct drm_exec exec;
> > +	int err = 0;
> > +	int attr_type;
> > +
> > +	vm = xe_vm_lookup(xef, args->vm_id);
> > +	if (XE_IOCTL_DBG(xe, !vm))
> > +		return -EINVAL;
> > +
> > +	if (drm_xe_madvise_args_are_sane(vm->xe, args))
> > +		return -EINVAL;
> 
> The upper error return will miss the "xe_vm_put(vm)".
> BTW, the function name drm_xe_madvise_args_are_sane is somehow a little misleading. The name looks like a boolean function, while the return value is 0 for success and error code for failure.
> 

Agree with Shuicheng, drm_xe_madvise_args_are_sane should be a bool,
need to avoid a leak of the VM on a failure.

Also will I'm here, avoid drm_* prefix in Xe code. So...

s/drm_xe_madvise_args_are_sane/madvise_args_are_sane

Matt

> Shuicheng 
> 
> > +
> > +	down_write(&vm->lock);
> > +
> > +	if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
> > +		err = -ENOENT;
> > +		goto unlock_vm;
> > +	}
> > +
> > +	xe_vm_alloc_madvise_vma(vm, args->start, args->range);
> > +
> > +	struct xe_vmas_in_madvise_range madvise_range = {.addr = args->start,
> > +							 .range =  args-
> > >range, };
> > +	err = get_vmas(vm, &madvise_range);
> > +	if (err || !madvise_range.num_vmas)
> > +		goto unlock_vm;
> > +
> > +	if (madvise_range.has_bo_vmas) {
> > +		drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
> > +		drm_exec_until_all_locked(&exec) {
> > +			for (int i = 0; i < madvise_range.num_vmas; i++) {
> > +				bo = xe_vma_bo(madvise_range.vmas[i]);
> > +				if (!bo)
> > +					continue;
> > +				err = drm_exec_lock_obj(&exec, &bo-
> > >ttm.base);
> > +				drm_exec_retry_on_contention(&exec);
> > +				if (err)
> > +					goto err_fini;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (madvise_range.has_userptr_vmas)
> > +		down_read(&vm->userptr.notifier_lock);
> > +
> > +	if (madvise_range.has_svm_vmas)
> > +		xe_svm_notifier_lock(vm);
> > +
> > +	attr_type = array_index_nospec(args->type,
> > ARRAY_SIZE(madvise_funcs));
> > +	madvise_funcs[attr_type](xe, vm, madvise_range.vmas,
> > +madvise_range.num_vmas, args);
> > +
> > +	kfree(madvise_range.vmas);
> > +	madvise_range.vmas = NULL;
> > +
> > +	err = xe_vm_invalidate_madvise_range(vm, args->start, args->start +
> > +args->range);
> > +
> > +	if (madvise_range.has_svm_vmas)
> > +		xe_svm_notifier_unlock(vm);
> > +
> > +	if (madvise_range.has_userptr_vmas)
> > +		up_read(&vm->userptr.notifier_lock);
> > +err_fini:
> > +	if (madvise_range.has_bo_vmas)
> > +		drm_exec_fini(&exec);
> > +unlock_vm:
> > +	up_write(&vm->lock);
> > +	xe_vm_put(vm);
> > +	return err;
> > +}
> > diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.h
> > b/drivers/gpu/drm/xe/xe_vm_madvise.h
> > new file mode 100644
> > index 000000000000..b0e1fc445f23
> > --- /dev/null
> > +++ b/drivers/gpu/drm/xe/xe_vm_madvise.h
> > @@ -0,0 +1,15 @@
> > +/* SPDX-License-Identifier: MIT */
> > +/*
> > + * Copyright © 2025 Intel Corporation
> > + */
> > +
> > +#ifndef _XE_VM_MADVISE_H_
> > +#define _XE_VM_MADVISE_H_
> > +
> > +struct drm_device;
> > +struct drm_file;
> > +
> > +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data,
> > +			struct drm_file *file);
> > +
> > +#endif
> > --
> > 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe
  2025-06-26  6:04   ` Lin, Shuicheng
  2025-06-26  6:15     ` Matthew Brost
@ 2025-06-26  8:34     ` Ghimiray, Himal Prasad
  1 sibling, 0 replies; 68+ messages in thread
From: Ghimiray, Himal Prasad @ 2025-06-26  8:34 UTC (permalink / raw)
  To: Lin, Shuicheng, intel-xe@lists.freedesktop.org
  Cc: Brost, Matthew, thomas.hellstrom@linux.intel.com



On 26-06-2025 11:34, Lin, Shuicheng wrote:
> On Fri, June 13, 2025 8:56 PM Himal Prasad Ghimiray wrote:
>> This driver-specific ioctl enables UMDs to control the memory attributes for GPU
>> VMAs within a specified input range. If the start or end addresses fall within an
>> existing VMA, the VMA is split accordingly. The attributes of the VMA are
>> modified as provided by the users. The old mappings of the VMAs are invalidated,
>> and TLB invalidation is performed if necessary.
>>
>> v2(Matthew brost)
>> - xe_vm_in_fault_mode can't be enabled by Mesa, hence allow ioctl in non fault
>> mode too
>> - fix tlb invalidation skip for same ranges in multiple op
>> - use helper for tlb invalidation
>> - use xe_svm_notifier_lock/unlock helper
>> - s/lockdep_assert_held/lockdep_assert_held_write
>> - Add kernel-doc
>>
>> v3(Matthew Brost)
>> - make vfunc fail safe
>> - Add sanitizing input args before vfunc
>>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> ---
>>   drivers/gpu/drm/xe/Makefile        |   1 +
>>   drivers/gpu/drm/xe/xe_device.c     |   2 +
>>   drivers/gpu/drm/xe/xe_vm_madvise.c | 282
>> +++++++++++++++++++++++++++++  drivers/gpu/drm/xe/xe_vm_madvise.h |  15
>> ++
>>   4 files changed, 300 insertions(+)
>>   create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
>>   create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h
>>
>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index
>> f5f5775acdc0..d375b549c30f 100644
>> --- a/drivers/gpu/drm/xe/Makefile
>> +++ b/drivers/gpu/drm/xe/Makefile
>> @@ -117,6 +117,7 @@ xe-y += xe_bb.o \
>>   	xe_uc.o \
>>   	xe_uc_fw.o \
>>   	xe_vm.o \
>> +	xe_vm_madvise.o \
>>   	xe_vram.o \
>>   	xe_vram_freq.o \
>>   	xe_vsec.o \
>> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
>> index 7d9a31868ea9..632d3ab12392 100644
>> --- a/drivers/gpu/drm/xe/xe_device.c
>> +++ b/drivers/gpu/drm/xe/xe_device.c
>> @@ -61,6 +61,7 @@
>>   #include "xe_ttm_stolen_mgr.h"
>>   #include "xe_ttm_sys_mgr.h"
>>   #include "xe_vm.h"
>> +#include "xe_vm_madvise.h"
>>   #include "xe_vram.h"
>>   #include "xe_vsec.h"
>>   #include "xe_wait_user_fence.h"
>> @@ -197,6 +198,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
>>   	DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE,
>> xe_wait_user_fence_ioctl,
>>   			  DRM_RENDER_ALLOW),
>>   	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl,
>> DRM_RENDER_ALLOW),
>> +	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl,
>> DRM_RENDER_ALLOW),
>>   };
>>
>>   static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) diff
>> --git a/drivers/gpu/drm/xe/xe_vm_madvise.c
>> b/drivers/gpu/drm/xe/xe_vm_madvise.c
>> new file mode 100644
>> index 000000000000..ff560914ad7e
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
>> @@ -0,0 +1,282 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2025 Intel Corporation
>> + */
>> +
>> +#include "xe_vm_madvise.h"
>> +
>> +#include <linux/nospec.h>
>> +#include <drm/ttm/ttm_tt.h>
>> +#include <drm/xe_drm.h>
>> +
>> +#include "xe_bo.h"
>> +#include "xe_gt_tlb_invalidation.h"
>> +#include "xe_pt.h"
>> +#include "xe_svm.h"
>> +
>> +struct xe_vmas_in_madvise_range {
>> +	u64 addr;
>> +	u64 range;
>> +	struct xe_vma **vmas;
>> +	int num_vmas;
>> +	bool has_svm_vmas;
>> +	bool has_bo_vmas;
>> +	bool has_userptr_vmas;
>> +};
>> +
>> +static int get_vmas(struct xe_vm *vm, struct xe_vmas_in_madvise_range
>> +*madvise_range) {
>> +	u64 addr = madvise_range->addr;
>> +	u64 range = madvise_range->range;
>> +
>> +	struct xe_vma  **__vmas;
>> +	struct drm_gpuva *gpuva;
>> +	int max_vmas = 8;
>> +
>> +	lockdep_assert_held(&vm->lock);
>> +
>> +	madvise_range->num_vmas = 0;
>> +	madvise_range->vmas = kmalloc_array(max_vmas,
>> sizeof(*madvise_range->vmas), GFP_KERNEL);
>> +	if (!madvise_range->vmas)
>> +		return -ENOMEM;
>> +
>> +	vm_dbg(&vm->xe->drm, "VMA's in range: start=0x%016llx,
>> end=0x%016llx",
>> +addr, addr + range);
>> +
>> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, addr, addr +
>> range) {
>> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
>> +
>> +		if (xe_vma_bo(vma))
>> +			madvise_range->has_bo_vmas = true;
>> +		else if (xe_vma_is_cpu_addr_mirror(vma))
>> +			madvise_range->has_svm_vmas = true;
>> +		else if (xe_vma_is_userptr(vma))
>> +			madvise_range->has_userptr_vmas = true;
>> +		else
>> +			XE_WARN_ON("UNEXPECTED VMA");
>> +
>> +		if (madvise_range->num_vmas == max_vmas) {
>> +			max_vmas <<= 1;
>> +			__vmas = krealloc(madvise_range->vmas,
>> +					  max_vmas * sizeof(*madvise_range-
>>> vmas),
>> +					  GFP_KERNEL);
>> +			if (!__vmas) {
>> +				kfree(madvise_range->vmas);
>> +				return -ENOMEM;
>> +			}
>> +			madvise_range->vmas = __vmas;
>> +		}
>> +
>> +		madvise_range->vmas[madvise_range->num_vmas] = vma;
>> +		(madvise_range->num_vmas)++;
>> +	}
>> +
>> +	if (!madvise_range->num_vmas)
>> +		kfree(madvise_range->vmas);
>> +
>> +	vm_dbg(&vm->xe->drm, "madvise_range-num_vmas = %d\n",
>> +madvise_range->num_vmas);
>> +
>> +	return 0;
>> +}
>> +
>> +static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm
>> *vm,
>> +				      struct xe_vma **vmas, int num_vmas,
>> +				      struct drm_xe_madvise *op)
>> +{
>> +	/* Implementation pending */
>> +}
>> +
>> +static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
>> +			   struct xe_vma **vmas, int num_vmas,
>> +			   struct drm_xe_madvise *op)
>> +{
>> +	/* Implementation pending */
>> +}
>> +
>> +static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
>> +			      struct xe_vma **vmas, int num_vmas,
>> +			      struct drm_xe_madvise *op)
>> +{
>> +	/* Implementation pending */
>> +}
>> +
>> +typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
>> +			     struct xe_vma **vmas, int num_vmas,
>> +			     struct drm_xe_madvise *op);
>> +
>> +static const madvise_func madvise_funcs[] = {
>> +	[DRM_XE_VMA_ATTR_PREFERRED_LOC] =
>> madvise_preferred_mem_loc,
>> +	[DRM_XE_VMA_ATTR_ATOMIC] = madvise_atomic,
>> +	[DRM_XE_VMA_ATTR_PAT] = madvise_pat_index, };
>> +
>> +static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start,
>> +u64 end, u8 *tile_mask) {
>> +	struct drm_gpuva *gpuva;
>> +	struct xe_tile *tile;
>> +	u8 id;
>> +
>> +	lockdep_assert_held_write(&vm->lock);
>> +
>> +	if (dma_resv_wait_timeout(xe_vm_resv(vm),
>> DMA_RESV_USAGE_BOOKKEEP,
>> +				  false, MAX_SCHEDULE_TIMEOUT) <= 0)
>> +		XE_WARN_ON(1);
>> +
>> +	*tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
>> +
>> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
>> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
>> +
>> +		if (xe_vma_is_cpu_addr_mirror(vma))
>> +			continue;
>> +
>> +		if (xe_vma_is_userptr(vma)) {
>> +
>> 	WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(v
>> ma)),
>> +
>> DMA_RESV_USAGE_BOOKKEEP));
>> +		}
>> +
>> +		for_each_tile(tile, vm->xe, id) {
>> +			if (xe_pt_zap_ptes(tile, vma)) {
>> +				*tile_mask |= BIT(id);
>> +				vma->tile_invalidated |= BIT(id);
>> +			}
>> +		}
>> +	}
>> +}
>> +
>> +static int xe_vm_invalidate_madvise_range(struct xe_vm *vm, u64 start,
>> +u64 end) {
>> +	u8 tile_mask = 0;
>> +
>> +	xe_zap_ptes_in_madvise_range(vm, start, end, &tile_mask);
>> +	if (!tile_mask)
>> +		return 0;
>> +
>> +	xe_device_wmb(vm->xe);
>> +
>> +	return xe_vm_range_tilemask_tlb_invalidation(vm, start, end,
>> +tile_mask); }
>> +
>> +static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const
>> +struct drm_xe_madvise *args) {
>> +	if (XE_IOCTL_DBG(xe, !args))
>> +		return -EINVAL;
>> +
>> +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->start, SZ_4K)))
>> +		return -EINVAL;
>> +
>> +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->range, SZ_4K)))
>> +		return -EINVAL;
>> +
>> +	if (XE_IOCTL_DBG(xe, args->range < SZ_4K))
>> +		return -EINVAL;
>> +
>> +	switch (args->type) {
>> +	case DRM_XE_VMA_ATTR_ATOMIC:
>> +		if (XE_IOCTL_DBG(xe, args->atomic.val >
>> DRM_XE_VMA_ATOMIC_CPU))
>> +			return -EINVAL;
>> +		break;
>> +	case DRM_XE_VMA_ATTR_PAT:
>> +		/*TODO: Add valid pat check */
>> +		break;
>> +	case DRM_XE_VMA_ATTR_PREFERRED_LOC:
>> +		if (XE_IOCTL_DBG(xe, args-
>>> preferred_mem_loc.migration_policy >
>> +				     DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES))
>> +			return -EINVAL;
>> +		break;
>> +	default:
>> +		if (XE_IOCTL_DBG(xe, 1))
>> +			return -EINVAL;
>> +	}
>> +
>> +	if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
>> +		return -EINVAL;
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * xe_vm_madvise_ioctl - Handle MADVise ioctl for a VM
>> + * @dev: DRM device pointer
>> + * @data: Pointer to ioctl data (drm_xe_madvise*)
>> + * @file: DRM file pointer
>> + *
>> + * Handles the MADVISE ioctl to provide memory advice for vma's within
>> + * input range.
>> + *
>> + * Return: 0 on success or a negative error code on failure.
>> + */
>> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct
>> +drm_file *file) {
>> +	struct xe_device *xe = to_xe_device(dev);
>> +	struct xe_file *xef = to_xe_file(file);
>> +	struct drm_xe_madvise *args = data;
>> +	struct xe_vm *vm;
>> +	struct xe_bo *bo;
>> +	struct drm_exec exec;
>> +	int err = 0;
>> +	int attr_type;
>> +
>> +	vm = xe_vm_lookup(xef, args->vm_id);
>> +	if (XE_IOCTL_DBG(xe, !vm))
>> +		return -EINVAL;
>> +
>> +	if (drm_xe_madvise_args_are_sane(vm->xe, args))
>> +		return -EINVAL;
> 
> The upper error return will miss the "xe_vm_put(vm)".
> BTW, the function name drm_xe_madvise_args_are_sane is somehow a little misleading. The name looks like a boolean function, while the return value is 0 for success and error code for failure.

Thanks for the review. Will address in next rev.

> 
> Shuicheng
> 
>> +
>> +	down_write(&vm->lock);
>> +
>> +	if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
>> +		err = -ENOENT;
>> +		goto unlock_vm;
>> +	}
>> +
>> +	xe_vm_alloc_madvise_vma(vm, args->start, args->range);
>> +
>> +	struct xe_vmas_in_madvise_range madvise_range = {.addr = args->start,
>> +							 .range =  args-
>>> range, };
>> +	err = get_vmas(vm, &madvise_range);
>> +	if (err || !madvise_range.num_vmas)
>> +		goto unlock_vm;
>> +
>> +	if (madvise_range.has_bo_vmas) {
>> +		drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
>> +		drm_exec_until_all_locked(&exec) {
>> +			for (int i = 0; i < madvise_range.num_vmas; i++) {
>> +				bo = xe_vma_bo(madvise_range.vmas[i]);
>> +				if (!bo)
>> +					continue;
>> +				err = drm_exec_lock_obj(&exec, &bo-
>>> ttm.base);
>> +				drm_exec_retry_on_contention(&exec);
>> +				if (err)
>> +					goto err_fini;
>> +			}
>> +		}
>> +	}
>> +
>> +	if (madvise_range.has_userptr_vmas)
>> +		down_read(&vm->userptr.notifier_lock);
>> +
>> +	if (madvise_range.has_svm_vmas)
>> +		xe_svm_notifier_lock(vm);
>> +
>> +	attr_type = array_index_nospec(args->type,
>> ARRAY_SIZE(madvise_funcs));
>> +	madvise_funcs[attr_type](xe, vm, madvise_range.vmas,
>> +madvise_range.num_vmas, args);
>> +
>> +	kfree(madvise_range.vmas);
>> +	madvise_range.vmas = NULL;
>> +
>> +	err = xe_vm_invalidate_madvise_range(vm, args->start, args->start +
>> +args->range);
>> +
>> +	if (madvise_range.has_svm_vmas)
>> +		xe_svm_notifier_unlock(vm);
>> +
>> +	if (madvise_range.has_userptr_vmas)
>> +		up_read(&vm->userptr.notifier_lock);
>> +err_fini:
>> +	if (madvise_range.has_bo_vmas)
>> +		drm_exec_fini(&exec);
>> +unlock_vm:
>> +	up_write(&vm->lock);
>> +	xe_vm_put(vm);
>> +	return err;
>> +}
>> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.h
>> b/drivers/gpu/drm/xe/xe_vm_madvise.h
>> new file mode 100644
>> index 000000000000..b0e1fc445f23
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.h
>> @@ -0,0 +1,15 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2025 Intel Corporation
>> + */
>> +
>> +#ifndef _XE_VM_MADVISE_H_
>> +#define _XE_VM_MADVISE_H_
>> +
>> +struct drm_device;
>> +struct drm_file;
>> +
>> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data,
>> +			struct drm_file *file);
>> +
>> +#endif
>> --
>> 2.34.1
> 


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe
  2025-06-26  6:15     ` Matthew Brost
@ 2025-06-26  8:36       ` Ghimiray, Himal Prasad
  0 siblings, 0 replies; 68+ messages in thread
From: Ghimiray, Himal Prasad @ 2025-06-26  8:36 UTC (permalink / raw)
  To: Matthew Brost, Lin, Shuicheng
  Cc: intel-xe@lists.freedesktop.org, thomas.hellstrom@linux.intel.com



On 26-06-2025 11:45, Matthew Brost wrote:
> On Thu, Jun 26, 2025 at 12:04:07AM -0600, Lin, Shuicheng wrote:
>> On Fri, June 13, 2025 8:56 PM Himal Prasad Ghimiray wrote:
>>> This driver-specific ioctl enables UMDs to control the memory attributes for GPU
>>> VMAs within a specified input range. If the start or end addresses fall within an
>>> existing VMA, the VMA is split accordingly. The attributes of the VMA are
>>> modified as provided by the users. The old mappings of the VMAs are invalidated,
>>> and TLB invalidation is performed if necessary.
>>>
>>> v2(Matthew brost)
>>> - xe_vm_in_fault_mode can't be enabled by Mesa, hence allow ioctl in non fault
>>> mode too
>>> - fix tlb invalidation skip for same ranges in multiple op
>>> - use helper for tlb invalidation
>>> - use xe_svm_notifier_lock/unlock helper
>>> - s/lockdep_assert_held/lockdep_assert_held_write
>>> - Add kernel-doc
>>>
>>> v3(Matthew Brost)
>>> - make vfunc fail safe
>>> - Add sanitizing input args before vfunc
>>>
>>> Cc: Matthew Brost <matthew.brost@intel.com>
>>> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>>> ---
>>>   drivers/gpu/drm/xe/Makefile        |   1 +
>>>   drivers/gpu/drm/xe/xe_device.c     |   2 +
>>>   drivers/gpu/drm/xe/xe_vm_madvise.c | 282
>>> +++++++++++++++++++++++++++++  drivers/gpu/drm/xe/xe_vm_madvise.h |  15
>>> ++
>>>   4 files changed, 300 insertions(+)
>>>   create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
>>>   create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h
>>>
>>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index
>>> f5f5775acdc0..d375b549c30f 100644
>>> --- a/drivers/gpu/drm/xe/Makefile
>>> +++ b/drivers/gpu/drm/xe/Makefile
>>> @@ -117,6 +117,7 @@ xe-y += xe_bb.o \
>>>   	xe_uc.o \
>>>   	xe_uc_fw.o \
>>>   	xe_vm.o \
>>> +	xe_vm_madvise.o \
>>>   	xe_vram.o \
>>>   	xe_vram_freq.o \
>>>   	xe_vsec.o \
>>> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
>>> index 7d9a31868ea9..632d3ab12392 100644
>>> --- a/drivers/gpu/drm/xe/xe_device.c
>>> +++ b/drivers/gpu/drm/xe/xe_device.c
>>> @@ -61,6 +61,7 @@
>>>   #include "xe_ttm_stolen_mgr.h"
>>>   #include "xe_ttm_sys_mgr.h"
>>>   #include "xe_vm.h"
>>> +#include "xe_vm_madvise.h"
>>>   #include "xe_vram.h"
>>>   #include "xe_vsec.h"
>>>   #include "xe_wait_user_fence.h"
>>> @@ -197,6 +198,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
>>>   	DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE,
>>> xe_wait_user_fence_ioctl,
>>>   			  DRM_RENDER_ALLOW),
>>>   	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl,
>>> DRM_RENDER_ALLOW),
>>> +	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl,
>>> DRM_RENDER_ALLOW),
>>>   };
>>>
>>>   static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) diff
>>> --git a/drivers/gpu/drm/xe/xe_vm_madvise.c
>>> b/drivers/gpu/drm/xe/xe_vm_madvise.c
>>> new file mode 100644
>>> index 000000000000..ff560914ad7e
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
>>> @@ -0,0 +1,282 @@
>>> +// SPDX-License-Identifier: MIT
>>> +/*
>>> + * Copyright © 2025 Intel Corporation
>>> + */
>>> +
>>> +#include "xe_vm_madvise.h"
>>> +
>>> +#include <linux/nospec.h>
>>> +#include <drm/ttm/ttm_tt.h>
>>> +#include <drm/xe_drm.h>
>>> +
>>> +#include "xe_bo.h"
>>> +#include "xe_gt_tlb_invalidation.h"
>>> +#include "xe_pt.h"
>>> +#include "xe_svm.h"
>>> +
>>> +struct xe_vmas_in_madvise_range {
>>> +	u64 addr;
>>> +	u64 range;
>>> +	struct xe_vma **vmas;
>>> +	int num_vmas;
>>> +	bool has_svm_vmas;
>>> +	bool has_bo_vmas;
>>> +	bool has_userptr_vmas;
>>> +};
>>> +
>>> +static int get_vmas(struct xe_vm *vm, struct xe_vmas_in_madvise_range
>>> +*madvise_range) {
>>> +	u64 addr = madvise_range->addr;
>>> +	u64 range = madvise_range->range;
>>> +
>>> +	struct xe_vma  **__vmas;
>>> +	struct drm_gpuva *gpuva;
>>> +	int max_vmas = 8;
>>> +
>>> +	lockdep_assert_held(&vm->lock);
>>> +
>>> +	madvise_range->num_vmas = 0;
>>> +	madvise_range->vmas = kmalloc_array(max_vmas,
>>> sizeof(*madvise_range->vmas), GFP_KERNEL);
>>> +	if (!madvise_range->vmas)
>>> +		return -ENOMEM;
>>> +
>>> +	vm_dbg(&vm->xe->drm, "VMA's in range: start=0x%016llx,
>>> end=0x%016llx",
>>> +addr, addr + range);
>>> +
>>> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, addr, addr +
>>> range) {
>>> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
>>> +
>>> +		if (xe_vma_bo(vma))
>>> +			madvise_range->has_bo_vmas = true;
>>> +		else if (xe_vma_is_cpu_addr_mirror(vma))
>>> +			madvise_range->has_svm_vmas = true;
>>> +		else if (xe_vma_is_userptr(vma))
>>> +			madvise_range->has_userptr_vmas = true;
>>> +		else
>>> +			XE_WARN_ON("UNEXPECTED VMA");
>>> +
>>> +		if (madvise_range->num_vmas == max_vmas) {
>>> +			max_vmas <<= 1;
>>> +			__vmas = krealloc(madvise_range->vmas,
>>> +					  max_vmas * sizeof(*madvise_range-
>>>> vmas),
>>> +					  GFP_KERNEL);
>>> +			if (!__vmas) {
>>> +				kfree(madvise_range->vmas);
>>> +				return -ENOMEM;
>>> +			}
>>> +			madvise_range->vmas = __vmas;
>>> +		}
>>> +
>>> +		madvise_range->vmas[madvise_range->num_vmas] = vma;
>>> +		(madvise_range->num_vmas)++;
>>> +	}
>>> +
>>> +	if (!madvise_range->num_vmas)
>>> +		kfree(madvise_range->vmas);
>>> +
>>> +	vm_dbg(&vm->xe->drm, "madvise_range-num_vmas = %d\n",
>>> +madvise_range->num_vmas);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm
>>> *vm,
>>> +				      struct xe_vma **vmas, int num_vmas,
>>> +				      struct drm_xe_madvise *op)
>>> +{
>>> +	/* Implementation pending */
>>> +}
>>> +
>>> +static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
>>> +			   struct xe_vma **vmas, int num_vmas,
>>> +			   struct drm_xe_madvise *op)
>>> +{
>>> +	/* Implementation pending */
>>> +}
>>> +
>>> +static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
>>> +			      struct xe_vma **vmas, int num_vmas,
>>> +			      struct drm_xe_madvise *op)
>>> +{
>>> +	/* Implementation pending */
>>> +}
>>> +
>>> +typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
>>> +			     struct xe_vma **vmas, int num_vmas,
>>> +			     struct drm_xe_madvise *op);
>>> +
>>> +static const madvise_func madvise_funcs[] = {
>>> +	[DRM_XE_VMA_ATTR_PREFERRED_LOC] =
>>> madvise_preferred_mem_loc,
>>> +	[DRM_XE_VMA_ATTR_ATOMIC] = madvise_atomic,
>>> +	[DRM_XE_VMA_ATTR_PAT] = madvise_pat_index, };
>>> +
>>> +static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start,
>>> +u64 end, u8 *tile_mask) {
>>> +	struct drm_gpuva *gpuva;
>>> +	struct xe_tile *tile;
>>> +	u8 id;
>>> +
>>> +	lockdep_assert_held_write(&vm->lock);
>>> +
>>> +	if (dma_resv_wait_timeout(xe_vm_resv(vm),
>>> DMA_RESV_USAGE_BOOKKEEP,
>>> +				  false, MAX_SCHEDULE_TIMEOUT) <= 0)
>>> +		XE_WARN_ON(1);
>>> +
>>> +	*tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
>>> +
>>> +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
>>> +		struct xe_vma *vma = gpuva_to_vma(gpuva);
>>> +
>>> +		if (xe_vma_is_cpu_addr_mirror(vma))
>>> +			continue;
>>> +
>>> +		if (xe_vma_is_userptr(vma)) {
>>> +
>>> 	WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(v
>>> ma)),
>>> +
>>> DMA_RESV_USAGE_BOOKKEEP));
>>> +		}
>>> +
>>> +		for_each_tile(tile, vm->xe, id) {
>>> +			if (xe_pt_zap_ptes(tile, vma)) {
>>> +				*tile_mask |= BIT(id);
>>> +				vma->tile_invalidated |= BIT(id);
>>> +			}
>>> +		}
>>> +	}
>>> +}
>>> +
>>> +static int xe_vm_invalidate_madvise_range(struct xe_vm *vm, u64 start,
>>> +u64 end) {
>>> +	u8 tile_mask = 0;
>>> +
>>> +	xe_zap_ptes_in_madvise_range(vm, start, end, &tile_mask);
>>> +	if (!tile_mask)
>>> +		return 0;
>>> +
>>> +	xe_device_wmb(vm->xe);
>>> +
>>> +	return xe_vm_range_tilemask_tlb_invalidation(vm, start, end,
>>> +tile_mask); }
>>> +
>>> +static int drm_xe_madvise_args_are_sane(struct xe_device *xe, const
>>> +struct drm_xe_madvise *args) {
>>> +	if (XE_IOCTL_DBG(xe, !args))
>>> +		return -EINVAL;
>>> +
>>> +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->start, SZ_4K)))
>>> +		return -EINVAL;
>>> +
>>> +	if (XE_IOCTL_DBG(xe, !IS_ALIGNED(args->range, SZ_4K)))
>>> +		return -EINVAL;
>>> +
>>> +	if (XE_IOCTL_DBG(xe, args->range < SZ_4K))
>>> +		return -EINVAL;
>>> +
>>> +	switch (args->type) {
>>> +	case DRM_XE_VMA_ATTR_ATOMIC:
>>> +		if (XE_IOCTL_DBG(xe, args->atomic.val >
>>> DRM_XE_VMA_ATOMIC_CPU))
>>> +			return -EINVAL;
>>> +		break;
>>> +	case DRM_XE_VMA_ATTR_PAT:
>>> +		/*TODO: Add valid pat check */
>>> +		break;
>>> +	case DRM_XE_VMA_ATTR_PREFERRED_LOC:
>>> +		if (XE_IOCTL_DBG(xe, args-
>>>> preferred_mem_loc.migration_policy >
>>> +				     DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES))
>>> +			return -EINVAL;
>>> +		break;
>>> +	default:
>>> +		if (XE_IOCTL_DBG(xe, 1))
>>> +			return -EINVAL;
>>> +	}
>>> +
>>> +	if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
>>> +		return -EINVAL;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +/**
>>> + * xe_vm_madvise_ioctl - Handle MADVise ioctl for a VM
>>> + * @dev: DRM device pointer
>>> + * @data: Pointer to ioctl data (drm_xe_madvise*)
>>> + * @file: DRM file pointer
>>> + *
>>> + * Handles the MADVISE ioctl to provide memory advice for vma's within
>>> + * input range.
>>> + *
>>> + * Return: 0 on success or a negative error code on failure.
>>> + */
>>> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct
>>> +drm_file *file) {
>>> +	struct xe_device *xe = to_xe_device(dev);
>>> +	struct xe_file *xef = to_xe_file(file);
>>> +	struct drm_xe_madvise *args = data;
>>> +	struct xe_vm *vm;
>>> +	struct xe_bo *bo;
>>> +	struct drm_exec exec;
>>> +	int err = 0;
>>> +	int attr_type;
>>> +
>>> +	vm = xe_vm_lookup(xef, args->vm_id);
>>> +	if (XE_IOCTL_DBG(xe, !vm))
>>> +		return -EINVAL;
>>> +
>>> +	if (drm_xe_madvise_args_are_sane(vm->xe, args))
>>> +		return -EINVAL;
>>
>> The upper error return will miss the "xe_vm_put(vm)".
>> BTW, the function name drm_xe_madvise_args_are_sane is somehow a little misleading. The name looks like a boolean function, while the return value is 0 for success and error code for failure.
>>
> 
> Agree with Shuicheng, drm_xe_madvise_args_are_sane should be a bool,
> need to avoid a leak of the VM on a failure.
> 
> Also will I'm here, avoid drm_* prefix in Xe code. So...
> 
> s/drm_xe_madvise_args_are_sane/madvise_args_are_sane

Sure. Assuming the incorrect value from user should always be -EINVAL, 
making it return bool and return EINVAL at caller sounds ok.

> 
> Matt
> 
>> Shuicheng
>>
>>> +
>>> +	down_write(&vm->lock);
>>> +
>>> +	if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
>>> +		err = -ENOENT;
>>> +		goto unlock_vm;
>>> +	}
>>> +
>>> +	xe_vm_alloc_madvise_vma(vm, args->start, args->range);
>>> +
>>> +	struct xe_vmas_in_madvise_range madvise_range = {.addr = args->start,
>>> +							 .range =  args-
>>>> range, };
>>> +	err = get_vmas(vm, &madvise_range);
>>> +	if (err || !madvise_range.num_vmas)
>>> +		goto unlock_vm;
>>> +
>>> +	if (madvise_range.has_bo_vmas) {
>>> +		drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
>>> +		drm_exec_until_all_locked(&exec) {
>>> +			for (int i = 0; i < madvise_range.num_vmas; i++) {
>>> +				bo = xe_vma_bo(madvise_range.vmas[i]);
>>> +				if (!bo)
>>> +					continue;
>>> +				err = drm_exec_lock_obj(&exec, &bo-
>>>> ttm.base);
>>> +				drm_exec_retry_on_contention(&exec);
>>> +				if (err)
>>> +					goto err_fini;
>>> +			}
>>> +		}
>>> +	}
>>> +
>>> +	if (madvise_range.has_userptr_vmas)
>>> +		down_read(&vm->userptr.notifier_lock);
>>> +
>>> +	if (madvise_range.has_svm_vmas)
>>> +		xe_svm_notifier_lock(vm);
>>> +
>>> +	attr_type = array_index_nospec(args->type,
>>> ARRAY_SIZE(madvise_funcs));
>>> +	madvise_funcs[attr_type](xe, vm, madvise_range.vmas,
>>> +madvise_range.num_vmas, args);
>>> +
>>> +	kfree(madvise_range.vmas);
>>> +	madvise_range.vmas = NULL;
>>> +
>>> +	err = xe_vm_invalidate_madvise_range(vm, args->start, args->start +
>>> +args->range);
>>> +
>>> +	if (madvise_range.has_svm_vmas)
>>> +		xe_svm_notifier_unlock(vm);
>>> +
>>> +	if (madvise_range.has_userptr_vmas)
>>> +		up_read(&vm->userptr.notifier_lock);
>>> +err_fini:
>>> +	if (madvise_range.has_bo_vmas)
>>> +		drm_exec_fini(&exec);
>>> +unlock_vm:
>>> +	up_write(&vm->lock);
>>> +	xe_vm_put(vm);
>>> +	return err;
>>> +}
>>> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.h
>>> b/drivers/gpu/drm/xe/xe_vm_madvise.h
>>> new file mode 100644
>>> index 000000000000..b0e1fc445f23
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.h
>>> @@ -0,0 +1,15 @@
>>> +/* SPDX-License-Identifier: MIT */
>>> +/*
>>> + * Copyright © 2025 Intel Corporation
>>> + */
>>> +
>>> +#ifndef _XE_VM_MADVISE_H_
>>> +#define _XE_VM_MADVISE_H_
>>> +
>>> +struct drm_device;
>>> +struct drm_file;
>>> +
>>> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data,
>>> +			struct drm_file *file);
>>> +
>>> +#endif
>>> --
>>> 2.34.1
>>



^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 20/20] drm/xe/madvise: Skip vma invalidation if mem attr are unchanged
  2025-06-23 22:28   ` Matthew Brost
@ 2025-06-26  8:54     ` Ghimiray, Himal Prasad
  0 siblings, 0 replies; 68+ messages in thread
From: Ghimiray, Himal Prasad @ 2025-06-26  8:54 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe, thomas.hellstrom



On 24-06-2025 03:58, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:58PM +0530, Himal Prasad Ghimiray wrote:
>> If a VMA within the madvise input range already has the same memory
>> attribute as the one requested by the user, skip PTE zapping for that
>> VMA to avoid unnecessary invalidation.
>>
>> Suggested-by: Matthew Brost <matthew.brost@intel.com>
>> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_vm.c         |  1 +
>>   drivers/gpu/drm/xe/xe_vm_madvise.c | 57 ++++++++++++++++++------------
>>   drivers/gpu/drm/xe/xe_vm_types.h   |  6 ++++
>>   3 files changed, 42 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
>> index d9ce25f3abf4..56d6c286e3d3 100644
>> --- a/drivers/gpu/drm/xe/xe_vm.c
>> +++ b/drivers/gpu/drm/xe/xe_vm.c
>> @@ -1226,6 +1226,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
>>   		vma->gpuva.flags |= XE_VMA_ATOMIC_PTE_BIT;
>>   
>>   	vma->attr = *attr;
>> +	vma->skip_invalidation = 0;
> 
> This kzalloc'd so not needed.
> 
>>   
>>   	if (bo) {
>>   		struct drm_gpuvm_bo *vm_bo;
>> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
>> index 5b96c8fc73a5..06e40ab0970e 100644
>> --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
>> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
>> @@ -88,13 +88,18 @@ static void madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm *vm,
>>   	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_PREFERRED_LOC);
>>   
>>   	for (i = 0; i < num_vmas; i++) {
>> -		vmas[i]->attr.preferred_loc.devmem_fd = op->preferred_mem_loc.devmem_fd;
>> -
>> -		/* Till multi-device support is not added migration_policy
>> -		 * is of no use and can be ignored.
>> -		 */
>> -		vmas[i]->attr.preferred_loc.migration_policy =
>> +		if (vmas[i]->attr.preferred_loc.devmem_fd == op->preferred_mem_loc.devmem_fd &&
>> +		    vmas[i]->attr.preferred_loc.migration_policy ==
>> +		    op->preferred_mem_loc.migration_policy) {
>> +			vmas[i]->skip_invalidation = 1;
> 
> In the else statement, you need to clear this so subsequent madvise
> which change properties do issue invalidations.

Missed it. Will fix

> 
>> +		} else {
>> +			vmas[i]->attr.preferred_loc.devmem_fd = op->preferred_mem_loc.devmem_fd;
>> +			/* Till multi-device support is not added migration_policy
>> +			 * is of no use and can be ignored.
>> +			 */
>> +			vmas[i]->attr.preferred_loc.migration_policy =
>>   						op->preferred_mem_loc.migration_policy;
>> +		}
>>   	}
>>   }
>>   
>> @@ -109,7 +114,10 @@ static void madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
>>   	xe_assert(vm->xe, op->atomic.val <= DRM_XE_VMA_ATOMIC_CPU);
>>   
>>   	for (i = 0; i < num_vmas; i++) {
>> -		vmas[i]->attr.atomic_access = op->atomic.val;
>> +		if (vmas[i]->attr.atomic_access == op->atomic.val)
>> +			vmas[i]->skip_invalidation = 1;
>> +		else
>> +			vmas[i]->attr.atomic_access = op->atomic.val;
>>   
>>   		bo = xe_vma_bo(vmas[i]);
>>   		if (!bo)
>> @@ -134,9 +142,12 @@ static void madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
>>   
>>   	xe_assert(vm->xe, op->type == DRM_XE_VMA_ATTR_PAT);
>>   
>> -	for (i = 0; i < num_vmas; i++)
>> -		vmas[i]->attr.pat_index = op->pat_index.val;
>> -
>> +	for (i = 0; i < num_vmas; i++) {
>> +		if (vmas[i]->attr.pat_index == op->pat_index.val)
>> +			vmas[i]->skip_invalidation = 1;
>> +		else
>> +			vmas[i]->attr.pat_index = op->pat_index.val;
>> +	}
>>   }
>>   
>>   typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
>> @@ -161,23 +172,25 @@ static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start, u64 end, u
>>   				  false, MAX_SCHEDULE_TIMEOUT) <= 0)
>>   		XE_WARN_ON(1);
>>   
>> -	*tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
>> -
>>   	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
>>   		struct xe_vma *vma = gpuva_to_vma(gpuva);
>>   
>> -		if (xe_vma_is_cpu_addr_mirror(vma))
>> +		if (vma->skip_invalidation)
>>   			continue;
>>   
>> -		if (xe_vma_is_userptr(vma)) {
>> -			WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
>> -							     DMA_RESV_USAGE_BOOKKEEP));
>> -		}
>> -
>> -		for_each_tile(tile, vm->xe, id) {
>> -			if (xe_pt_zap_ptes(tile, vma)) {
>> -				*tile_mask |= BIT(id);
>> -				vma->tile_invalidated |= BIT(id);
>> +		if (xe_vma_is_cpu_addr_mirror(vma)) {
>> +			*tile_mask |= xe_svm_ranges_zap_ptes_in_range(vm,
>> +								      xe_vma_start(vma),
>> +								      xe_vma_end(vma));
>> +		} else {
>> +			if (xe_vma_is_userptr(vma))
>> +				WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
>> +								     DMA_RESV_USAGE_BOOKKEEP));
>> +			for_each_tile(tile, vm->xe, id) {
>> +				if (xe_pt_zap_ptes(tile, vma)) {
>> +					*tile_mask |= BIT(id);
>> +					vma->tile_invalidated |= BIT(id);
>> +				}
>>   			}
>>   		}
>>   	}
>> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
>> index c7156f8e2ed2..3b3019ecbfab 100644
>> --- a/drivers/gpu/drm/xe/xe_vm_types.h
>> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
>> @@ -151,6 +151,12 @@ struct xe_vma {
>>   	/** @tile_staged: bind is staged for this VMA */
>>   	u8 tile_staged;
>>   
>> +	/**
>> +	 * @skip_invalidation: Used in madvise to avoid invalidation
>> +	 * if mem attributes doesn't change
>> +	 */
>> +	u32 skip_invalidation;
> 
> bool or I think you can safely stuff this into gpuva flags (e.g.,
> DRM_GPUVA_USERBITS) as this only set / cleared / viewed by a single
> thread and all other flags are set at init time or bind time (i.e., no
> races).

would change it to bool.

  If you choose the latter, or regardless, we should probably
> document the gpuva usage.

do you mean gpuva userbit flags ?
  >
> Matt
> 
>> +
>>   	/**
>>   	 * @ufence: The user fence that was provided with MAP.
>>   	 * Needs to be signalled before UNMAP can be processed.
>> -- 
>> 2.34.1
>>




^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
  2025-06-24  2:18   ` Matthew Brost
@ 2025-06-27 13:20     ` Thomas Hellström
  2025-06-27 13:43     ` Thomas Hellström
  1 sibling, 0 replies; 68+ messages in thread
From: Thomas Hellström @ 2025-06-27 13:20 UTC (permalink / raw)
  To: Matthew Brost, Himal Prasad Ghimiray; +Cc: intel-xe

On Mon, 2025-06-23 at 19:18 -0700, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:57PM +0530, Himal Prasad Ghimiray
> wrote:
> > Introduce the DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl to allow
> > userspace
> > to query memory attributes of VMAs within a specified virtual
> > address
> > range.
> > If num_vmas == 0 and vector_of_vma_mem_attr == NULL, the ioctl
> > returns
> > the number of VMAs in the specified range.
> > If num_vmas > 0 and a valid user pointer is provided in
> > vector_of_vma_mem_attr, the ioctl fills the buffer with memory
> > attributes for each VMA.
> > This two-step interface allows userspace to first query the
> > required
> > buffer size, then retrieve detailed attributes efficiently.
> > 
> > v2 (Matthew Brost)
> > - Use same ioctl to overload functionality
> > 
> > v3
> > - Add kernel-doc
> > 
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Signed-off-by: Himal Prasad Ghimiray
> > <himal.prasad.ghimiray@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_device.c |   1 +
> >  drivers/gpu/drm/xe/xe_vm.c     |  89 ++++++++++++++++++++++
> >  drivers/gpu/drm/xe/xe_vm.h     |   2 +-
> >  include/uapi/drm/xe_drm.h      | 130
> > +++++++++++++++++++++++++++++++++
> >  4 files changed, 221 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_device.c
> > b/drivers/gpu/drm/xe/xe_device.c
> > index 632d3ab12392..1f9969acbcd9 100644
> > --- a/drivers/gpu/drm/xe/xe_device.c
> > +++ b/drivers/gpu/drm/xe/xe_device.c
> > @@ -199,6 +199,7 @@ static const struct drm_ioctl_desc xe_ioctls[]
> > = {
> >  			  DRM_RENDER_ALLOW),
> >  	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl,
> > DRM_RENDER_ALLOW),
> >  	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl,
> > DRM_RENDER_ALLOW),
> > +	DRM_IOCTL_DEF_DRV(XE_VM_QUERY_VMAS_ATTRS,
> > xe_vm_query_vmas_attrs_ioctl, DRM_RENDER_ALLOW),
> >  };
> >  
> >  static long xe_drm_ioctl(struct file *file, unsigned int cmd,
> > unsigned long arg)
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c
> > b/drivers/gpu/drm/xe/xe_vm.c
> > index 14e554f3f4d5..d9ce25f3abf4 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -2171,6 +2171,95 @@ int xe_vm_destroy_ioctl(struct drm_device
> > *dev, void *data,
> >  	return err;
> >  }
> >  
> > +static void xe_vm_query_vmas(struct xe_vm *vm, u32 *num_vmas, u64
> > start, u64 end)
> > +{
> > +	struct drm_gpuva *gpuva;
> > +
> > +	lockdep_assert_held(&vm->lock);
> > +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end)
> > +		(*num_vmas)++;
> > +}
> > +
> > +static int get_mem_attrs(struct xe_vm *vm, u32 *num_vmas, u64
> > start,
> > +			 u64 end, struct drm_xe_vma_mem_attr
> > *attrs)
> > +{
> > +	struct drm_gpuva *gpuva;
> > +	int i = 0;
> > +
> > +	lockdep_assert_held(&vm->lock);
> > +
> > +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end)
> > {
> > +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> > +
> > +		if (i == *num_vmas)
> > +			return -EINVAL;
> > +
> > +		attrs[i].start = xe_vma_start(vma);
> > +		attrs[i].end = xe_vma_end(vma);
> > +		attrs[i].atomic.val = vma->attr.atomic_access;
> > +		attrs[i].pat_index.val = vma->attr.pat_index;
> > +		attrs[i].preferred_mem_loc.devmem_fd = vma-
> > >attr.preferred_loc.devmem_fd;
> > +		attrs[i].preferred_mem_loc.migration_policy = vma-
> > >attr.preferred_loc.migration_policy;
> > +
> > +		i++;
> > +	}
> > +
> > +	if (i <  (*num_vmas - 1))
> > +		*num_vmas = i;
> > +	return 0;
> > +}
> > +
> > +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void
> > *data, struct drm_file *file)
> > +{
> > +	struct xe_device *xe = to_xe_device(dev);
> > +	struct xe_file *xef = to_xe_file(file);
> > +	struct drm_xe_vma_mem_attr *mem_attrs;
> > +	struct drm_xe_vm_query_vmas_attr *args = data;
> > +	u64 __user *attrs_user = u64_to_user_ptr(args-
> > >vector_of_vma_mem_attr);
> > +	struct xe_vm *vm;
> > +	int err = 0;
> > +
> > +	if (XE_IOCTL_DBG(xe,
> > +			 (args->num_vmas == 0 && attrs_user) ||
> > +			(args->num_vmas > 0 && !attrs_user)))
> > +		return -EINVAL;
> > +
> > +	vm = xe_vm_lookup(xef, args->vm_id);
> > +	if (XE_IOCTL_DBG(xe, !vm))
> > +		return -EINVAL;
> > +
> > +	down_read(&vm->lock);
> > +
> > +	attrs_user = u64_to_user_ptr(args-
> > >vector_of_vma_mem_attr);
> > +
> > +	if (args->num_vmas == 0 && !attrs_user) {
> > +		xe_vm_query_vmas(vm, &args->num_vmas, args->start,
> > args->start + args->range);
> > +		goto unlock_vm;
> > +	}
> > +
> > +	mem_attrs = kvmalloc_array(args->num_vmas, sizeof(struct
> > drm_xe_vma_mem_attr),
> > +				   GFP_KERNEL | __GFP_ACCOUNT |
> > +				   __GFP_RETRY_MAYFAIL |
> > __GFP_NOWARN);
> > +	if (!mem_attrs) {
> > +		err = args->num_vmas > 1 ? -ENOBUFS : -ENOMEM;
> > +		goto unlock_vm;
> > +	}
> > +
> > +	err = get_mem_attrs(vm, &args->num_vmas, args->start,
> > +			    args->start + args->range, mem_attrs);
> > +	if (err)
> > +		goto free_mem_attrs;
> > +
> > +	err = __copy_to_user(attrs_user, mem_attrs,
> > +			     sizeof(struct drm_xe_vma_mem_attr) *
> > args->num_vmas);
> > +
> > +free_mem_attrs:
> > +	kvfree(mem_attrs);
> > +unlock_vm:
> > +	up_read(&vm->lock);
> > +	return err;
> > +}
> > +
> >  static bool vma_matches(struct xe_vma *vma, u64 page_addr)
> >  {
> >  	if (page_addr > xe_vma_end(vma) - 1 ||
> > diff --git a/drivers/gpu/drm/xe/xe_vm.h
> > b/drivers/gpu/drm/xe/xe_vm.h
> > index 1fb639a33ffb..e4a601a3583f 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.h
> > +++ b/drivers/gpu/drm/xe/xe_vm.h
> > @@ -195,7 +195,7 @@ int xe_vm_destroy_ioctl(struct drm_device *dev,
> > void *data,
> >  			struct drm_file *file);
> >  int xe_vm_bind_ioctl(struct drm_device *dev, void *data,
> >  		     struct drm_file *file);
> > -
> > +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void
> > *data, struct drm_file *file);
> >  void xe_vm_close_and_put(struct xe_vm *vm);
> >  
> >  static inline bool xe_vm_in_fault_mode(struct xe_vm *vm)
> > diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> > index 81e90270313d..c0aa7c19870e 100644
> > --- a/include/uapi/drm/xe_drm.h
> > +++ b/include/uapi/drm/xe_drm.h
> > @@ -82,6 +82,7 @@ extern "C" {
> >   *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
> >   *  - &DRM_IOCTL_XE_OBSERVATION
> >   *  - &DRM_IOCTL_XE_MADVISE
> > + *  - &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
> >   */
> >  
> >  /*
> > @@ -104,6 +105,7 @@ extern "C" {
> >  #define DRM_XE_WAIT_USER_FENCE		0x0a
> >  #define DRM_XE_OBSERVATION		0x0b
> >  #define DRM_XE_MADVISE			0x0c
> > +#define DRM_XE_VM_QUERY_VMAS_ATTRS	0x0d
> >  
> >  /* Must be kept compact -- no holes */
> >  
> > @@ -120,6 +122,7 @@ extern "C" {
> >  #define
> > DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE,structdrm_xe_wait_user_fence)
> >  #define
> > DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION,structdrm_xe_observation_param)
> >  #define
> > DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, structdrm_xe_madvise)
> > +#define
> > DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_VMAS_ATTRS,structdrm_xe_vm_query_vmas_attr)
> >  
> >  /**
> >   * DOC: Xe IOCTL Extensions
> > @@ -2093,6 +2096,133 @@ struct drm_xe_madvise {
> >  	__u64 reserved[2];
> >  };
> >  
> > +/**
> > + * struct drm_xe_vma_mem_attr - Output of
> > &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
> > + *
> > + * This structure is provided by userspace and filled by KMD in
> > response to the
> > + * DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl. It describes memory
> > attributes of
> > + * a VMA within a specified address range in a VM.
> > + *
> > + * The structure includes information such as atomic access
> > policy, purgeable
> > + * state, page attribute table (PAT) index, and preferred memory
> > location.
> > + * Userspace allocates an array of these structures and passes a
> > pointer to the
> > + * ioctl to retrieve attributes for each VMA
> > + *
> > + * @extensions: Pointer to the first extension struct, if any
> > + * @start: Start address of the virtual memory area
> > + * @end: End address of the virtual memory area
> > + *
> > + * @atomic.val: Value of atomic operation policy
> > + * @atomic.reserved: Reserved, must be zero
> > + *
> > + * @purge_state_val.val: Value for DRM_XE_VMA_ATTR_PURGEABLE_STATE
> > + * @purge_state_val.reserved: Reserved, must be zero
> > + *
> > + * @pat_index.val: Page Attribute Table (PAT) index
> > + * @pat_index.reserved: Reserved, must be zero
> > + *
> > + * @preferred_mem_loc.devmem_fd: File descriptor for preferred
> > device memory
> > + * @preferred_mem_loc.migration_policy: Migration policy for
> > memory placement
> > + *
> > + */
> > +struct drm_xe_vma_mem_attr {
> > +	 /** @extensions: Pointer to the first extension struct,
> > if any */
> > +	__u64 extensions;
> > +
> > +	/** @start: start of the vma */
> > +	__u64 start;
> > +
> > +	/** @end: end of the vma */
> > +	__u64 end;
> > +
> > +	struct {
> > +		struct {
> > +		/** @atomic.val: atomic attribute for vma*/
> > +			__u32 val;
> > +
> > +		/** @atomic.reserved: Reserved */
> > +			__u32 reserved;
> > +		} atomic;
> > +
> > +		struct {
> > +			/** @pat_index.val: PAT index of vma */
> > +			__u32 val;
> > +
> > +			/** @pat_index.reserved: Reserved */
> > +			__u32 reserved;
> > +		} pat_index;
> > +
> > +		/** @preferred_mem_loc: preferred memory location
> > */
> > +		struct {
> > +			/** @preferred_mem_loc.devmem_fd: fd for
> > preferred loc */
> > +			__u32 devmem_fd;
> > +
> > +			/** @preferred_mem_loc.migration_policy:
> > Page migration policy */
> > +			__u32 migration_policy;
> > +		} preferred_mem_loc;
> > +	};
> 
> I just realized this interface isn’t very future-proof. Let me give
> an
> easy example of how this could break. Let’s say we add three more
> madvise attributes at some point in the future — we wouldn’t be able
> to
> fit those three additional attributes here.
> 
> Hmm, maybe in drm_xe_vm_query_vmas_attr we could also return the
> sizeof
> a single struct drm_xe_vma_mem_attr entry. That would allow us to
> grow
> individual entries indefinitely without breaking userspace, as long
> as
> it does something like the code below, and as long as we only grow
> struct drm_xe_vm_query_vmas_attr by appending new fields (i.e. we
> never
> reorder existing ones).
> 
> struct drm_xe_vm_query_vmas_attr query = {
>     .vm_id = vm,
>     .start = start,
>     .range = range,
> };
> 
> /* First ioctl to get number of VMAs and the size of each attribute
> */
> ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> 
> /* Allocate buffer for the VMA attributes */
> void *ptr = malloc(query.num_vmas * query.sizeof_vma_mem_attr);
> 
> query.vector_of_vma_mem_attr = (uintptr_t)ptr;
> 
> /* Second ioctl to actually fill the VMA attributes */
> ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> 
> /* Iterate over the returned VMA attributes */
> for (unsigned int i = 0; i < query.num_vmas; ++i) {
>     struct drm_xe_vma_mem_attr *vma_attr = (struct
> drm_xe_vma_mem_attr *)ptr;
> 
>     /* Do something with vma_attr */
> 
>     /* Move pointer by one VMA entry */
>     ptr += query.sizeof_vma_mem_attr;
> }
> 
> I think we need to double-check with the maintainer to see if this
> type
> of interface is allowed, but I don’t see any reason why it wouldn’t
> be.

Please check how this is handled in the other query ioctls, that is
when the total size of the number of items return exceeds the space
reserved for them.

I think we do something like Matt describes, calling twice.

/Thomas



> 
> Matt
> 
> > +
> > +	 /** @reserved: Reserved */
> > +	__u64 reserved[2];
> > +};
> > +
> > +/**
> > + * struct drm_xe_vm_query_vmas_attr - Input of
> > &DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES
> > + *
> > + * This structure is used to query memory attributes of virtual
> > memory areas
> > + * (VMAs) within a specified address range in a VM. It provides
> > detailed
> > + * information about each VMA, including atomic access policy,
> > purgeable state,
> > + * page attribute table (PAT) index, and preferred memory
> > location.
> > + *
> > + * Userspace first calls the ioctl with @num_vmas = 0 and
> > + * @vector_of_vma_mem_attr = NULL to retrieve the number of VMAs
> > in the range.
> > + * Then, it allocates a buffer of that size and calls the ioctl
> > again to fill
> > + * the buffer with VMA attributes.
> > + *
> > + * Example:
> > + *
> > + * .. code-block:: C
> > + *
> > + *     struct drm_xe_vma_mem_attr *attrs;
> > + *     __u32 num_vmas;
> > + *
> > + *     // First call to get number of VMAs
> > + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> > + *     num_vmas = query.num_vmas;
> > + *
> > + *     // Allocate and query attributes
> > + *     attrs = malloc(num_vmas, sizeof(*attrs));
> > + *     query.vector_of_vma_mem_attr = (__u64)(uintptr_t)attrs;
> > + *     query.num_vmas = num_vmas;
> > + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> > + */
> > +struct drm_xe_vm_query_vmas_attr {
> > +	/** @extensions: Pointer to the first extension struct, if
> > any */
> > +	__u64 extensions;
> > +
> > +	/** @vm_id: vm_id of the virtual range */
> > +	__u32 vm_id;
> > +
> > +	/** @num_vmas: number of vmas in range */
> > +	__u32 num_vmas;
> > +
> > +	/** @start: start of the virtual address range */
> > +	__u64 start;
> > +
> > +	/** @size: size of the virtual address range */
> > +	__u64 range;
> > +
> > +	/**
> > +	 * @vector_of_ops: userptr to array of struct
> > +	 * drm_xe_vma_mem_attr
> > +	 */
> > +	__u64 vector_of_vma_mem_attr;
> > +
> > +	/** @reserved: Reserved */
> > +	__u64 reserved[2];
> > +
> > +};
> > +
> >  #if defined(__cplusplus)
> >  }
> >  #endif
> > -- 
> > 2.34.1
> > 


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
  2025-06-24  2:18   ` Matthew Brost
  2025-06-27 13:20     ` Thomas Hellström
@ 2025-06-27 13:43     ` Thomas Hellström
  1 sibling, 0 replies; 68+ messages in thread
From: Thomas Hellström @ 2025-06-27 13:43 UTC (permalink / raw)
  To: Matthew Brost, Himal Prasad Ghimiray; +Cc: intel-xe

On Mon, 2025-06-23 at 19:18 -0700, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:57PM +0530, Himal Prasad Ghimiray
> wrote:
> > Introduce the DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl to allow
> > userspace
> > to query memory attributes of VMAs within a specified virtual
> > address
> > range.
> > If num_vmas == 0 and vector_of_vma_mem_attr == NULL, the ioctl
> > returns
> > the number of VMAs in the specified range.
> > If num_vmas > 0 and a valid user pointer is provided in
> > vector_of_vma_mem_attr, the ioctl fills the buffer with memory
> > attributes for each VMA.
> > This two-step interface allows userspace to first query the
> > required
> > buffer size, then retrieve detailed attributes efficiently.
> > 
> > v2 (Matthew Brost)
> > - Use same ioctl to overload functionality
> > 
> > v3
> > - Add kernel-doc
> > 
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Signed-off-by: Himal Prasad Ghimiray
> > <himal.prasad.ghimiray@intel.com>

I think this commit message needs a motivation as to why this can't be
done in user-space, also given that CPU madvise(2) doesn't have an
interface like this.

Also I think one need to point out in the docs that the result is only
advisory. When a value is read, it can immediately be changed by
another thread.

Finally, a VMA is really a KMD thing? I see also that it's mentioned in
the context of prefetch, but should we try to use the "memory range"
terminology instead, like madvise(2)?

Thanks,
Thomas



> > ---
> >  drivers/gpu/drm/xe/xe_device.c |   1 +
> >  drivers/gpu/drm/xe/xe_vm.c     |  89 ++++++++++++++++++++++
> >  drivers/gpu/drm/xe/xe_vm.h     |   2 +-
> >  include/uapi/drm/xe_drm.h      | 130
> > +++++++++++++++++++++++++++++++++
> >  4 files changed, 221 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_device.c
> > b/drivers/gpu/drm/xe/xe_device.c
> > index 632d3ab12392..1f9969acbcd9 100644
> > --- a/drivers/gpu/drm/xe/xe_device.c
> > +++ b/drivers/gpu/drm/xe/xe_device.c
> > @@ -199,6 +199,7 @@ static const struct drm_ioctl_desc xe_ioctls[]
> > = {
> >  			  DRM_RENDER_ALLOW),
> >  	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl,
> > DRM_RENDER_ALLOW),
> >  	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl,
> > DRM_RENDER_ALLOW),
> > +	DRM_IOCTL_DEF_DRV(XE_VM_QUERY_VMAS_ATTRS,
> > xe_vm_query_vmas_attrs_ioctl, DRM_RENDER_ALLOW),
> >  };
> >  
> >  static long xe_drm_ioctl(struct file *file, unsigned int cmd,
> > unsigned long arg)
> > diff --git a/drivers/gpu/drm/xe/xe_vm.c
> > b/drivers/gpu/drm/xe/xe_vm.c
> > index 14e554f3f4d5..d9ce25f3abf4 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.c
> > +++ b/drivers/gpu/drm/xe/xe_vm.c
> > @@ -2171,6 +2171,95 @@ int xe_vm_destroy_ioctl(struct drm_device
> > *dev, void *data,
> >  	return err;
> >  }
> >  
> > +static void xe_vm_query_vmas(struct xe_vm *vm, u32 *num_vmas, u64
> > start, u64 end)
> > +{
> > +	struct drm_gpuva *gpuva;
> > +
> > +	lockdep_assert_held(&vm->lock);
> > +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end)
> > +		(*num_vmas)++;
> > +}
> > +
> > +static int get_mem_attrs(struct xe_vm *vm, u32 *num_vmas, u64
> > start,
> > +			 u64 end, struct drm_xe_vma_mem_attr
> > *attrs)
> > +{
> > +	struct drm_gpuva *gpuva;
> > +	int i = 0;
> > +
> > +	lockdep_assert_held(&vm->lock);
> > +
> > +	drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end)
> > {
> > +		struct xe_vma *vma = gpuva_to_vma(gpuva);
> > +
> > +		if (i == *num_vmas)
> > +			return -EINVAL;
> > +
> > +		attrs[i].start = xe_vma_start(vma);
> > +		attrs[i].end = xe_vma_end(vma);
> > +		attrs[i].atomic.val = vma->attr.atomic_access;
> > +		attrs[i].pat_index.val = vma->attr.pat_index;
> > +		attrs[i].preferred_mem_loc.devmem_fd = vma-
> > >attr.preferred_loc.devmem_fd;
> > +		attrs[i].preferred_mem_loc.migration_policy = vma-
> > >attr.preferred_loc.migration_policy;
> > +
> > +		i++;
> > +	}
> > +
> > +	if (i <  (*num_vmas - 1))
> > +		*num_vmas = i;
> > +	return 0;
> > +}
> > +
> > +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void
> > *data, struct drm_file *file)
> > +{
> > +	struct xe_device *xe = to_xe_device(dev);
> > +	struct xe_file *xef = to_xe_file(file);
> > +	struct drm_xe_vma_mem_attr *mem_attrs;
> > +	struct drm_xe_vm_query_vmas_attr *args = data;
> > +	u64 __user *attrs_user = u64_to_user_ptr(args-
> > >vector_of_vma_mem_attr);
> > +	struct xe_vm *vm;
> > +	int err = 0;
> > +
> > +	if (XE_IOCTL_DBG(xe,
> > +			 (args->num_vmas == 0 && attrs_user) ||
> > +			(args->num_vmas > 0 && !attrs_user)))
> > +		return -EINVAL;
> > +
> > +	vm = xe_vm_lookup(xef, args->vm_id);
> > +	if (XE_IOCTL_DBG(xe, !vm))
> > +		return -EINVAL;
> > +
> > +	down_read(&vm->lock);
> > +
> > +	attrs_user = u64_to_user_ptr(args-
> > >vector_of_vma_mem_attr);
> > +
> > +	if (args->num_vmas == 0 && !attrs_user) {
> > +		xe_vm_query_vmas(vm, &args->num_vmas, args->start,
> > args->start + args->range);
> > +		goto unlock_vm;
> > +	}
> > +
> > +	mem_attrs = kvmalloc_array(args->num_vmas, sizeof(struct
> > drm_xe_vma_mem_attr),
> > +				   GFP_KERNEL | __GFP_ACCOUNT |
> > +				   __GFP_RETRY_MAYFAIL |
> > __GFP_NOWARN);
> > +	if (!mem_attrs) {
> > +		err = args->num_vmas > 1 ? -ENOBUFS : -ENOMEM;
> > +		goto unlock_vm;
> > +	}
> > +
> > +	err = get_mem_attrs(vm, &args->num_vmas, args->start,
> > +			    args->start + args->range, mem_attrs);
> > +	if (err)
> > +		goto free_mem_attrs;
> > +
> > +	err = __copy_to_user(attrs_user, mem_attrs,
> > +			     sizeof(struct drm_xe_vma_mem_attr) *
> > args->num_vmas);
> > +
> > +free_mem_attrs:
> > +	kvfree(mem_attrs);
> > +unlock_vm:
> > +	up_read(&vm->lock);
> > +	return err;
> > +}
> > +
> >  static bool vma_matches(struct xe_vma *vma, u64 page_addr)
> >  {
> >  	if (page_addr > xe_vma_end(vma) - 1 ||
> > diff --git a/drivers/gpu/drm/xe/xe_vm.h
> > b/drivers/gpu/drm/xe/xe_vm.h
> > index 1fb639a33ffb..e4a601a3583f 100644
> > --- a/drivers/gpu/drm/xe/xe_vm.h
> > +++ b/drivers/gpu/drm/xe/xe_vm.h
> > @@ -195,7 +195,7 @@ int xe_vm_destroy_ioctl(struct drm_device *dev,
> > void *data,
> >  			struct drm_file *file);
> >  int xe_vm_bind_ioctl(struct drm_device *dev, void *data,
> >  		     struct drm_file *file);
> > -
> > +int xe_vm_query_vmas_attrs_ioctl(struct drm_device *dev, void
> > *data, struct drm_file *file);
> >  void xe_vm_close_and_put(struct xe_vm *vm);
> >  
> >  static inline bool xe_vm_in_fault_mode(struct xe_vm *vm)
> > diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> > index 81e90270313d..c0aa7c19870e 100644
> > --- a/include/uapi/drm/xe_drm.h
> > +++ b/include/uapi/drm/xe_drm.h
> > @@ -82,6 +82,7 @@ extern "C" {
> >   *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
> >   *  - &DRM_IOCTL_XE_OBSERVATION
> >   *  - &DRM_IOCTL_XE_MADVISE
> > + *  - &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
> >   */
> >  
> >  /*
> > @@ -104,6 +105,7 @@ extern "C" {
> >  #define DRM_XE_WAIT_USER_FENCE		0x0a
> >  #define DRM_XE_OBSERVATION		0x0b
> >  #define DRM_XE_MADVISE			0x0c
> > +#define DRM_XE_VM_QUERY_VMAS_ATTRS	0x0d
> >  
> >  /* Must be kept compact -- no holes */
> >  
> > @@ -120,6 +122,7 @@ extern "C" {
> >  #define
> > DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE,structdrm_xe_wait_user_fence)
> >  #define
> > DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION,structdrm_xe_observation_param)
> >  #define
> > DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, structdrm_xe_madvise)
> > +#define
> > DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_VMAS_ATTRS,structdrm_xe_vm_query_vmas_attr)
> >  
> >  /**
> >   * DOC: Xe IOCTL Extensions
> > @@ -2093,6 +2096,133 @@ struct drm_xe_madvise {
> >  	__u64 reserved[2];
> >  };
> >  
> > +/**
> > + * struct drm_xe_vma_mem_attr - Output of
> > &DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS
> > + *
> > + * This structure is provided by userspace and filled by KMD in
> > response to the
> > + * DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS ioctl. It describes memory
> > attributes of
> > + * a VMA within a specified address range in a VM.
> > + *
> > + * The structure includes information such as atomic access
> > policy, purgeable
> > + * state, page attribute table (PAT) index, and preferred memory
> > location.
> > + * Userspace allocates an array of these structures and passes a
> > pointer to the
> > + * ioctl to retrieve attributes for each VMA
> > + *
> > + * @extensions: Pointer to the first extension struct, if any
> > + * @start: Start address of the virtual memory area
> > + * @end: End address of the virtual memory area
> > + *
> > + * @atomic.val: Value of atomic operation policy
> > + * @atomic.reserved: Reserved, must be zero
> > + *
> > + * @purge_state_val.val: Value for DRM_XE_VMA_ATTR_PURGEABLE_STATE
> > + * @purge_state_val.reserved: Reserved, must be zero
> > + *
> > + * @pat_index.val: Page Attribute Table (PAT) index
> > + * @pat_index.reserved: Reserved, must be zero
> > + *
> > + * @preferred_mem_loc.devmem_fd: File descriptor for preferred
> > device memory
> > + * @preferred_mem_loc.migration_policy: Migration policy for
> > memory placement
> > + *
> > + */
> > +struct drm_xe_vma_mem_attr {
> > +	 /** @extensions: Pointer to the first extension struct,
> > if any */
> > +	__u64 extensions;
> > +
> > +	/** @start: start of the vma */
> > +	__u64 start;
> > +
> > +	/** @end: end of the vma */
> > +	__u64 end;
> > +
> > +	struct {
> > +		struct {
> > +		/** @atomic.val: atomic attribute for vma*/
> > +			__u32 val;
> > +
> > +		/** @atomic.reserved: Reserved */
> > +			__u32 reserved;
> > +		} atomic;
> > +
> > +		struct {
> > +			/** @pat_index.val: PAT index of vma */
> > +			__u32 val;
> > +
> > +			/** @pat_index.reserved: Reserved */
> > +			__u32 reserved;
> > +		} pat_index;
> > +
> > +		/** @preferred_mem_loc: preferred memory location
> > */
> > +		struct {
> > +			/** @preferred_mem_loc.devmem_fd: fd for
> > preferred loc */
> > +			__u32 devmem_fd;
> > +
> > +			/** @preferred_mem_loc.migration_policy:
> > Page migration policy */
> > +			__u32 migration_policy;
> > +		} preferred_mem_loc;
> > +	};
> 
> I just realized this interface isn’t very future-proof. Let me give
> an
> easy example of how this could break. Let’s say we add three more
> madvise attributes at some point in the future — we wouldn’t be able
> to
> fit those three additional attributes here.
> 
> Hmm, maybe in drm_xe_vm_query_vmas_attr we could also return the
> sizeof
> a single struct drm_xe_vma_mem_attr entry. That would allow us to
> grow
> individual entries indefinitely without breaking userspace, as long
> as
> it does something like the code below, and as long as we only grow
> struct drm_xe_vm_query_vmas_attr by appending new fields (i.e. we
> never
> reorder existing ones).
> 
> struct drm_xe_vm_query_vmas_attr query = {
>     .vm_id = vm,
>     .start = start,
>     .range = range,
> };
> 
> /* First ioctl to get number of VMAs and the size of each attribute
> */
> ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> 
> /* Allocate buffer for the VMA attributes */
> void *ptr = malloc(query.num_vmas * query.sizeof_vma_mem_attr);
> 
> query.vector_of_vma_mem_attr = (uintptr_t)ptr;
> 
> /* Second ioctl to actually fill the VMA attributes */
> ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> 
> /* Iterate over the returned VMA attributes */
> for (unsigned int i = 0; i < query.num_vmas; ++i) {
>     struct drm_xe_vma_mem_attr *vma_attr = (struct
> drm_xe_vma_mem_attr *)ptr;
> 
>     /* Do something with vma_attr */
> 
>     /* Move pointer by one VMA entry */
>     ptr += query.sizeof_vma_mem_attr;
> }
> 
> I think we need to double-check with the maintainer to see if this
> type
> of interface is allowed, but I don’t see any reason why it wouldn’t
> be.
> 
> Matt
> 
> > +
> > +	 /** @reserved: Reserved */
> > +	__u64 reserved[2];
> > +};
> > +
> > +/**
> > + * struct drm_xe_vm_query_vmas_attr - Input of
> > &DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES
> > + *
> > + * This structure is used to query memory attributes of virtual
> > memory areas
> > + * (VMAs) within a specified address range in a VM. It provides
> > detailed
> > + * information about each VMA, including atomic access policy,
> > purgeable state,
> > + * page attribute table (PAT) index, and preferred memory
> > location.
> > + *
> > + * Userspace first calls the ioctl with @num_vmas = 0 and
> > + * @vector_of_vma_mem_attr = NULL to retrieve the number of VMAs
> > in the range.
> > + * Then, it allocates a buffer of that size and calls the ioctl
> > again to fill
> > + * the buffer with VMA attributes.
> > + *
> > + * Example:
> > + *
> > + * .. code-block:: C
> > + *
> > + *     struct drm_xe_vma_mem_attr *attrs;
> > + *     __u32 num_vmas;
> > + *
> > + *     // First call to get number of VMAs
> > + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> > + *     num_vmas = query.num_vmas;
> > + *
> > + *     // Allocate and query attributes
> > + *     attrs = malloc(num_vmas, sizeof(*attrs));
> > + *     query.vector_of_vma_mem_attr = (__u64)(uintptr_t)attrs;
> > + *     query.num_vmas = num_vmas;
> > + *     ioctl(fd, DRM_IOCTL_XE_VM_QUERY_VMAS_ATTRS, &query);
> > + */
> > +struct drm_xe_vm_query_vmas_attr {
> > +	/** @extensions: Pointer to the first extension struct, if
> > any */
> > +	__u64 extensions;
> > +
> > +	/** @vm_id: vm_id of the virtual range */
> > +	__u32 vm_id;
> > +
> > +	/** @num_vmas: number of vmas in range */
> > +	__u32 num_vmas;
> > +
> > +	/** @start: start of the virtual address range */
> > +	__u64 start;
> > +
> > +	/** @size: size of the virtual address range */
> > +	__u64 range;
> > +
> > +	/**
> > +	 * @vector_of_ops: userptr to array of struct
> > +	 * drm_xe_vma_mem_attr
> > +	 */
> > +	__u64 vector_of_vma_mem_attr;
> > +
> > +	/** @reserved: Reserved */
> > +	__u64 reserved[2];
> > +
> > +};
> > +
> >  #if defined(__cplusplus)
> >  }
> >  #endif
> > -- 
> > 2.34.1
> > 


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 02/20] drm/xe/uapi: Add madvise interface
  2025-06-23  6:20     ` Ghimiray, Himal Prasad
@ 2025-06-27 13:47       ` Thomas Hellström
  0 siblings, 0 replies; 68+ messages in thread
From: Thomas Hellström @ 2025-06-27 13:47 UTC (permalink / raw)
  To: Ghimiray, Himal Prasad, Matthew Brost
  Cc: intel-xe, José Roberto de Souza

On Mon, 2025-06-23 at 11:50 +0530, Ghimiray, Himal Prasad wrote:
> 
> 
> On 23-06-2025 10:00, Matthew Brost wrote:
> > On Fri, Jun 13, 2025 at 06:25:40PM +0530, Himal Prasad Ghimiray
> > wrote:
> > > This commit introduces a new madvise interface to support
> > > driver-specific ioctl operations. The madvise interface allows
> > > for more
> > > efficient memory management by providing hints to the driver
> > > about the
> > > expected memory usage and pte update policy for gpuvma.
> > > 
> > > v2 (Matthew/Thomas)
> > > - Drop num_ops support
> > > - Drop purgeable support
> > > - Add kernel-docs
> > > - IOWR/IOW
> > > 
> > > Cc: Matthew Brost <matthew.brost@intel.com>
> > > Signed-off-by: Himal Prasad Ghimiray
> > > <himal.prasad.ghimiray@intel.com>
> > > Acked-by: José Roberto de Souza <jose.souza@intel.com>
> > > ---
> > >   include/uapi/drm/xe_drm.h | 118
> > > ++++++++++++++++++++++++++++++++++++++
> > >   1 file changed, 118 insertions(+)
> > > 
> > > diff --git a/include/uapi/drm/xe_drm.h
> > > b/include/uapi/drm/xe_drm.h
> > > index 6a702ba7817c..b5f8d11faaa8 100644
> > > --- a/include/uapi/drm/xe_drm.h
> > > +++ b/include/uapi/drm/xe_drm.h
> > > @@ -81,6 +81,7 @@ extern "C" {
> > >    *  - &DRM_IOCTL_XE_EXEC
> > >    *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
> > >    *  - &DRM_IOCTL_XE_OBSERVATION
> > > + *  - &DRM_IOCTL_XE_MADVISE
> > >    */
> > >   
> > >   /*
> > > @@ -102,6 +103,7 @@ extern "C" {
> > >   #define DRM_XE_EXEC			0x09
> > >   #define DRM_XE_WAIT_USER_FENCE		0x0a
> > >   #define DRM_XE_OBSERVATION		0x0b
> > > +#define DRM_XE_MADVISE			0x0c
> > >   
> > >   /* Must be kept compact -- no holes */
> > >   
> > > @@ -117,6 +119,7 @@ extern "C" {
> > >   #define
> > > DRM_IOCTL_XE_EXEC			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, structdrm_xe_exec)
> > >   #define
> > > DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE,structdrm_xe_wait_user_fence)
> > >   #define
> > > DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION,structdrm_xe_observation_param)
> > > +#define
> > > DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE,structdrm_xe_madvise)
> > >   
> > >   /**
> > >    * DOC: Xe IOCTL Extensions
> > > @@ -1970,6 +1973,121 @@ struct drm_xe_query_eu_stall {
> > >   	__u64 sampling_rates[];
> > >   };
> > >   
> > > +/**
> > > + * struct drm_xe_madvise - Input of &DRM_IOCTL_XE_MADVISE
> > > + *
> > > + * This structure is used to set memory attributes for a virtual
> > > address range
> > > + * in a VM. The type of attribute is specified by @type, and the
> > > corresponding
> > > + * union member is used to provide additional parameters for
> > > @type.
> > > + *
> > > + * Supported attribute types:
> > > + * - DRM_XE_VMA_ATTR_PREFERRED_LOC: Set preferred memory
> > > location.
> > > + * - DRM_XE_VMA_ATTR_ATOMIC: Set atomic access policy.
> > > + * - DRM_XE_VMA_ATTR_PAT: Set page attribute table index.
> > > + *
> > > + * Example:
> > > + *
> > > + * .. code-block:: C
> > > + *
> > > + * struct drm_xe_madvise madvise = {
> > > + *          .vm_id = vm_id,
> > > + *          .start = 0x100000,
> > > + *          .range = 0x2000,
> > > + *          .type = DRM_XE_VMA_ATTR_ATOMIC,
> > > + *          .atomic_val = DRM_XE_VMA_ATOMIC_DEVICE,
> > > + *         };
> > > + *
> > > + * ioctl(fd, DRM_IOCTL_XE_MADVISE, &madvise);
> > > + *
> > > + */
> > > +struct drm_xe_madvise {
> > > +	/** @extensions: Pointer to the first extension struct,
> > > if any */
> > > +	__u64 extensions;
> > > +
> > > +	/** @start: start of the virtual address range */
> > > +	__u64 start;
> > > +
> > > +	/** @size: size of the virtual address range */
> > > +	__u64 range;
> > > +
> > > +	/** @vm_id: vm_id of the virtual range */
> > > +	__u32 vm_id;
> > > +
> > > +#define DRM_XE_VMA_ATTR_PREFERRED_LOC	0
> > > +#define DRM_XE_VMA_ATTR_ATOMIC		1
> > > +#define DRM_XE_VMA_ATTR_PAT		2
> > > +	/** @type: type of attribute */
> > > +	__u32 type;
> > > +
> > > +	union {
> > 
> > Nit: I'd make this union is same order as the defines (e.g.,
> > preferred location
> > first, atomic second, pat third).
> 
> sure
> 
> > 
> > > +		/**
> > > +		 * @atomic: Atomic access policy
> > > +		 *
> > > +		 * Used when @type == DRM_XE_VMA_ATTR_ATOMIC.
> > > +		 *
> > > +		 * Supported values for @atomic.val:
> > > +		 * - DRM_XE_VMA_ATOMIC_UNDEFINED: Undefined or
> > > default behaviour
> > > +		 *   Support both GPU and CPU atomic operations
> > > for system allocator
> > > +		 *   Support GPU atomic operations for
> > > normal(bo) allocator
> > > +		 * - DRM_XE_VMA_ATOMIC_DEVICE: Support GPU
> > > atomic operations
> > > +		 * - DRM_XE_VMA_ATOMIC_GLOBAL: Support both GPU
> > > and CPU atomic operations
> > > +		 * - DRM_XE_VMA_ATOMIC_CPU: Support CPU atomic
> > > +		 */
> > > +		struct {
> > > +#define DRM_XE_VMA_ATOMIC_UNDEFINED	0
> > > +#define DRM_XE_VMA_ATOMIC_DEVICE	1
> > > +#define DRM_XE_VMA_ATOMIC_GLOBAL	2
> > > +#define DRM_XE_VMA_ATOMIC_CPU		3
> > > +			/** @atomic.val: value of atomic
> > > operation */
> > > +			__u32 val;
> > > +
> > > +			/** @atomic.reserved: Reserved */
> > > +			__u32 reserved;
> > > +		} atomic;
> > > +
> > > +		/**
> > > +		 * @pat_index: Page attribute table index
> > > +		 *
> > > +		 * Used when @type == DRM_XE_VMA_ATTR_PAT.
> > > +		 */
> > > +		struct {
> > > +			/** @pat_index.val: PAT index value */
> > > +			__u32 val;
> > > +
> > > +			/** @pat_index.reserved: Reserved */
> > > +			__u32 reserved;
> > > +		} pat_index;
> > > +
> > > +		/**
> > > +		 * @preferred_mem_loc: preferred memory location
> > > +		 *
> > > +		 * Used when @type ==
> > > DRM_XE_VMA_ATTR_PREFERRED_LOC
> > > +		 *
> > > +		 * Supported values for
> > > @preferred_mem_loc.devmem_fd:
> > > +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE: set
> > > vram of faulting tile as preferred loc
> > > +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM: set
> > > smem as preferred loc
> > > +		 *
> > > +		 * Supported values for
> > > @preferred_mem_loc.migration_policy:
> > > +		 * - DRM_XE_MIGRATE_ALL_PAGES
> > > +		 * - DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES
> > > +		 */
> > > +		struct {
> > > +#define DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE	0
> > > +#define DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM	-1
> > > +			/** @preferred_mem_loc.devmem_fd: fd for
> > > preferred loc */
> > > +			__u32 devmem_fd;
> > > +
> > > +#define DRM_XE_MIGRATE_ALL_PAGES		0
> > > +#define DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES	1
> > 
> > I'd double check with Thomas / maintainers if they want this
> > (migration_policy)
> > to be included in this version as still more or less unused in this
> > series.

I think if UMD wants it now to distinguish between VRAM and system
that's fine. I think we'd want to add another op or an extension for
multi-device and any advanced migration strategies UMD would want us to
support. If UMD doesn't use this now at all, we'd need to leave it out
for now.

/Thomas


> 
> Sure
> 
> > 
> > > +			/** @preferred_mem_loc.migration_policy:
> > > Page migration policy */
> > > +			__u32 migration_policy;
> > 
> > Could we future proof a little, maybe migration_policy is a __u16
> > (or __u8?) and
> > stick a reserved __u16 in here?
> 
> OK
> 
> > 
> > Matt
> > 
> > > +		} preferred_mem_loc;
> > > +	};
> > > +
> > > +	/** @reserved: Reserved */
> > > +	__u64 reserved[2];
> > > +};
> > > +
> > >   #if defined(__cplusplus)
> > >   }
> > >   #endif
> > > -- 
> > > 2.34.1
> > > 
> 
> 


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 02/20] drm/xe/uapi: Add madvise interface
  2025-06-23  4:30   ` Matthew Brost
  2025-06-23  6:20     ` Ghimiray, Himal Prasad
@ 2025-06-27 14:29     ` Thomas Hellström
  2025-06-27 18:13       ` Matthew Brost
  1 sibling, 1 reply; 68+ messages in thread
From: Thomas Hellström @ 2025-06-27 14:29 UTC (permalink / raw)
  To: Matthew Brost, Himal Prasad Ghimiray; +Cc: intel-xe, José Roberto de Souza

On Sun, 2025-06-22 at 21:30 -0700, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:40PM +0530, Himal Prasad Ghimiray
> wrote:
> > This commit introduces a new madvise interface to support
> > driver-specific ioctl operations. The madvise interface allows for
> > more
> > efficient memory management by providing hints to the driver about
> > the
> > expected memory usage and pte update policy for gpuvma.
> > 
> > v2 (Matthew/Thomas)
> > - Drop num_ops support
> > - Drop purgeable support
> > - Add kernel-docs
> > - IOWR/IOW
> > 
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Signed-off-by: Himal Prasad Ghimiray
> > <himal.prasad.ghimiray@intel.com>
> > Acked-by: José Roberto de Souza <jose.souza@intel.com>
> > ---
> >  include/uapi/drm/xe_drm.h | 118
> > ++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 118 insertions(+)
> > 
> > diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> > index 6a702ba7817c..b5f8d11faaa8 100644
> > --- a/include/uapi/drm/xe_drm.h
> > +++ b/include/uapi/drm/xe_drm.h
> > @@ -81,6 +81,7 @@ extern "C" {
> >   *  - &DRM_IOCTL_XE_EXEC
> >   *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
> >   *  - &DRM_IOCTL_XE_OBSERVATION
> > + *  - &DRM_IOCTL_XE_MADVISE
> >   */
> >  
> >  /*
> > @@ -102,6 +103,7 @@ extern "C" {
> >  #define DRM_XE_EXEC			0x09
> >  #define DRM_XE_WAIT_USER_FENCE		0x0a
> >  #define DRM_XE_OBSERVATION		0x0b
> > +#define DRM_XE_MADVISE			0x0c
> >  
> >  /* Must be kept compact -- no holes */
> >  
> > @@ -117,6 +119,7 @@ extern "C" {
> >  #define
> > DRM_IOCTL_XE_EXEC			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec)
> >  #define
> > DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE,structdrm_xe_wait_user_fence)
> >  #define
> > DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION,structdrm_xe_observation_param)
> > +#define
> > DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, structdrm_xe_madvise)
> >  
> >  /**
> >   * DOC: Xe IOCTL Extensions
> > @@ -1970,6 +1973,121 @@ struct drm_xe_query_eu_stall {
> >  	__u64 sampling_rates[];
> >  };
> >  
> > +/**
> > + * struct drm_xe_madvise - Input of &DRM_IOCTL_XE_MADVISE
> > + *
> > + * This structure is used to set memory attributes for a virtual
> > address range
> > + * in a VM. The type of attribute is specified by @type, and the
> > corresponding
> > + * union member is used to provide additional parameters for
> > @type.
> > + *
> > + * Supported attribute types:
> > + * - DRM_XE_VMA_ATTR_PREFERRED_LOC: Set preferred memory location.
> > + * - DRM_XE_VMA_ATTR_ATOMIC: Set atomic access policy.
> > + * - DRM_XE_VMA_ATTR_PAT: Set page attribute table index.
> > + *
> > + * Example:
> > + *
> > + * .. code-block:: C
> > + *
> > + * struct drm_xe_madvise madvise = {
> > + *          .vm_id = vm_id,
> > + *          .start = 0x100000,
> > + *          .range = 0x2000,
> > + *          .type = DRM_XE_VMA_ATTR_ATOMIC,
> > + *          .atomic_val = DRM_XE_VMA_ATOMIC_DEVICE,
> > + *         };
> > + *
> > + * ioctl(fd, DRM_IOCTL_XE_MADVISE, &madvise);
> > + *
> > + */
> > +struct drm_xe_madvise {
> > +	/** @extensions: Pointer to the first extension struct, if
> > any */
> > +	__u64 extensions;
> > +
> > +	/** @start: start of the virtual address range */
> > +	__u64 start;
> > +
> > +	/** @size: size of the virtual address range */
> > +	__u64 range;
> > +
> > +	/** @vm_id: vm_id of the virtual range */
> > +	__u32 vm_id;
> > +
> > +#define DRM_XE_VMA_ATTR_PREFERRED_LOC	0
> > +#define DRM_XE_VMA_ATTR_ATOMIC		1
> > +#define DRM_XE_VMA_ATTR_PAT		2
> > +	/** @type: type of attribute */
> > +	__u32 type;
> > +
> > +	union {
> 
> Nit: I'd make this union is same order as the defines (e.g.,
> preferred location
> first, atomic second, pat third).
> 
> > +		/**
> > +		 * @atomic: Atomic access policy
> > +		 *
> > +		 * Used when @type == DRM_XE_VMA_ATTR_ATOMIC.
> > +		 *
> > +		 * Supported values for @atomic.val:
> > +		 * - DRM_XE_VMA_ATOMIC_UNDEFINED: Undefined or
> > default behaviour
> > +		 *   Support both GPU and CPU atomic operations
> > for system allocator
> > +		 *   Support GPU atomic operations for normal(bo)
> > allocator
> > +		 * - DRM_XE_VMA_ATOMIC_DEVICE: Support GPU atomic
> > operations
> > +		 * - DRM_XE_VMA_ATOMIC_GLOBAL: Support both GPU
> > and CPU atomic operations
> > +		 * - DRM_XE_VMA_ATOMIC_CPU: Support CPU atomic
> > +		 */
> > +		struct {
> > +#define DRM_XE_VMA_ATOMIC_UNDEFINED	0
> > +#define DRM_XE_VMA_ATOMIC_DEVICE	1
> > +#define DRM_XE_VMA_ATOMIC_GLOBAL	2
> > +#define DRM_XE_VMA_ATOMIC_CPU		3
> > +			/** @atomic.val: value of atomic operation
> > */
> > +			__u32 val;
> > +
> > +			/** @atomic.reserved: Reserved */
> > +			__u32 reserved;
> > +		} atomic;
> > +
> > +		/**
> > +		 * @pat_index: Page attribute table index
> > +		 *
> > +		 * Used when @type == DRM_XE_VMA_ATTR_PAT.
> > +		 */
> > +		struct {
> > +			/** @pat_index.val: PAT index value */
> > +			__u32 val;
> > +
> > +			/** @pat_index.reserved: Reserved */
> > +			__u32 reserved;
> > +		} pat_index;
> > +
> > +		/**
> > +		 * @preferred_mem_loc: preferred memory location
> > +		 *
> > +		 * Used when @type ==
> > DRM_XE_VMA_ATTR_PREFERRED_LOC
> > +		 *
> > +		 * Supported values for
> > @preferred_mem_loc.devmem_fd:
> > +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE: set vram
> > of faulting tile as preferred loc
> > +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM: set smem
> > as preferred loc
> > +		 *
> > +		 * Supported values for
> > @preferred_mem_loc.migration_policy:
> > +		 * - DRM_XE_MIGRATE_ALL_PAGES
> > +		 * - DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES
> > +		 */
> > +		struct {
> > +#define DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE	0
> > +#define DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM	-1
> > +			/** @preferred_mem_loc.devmem_fd: fd for
> > preferred loc */
> > +			__u32 devmem_fd;
> > +
> > +#define DRM_XE_MIGRATE_ALL_PAGES		0
> > +#define DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES	1
> 
> I'd double check with Thomas / maintainers if they want this
> (migration_policy)
> to be included in this version as still more or less unused in this
> series.
> 
> > +			/** @preferred_mem_loc.migration_policy:
> > Page migration policy */
> > +			__u32 migration_policy;
> 
> Could we future proof a little, maybe migration_policy is a __u16 (or
> __u8?) and
> stick a reserved __u16 in here?
> 
> Matt

Yeah, I think we need to have a strategy for extensions here. Perhaps
we could add new madvise types by extending the union and add
additional types, but then I think we need to expand the union size to
accomodate reasonable future additions.

Additions could also be made using extensions, so that if a suitable
extension is present, the union is never used?

/Thomas



> 
> > +		} preferred_mem_loc;
> > +	};
> > +
> > +	/** @reserved: Reserved */
> > +	__u64 reserved[2];
> > +};
> > +
> >  #if defined(__cplusplus)
> >  }
> >  #endif
> > -- 
> > 2.34.1
> > 


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 03/20] drm/xe/vm: Add attributes struct as member of vma
  2025-06-23  4:18   ` Matthew Brost
  2025-06-23  6:21     ` Ghimiray, Himal Prasad
@ 2025-06-27 14:32     ` Thomas Hellström
  1 sibling, 0 replies; 68+ messages in thread
From: Thomas Hellström @ 2025-06-27 14:32 UTC (permalink / raw)
  To: Matthew Brost, Himal Prasad Ghimiray; +Cc: intel-xe

On Sun, 2025-06-22 at 21:18 -0700, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:41PM +0530, Himal Prasad Ghimiray
> wrote:
> > The attribute of xe_vma will determine the migration policy and the
> > encoding of the page table entries (PTEs) for that vma.
> > This attribute helps manage how memory pages are moved and how
> > their
> > addresses are translated. It will be used by madvise to set the
> > behavior of the vma.
> > 
> > v2 (Matthew Brost)
> > - Add docs
> > 
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Signed-off-by: Himal Prasad Ghimiray
> > <himal.prasad.ghimiray@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_vm_types.h | 28 ++++++++++++++++++++++++++++
> >  1 file changed, 28 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> > b/drivers/gpu/drm/xe/xe_vm_types.h
> > index bed6088e1bb3..c7663058a7e3 100644
> > --- a/drivers/gpu/drm/xe/xe_vm_types.h
> > +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> > @@ -77,6 +77,27 @@ struct xe_userptr {
> >  #endif
> >  };
> >  
> > +/**
> > + * struct xe_vma_mem_attr - memory attributes associated with vma
> > + */
> > +struct xe_vma_mem_attr {
> > +	/** @preferred_loc: perferred memory_location*/
> > +	struct {
> > +		/** @preferred_loc.migration_policy: Policy for
> > migration of pages */
> > +		u32 migration_policy;
> > +
> > +		/**
> > +		 * @preferred_loc.devmem_fd: used for determining
> > pagemap_fd requested by user
> > +		 * DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM and
> > DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE mean
> > +		 * system memory or closest device memory
> > respectively.
> 
> Nit, I generally prefer 80 character line wraps. I know checkpatch
> allows 100 but in general I think Xe generally wraps at 80 unless it
> is
> an odd case with nested code and an 80 character wrap makes the code
> unreadable.
> 
> 80 generally allows 2 windows split vertically in vi on a typical
> laptop
> which makes navigating the code a bit easier.
> 
> > +		 */
> > +		u32 devmem_fd;
> > +	} preferred_loc;
> > +
> > +	/** @atomic_access: The atomic access type for the vma */
> 
> I'd reference the uAPI here. e.g., DRM_XE_VMA_ATOMIC_*

+1.

> 
> With the minor nits fixed:
> Reviewed-by: Matthew Brost <matthew.brost@intel.com>

Also with those fixes, feel free to add
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>

> 
> Matt
> 
> > +	u32 atomic_access;
> > +};
> > +
> >  struct xe_vma {
> >  	/** @gpuva: Base GPUVA object */
> >  	struct drm_gpuva gpuva;
> > @@ -135,6 +156,13 @@ struct xe_vma {
> >  	 * Needs to be signalled before UNMAP can be processed.
> >  	 */
> >  	struct xe_user_fence *ufence;
> > +
> > +	/**
> > +	 * @attr: The attributes of vma which determines the
> > migration policy
> > +	 * and encoding of the PTEs for this vma.
> > +	 */
> > +	struct xe_vma_mem_attr attr;
> > +
> >  };
> >  
> >  /**
> > -- 
> > 2.34.1
> > 


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 02/20] drm/xe/uapi: Add madvise interface
  2025-06-27 14:29     ` Thomas Hellström
@ 2025-06-27 18:13       ` Matthew Brost
  0 siblings, 0 replies; 68+ messages in thread
From: Matthew Brost @ 2025-06-27 18:13 UTC (permalink / raw)
  To: Thomas Hellström
  Cc: Himal Prasad Ghimiray, intel-xe, José Roberto de Souza

On Fri, Jun 27, 2025 at 04:29:02PM +0200, Thomas Hellström wrote:
> On Sun, 2025-06-22 at 21:30 -0700, Matthew Brost wrote:
> > On Fri, Jun 13, 2025 at 06:25:40PM +0530, Himal Prasad Ghimiray
> > wrote:
> > > This commit introduces a new madvise interface to support
> > > driver-specific ioctl operations. The madvise interface allows for
> > > more
> > > efficient memory management by providing hints to the driver about
> > > the
> > > expected memory usage and pte update policy for gpuvma.
> > > 
> > > v2 (Matthew/Thomas)
> > > - Drop num_ops support
> > > - Drop purgeable support
> > > - Add kernel-docs
> > > - IOWR/IOW
> > > 
> > > Cc: Matthew Brost <matthew.brost@intel.com>
> > > Signed-off-by: Himal Prasad Ghimiray
> > > <himal.prasad.ghimiray@intel.com>
> > > Acked-by: José Roberto de Souza <jose.souza@intel.com>
> > > ---
> > >  include/uapi/drm/xe_drm.h | 118
> > > ++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 118 insertions(+)
> > > 
> > > diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> > > index 6a702ba7817c..b5f8d11faaa8 100644
> > > --- a/include/uapi/drm/xe_drm.h
> > > +++ b/include/uapi/drm/xe_drm.h
> > > @@ -81,6 +81,7 @@ extern "C" {
> > >   *  - &DRM_IOCTL_XE_EXEC
> > >   *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
> > >   *  - &DRM_IOCTL_XE_OBSERVATION
> > > + *  - &DRM_IOCTL_XE_MADVISE
> > >   */
> > >  
> > >  /*
> > > @@ -102,6 +103,7 @@ extern "C" {
> > >  #define DRM_XE_EXEC			0x09
> > >  #define DRM_XE_WAIT_USER_FENCE		0x0a
> > >  #define DRM_XE_OBSERVATION		0x0b
> > > +#define DRM_XE_MADVISE			0x0c
> > >  
> > >  /* Must be kept compact -- no holes */
> > >  
> > > @@ -117,6 +119,7 @@ extern "C" {
> > >  #define
> > > DRM_IOCTL_XE_EXEC			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec)
> > >  #define
> > > DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE,structdrm_xe_wait_user_fence)
> > >  #define
> > > DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION,structdrm_xe_observation_param)
> > > +#define
> > > DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, structdrm_xe_madvise)
> > >  
> > >  /**
> > >   * DOC: Xe IOCTL Extensions
> > > @@ -1970,6 +1973,121 @@ struct drm_xe_query_eu_stall {
> > >  	__u64 sampling_rates[];
> > >  };
> > >  
> > > +/**
> > > + * struct drm_xe_madvise - Input of &DRM_IOCTL_XE_MADVISE
> > > + *
> > > + * This structure is used to set memory attributes for a virtual
> > > address range
> > > + * in a VM. The type of attribute is specified by @type, and the
> > > corresponding
> > > + * union member is used to provide additional parameters for
> > > @type.
> > > + *
> > > + * Supported attribute types:
> > > + * - DRM_XE_VMA_ATTR_PREFERRED_LOC: Set preferred memory location.
> > > + * - DRM_XE_VMA_ATTR_ATOMIC: Set atomic access policy.
> > > + * - DRM_XE_VMA_ATTR_PAT: Set page attribute table index.
> > > + *
> > > + * Example:
> > > + *
> > > + * .. code-block:: C
> > > + *
> > > + * struct drm_xe_madvise madvise = {
> > > + *          .vm_id = vm_id,
> > > + *          .start = 0x100000,
> > > + *          .range = 0x2000,
> > > + *          .type = DRM_XE_VMA_ATTR_ATOMIC,
> > > + *          .atomic_val = DRM_XE_VMA_ATOMIC_DEVICE,
> > > + *         };
> > > + *
> > > + * ioctl(fd, DRM_IOCTL_XE_MADVISE, &madvise);
> > > + *
> > > + */
> > > +struct drm_xe_madvise {
> > > +	/** @extensions: Pointer to the first extension struct, if
> > > any */
> > > +	__u64 extensions;
> > > +
> > > +	/** @start: start of the virtual address range */
> > > +	__u64 start;
> > > +
> > > +	/** @size: size of the virtual address range */
> > > +	__u64 range;
> > > +
> > > +	/** @vm_id: vm_id of the virtual range */
> > > +	__u32 vm_id;
> > > +
> > > +#define DRM_XE_VMA_ATTR_PREFERRED_LOC	0
> > > +#define DRM_XE_VMA_ATTR_ATOMIC		1
> > > +#define DRM_XE_VMA_ATTR_PAT		2
> > > +	/** @type: type of attribute */
> > > +	__u32 type;
> > > +
> > > +	union {
> > 
> > Nit: I'd make this union is same order as the defines (e.g.,
> > preferred location
> > first, atomic second, pat third).
> > 
> > > +		/**
> > > +		 * @atomic: Atomic access policy
> > > +		 *
> > > +		 * Used when @type == DRM_XE_VMA_ATTR_ATOMIC.
> > > +		 *
> > > +		 * Supported values for @atomic.val:
> > > +		 * - DRM_XE_VMA_ATOMIC_UNDEFINED: Undefined or
> > > default behaviour
> > > +		 *   Support both GPU and CPU atomic operations
> > > for system allocator
> > > +		 *   Support GPU atomic operations for normal(bo)
> > > allocator
> > > +		 * - DRM_XE_VMA_ATOMIC_DEVICE: Support GPU atomic
> > > operations
> > > +		 * - DRM_XE_VMA_ATOMIC_GLOBAL: Support both GPU
> > > and CPU atomic operations
> > > +		 * - DRM_XE_VMA_ATOMIC_CPU: Support CPU atomic
> > > +		 */
> > > +		struct {
> > > +#define DRM_XE_VMA_ATOMIC_UNDEFINED	0
> > > +#define DRM_XE_VMA_ATOMIC_DEVICE	1
> > > +#define DRM_XE_VMA_ATOMIC_GLOBAL	2
> > > +#define DRM_XE_VMA_ATOMIC_CPU		3
> > > +			/** @atomic.val: value of atomic operation
> > > */
> > > +			__u32 val;
> > > +
> > > +			/** @atomic.reserved: Reserved */
> > > +			__u32 reserved;
> > > +		} atomic;
> > > +
> > > +		/**
> > > +		 * @pat_index: Page attribute table index
> > > +		 *
> > > +		 * Used when @type == DRM_XE_VMA_ATTR_PAT.
> > > +		 */
> > > +		struct {
> > > +			/** @pat_index.val: PAT index value */
> > > +			__u32 val;
> > > +
> > > +			/** @pat_index.reserved: Reserved */
> > > +			__u32 reserved;
> > > +		} pat_index;
> > > +
> > > +		/**
> > > +		 * @preferred_mem_loc: preferred memory location
> > > +		 *
> > > +		 * Used when @type ==
> > > DRM_XE_VMA_ATTR_PREFERRED_LOC
> > > +		 *
> > > +		 * Supported values for
> > > @preferred_mem_loc.devmem_fd:
> > > +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE: set vram
> > > of faulting tile as preferred loc
> > > +		 * - DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM: set smem
> > > as preferred loc
> > > +		 *
> > > +		 * Supported values for
> > > @preferred_mem_loc.migration_policy:
> > > +		 * - DRM_XE_MIGRATE_ALL_PAGES
> > > +		 * - DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES
> > > +		 */
> > > +		struct {
> > > +#define DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE	0
> > > +#define DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM	-1
> > > +			/** @preferred_mem_loc.devmem_fd: fd for
> > > preferred loc */
> > > +			__u32 devmem_fd;
> > > +
> > > +#define DRM_XE_MIGRATE_ALL_PAGES		0
> > > +#define DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES	1
> > 
> > I'd double check with Thomas / maintainers if they want this
> > (migration_policy)
> > to be included in this version as still more or less unused in this
> > series.
> > 
> > > +			/** @preferred_mem_loc.migration_policy:
> > > Page migration policy */
> > > +			__u32 migration_policy;
> > 
> > Could we future proof a little, maybe migration_policy is a __u16 (or
> > __u8?) and
> > stick a reserved __u16 in here?
> > 
> > Matt
> 
> Yeah, I think we need to have a strategy for extensions here. Perhaps
> we could add new madvise types by extending the union and add
> additional types, but then I think we need to expand the union size to
> accomodate reasonable future additions.
> 

I agree that adding some extra bits in the member for the union is a
reasonable idea. Maybe add an extra __u64 to each union member as well.

> Additions could also be made using extensions, so that if a suitable
> extension is present, the union is never used?
> 

Implementing this purely as extensions could work too.

That said, these two ideas are not mutually exclusive. I’d suggest
starting by adding some extra bits to the union, and if we later back
ourselves into a corner where there aren’t enough bits for a future
property, we can introduce an extension for that property if needed.

Matt

> /Thomas
> 
> 
> 
> > 
> > > +		} preferred_mem_loc;
> > > +	};
> > > +
> > > +	/** @reserved: Reserved */
> > > +	__u64 reserved[2];
> > > +};
> > > +
> > >  #if defined(__cplusplus)
> > >  }
> > >  #endif
> > > -- 
> > > 2.34.1
> > > 
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 00/20] MADVISE FOR XE
  2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
                   ` (26 preceding siblings ...)
  2025-06-16 15:06 ` ✗ Xe.CI.Full: failure " Patchwork
@ 2025-07-29  4:41 ` Matthew Brost
  2025-07-30 11:16   ` Ghimiray, Himal Prasad
  27 siblings, 1 reply; 68+ messages in thread
From: Matthew Brost @ 2025-07-29  4:41 UTC (permalink / raw)
  To: Himal Prasad Ghimiray; +Cc: intel-xe, thomas.hellstrom

On Fri, Jun 13, 2025 at 06:25:38PM +0530, Himal Prasad Ghimiray wrote:
> Provides a user API to assign attributes like pat_index, atomic
> operation type, and preferred location for SVM ranges.
> The Kernel Mode Driver (KMD) may split existing VMAs to cover input
> ranges, assign user-provided attributes, and invalidate existing PTEs so
> that the next page fault/prefetch can use the new attributes.
> 
> -v4:
> fix atomic policies
> fix attribute copy
> address review comments
> 

We are getting real close to this being fully reviewed, so I think we
need a UMD PR for this ASAP.

Matt

> Himal Prasad Ghimiray (20):
>   Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops
>   drm/xe/uapi: Add madvise interface
>   drm/xe/vm: Add attributes struct as member of vma
>   drm/xe/vma: Move pat_index to vma attributes
>   drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as
>     parameter
>   drm/gpusvm: Make drm_gpusvm_for_each_* macros public
>   drm/xe/svm: Split system allocator vma incase of madvise call
>   drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping
>   drm/xe: Implement madvise ioctl for xe
>   drm/xe/vm: Add an identifier for madvise in xe_vma_ops
>   drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for
>     madvise
>   drm/xe/svm : Add svm ranges migration policy on atomic access
>   drm/xe/madvise: Update migration policy based on preferred location
>   drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute
>   drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch
>   drm/xe/svm: Consult madvise preferred location in prefetch
>   drm/xe/bo: Add attributes field to xe_bo
>   drm/xe/bo: Update atomic_access attribute on madvise
>   drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
>   drm/xe/madvise: Skip vma invalidation if mem attr are unchanged
> 
>  drivers/gpu/drm/drm_gpusvm.c           | 122 ++------
>  drivers/gpu/drm/drm_gpuvm.c            |  93 ++++--
>  drivers/gpu/drm/nouveau/nouveau_uvmm.c |   1 +
>  drivers/gpu/drm/xe/Makefile            |   1 +
>  drivers/gpu/drm/xe/xe_bo.c             |  21 +-
>  drivers/gpu/drm/xe/xe_bo_types.h       |   8 +
>  drivers/gpu/drm/xe/xe_device.c         |   3 +
>  drivers/gpu/drm/xe/xe_gt_pagefault.c   |   2 +-
>  drivers/gpu/drm/xe/xe_pt.c             |  25 +-
>  drivers/gpu/drm/xe/xe_svm.c            | 110 ++++++-
>  drivers/gpu/drm/xe/xe_svm.h            |  22 ++
>  drivers/gpu/drm/xe/xe_tile.h           |  18 ++
>  drivers/gpu/drm/xe/xe_vm.c             | 295 +++++++++++++++++--
>  drivers/gpu/drm/xe/xe_vm.h             |   6 +-
>  drivers/gpu/drm/xe/xe_vm_madvise.c     | 389 +++++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_vm_madvise.h     |  15 +
>  drivers/gpu/drm/xe/xe_vm_types.h       |  38 ++-
>  include/drm/drm_gpusvm.h               |  70 +++++
>  include/drm/drm_gpuvm.h                |  25 +-
>  include/uapi/drm/xe_drm.h              | 253 ++++++++++++++++
>  20 files changed, 1368 insertions(+), 149 deletions(-)
>  create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
>  create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h
> 
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v4 00/20] MADVISE FOR XE
  2025-07-29  4:41 ` [PATCH v4 00/20] MADVISE FOR XE Matthew Brost
@ 2025-07-30 11:16   ` Ghimiray, Himal Prasad
  0 siblings, 0 replies; 68+ messages in thread
From: Ghimiray, Himal Prasad @ 2025-07-30 11:16 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe, thomas.hellstrom



On 29-07-2025 10:11, Matthew Brost wrote:
> On Fri, Jun 13, 2025 at 06:25:38PM +0530, Himal Prasad Ghimiray wrote:
>> Provides a user API to assign attributes like pat_index, atomic
>> operation type, and preferred location for SVM ranges.
>> The Kernel Mode Driver (KMD) may split existing VMAs to cover input
>> ranges, assign user-provided attributes, and invalidate existing PTEs so
>> that the next page fault/prefetch can use the new attributes.
>>
>> -v4:
>> fix atomic policies
>> fix attribute copy
>> address review comments
>>
> 
> We are getting real close to this being fully reviewed, so I think we
> need a UMD PR for this ASAP.

Sure

> 
> Matt
> 
>> Himal Prasad Ghimiray (20):
>>    Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops
>>    drm/xe/uapi: Add madvise interface
>>    drm/xe/vm: Add attributes struct as member of vma
>>    drm/xe/vma: Move pat_index to vma attributes
>>    drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as
>>      parameter
>>    drm/gpusvm: Make drm_gpusvm_for_each_* macros public
>>    drm/xe/svm: Split system allocator vma incase of madvise call
>>    drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping
>>    drm/xe: Implement madvise ioctl for xe
>>    drm/xe/vm: Add an identifier for madvise in xe_vma_ops
>>    drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for
>>      madvise
>>    drm/xe/svm : Add svm ranges migration policy on atomic access
>>    drm/xe/madvise: Update migration policy based on preferred location
>>    drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute
>>    drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch
>>    drm/xe/svm: Consult madvise preferred location in prefetch
>>    drm/xe/bo: Add attributes field to xe_bo
>>    drm/xe/bo: Update atomic_access attribute on madvise
>>    drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
>>    drm/xe/madvise: Skip vma invalidation if mem attr are unchanged
>>
>>   drivers/gpu/drm/drm_gpusvm.c           | 122 ++------
>>   drivers/gpu/drm/drm_gpuvm.c            |  93 ++++--
>>   drivers/gpu/drm/nouveau/nouveau_uvmm.c |   1 +
>>   drivers/gpu/drm/xe/Makefile            |   1 +
>>   drivers/gpu/drm/xe/xe_bo.c             |  21 +-
>>   drivers/gpu/drm/xe/xe_bo_types.h       |   8 +
>>   drivers/gpu/drm/xe/xe_device.c         |   3 +
>>   drivers/gpu/drm/xe/xe_gt_pagefault.c   |   2 +-
>>   drivers/gpu/drm/xe/xe_pt.c             |  25 +-
>>   drivers/gpu/drm/xe/xe_svm.c            | 110 ++++++-
>>   drivers/gpu/drm/xe/xe_svm.h            |  22 ++
>>   drivers/gpu/drm/xe/xe_tile.h           |  18 ++
>>   drivers/gpu/drm/xe/xe_vm.c             | 295 +++++++++++++++++--
>>   drivers/gpu/drm/xe/xe_vm.h             |   6 +-
>>   drivers/gpu/drm/xe/xe_vm_madvise.c     | 389 +++++++++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_vm_madvise.h     |  15 +
>>   drivers/gpu/drm/xe/xe_vm_types.h       |  38 ++-
>>   include/drm/drm_gpusvm.h               |  70 +++++
>>   include/drm/drm_gpuvm.h                |  25 +-
>>   include/uapi/drm/xe_drm.h              | 253 ++++++++++++++++
>>   20 files changed, 1368 insertions(+), 149 deletions(-)
>>   create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
>>   create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h
>>
>> -- 
>> 2.34.1
>>


^ permalink raw reply	[flat|nested] 68+ messages in thread

end of thread, other threads:[~2025-07-30 11:16 UTC | newest]

Thread overview: 68+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-13 12:55 [PATCH v4 00/20] MADVISE FOR XE Himal Prasad Ghimiray
2025-06-13 12:43 ` ✗ CI.checkpatch: warning for MADVISE FOR XE (rev2) Patchwork
2025-06-13 12:44 ` ✗ CI.KUnit: failure " Patchwork
2025-06-13 12:55 ` [PATCH v4 01/20] Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops Himal Prasad Ghimiray
2025-06-13 12:55 ` [PATCH v4 02/20] drm/xe/uapi: Add madvise interface Himal Prasad Ghimiray
2025-06-13 14:15   ` Souza, Jose
2025-06-23  4:30   ` Matthew Brost
2025-06-23  6:20     ` Ghimiray, Himal Prasad
2025-06-27 13:47       ` Thomas Hellström
2025-06-27 14:29     ` Thomas Hellström
2025-06-27 18:13       ` Matthew Brost
2025-06-13 12:55 ` [PATCH v4 03/20] drm/xe/vm: Add attributes struct as member of vma Himal Prasad Ghimiray
2025-06-23  4:18   ` Matthew Brost
2025-06-23  6:21     ` Ghimiray, Himal Prasad
2025-06-27 14:32     ` Thomas Hellström
2025-06-13 12:55 ` [PATCH v4 04/20] drm/xe/vma: Move pat_index to vma attributes Himal Prasad Ghimiray
2025-06-13 12:55 ` [PATCH v4 05/20] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter Himal Prasad Ghimiray
2025-06-23  4:38   ` Matthew Brost
2025-06-23 16:21     ` Matthew Brost
2025-06-13 12:55 ` [PATCH v4 06/20] drm/gpusvm: Make drm_gpusvm_for_each_* macros public Himal Prasad Ghimiray
2025-06-13 12:55 ` [PATCH v4 07/20] drm/xe/svm: Split system allocator vma incase of madvise call Himal Prasad Ghimiray
2025-06-13 12:55 ` [PATCH v4 08/20] drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping Himal Prasad Ghimiray
2025-06-23  4:56   ` Matthew Brost
2025-06-23  6:25     ` Ghimiray, Himal Prasad
2025-06-13 12:55 ` [PATCH v4 09/20] drm/xe: Implement madvise ioctl for xe Himal Prasad Ghimiray
2025-06-23  5:33   ` Matthew Brost
2025-06-26  6:04   ` Lin, Shuicheng
2025-06-26  6:15     ` Matthew Brost
2025-06-26  8:36       ` Ghimiray, Himal Prasad
2025-06-26  8:34     ` Ghimiray, Himal Prasad
2025-06-13 12:55 ` [PATCH v4 10/20] drm/xe/vm: Add an identifier for madvise in xe_vma_ops Himal Prasad Ghimiray
2025-06-23  5:38   ` Matthew Brost
2025-06-23  6:28     ` Ghimiray, Himal Prasad
2025-06-13 12:55 ` [PATCH v4 11/20] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise Himal Prasad Ghimiray
2025-06-14  4:31   ` kernel test robot
2025-06-23  5:52   ` Matthew Brost
2025-06-23  6:18     ` Ghimiray, Himal Prasad
2025-06-23 11:45       ` Matthew Brost
2025-06-13 12:55 ` [PATCH v4 12/20] drm/xe/svm : Add svm ranges migration policy on atomic access Himal Prasad Ghimiray
2025-06-23 16:32   ` Matthew Brost
2025-06-13 12:55 ` [PATCH v4 13/20] drm/xe/madvise: Update migration policy based on preferred location Himal Prasad Ghimiray
2025-06-13 23:31   ` kernel test robot
2025-06-14  5:33   ` kernel test robot
2025-06-13 12:55 ` [PATCH v4 14/20] drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute Himal Prasad Ghimiray
2025-06-23 16:34   ` Matthew Brost
2025-06-13 12:55 ` [PATCH v4 15/20] drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch Himal Prasad Ghimiray
2025-06-23 16:36   ` Matthew Brost
2025-06-13 12:55 ` [PATCH v4 16/20] drm/xe/svm: Consult madvise preferred location in prefetch Himal Prasad Ghimiray
2025-06-23 22:07   ` Matthew Brost
2025-06-13 12:55 ` [PATCH v4 17/20] drm/xe/bo: Add attributes field to xe_bo Himal Prasad Ghimiray
2025-06-13 12:55 ` [PATCH v4 18/20] drm/xe/bo: Update atomic_access attribute on madvise Himal Prasad Ghimiray
2025-06-23 16:19   ` Matthew Brost
2025-06-13 12:55 ` [PATCH v4 19/20] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes Himal Prasad Ghimiray
2025-06-23 22:43   ` Matthew Brost
2025-06-24  2:18   ` Matthew Brost
2025-06-27 13:20     ` Thomas Hellström
2025-06-27 13:43     ` Thomas Hellström
2025-06-26  3:44   ` Lin, Shuicheng
2025-06-13 12:55 ` [PATCH v4 20/20] drm/xe/madvise: Skip vma invalidation if mem attr are unchanged Himal Prasad Ghimiray
2025-06-23 22:28   ` Matthew Brost
2025-06-26  8:54     ` Ghimiray, Himal Prasad
2025-06-16  4:30 ` ✗ CI.checkpatch: warning for MADVISE FOR XE (rev3) Patchwork
2025-06-16  4:31 ` ✓ CI.KUnit: success " Patchwork
2025-06-16  4:45 ` ✗ CI.checksparse: warning " Patchwork
2025-06-16  5:13 ` ✓ Xe.CI.BAT: success " Patchwork
2025-06-16 15:06 ` ✗ Xe.CI.Full: failure " Patchwork
2025-07-29  4:41 ` [PATCH v4 00/20] MADVISE FOR XE Matthew Brost
2025-07-30 11:16   ` Ghimiray, Himal Prasad

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox