From: Matthew Brost <matthew.brost@intel.com>
To: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Cc: intel-xe@lists.freedesktop.org,
"Thomas Hellström" <thomas.hellstrom@linux.intel.com>,
"Shuicheng Lin" <shuicheng.lin@intel.com>
Subject: Re: [PATCH v5 25/25] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes
Date: Tue, 5 Aug 2025 12:29:51 -0700 [thread overview]
Message-ID: <aJJbr/TSuv4ae13m@lstrano-desk.jf.intel.com> (raw)
In-Reply-To: <20250730130050.1001648-26-himal.prasad.ghimiray@intel.com>
On Wed, Jul 30, 2025 at 06:30:50PM +0530, Himal Prasad Ghimiray wrote:
> Introduce the DRM_IOCTL_XE_VM_QUERY_MEMORY_RANGE_ATTRS ioctl to allow
> userspace to query memory attributes of VMAs within a user specified
> virtual address range.
>
> Userspace first calls the ioctl with num_mem_ranges = 0,
> sizeof_mem_ranges_attr = 0 and vector_of_vma_mem_attr = NULL to retrieve
> the number of memory ranges (vmas) and size of each memory range attribute.
> Then, it allocates a buffer of that size and calls the ioctl again to fill
> the buffer with memory range attributes.
>
> 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
>
> v4
> - Make uapi future proof by passing struct size (Matthew Brost)
> - make lock interruptible (Matthew Brost)
> - set reserved bits to zero (Matthew Brost)
> - s/__copy_to_user/copy_to_user (Matthew Brost)
> - Avod using VMA term in uapi (Thomas)
> - xe_vm_put(vm) is missing (Shuicheng)
>
> v5
> - Nits
> - Fix kernel-doc
>
> Cc: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
> Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> ---
> drivers/gpu/drm/xe/xe_device.c | 2 +
> drivers/gpu/drm/xe/xe_vm.c | 102 ++++++++++++++++++++++++
> drivers/gpu/drm/xe/xe_vm.h | 2 +-
> include/uapi/drm/xe_drm.h | 139 +++++++++++++++++++++++++++++++++
> 4 files changed, 244 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 80a77488381a..1e4334f8bdf4 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -203,6 +203,8 @@ 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_MEM_RANGE_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 e77c04f92d0b..a3ca3041e812 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -2171,6 +2171,108 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data,
> return err;
> }
>
> +static int xe_vm_query_vmas(struct xe_vm *vm, u64 start, u64 end)
> +{
> + struct drm_gpuva *gpuva;
> + u32 num_vmas = 0;
> +
> + lockdep_assert_held(&vm->lock);
> + drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end)
> + num_vmas++;
> +
> + return num_vmas;
> +}
> +
> +static int get_mem_attrs(struct xe_vm *vm, u32 *num_vmas, u64 start,
> + u64 end, struct drm_xe_mem_range_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 -ENOSPC;
> +
> + 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++;
> + }
> +
> + *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_mem_range_attr *mem_attrs;
> + struct drm_xe_vm_query_mem_range_attr *args = data;
> + u64 __user *attrs_user = u64_to_user_ptr(args->vector_of_mem_attr);
> + struct xe_vm *vm;
> + int err = 0;
> +
> + if (XE_IOCTL_DBG(xe,
> + ((args->num_mem_ranges == 0 &&
> + (attrs_user || args->sizeof_mem_range_attr != 0)) ||
> + (args->num_mem_ranges > 0 &&
> + (!attrs_user ||
> + args->sizeof_mem_range_attr !=
> + sizeof(struct drm_xe_mem_range_attr))))))
> + return -EINVAL;
> +
> + vm = xe_vm_lookup(xef, args->vm_id);
> + if (XE_IOCTL_DBG(xe, !vm))
> + return -EINVAL;
> +
> + err = down_read_interruptible(&vm->lock);
> + if (err)
> + goto put_vm;
> +
> + attrs_user = u64_to_user_ptr(args->vector_of_mem_attr);
> +
> + if (args->num_mem_ranges == 0 && !attrs_user) {
> + args->num_mem_ranges = xe_vm_query_vmas(vm, args->start, args->start + args->range);
> + args->sizeof_mem_range_attr = sizeof(struct drm_xe_mem_range_attr);
> + goto unlock_vm;
> + }
> +
> + mem_attrs = kvmalloc_array(args->num_mem_ranges, args->sizeof_mem_range_attr,
> + GFP_KERNEL | __GFP_ACCOUNT |
> + __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
> + if (!mem_attrs) {
> + err = args->num_mem_ranges > 1 ? -ENOBUFS : -ENOMEM;
> + goto unlock_vm;
> + }
> +
> + memset(mem_attrs, 0, args->num_mem_ranges * args->sizeof_mem_range_attr);
> + err = get_mem_attrs(vm, &args->num_mem_ranges, args->start,
> + args->start + args->range, mem_attrs);
> + if (err)
> + goto free_mem_attrs;
> +
> + err = copy_to_user(attrs_user, mem_attrs,
> + args->sizeof_mem_range_attr * args->num_mem_ranges);
> +
> +free_mem_attrs:
> + kvfree(mem_attrs);
> +unlock_vm:
> + up_read(&vm->lock);
> +put_vm:
> + xe_vm_put(vm);
> + 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 6538cddf158b..3953b3ee2955 100644
> --- a/drivers/gpu/drm/xe/xe_vm.h
> +++ b/drivers/gpu/drm/xe/xe_vm.h
> @@ -199,7 +199,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 115b9bca2a25..6b03f319ab70 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_MEM_RANGE_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_MEM_RANGE_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_MEM_RANGE_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_MEM_RANGE_ATTRS, struct drm_xe_vm_query_mem_range_attr)
>
> /**
> * DOC: Xe IOCTL Extensions
> @@ -2113,6 +2116,142 @@ struct drm_xe_madvise {
> __u64 reserved[2];
> };
>
> +/**
> + * struct drm_xe_mem_range_attr - Output of &DRM_IOCTL_XE_VM_QUERY_MEM_RANGES_ATTRS
> + *
> + * This structure is provided by userspace and filled by KMD in response to the
> + * DRM_IOCTL_XE_VM_QUERY_MEM_RANGES_ATTRS ioctl. It describes memory attributes of
> + * a memory ranges within a user specified address range in a VM.
> + *
> + * The structure includes information such as atomic access policy,
> + * 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 memory ranges
> + *
> + * @extensions: Pointer to the first extension struct, if any
> + * @start: Start address of the memory range
> + * @end: End address of the virtual memory range
> + *
> + */
> +struct drm_xe_mem_range_attr {
> + /** @extensions: Pointer to the first extension struct, if any */
> + __u64 extensions;
> +
> + /** @start: start of the memory range */
> + __u64 start;
> +
> + /** @end: end of the memory range */
> + __u64 end;
> +
> + /** @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;
> +
> + /** * @atomic: Atomic access policy */
> + struct {
> + /** @atomic.val: atomic attribute */
> + __u32 val;
> +
> + /** @atomic.reserved: Reserved */
> + __u32 reserved;
> + } atomic;
> +
> + /** @pat_index: Page attribute table index */
> + struct {
> + /** @pat_index.val: PAT index */
> + __u32 val;
> +
> + /** @pat_index.reserved: Reserved */
> + __u32 reserved;
> + } pat_index;
> +
> + /** @reserved: Reserved */
> + __u64 reserved[2];
> +};
> +
> +/**
> + * struct drm_xe_vm_query_mem_range_attr - Input of &DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES
> + *
> + * This structure is used to query memory attributes of memory regions
> + * within a user specified address range in a VM. It provides detailed
> + * information about each memory range, including atomic access policy,
> + * page attribute table (PAT) index, and preferred memory location.
> + *
> + * Userspace first calls the ioctl with @num_mem_ranges = 0,
> + * @sizeof_mem_ranges_attr = 0 and @vector_of_vma_mem_attr = NULL to retrieve
> + * the number of memory regions and size of each memory range attribute.
> + * Then, it allocates a buffer of that size and calls the ioctl again to fill
> + * the buffer with memory range attributes.
> + *
> + * If second call fails with -ENOSPC, it means memory ranges changed between
> + * first call and now, retry IOCTL again with @num_mem_ranges = 0,
> + * @sizeof_mem_ranges_attr = 0 and @vector_of_vma_mem_attr = NULL followed by
> + * Second ioctl call.
> + *
> + * Example:
> + *
> + * .. code-block:: C
> + * struct drm_xe_vm_query_mem_range_attr query = {
> + * .vm_id = vm_id,
> + * .start = 0x100000,
> + * .range = 0x2000,
> + * };
> + *
> + * // First ioctl call to get num of mem regions and sizeof each attribute
> + * ioctl(fd, DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS, &query);
> + *
> + * // Allocate buffer for the memory region attributes
> + * void *ptr = malloc(query.num_mem_ranges * query.sizeof_mem_range_attr);
> + *
> + * query.vector_of_mem_attr = (uintptr_t)ptr;
> + *
> + * // Second ioctl call to actually fill the memory attributes
> + * ioctl(fd, DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS, &query);
> + *
> + * // Iterate over the returned memory region attributes
> + * for (unsigned int i = 0; i < query.num_mem_ranges; ++i) {
> + * struct drm_xe_mem_range_attr *attr = (struct drm_xe_mem_range_attr *)ptr;
> + *
> + * // Do something with attr
> + *
> + * // Move pointer by one entry
> + * ptr += query.sizeof_mem_range_attr;
> + * }
> + *
> + * free(ptr);
> + */
> +struct drm_xe_vm_query_mem_range_attr {
> + /** @extensions: Pointer to the first extension struct, if any */
> + __u64 extensions;
> +
> + /** @vm_id: vm_id of the virtual range */
> + __u32 vm_id;
> +
> + /** @num_mem_ranges: number of mem_ranges in range */
> + __u32 num_mem_ranges;
> +
> + /** @start: start of the virtual address range */
> + __u64 start;
> +
> + /** @range: size of the virtual address range */
> + __u64 range;
> +
> + /** @sizeof_mem_range_attr: size of struct drm_xe_mem_range_attr */
> + __u64 sizeof_mem_range_attr;
> +
> + /** @vector_of_mem_attr: userptr to array of struct drm_xe_mem_range_attr */
> + __u64 vector_of_mem_attr;
> +
> + /** @reserved: Reserved */
> + __u64 reserved[2];
> +
> +};
> +
> #if defined(__cplusplus)
> }
> #endif
> --
> 2.34.1
>
next prev parent reply other threads:[~2025-08-05 19:30 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-30 13:00 [PATCH v5 00/25] MADVISE FOR XE Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 01/25] drm/gpuvm: Pass map arguments through a struct Himal Prasad Ghimiray
2025-07-30 23:23 ` kernel test robot
2025-08-05 3:56 ` Matthew Brost
2025-08-05 5:24 ` Ghimiray, Himal Prasad
2025-08-05 10:10 ` Danilo Krummrich
2025-08-05 11:04 ` Ghimiray, Himal Prasad
2025-08-05 9:40 ` Danilo Krummrich
2025-08-05 11:02 ` Ghimiray, Himal Prasad
2025-07-30 13:00 ` [PATCH v5 02/25] drm/gpuvm: Kill drm_gpuva_init() Himal Prasad Ghimiray
2025-08-05 3:45 ` Matthew Brost
2025-08-05 9:35 ` Danilo Krummrich
2025-07-30 13:00 ` [PATCH v5 03/25] drm/gpuvm: Support flags in drm_gpuva_op_map Himal Prasad Ghimiray
2025-08-05 3:58 ` Matthew Brost
2025-08-05 11:05 ` Ghimiray, Himal Prasad
2025-07-30 13:00 ` [PATCH v5 04/25] drm/gpuvm: Introduce DRM_GPUVM_SM_MAP_OPS_FLAG_SPLIT_MADVISE flag Himal Prasad Ghimiray
2025-08-05 19:24 ` Matthew Brost
2025-07-30 13:00 ` [PATCH v5 05/25] drm/xe/uapi: Add madvise interface Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 06/25] drm/xe/vm: Add attributes struct as member of vma Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 07/25] drm/xe/vma: Move pat_index to vma attributes Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 08/25] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 09/25] drm/gpusvm: Make drm_gpusvm_for_each_* macros public Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 10/25] drm/xe/svm: Split system allocator vma incase of madvise call Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 11/25] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise Himal Prasad Ghimiray
2025-08-05 4:00 ` Matthew Brost
2025-07-30 13:00 ` [PATCH v5 12/25] drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 13/25] drm/xe: Implement madvise ioctl for xe Himal Prasad Ghimiray
2025-08-05 4:43 ` Matthew Brost
2025-07-30 13:00 ` [PATCH v5 14/25] drm/xe/svm : Add svm ranges migration policy on atomic access Himal Prasad Ghimiray
2025-08-05 20:03 ` Matthew Brost
2025-08-06 5:30 ` Ghimiray, Himal Prasad
2025-08-05 20:10 ` Matthew Brost
2025-08-06 5:29 ` Ghimiray, Himal Prasad
2025-07-30 13:00 ` [PATCH v5 15/25] drm/xe/madvise: Update migration policy based on preferred location Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 16/25] drm/xe/svm: Support DRM_XE_SVM_MEM_RANGE_ATTR_PAT memory attribute Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 17/25] drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 18/25] drm/xe/svm: Consult madvise preferred location in prefetch Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 19/25] drm/xe/bo: Add attributes field to xe_bo Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 20/25] drm/xe/bo: Update atomic_access attribute on madvise Himal Prasad Ghimiray
2025-08-05 20:06 ` Matthew Brost
2025-07-30 13:00 ` [PATCH v5 21/25] drm/xe/madvise: Skip vma invalidation if mem attr are unchanged Himal Prasad Ghimiray
2025-07-30 20:57 ` kernel test robot
2025-07-30 13:00 ` [PATCH v5 22/25] drm/xe/vm: Add helper to check for default VMA memory attributes Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 23/25] drm/xe: Reset VMA attributes to default in SVM garbage collector Himal Prasad Ghimiray
2025-08-06 4:06 ` Matthew Brost
2025-08-06 5:32 ` Ghimiray, Himal Prasad
2025-07-30 13:00 ` [PATCH v5 24/25] drm/xe: Enable madvise ioctl for xe Himal Prasad Ghimiray
2025-07-30 13:00 ` [PATCH v5 25/25] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes Himal Prasad Ghimiray
2025-08-05 19:29 ` Matthew Brost [this message]
2025-07-30 14:20 ` ✗ CI.checkpatch: warning for MADVISE FOR XE (rev5) Patchwork
2025-07-30 14:21 ` ✓ CI.KUnit: success " Patchwork
2025-07-30 14:36 ` ✗ CI.checksparse: warning " Patchwork
2025-07-30 15:36 ` ✓ Xe.CI.BAT: success " Patchwork
2025-07-30 17:51 ` ✗ Xe.CI.Full: failure " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aJJbr/TSuv4ae13m@lstrano-desk.jf.intel.com \
--to=matthew.brost@intel.com \
--cc=himal.prasad.ghimiray@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=shuicheng.lin@intel.com \
--cc=thomas.hellstrom@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.