linux/include/uapi/drm/xe_drm.h

/* SPDX-License-Identifier: MIT */
/*
 * Copyright © 2023 Intel Corporation
 */

#ifndef _UAPI_XE_DRM_H_
#define _UAPI_XE_DRM_H_

#include "drm.h"

#if defined(__cplusplus)
extern "C" {
#endif

/*
 * Please note that modifications to all structs defined here are
 * subject to backwards-compatibility constraints.
 * Sections in this file are organized as follows:
 *   1. IOCTL definition
 *   2. Extension definition and helper structs
 *   3. IOCTL's Query structs in the order of the Query's entries.
 *   4. The rest of IOCTL structs in the order of IOCTL declaration.
 */

/**
 * DOC: Xe Device Block Diagram
 *
 * The diagram below represents a high-level simplification of a discrete
 * GPU supported by the Xe driver. It shows some device components which
 * are necessary to understand this API, as well as how their relations
 * to each other. This diagram does not represent real hardware::
 *
 *   ┌──────────────────────────────────────────────────────────────────┐
 *   │ ┌──────────────────────────────────────────────────┐ ┌─────────┐ │
 *   │ │        ┌───────────────────────┐   ┌─────┐       │ │ ┌─────┐ │ │
 *   │ │        │         VRAM0         ├───┤ ... │       │ │ │VRAM1│ │ │
 *   │ │        └───────────┬───────────┘   └─GT1─┘       │ │ └──┬──┘ │ │
 *   │ │ ┌──────────────────┴───────────────────────────┐ │ │ ┌──┴──┐ │ │
 *   │ │ │ ┌─────────────────────┐  ┌─────────────────┐ │ │ │ │     │ │ │
 *   │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
 *   │ │ │ │ │EU│ │EU│ │EU│ │EU│ │  │ │RCS0 │ │BCS0 │ │ │ │ │ │     │ │ │
 *   │ │ │ │ └──┘ └──┘ └──┘ └──┘ │  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
 *   │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
 *   │ │ │ │ │EU│ │EU│ │EU│ │EU│ │  │ │VCS0 │ │VCS1 │ │ │ │ │ │     │ │ │
 *   │ │ │ │ └──┘ └──┘ └──┘ └──┘ │  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
 *   │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
 *   │ │ │ │ │EU│ │EU│ │EU│ │EU│ │  │ │VECS0│ │VECS1│ │ │ │ │ │ ... │ │ │
 *   │ │ │ │ └──┘ └──┘ └──┘ └──┘ │  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
 *   │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
 *   │ │ │ │ │EU│ │EU│ │EU│ │EU│ │  │ │CCS0 │ │CCS1 │ │ │ │ │ │     │ │ │
 *   │ │ │ │ └──┘ └──┘ └──┘ └──┘ │  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
 *   │ │ │ └─────────DSS─────────┘  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
 *   │ │ │                          │ │CCS2 │ │CCS3 │ │ │ │ │ │     │ │ │
 *   │ │ │ ┌─────┐ ┌─────┐ ┌─────┐  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
 *   │ │ │ │ ... │ │ ... │ │ ... │  │                 │ │ │ │ │     │ │ │
 *   │ │ │ └─DSS─┘ └─DSS─┘ └─DSS─┘  └─────Engines─────┘ │ │ │ │     │ │ │
 *   │ │ └───────────────────────────GT0────────────────┘ │ │ └─GT2─┘ │ │
 *   │ └────────────────────────────Tile0─────────────────┘ └─ Tile1──┘ │
 *   └─────────────────────────────Device0───────┬──────────────────────┘
 *                                               │
 *                        ───────────────────────┴────────── PCI bus
 */

/**
 * DOC: Xe uAPI Overview
 *
 * This section aims to describe the Xe's IOCTL entries, its structs, and other
 * Xe related uAPI such as uevents and PMU (Platform Monitoring Unit) related
 * entries and usage.
 *
 * List of supported IOCTLs:
 *  - &DRM_IOCTL_XE_DEVICE_QUERY
 *  - &DRM_IOCTL_XE_GEM_CREATE
 *  - &DRM_IOCTL_XE_GEM_MMAP_OFFSET
 *  - &DRM_IOCTL_XE_VM_CREATE
 *  - &DRM_IOCTL_XE_VM_DESTROY
 *  - &DRM_IOCTL_XE_VM_BIND
 *  - &DRM_IOCTL_XE_EXEC_QUEUE_CREATE
 *  - &DRM_IOCTL_XE_EXEC_QUEUE_DESTROY
 *  - &DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY
 *  - &DRM_IOCTL_XE_EXEC
 *  - &DRM_IOCTL_XE_WAIT_USER_FENCE
 *  - &DRM_IOCTL_XE_OBSERVATION
 */

/*
 * xe specific ioctls.
 *
 * The device specific ioctl range is [DRM_COMMAND_BASE, DRM_COMMAND_END) ie
 * [0x40, 0xa0) (a0 is excluded). The numbers below are defined as offset
 * against DRM_COMMAND_BASE and should be between [0x0, 0x60).
 */
#define DRM_XE_DEVICE_QUERY
#define DRM_XE_GEM_CREATE
#define DRM_XE_GEM_MMAP_OFFSET
#define DRM_XE_VM_CREATE
#define DRM_XE_VM_DESTROY
#define DRM_XE_VM_BIND
#define DRM_XE_EXEC_QUEUE_CREATE
#define DRM_XE_EXEC_QUEUE_DESTROY
#define DRM_XE_EXEC_QUEUE_GET_PROPERTY
#define DRM_XE_EXEC
#define DRM_XE_WAIT_USER_FENCE
#define DRM_XE_OBSERVATION

/* Must be kept compact -- no holes */

#define DRM_IOCTL_XE_DEVICE_QUERY
#define DRM_IOCTL_XE_GEM_CREATE
#define DRM_IOCTL_XE_GEM_MMAP_OFFSET
#define DRM_IOCTL_XE_VM_CREATE
#define DRM_IOCTL_XE_VM_DESTROY
#define DRM_IOCTL_XE_VM_BIND
#define DRM_IOCTL_XE_EXEC_QUEUE_CREATE
#define DRM_IOCTL_XE_EXEC_QUEUE_DESTROY
#define DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY
#define DRM_IOCTL_XE_EXEC
#define DRM_IOCTL_XE_WAIT_USER_FENCE
#define DRM_IOCTL_XE_OBSERVATION

/**
 * DOC: Xe IOCTL Extensions
 *
 * Before detailing the IOCTLs and its structs, it is important to highlight
 * that every IOCTL in Xe is extensible.
 *
 * Many interfaces need to grow over time. In most cases we can simply
 * extend the struct and have userspace pass in more data. Another option,
 * as demonstrated by Vulkan's approach to providing extensions for forward
 * and backward compatibility, is to use a list of optional structs to
 * provide those extra details.
 *
 * The key advantage to using an extension chain is that it allows us to
 * redefine the interface more easily than an ever growing struct of
 * increasing complexity, and for large parts of that interface to be
 * entirely optional. The downside is more pointer chasing; chasing across
 * the __user boundary with pointers encapsulated inside u64.
 *
 * Example chaining:
 *
 * .. code-block:: C
 *
 *	struct drm_xe_user_extension ext3 {
 *		.next_extension = 0, // end
 *		.name = ...,
 *	};
 *	struct drm_xe_user_extension ext2 {
 *		.next_extension = (uintptr_t)&ext3,
 *		.name = ...,
 *	};
 *	struct drm_xe_user_extension ext1 {
 *		.next_extension = (uintptr_t)&ext2,
 *		.name = ...,
 *	};
 *
 * Typically the struct drm_xe_user_extension would be embedded in some uAPI
 * struct, and in this case we would feed it the head of the chain(i.e ext1),
 * which would then apply all of the above extensions.
*/

/**
 * struct drm_xe_user_extension - Base class for defining a chain of extensions
 */
struct drm_xe_user_extension {};

/**
 * struct drm_xe_ext_set_property - Generic set property extension
 *
 * A generic struct that allows any of the Xe's IOCTL to be extended
 * with a set_property operation.
 */
struct drm_xe_ext_set_property {};

/**
 * struct drm_xe_engine_class_instance - instance of an engine class
 *
 * It is returned as part of the @drm_xe_engine, but it also is used as
 * the input of engine selection for both @drm_xe_exec_queue_create and
 * @drm_xe_query_engine_cycles
 *
 * The @engine_class can be:
 *  - %DRM_XE_ENGINE_CLASS_RENDER
 *  - %DRM_XE_ENGINE_CLASS_COPY
 *  - %DRM_XE_ENGINE_CLASS_VIDEO_DECODE
 *  - %DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE
 *  - %DRM_XE_ENGINE_CLASS_COMPUTE
 *  - %DRM_XE_ENGINE_CLASS_VM_BIND - Kernel only classes (not actual
 *    hardware engine class). Used for creating ordered queues of VM
 *    bind operations.
 */
struct drm_xe_engine_class_instance {};

/**
 * struct drm_xe_engine - describe hardware engine
 */
struct drm_xe_engine {};

/**
 * struct drm_xe_query_engines - describe engines
 *
 * If a query is made with a struct @drm_xe_device_query where .query
 * is equal to %DRM_XE_DEVICE_QUERY_ENGINES, then the reply uses an array of
 * struct @drm_xe_query_engines in .data.
 */
struct drm_xe_query_engines {};

/**
 * enum drm_xe_memory_class - Supported memory classes.
 */
enum drm_xe_memory_class {};

/**
 * struct drm_xe_mem_region - Describes some region as known to
 * the driver.
 */
struct drm_xe_mem_region {};

/**
 * struct drm_xe_query_mem_regions - describe memory regions
 *
 * If a query is made with a struct drm_xe_device_query where .query
 * is equal to DRM_XE_DEVICE_QUERY_MEM_REGIONS, then the reply uses
 * struct drm_xe_query_mem_regions in .data.
 */
struct drm_xe_query_mem_regions {};

/**
 * struct drm_xe_query_config - describe the device configuration
 *
 * If a query is made with a struct drm_xe_device_query where .query
 * is equal to DRM_XE_DEVICE_QUERY_CONFIG, then the reply uses
 * struct drm_xe_query_config in .data.
 *
 * The index in @info can be:
 *  - %DRM_XE_QUERY_CONFIG_REV_AND_DEVICE_ID - Device ID (lower 16 bits)
 *    and the device revision (next 8 bits)
 *  - %DRM_XE_QUERY_CONFIG_FLAGS - Flags describing the device
 *    configuration, see list below
 *
 *    - %DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM - Flag is set if the device
 *      has usable VRAM
 *  - %DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - Minimal memory alignment
 *    required by this device, typically SZ_4K or SZ_64K
 *  - %DRM_XE_QUERY_CONFIG_VA_BITS - Maximum bits of a virtual address
 *  - %DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY - Value of the highest
 *    available exec queue priority
 */
struct drm_xe_query_config {};

/**
 * struct drm_xe_gt - describe an individual GT.
 *
 * To be used with drm_xe_query_gt_list, which will return a list with all the
 * existing GT individual descriptions.
 * Graphics Technology (GT) is a subset of a GPU/tile that is responsible for
 * implementing graphics and/or media operations.
 *
 * The index in @type can be:
 *  - %DRM_XE_QUERY_GT_TYPE_MAIN
 *  - %DRM_XE_QUERY_GT_TYPE_MEDIA
 */
struct drm_xe_gt {};

/**
 * struct drm_xe_query_gt_list - A list with GT description items.
 *
 * If a query is made with a struct drm_xe_device_query where .query
 * is equal to DRM_XE_DEVICE_QUERY_GT_LIST, then the reply uses struct
 * drm_xe_query_gt_list in .data.
 */
struct drm_xe_query_gt_list {};

/**
 * struct drm_xe_query_topology_mask - describe the topology mask of a GT
 *
 * This is the hardware topology which reflects the internal physical
 * structure of the GPU.
 *
 * If a query is made with a struct drm_xe_device_query where .query
 * is equal to DRM_XE_DEVICE_QUERY_GT_TOPOLOGY, then the reply uses
 * struct drm_xe_query_topology_mask in .data.
 *
 * The @type can be:
 *  - %DRM_XE_TOPO_DSS_GEOMETRY - To query the mask of Dual Sub Slices
 *    (DSS) available for geometry operations. For example a query response
 *    containing the following in mask:
 *    ``DSS_GEOMETRY    ff ff ff ff 00 00 00 00``
 *    means 32 DSS are available for geometry.
 *  - %DRM_XE_TOPO_DSS_COMPUTE - To query the mask of Dual Sub Slices
 *    (DSS) available for compute operations. For example a query response
 *    containing the following in mask:
 *    ``DSS_COMPUTE    ff ff ff ff 00 00 00 00``
 *    means 32 DSS are available for compute.
 *  - %DRM_XE_TOPO_L3_BANK - To query the mask of enabled L3 banks
 *  - %DRM_XE_TOPO_EU_PER_DSS - To query the mask of Execution Units (EU)
 *    available per Dual Sub Slices (DSS). For example a query response
 *    containing the following in mask:
 *    ``EU_PER_DSS    ff ff 00 00 00 00 00 00``
 *    means each DSS has 16 SIMD8 EUs. This type may be omitted if device
 *    doesn't have SIMD8 EUs.
 *  - %DRM_XE_TOPO_SIMD16_EU_PER_DSS - To query the mask of SIMD16 Execution
 *    Units (EU) available per Dual Sub Slices (DSS). For example a query
 *    response containing the following in mask:
 *    ``SIMD16_EU_PER_DSS    ff ff 00 00 00 00 00 00``
 *    means each DSS has 16 SIMD16 EUs. This type may be omitted if device
 *    doesn't have SIMD16 EUs.
 */
struct drm_xe_query_topology_mask {};

/**
 * struct drm_xe_query_engine_cycles - correlate CPU and GPU timestamps
 *
 * If a query is made with a struct drm_xe_device_query where .query is equal to
 * DRM_XE_DEVICE_QUERY_ENGINE_CYCLES, then the reply uses struct drm_xe_query_engine_cycles
 * in .data. struct drm_xe_query_engine_cycles is allocated by the user and
 * .data points to this allocated structure.
 *
 * The query returns the engine cycles, which along with GT's @reference_clock,
 * can be used to calculate the engine timestamp. In addition the
 * query returns a set of cpu timestamps that indicate when the command
 * streamer cycle count was captured.
 */
struct drm_xe_query_engine_cycles {};

/**
 * struct drm_xe_query_uc_fw_version - query a micro-controller firmware version
 *
 * Given a uc_type this will return the branch, major, minor and patch version
 * of the micro-controller firmware.
 */
struct drm_xe_query_uc_fw_version {};

/**
 * struct drm_xe_device_query - Input of &DRM_IOCTL_XE_DEVICE_QUERY - main
 * structure to query device information
 *
 * The user selects the type of data to query among DRM_XE_DEVICE_QUERY_*
 * and sets the value in the query member. This determines the type of
 * the structure provided by the driver in data, among struct drm_xe_query_*.
 *
 * The @query can be:
 *  - %DRM_XE_DEVICE_QUERY_ENGINES
 *  - %DRM_XE_DEVICE_QUERY_MEM_REGIONS
 *  - %DRM_XE_DEVICE_QUERY_CONFIG
 *  - %DRM_XE_DEVICE_QUERY_GT_LIST
 *  - %DRM_XE_DEVICE_QUERY_HWCONFIG - Query type to retrieve the hardware
 *    configuration of the device such as information on slices, memory,
 *    caches, and so on. It is provided as a table of key / value
 *    attributes.
 *  - %DRM_XE_DEVICE_QUERY_GT_TOPOLOGY
 *  - %DRM_XE_DEVICE_QUERY_ENGINE_CYCLES
 *
 * If size is set to 0, the driver fills it with the required size for
 * the requested type of data to query. If size is equal to the required
 * size, the queried information is copied into data. If size is set to
 * a value different from 0 and different from the required size, the
 * IOCTL call returns -EINVAL.
 *
 * For example the following code snippet allows retrieving and printing
 * information about the device engines with DRM_XE_DEVICE_QUERY_ENGINES:
 *
 * .. code-block:: C
 *
 *     struct drm_xe_query_engines *engines;
 *     struct drm_xe_device_query query = {
 *         .extensions = 0,
 *         .query = DRM_XE_DEVICE_QUERY_ENGINES,
 *         .size = 0,
 *         .data = 0,
 *     };
 *     ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query);
 *     engines = malloc(query.size);
 *     query.data = (uintptr_t)engines;
 *     ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query);
 *     for (int i = 0; i < engines->num_engines; i++) {
 *         printf("Engine %d: %s\n", i,
 *             engines->engines[i].instance.engine_class ==
 *                 DRM_XE_ENGINE_CLASS_RENDER ? "RENDER":
 *             engines->engines[i].instance.engine_class ==
 *                 DRM_XE_ENGINE_CLASS_COPY ? "COPY":
 *             engines->engines[i].instance.engine_class ==
 *                 DRM_XE_ENGINE_CLASS_VIDEO_DECODE ? "VIDEO_DECODE":
 *             engines->engines[i].instance.engine_class ==
 *                 DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE ? "VIDEO_ENHANCE":
 *             engines->engines[i].instance.engine_class ==
 *                 DRM_XE_ENGINE_CLASS_COMPUTE ? "COMPUTE":
 *             "UNKNOWN");
 *     }
 *     free(engines);
 */
struct drm_xe_device_query {};

/**
 * struct drm_xe_gem_create - Input of &DRM_IOCTL_XE_GEM_CREATE - A structure for
 * gem creation
 *
 * The @flags can be:
 *  - %DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING
 *  - %DRM_XE_GEM_CREATE_FLAG_SCANOUT
 *  - %DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM - When using VRAM as a
 *    possible placement, ensure that the corresponding VRAM allocation
 *    will always use the CPU accessible part of VRAM. This is important
 *    for small-bar systems (on full-bar systems this gets turned into a
 *    noop).
 *    Note1: System memory can be used as an extra placement if the kernel
 *    should spill the allocation to system memory, if space can't be made
 *    available in the CPU accessible part of VRAM (giving the same
 *    behaviour as the i915 interface, see
 *    I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS).
 *    Note2: For clear-color CCS surfaces the kernel needs to read the
 *    clear-color value stored in the buffer, and on discrete platforms we
 *    need to use VRAM for display surfaces, therefore the kernel requires
 *    setting this flag for such objects, otherwise an error is thrown on
 *    small-bar systems.
 *
 * @cpu_caching supports the following values:
 *  - %DRM_XE_GEM_CPU_CACHING_WB - Allocate the pages with write-back
 *    caching. On iGPU this can't be used for scanout surfaces. Currently
 *    not allowed for objects placed in VRAM.
 *  - %DRM_XE_GEM_CPU_CACHING_WC - Allocate the pages as write-combined. This
 *    is uncached. Scanout surfaces should likely use this. All objects
 *    that can be placed in VRAM must use this.
 */
struct drm_xe_gem_create {};

/**
 * struct drm_xe_gem_mmap_offset - Input of &DRM_IOCTL_XE_GEM_MMAP_OFFSET
 */
struct drm_xe_gem_mmap_offset {};

/**
 * struct drm_xe_vm_create - Input of &DRM_IOCTL_XE_VM_CREATE
 *
 * The @flags can be:
 *  - %DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE
 *  - %DRM_XE_VM_CREATE_FLAG_LR_MODE - An LR, or Long Running VM accepts
 *    exec submissions to its exec_queues that don't have an upper time
 *    limit on the job execution time. But exec submissions to these
 *    don't allow any of the flags DRM_XE_SYNC_FLAG_SYNCOBJ,
 *    DRM_XE_SYNC_FLAG_TIMELINE_SYNCOBJ, DRM_XE_SYNC_FLAG_DMA_BUF,
 *    used as out-syncobjs, that is, together with DRM_XE_SYNC_FLAG_SIGNAL.
 *    LR VMs can be created in recoverable page-fault mode using
 *    DRM_XE_VM_CREATE_FLAG_FAULT_MODE, if the device supports it.
 *    If that flag is omitted, the UMD can not rely on the slightly
 *    different per-VM overcommit semantics that are enabled by
 *    DRM_XE_VM_CREATE_FLAG_FAULT_MODE (see below), but KMD may
 *    still enable recoverable pagefaults if supported by the device.
 *  - %DRM_XE_VM_CREATE_FLAG_FAULT_MODE - Requires also
 *    DRM_XE_VM_CREATE_FLAG_LR_MODE. It allows memory to be allocated on
 *    demand when accessed, and also allows per-VM overcommit of memory.
 *    The xe driver internally uses recoverable pagefaults to implement
 *    this.
 */
struct drm_xe_vm_create {};

/**
 * struct drm_xe_vm_destroy - Input of &DRM_IOCTL_XE_VM_DESTROY
 */
struct drm_xe_vm_destroy {};

/**
 * struct drm_xe_vm_bind_op - run bind operations
 *
 * The @op can be:
 *  - %DRM_XE_VM_BIND_OP_MAP
 *  - %DRM_XE_VM_BIND_OP_UNMAP
 *  - %DRM_XE_VM_BIND_OP_MAP_USERPTR
 *  - %DRM_XE_VM_BIND_OP_UNMAP_ALL
 *  - %DRM_XE_VM_BIND_OP_PREFETCH
 *
 * and the @flags can be:
 *  - %DRM_XE_VM_BIND_FLAG_READONLY - Setup the page tables as read-only
 *    to ensure write protection
 *  - %DRM_XE_VM_BIND_FLAG_IMMEDIATE - On a faulting VM, do the
 *    MAP operation immediately rather than deferring the MAP to the page
 *    fault handler. This is implied on a non-faulting VM as there is no
 *    fault handler to defer to.
 *  - %DRM_XE_VM_BIND_FLAG_NULL - When the NULL flag is set, the page
 *    tables are setup with a special bit which indicates writes are
 *    dropped and all reads return zero. In the future, the NULL flags
 *    will only be valid for DRM_XE_VM_BIND_OP_MAP operations, the BO
 *    handle MBZ, and the BO offset MBZ. This flag is intended to
 *    implement VK sparse bindings.
 */
struct drm_xe_vm_bind_op {};

/**
 * struct drm_xe_vm_bind - Input of &DRM_IOCTL_XE_VM_BIND
 *
 * Below is an example of a minimal use of @drm_xe_vm_bind to
 * asynchronously bind the buffer `data` at address `BIND_ADDRESS` to
 * illustrate `userptr`. It can be synchronized by using the example
 * provided for @drm_xe_sync.
 *
 * .. code-block:: C
 *
 *     data = aligned_alloc(ALIGNMENT, BO_SIZE);
 *     struct drm_xe_vm_bind bind = {
 *         .vm_id = vm,
 *         .num_binds = 1,
 *         .bind.obj = 0,
 *         .bind.obj_offset = to_user_pointer(data),
 *         .bind.range = BO_SIZE,
 *         .bind.addr = BIND_ADDRESS,
 *         .bind.op = DRM_XE_VM_BIND_OP_MAP_USERPTR,
 *         .bind.flags = 0,
 *         .num_syncs = 1,
 *         .syncs = &sync,
 *         .exec_queue_id = 0,
 *     };
 *     ioctl(fd, DRM_IOCTL_XE_VM_BIND, &bind);
 *
 */
struct drm_xe_vm_bind {};

/**
 * struct drm_xe_exec_queue_create - Input of &DRM_IOCTL_XE_EXEC_QUEUE_CREATE
 *
 * The example below shows how to use @drm_xe_exec_queue_create to create
 * a simple exec_queue (no parallel submission) of class
 * &DRM_XE_ENGINE_CLASS_RENDER.
 *
 * .. code-block:: C
 *
 *     struct drm_xe_engine_class_instance instance = {
 *         .engine_class = DRM_XE_ENGINE_CLASS_RENDER,
 *     };
 *     struct drm_xe_exec_queue_create exec_queue_create = {
 *          .extensions = 0,
 *          .vm_id = vm,
 *          .num_bb_per_exec = 1,
 *          .num_eng_per_bb = 1,
 *          .instances = to_user_pointer(&instance),
 *     };
 *     ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE, &exec_queue_create);
 *
 */
struct drm_xe_exec_queue_create {};

/**
 * struct drm_xe_exec_queue_destroy - Input of &DRM_IOCTL_XE_EXEC_QUEUE_DESTROY
 */
struct drm_xe_exec_queue_destroy {};

/**
 * struct drm_xe_exec_queue_get_property - Input of &DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY
 *
 * The @property can be:
 *  - %DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN
 */
struct drm_xe_exec_queue_get_property {};

/**
 * struct drm_xe_sync - sync object
 *
 * The @type can be:
 *  - %DRM_XE_SYNC_TYPE_SYNCOBJ
 *  - %DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ
 *  - %DRM_XE_SYNC_TYPE_USER_FENCE
 *
 * and the @flags can be:
 *  - %DRM_XE_SYNC_FLAG_SIGNAL
 *
 * A minimal use of @drm_xe_sync looks like this:
 *
 * .. code-block:: C
 *
 *     struct drm_xe_sync sync = {
 *         .flags = DRM_XE_SYNC_FLAG_SIGNAL,
 *         .type = DRM_XE_SYNC_TYPE_SYNCOBJ,
 *     };
 *     struct drm_syncobj_create syncobj_create = { 0 };
 *     ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &syncobj_create);
 *     sync.handle = syncobj_create.handle;
 *         ...
 *         use of &sync in drm_xe_exec or drm_xe_vm_bind
 *         ...
 *     struct drm_syncobj_wait wait = {
 *         .handles = &sync.handle,
 *         .timeout_nsec = INT64_MAX,
 *         .count_handles = 1,
 *         .flags = 0,
 *         .first_signaled = 0,
 *         .pad = 0,
 *     };
 *     ioctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
 */
struct drm_xe_sync {};

/**
 * struct drm_xe_exec - Input of &DRM_IOCTL_XE_EXEC
 *
 * This is an example to use @drm_xe_exec for execution of the object
 * at BIND_ADDRESS (see example in @drm_xe_vm_bind) by an exec_queue
 * (see example in @drm_xe_exec_queue_create). It can be synchronized
 * by using the example provided for @drm_xe_sync.
 *
 * .. code-block:: C
 *
 *     struct drm_xe_exec exec = {
 *         .exec_queue_id = exec_queue,
 *         .syncs = &sync,
 *         .num_syncs = 1,
 *         .address = BIND_ADDRESS,
 *         .num_batch_buffer = 1,
 *     };
 *     ioctl(fd, DRM_IOCTL_XE_EXEC, &exec);
 *
 */
struct drm_xe_exec {};

/**
 * struct drm_xe_wait_user_fence - Input of &DRM_IOCTL_XE_WAIT_USER_FENCE
 *
 * Wait on user fence, XE will wake-up on every HW engine interrupt in the
 * instances list and check if user fence is complete::
 *
 *	(*addr & MASK) OP (VALUE & MASK)
 *
 * Returns to user on user fence completion or timeout.
 *
 * The @op can be:
 *  - %DRM_XE_UFENCE_WAIT_OP_EQ
 *  - %DRM_XE_UFENCE_WAIT_OP_NEQ
 *  - %DRM_XE_UFENCE_WAIT_OP_GT
 *  - %DRM_XE_UFENCE_WAIT_OP_GTE
 *  - %DRM_XE_UFENCE_WAIT_OP_LT
 *  - %DRM_XE_UFENCE_WAIT_OP_LTE
 *
 * and the @flags can be:
 *  - %DRM_XE_UFENCE_WAIT_FLAG_ABSTIME
 *  - %DRM_XE_UFENCE_WAIT_FLAG_SOFT_OP
 *
 * The @mask values can be for example:
 *  - 0xffu for u8
 *  - 0xffffu for u16
 *  - 0xffffffffu for u32
 *  - 0xffffffffffffffffu for u64
 */
struct drm_xe_wait_user_fence {};

/**
 * enum drm_xe_observation_type - Observation stream types
 */
enum drm_xe_observation_type {};

/**
 * enum drm_xe_observation_op - Observation stream ops
 */
enum drm_xe_observation_op {};

/**
 * struct drm_xe_observation_param - Input of &DRM_XE_OBSERVATION
 *
 * The observation layer enables multiplexing observation streams of
 * multiple types. The actual params for a particular stream operation are
 * supplied via the @param pointer (use __copy_from_user to get these
 * params).
 */
struct drm_xe_observation_param {};

/**
 * enum drm_xe_observation_ioctls - Observation stream fd ioctl's
 *
 * Information exchanged between userspace and kernel for observation fd
 * ioctl's is stream type specific
 */
enum drm_xe_observation_ioctls {};

/**
 * enum drm_xe_oa_unit_type - OA unit types
 */
enum drm_xe_oa_unit_type {};

/**
 * struct drm_xe_oa_unit - describe OA unit
 */
struct drm_xe_oa_unit {};

/**
 * struct drm_xe_query_oa_units - describe OA units
 *
 * If a query is made with a struct drm_xe_device_query where .query
 * is equal to DRM_XE_DEVICE_QUERY_OA_UNITS, then the reply uses struct
 * drm_xe_query_oa_units in .data.
 *
 * OA unit properties for all OA units can be accessed using a code block
 * such as the one below:
 *
 * .. code-block:: C
 *
 *	struct drm_xe_query_oa_units *qoa;
 *	struct drm_xe_oa_unit *oau;
 *	u8 *poau;
 *
 *	// malloc qoa and issue DRM_XE_DEVICE_QUERY_OA_UNITS. Then:
 *	poau = (u8 *)&qoa->oa_units[0];
 *	for (int i = 0; i < qoa->num_oa_units; i++) {
 *		oau = (struct drm_xe_oa_unit *)poau;
 *		// Access 'struct drm_xe_oa_unit' fields here
 *		poau += sizeof(*oau) + oau->num_engines * sizeof(oau->eci[0]);
 *	}
 */
struct drm_xe_query_oa_units {};

/**
 * enum drm_xe_oa_format_type - OA format types as specified in PRM/Bspec
 * 52198/60942
 */
enum drm_xe_oa_format_type {};

/**
 * enum drm_xe_oa_property_id - OA stream property id's
 *
 * Stream params are specified as a chain of @drm_xe_ext_set_property
 * struct's, with @property values from enum @drm_xe_oa_property_id and
 * @drm_xe_user_extension base.name set to @DRM_XE_OA_EXTENSION_SET_PROPERTY.
 * @param field in struct @drm_xe_observation_param points to the first
 * @drm_xe_ext_set_property struct.
 *
 * Exactly the same mechanism is also used for stream reconfiguration using the
 * @DRM_XE_OBSERVATION_IOCTL_CONFIG observation stream fd ioctl, though only a
 * subset of properties below can be specified for stream reconfiguration.
 */
enum drm_xe_oa_property_id {};

/**
 * struct drm_xe_oa_config - OA metric configuration
 *
 * Multiple OA configs can be added using @DRM_XE_OBSERVATION_OP_ADD_CONFIG. A
 * particular config can be specified when opening an OA stream using
 * @DRM_XE_OA_PROPERTY_OA_METRIC_SET property.
 */
struct drm_xe_oa_config {};

/**
 * struct drm_xe_oa_stream_status - OA stream status returned from
 * @DRM_XE_OBSERVATION_IOCTL_STATUS observation stream fd ioctl. Userspace can
 * call the ioctl to query stream status in response to EIO errno from
 * observation fd read().
 */
struct drm_xe_oa_stream_status {};

/**
 * struct drm_xe_oa_stream_info - OA stream info returned from
 * @DRM_XE_OBSERVATION_IOCTL_INFO observation stream fd ioctl
 */
struct drm_xe_oa_stream_info {};

#if defined(__cplusplus)
}
#endif

#endif /* _UAPI_XE_DRM_H_ */