STRUCT DRM_XE_VM_QUERY_MEM_RANGE_ATTR(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

✨ struct drm_xe_vm_query_mem_range_attr(9) ✨

okay bestie, pull up a chair πŸ’… this one lives in the Kernel API Manual (the 9 at the end is the manual section, iykyk). It's a struct β€” a little info packet β€” and it's the input you hand to &DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS. Basically you're asking the kernel "hey what's the tea on the memory in this address range of my VM?" πŸ«–


🌸 NAME 🌸

struct drm_xe_vm_query_mem_range_attr β€” the input of &DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS. That's it, that's the vibe. ✨


πŸŽ€ SYNOPSIS πŸŽ€

struct drm_xe_vm_query_mem_range_attr {
    __u64 extensions;
    __u32 vm_id;
    __u32 num_mem_ranges;
    __u64 start;
    __u64 range;
    __u64 sizeof_mem_range_attr;
    __u64 vector_of_mem_attr;
    __u64 reserved[2];
 };

look at her. iconic struct. no notes. πŸ’–


πŸ¦‹ Members πŸ¦‹

  • extensions β€” pointer to the first extension struct, if there is one. optional queen, can be NULL. πŸ‘‘
  • vm_id β€” the vm_id of the virtual range. which VM are we snooping on, bestie?
  • num_mem_ranges β€” how many mem_ranges are in the range. the headcount.
  • start β€” start of the virtual address range. where the story begins.
  • range β€” size of the virtual address range. how far we're going.
  • sizeof_mem_range_attr β€” size of struct drm_xe_mem_range_attr. the kernel tells you this, you don't guess it. πŸ™ˆ
  • vector_of_mem_attr β€” userptr to an array of struct drm_xe_mem_range_attr. your buffer, your rules (well, mostly the kernel's rules).
  • reserved β€” reserved. don't touch, not for you, leave it alone πŸ’€

πŸ’œ Description πŸ’œ

So this structure is the whole reason you're here: it's what you use to query memory attributes of memory regions inside a user-specified address range in a VM. It hands back the detailed info on each memory range β€” and when we say detailed we mean the atomic access policy, the page attribute table (PAT) index, and the preferred memory location. all the good stuff. πŸ”₯

Now, the two-step dance (learn it, love it):

  1. Userspace first calls the ioctl with num_mem_ranges = 0, sizeof_mem_range_attr = 0 and vector_of_mem_attr = NULL to retrieve the number of memory regions and the size of each memory range attribute.
  2. Then it allocates a buffer of that size and calls the ioctl again to fill the buffer with the memory range attributes.
and here's the plot twist 😭 if the second call fails with -ENOSPC, it means the memory ranges changed between the first call and now. no cap. so you retry the IOCTL again with num_mem_ranges = 0, sizeof_mem_range_attr = 0 and vector_of_mem_attr = NULL, followed by the second ioctl call. round two, bestie.

🌈 Example 🌈

here's the whole routine, doing the two-step like a pro 🧚

   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);
   void *ptr_start = ptr;

   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_start);

notice ptr_start? yeah β€” you keep the original pointer around so free doesn't get confused once ptr has been scooted along. that's the self-care. 🫢


⭐ SEE ALSO ⭐

the whole friend group, fr fr. also the kernel file ./include/uapi/drm/xe_drm.h:

  • Xe Device Block Diagram(9)
  • Xe uAPI Overview(9)
  • Xe IOCTL Extensions(9)
  • struct drm_xe_user_extension(9)
  • struct drm_xe_ext_set_property(9)
  • struct drm_xe_engine_class_instance(9)
  • struct drm_xe_engine(9)
  • struct drm_xe_query_engines(9)
  • enum drm_xe_memory_class(9)
  • struct drm_xe_mem_region(9)
  • struct drm_xe_query_mem_regions(9)
  • struct drm_xe_query_config(9)
  • struct drm_xe_gt(9)
  • struct drm_xe_query_gt_list(9)
  • struct drm_xe_query_topology_mask(9)
  • struct drm_xe_query_engine_cycles(9)
  • struct drm_xe_query_uc_fw_version(9)
  • struct drm_xe_query_pxp_status(9)
  • struct drm_xe_device_query(9)
  • struct drm_xe_gem_create(9)
  • struct drm_xe_gem_mmap_offset(9)
  • struct drm_xe_vm_create(9)
  • struct drm_xe_vm_destroy(9)
  • struct drm_xe_vm_bind_op(9)
  • struct drm_xe_vm_bind(9)
  • struct drm_xe_vm_get_property(9)
  • struct drm_xe_exec_queue_create(9)
  • struct drm_xe_exec_queue_destroy(9)
  • struct drm_xe_exec_queue_get_property(9)
  • struct drm_xe_sync(9)
  • struct drm_xe_exec(9)
  • struct drm_xe_wait_user_fence(9)
  • enum drm_xe_observation_type(9)
  • enum drm_xe_observation_op(9)
  • struct drm_xe_observation_param(9)
  • enum drm_xe_observation_ioctls(9)
  • enum drm_xe_oa_unit_type(9)
  • struct drm_xe_oa_unit(9)
  • struct drm_xe_query_oa_units(9)
  • enum drm_xe_oa_format_type(9)
  • enum drm_xe_oa_property_id(9)
  • struct drm_xe_oa_config(9)
  • struct drm_xe_oa_stream_status(9)
  • struct drm_xe_oa_stream_info(9)
  • enum drm_xe_pxp_session_type(9)
  • enum drm_xe_eu_stall_property_id(9)
  • struct drm_xe_query_eu_stall(9)
  • struct drm_xe_madvise(9)
  • struct drm_xe_mem_range_attr(9)
  • struct drm_xe_exec_queue_set_property(9)
  • Xe DRM RAS(9)
  • enum drm_xe_ras_error_severity(9)
  • enum drm_xe_ras_error_component(9)

okay that's the whole page πŸ’– this one came from ./include/uapi/drm, dated October 2026 β€” and yes the header/footer was doing that cute little ellipsis thing (struct drm_...m_range_attr(9)) because the title doesn't fit the terminal. slay. go query your memory ranges, bestie, you've got this πŸŒŸπŸŽ€

πŸ“¦ where this page comes from