STRUCT DRM_XE_MADVISE(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct drm_xe_madvise(9) β€” like, the whole vibe check on DRM_IOCTL_XE_MADVISE

okay so bestie, this page lives in the Kernel API Manual, and it's literally all about struct drm_xe_madvise β€” the input struct for &DRM_IOCTL_XE_MADVISE. it's giving "tell the kernel how you feel about a chunk of your virtual address space" and honestly? iconic. πŸŽ€


✨ NAME ✨

struct drm_xe_madvise β€” the input of &DRM_IOCTL_XE_MADVISE 🫢


🌸 SYNOPSIS 🌸

no cap, here's the whole struct verbatim, every last byte:

struct drm_xe_madvise {
    __u64 extensions;
    __u64 start;
    __u64 range;
    __u32 vm_id;
  #define DRM_XE_MEM_RANGE_ATTR_PREFERRED_LOC     0;
  #define DRM_XE_MEM_RANGE_ATTR_ATOMIC            1;
  #define DRM_XE_MEM_RANGE_ATTR_PAT               2;
  #define DRM_XE_VMA_ATTR_PURGEABLE_STATE         3;
    __u32 type;
    union {
      struct {
  #define DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE     0;
  #define DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM     -1;
        __u32 devmem_fd;
  #define DRM_XE_MIGRATE_ALL_PAGES                0;
  #define DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES        1;
        __u16 migration_policy;
        __u16 region_instance;
        __u64 reserved;
      } preferred_mem_loc;
      struct {
  #define DRM_XE_ATOMIC_UNDEFINED 0;
  #define DRM_XE_ATOMIC_DEVICE    1;
  #define DRM_XE_ATOMIC_GLOBAL    2;
  #define DRM_XE_ATOMIC_CPU       3;
        __u32 val;
        __u32 pad;
        __u64 reserved;
      } atomic;
      struct {
        __u32 val;
        __u32 pad;
        __u64 reserved;
      } pat_index;
      struct {
  #define DRM_XE_VMA_PURGEABLE_STATE_WILLNEED     0;
  #define DRM_XE_VMA_PURGEABLE_STATE_DONTNEED     1;
        __u32 val;
        __u32 pad;
        __u64 retained_ptr;
      } purge_state_val;
    };
    __u64 reserved[2];
 };

πŸ¦‹ Members πŸ¦‹

  • extensions β€” pointer to the first extension struct, if any. (yes, "if any" β€” you can literally just not. πŸ’…)
  • start β€” where the virtual address range starts.
  • range β€” how big that virtual address range is.
  • vm_id β€” the vm_id of the virtual range, iykyk.
  • type β€” which kind of attribute you're setting. this is the main character field, fr fr.
  • {unnamed_union} β€” anonymous. mysterious. no name, all vibes. 🌈

πŸ’œ preferred_mem_loc β€” preferred memory location

Only used when type == DRM_XE_MEM_RANGE_ATTR_PREFERRED_LOC. 🎯

Supported values for preferred_mem_loc.devmem_fd:

  • DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE: sets vram of the fault tile as the preferred loc
  • DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM: sets smem as the preferred loc

Supported values for preferred_mem_loc.migration_policy:

  • DRM_XE_MIGRATE_ALL_PAGES
  • DRM_XE_MIGRATE_ONLY_SYSTEM_PAGES

the little fields inside it

  • preferred_mem_loc.devmem_fd β€” device file-descriptor of the device where the preferred memory lives, or one of the special values up there ⬆️. also pls pls pls see preferred_mem_loc.region_instance right below, they're a package deal.
  • preferred_mem_loc.migration_policy β€” the page migration policy. that's it, that's the whole thing.
  • preferred_mem_loc.region_instance β€” region instance. MBZ if devmem_fd <= DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE. otherwise it should point to the desired device VRAM instance of the device indicated by preferred_mem_loc.devmem_fd. πŸ‘‘
  • preferred_mem_loc.reserved β€” reserved. hands off. 🚫

πŸ”₯ atomic β€” atomic access policy

Used when type == DRM_XE_MEM_RANGE_ATTR_ATOMIC. βš›οΈ

Supported values for atomic.val:

  • DRM_XE_ATOMIC_UNDEFINED: undefined or default behaviour. supports both GPU and CPU atomic operations for the system allocator. supports GPU atomic operations for the normal(bo) allocator.
  • DRM_XE_ATOMIC_DEVICE: supports GPU atomic operations.
  • DRM_XE_ATOMIC_GLOBAL: supports both GPU and CPU atomic operations.
  • DRM_XE_ATOMIC_CPU: supports CPU atomic only, no GPU atomics supported. (CPU said "I got this" πŸ’€)

fields

  • atomic.val β€” value of the atomic operation.
  • atomic.pad β€” MBZ.
  • atomic.reserved β€” reserved.

πŸŽ€ pat_index β€” page attribute table index

Used when type == DRM_XE_MEM_RANGE_ATTR_PAT. πŸ“‡

  • pat_index.val β€” PAT index value.
  • pat_index.pad β€” MBZ.
  • pat_index.reserved β€” reserved.

🧚 purge_state_val β€” purgeable state configuration

Used when type == DRM_XE_VMA_ATTR_PURGEABLE_STATE. 🧹

This configures the purgeable state of buffer objects in the specified virtual address range β€” it lets applications hint to the kernel about a bo's usage patterns so memory management gets better. literally helping the kernel help you. 🫢

By default all VMAs are in WILLNEED state.

Supported values for purge_state_val.val:

  • DRM_XE_VMA_PURGEABLE_STATE_WILLNEED (0): marks the BO as needed. If the BO was previously purged, the kernel sets the __u32 at retained_ptr to 0 (backing store lost) so the application knows it must recreate the BO.
  • DRM_XE_VMA_PURGEABLE_STATE_DONTNEED (1): marks the BO as not currently needed. The kernel may purge it under memory pressure to reclaim memory. Only applies to non-shared BOs. The kernel sets the __u32 at retained_ptr to 1 if the backing store still exists (not yet purged), or 0 if it was already purged.
⚠️ Important, and I mean it bestie: once marked as DONTNEED, touching the BO's memory is undefined behavior. It may succeed temporarily (before the kernel purges the backing store) but will suddenly fail once the BO transitions to PURGED state. no cap, do not do this. 😭

To transition back: use WILLNEED and check retained_ptr β€” if it's 0, the backing store was lost and the BO must be recreated.

The following operations are blocked in DONTNEED state, to prevent the BO from being re-mapped after madvise:

  • New mmap calls: fail with -EBUSY
  • VM_BIND operations: fail with -EBUSY
  • New dma-buf exports: fail with -EBUSY
  • CPU page faults (existing mmap): fail with SIGBUS
  • GPU page faults (fault-mode VMs): fail with -EACCES

fields

  • purge_state_val.val β€” value for DRM_XE_VMA_ATTR_PURGEABLE_STATE.
  • purge_state_val.pad β€” MBZ.
  • purge_state_val.retained_ptr β€” pointer to a __u32 output field for backing store status.

Userspace must initialize the __u32 value at this address to 0 before the ioctl. the kernel writes a __u32 after the operation:

  • 1 if the backing store exists (not purged)
  • 0 if the backing store was purged

If userspace fails to initialize it to 0, the ioctl returns -EINVAL. this ensures a safe default (0 = assume purged) if the kernel cannot write the result. safety first, always. πŸ›Ÿ

Similar to i915's drm_i915_gem_madvise.retained field. (shoutout to the ancestor ✨)

🌟 reserved β€” reserved

reserved. not for you. πŸ™ˆ


⭐ Description ⭐

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. one struct, four personalities β€” pick your fighter. πŸ’…

Supported attribute types:

  • DRM_XE_MEM_RANGE_ATTR_PREFERRED_LOC: set preferred memory location.
  • DRM_XE_MEM_RANGE_ATTR_ATOMIC: set atomic access policy.
  • DRM_XE_MEM_RANGE_ATTR_PAT: set page attribute table index.
  • DRM_XE_VMA_ATTR_PURGEABLE_STATE: set purgeable state for BOs.

🌈 Example 🌈

here's the little snippet, exactly as it's written, go off:

struct drm_xe_madvise madvise = {
     .vm_id = vm_id,
     .start = 0x100000,
     .range = 0x2000,
     .type = DRM_XE_MEM_RANGE_ATTR_ATOMIC,
     .atomic.val = DRM_XE_ATOMIC_DEVICE,
};

ioctl(fd, DRM_IOCTL_XE_MADVISE, madvise);

πŸ‘‘ SEE ALSO πŸ‘‘

the whole friend group, every single one of them:

  • 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_mem_range_attr(9)
  • struct drm_xe_vm_query_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)

and that's the whole page, bestie 🫢 this one came from ./include/uapi/drm, dated October 2026 β€” mark your calendars, mwah πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from