STRUCT DRM_XE_VM_QUERY_MEM_RANGE_ATTR(9)
β¨ 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 beNULL. πvm_idβ thevm_idof the virtual range. which VM are we snooping on, bestie?num_mem_rangesβ how manymem_rangesare 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 ofstruct drm_xe_mem_range_attr. the kernel tells you this, you don't guess it. πvector_of_mem_attrβ userptr to an array ofstruct 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):
- Userspace first calls the ioctl with
num_mem_ranges = 0,sizeof_mem_range_attr = 0andvector_of_mem_attr = NULLto retrieve the number of memory regions and the size of each memory range attribute. - 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 withnum_mem_ranges = 0,sizeof_mem_range_attr = 0andvector_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
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms