ohmu
·
2026-10-15
1/* SPDX-License-Identifier: MIT */
2/*
3 * Copyright (C) The Asahi Linux Contributors
4 * Copyright (C) 2018-2023 Collabora Ltd.
5 * Copyright (C) 2014-2018 Broadcom
6 */
7#ifndef _ASAHI_DRM_H_
8#define _ASAHI_DRM_H_
9
10#if __has_include(<drm.h>)
11 #include <drm.h>
12#else
13 #include <drm/drm.h>
14#endif
15
16#if defined(__cplusplus)
17extern "C" {
18#endif
19
20/**
21 * DOC: Introduction to the Asahi UAPI
22 *
23 * This documentation describes the Asahi IOCTLs.
24 *
25 * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed
26 * from Panthor):
27 *
28 * - Structures must be aligned on 64-bit/8-byte. If the object is not
29 * naturally aligned, a padding field must be added.
30 * - Fields must be explicitly aligned to their natural type alignment with
31 * pad[0..N] fields.
32 * - All padding fields will be checked by the driver to make sure they are
33 * zeroed.
34 * - Flags can be added, but not removed/replaced.
35 * - New fields can be added to the main structures (the structures
36 * directly passed to the ioctl). Those fields can be added at the end of
37 * the structure, or replace existing padding fields. Any new field being
38 * added must preserve the behavior that existed before those fields were
39 * added when a value of zero is passed.
40 * - New fields can be added to indirect objects (objects pointed by the
41 * main structure), iff those objects are passed a size to reflect the
42 * size known by the userspace driver (see
43 * drm_asahi_cmd_header::size).
44 * - If the kernel driver is too old to know some fields, those will be
45 * ignored if zero, and otherwise rejected (and so will be zero on output).
46 * - If userspace is too old to know some fields, those will be zeroed
47 * (input) before the structure is parsed by the kernel driver.
48 * - Each new flag/field addition must come with a driver version update so
49 * the userspace driver doesn't have to guess which flags are supported.
50 * - Structures should not contain unions, as this would defeat the
51 * extensibility of such structures.
52 * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed
53 * at the end of the drm_asahi_ioctl_id enum.
54 */
55
56/**
57 * enum drm_asahi_ioctl_id - IOCTL IDs
58 *
59 * Place new ioctls at the end, don't re-order, don't replace or remove entries.
60 *
61 * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx
62 * definitions instead.
63 */
64enum drm_asahi_ioctl_id {
65 /** @DRM_ASAHI_GET_PARAMS: Query device properties. */
66 DRM_ASAHI_GET_PARAMS = 0,
67
68 /** @DRM_ASAHI_GET_TIME: Query device time. */
69 DRM_ASAHI_GET_TIME,
70
71 /** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */
72 DRM_ASAHI_VM_CREATE,
73
74 /** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */
75 DRM_ASAHI_VM_DESTROY,
76
77 /** @DRM_ASAHI_VM_BIND: Bind/unbind memory to a VM. */
78 DRM_ASAHI_VM_BIND,
79
80 /** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */
81 DRM_ASAHI_GEM_CREATE,
82
83 /**
84 * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a
85 * given GEM handle.
86 */
87 DRM_ASAHI_GEM_MMAP_OFFSET,
88
89 /** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */
90 DRM_ASAHI_GEM_BIND_OBJECT,
91
92 /** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */
93 DRM_ASAHI_QUEUE_CREATE,
94
95 /** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */
96 DRM_ASAHI_QUEUE_DESTROY,
97
98 /** @DRM_ASAHI_SUBMIT: Submit commands to a queue. */
99 DRM_ASAHI_SUBMIT,
100};
101
102#define DRM_ASAHI_MAX_CLUSTERS 64
103
104/**
105 * struct drm_asahi_params_global - Global parameters.
106 *
107 * This struct may be queried by drm_asahi_get_params.
108 */
109struct drm_asahi_params_global {
110 /** @features: Feature bits from drm_asahi_feature */
111 __u64 features;
112
113 /** @gpu_generation: GPU generation, e.g. 13 for G13G */
114 __u32 gpu_generation;
115
116 /** @gpu_variant: GPU variant as a character, e.g. 'C' for G13C */
117 __u32 gpu_variant;
118
119 /**
120 * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or
121 * 0x21 for 'C1'
122 */
123 __u32 gpu_revision;
124
125 /** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */
126 __u32 chip_id;
127
128 /** @num_dies: Number of dies in the SoC */
129 __u32 num_dies;
130
131 /** @num_clusters_total: Number of GPU clusters (across all dies) */
132 __u32 num_clusters_total;
133
134 /**
135 * @num_cores_per_cluster: Number of logical cores per cluster
136 * (including inactive/nonexistent)
137 */
138 __u32 num_cores_per_cluster;
139
140 /** @max_frequency_khz: Maximum GPU core clock frequency */
141 __u32 max_frequency_khz;
142
143 /** @core_masks: Bitmask of present/enabled cores per cluster */
144 __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
145
146 /**
147 * @vm_start: VM range start VMA. Together with @vm_end, this defines
148 * the window of valid GPU VAs. Userspace is expected to subdivide VAs
149 * out of this window.
150 *
151 * This window contains all virtual addresses that userspace needs to
152 * know about. There may be kernel-internal GPU VAs outside this range,
153 * but that detail is not relevant here.
154 */
155 __u64 vm_start;
156
157 /** @vm_end: VM range end VMA */
158 __u64 vm_end;
159
160 /**
161 * @vm_kernel_min_size: Minimum kernel VMA window size.
162 *
163 * When creating a VM, userspace is required to carve out a section of
164 * virtual addresses (within the range given by @vm_start and
165 * @vm_end). The kernel will allocate various internal structures
166 * within the specified VA range.
167 *
168 * Allowing userspace to choose the VA range for the kernel, rather than
169 * the kernel reserving VAs and requiring userspace to cope, can assist
170 * in implementing SVM.
171 */
172 __u64 vm_kernel_min_size;
173
174 /**
175 * @max_commands_per_submission: Maximum number of supported commands
176 * per submission. This mirrors firmware limits. Userspace must split up
177 * larger command buffers, which may require inserting additional
178 * synchronization.
179 */
180 __u32 max_commands_per_submission;
181
182 /**
183 * @max_attachments: Maximum number of drm_asahi_attachment's per
184 * command
185 */
186 __u32 max_attachments;
187
188 /**
189 * @command_timestamp_frequency_hz: Timebase frequency for timestamps
190 * written during command exeuction, specified via drm_asahi_timestamp
191 * structures. As this rate is controlled by the firmware, it is a
192 * queryable parameter.
193 *
194 * Userspace must divide by this frequency to convert timestamps to
195 * seconds, rather than hardcoding a particular firmware's rate.
196 */
197 __u64 command_timestamp_frequency_hz;
198};
199
200/**
201 * enum drm_asahi_feature - Feature bits
202 *
203 * This covers only features that userspace cannot infer from the architecture
204 * version. Most features don't need to be here.
205 */
206enum drm_asahi_feature {
207 /**
208 * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader
209 * loads of unmapped memory will return zero. Shader stores to unmapped
210 * memory will be silently discarded. Note that only shader load/store
211 * is affected. Other hardware units are not affected, notably including
212 * texture sampling.
213 *
214 * Soft fault is set when initializing the GPU and cannot be runtime
215 * toggled. Therefore, it is exposed as a feature bit and not a
216 * userspace-settable flag on the VM. When soft fault is enabled,
217 * userspace can speculate memory accesses more aggressively.
218 */
219 DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0,
220};
221
222/**
223 * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS
224 */
225struct drm_asahi_get_params {
226 /** @param_group: Parameter group to fetch (MBZ) */
227 __u32 param_group;
228
229 /** @pad: MBZ */
230 __u32 pad;
231
232 /** @pointer: User pointer to write parameter struct */
233 __u64 pointer;
234
235 /**
236 * @size: Size of the user buffer. In case of older userspace, this may
237 * be less than sizeof(struct drm_asahi_params_global). The kernel will
238 * not write past the length specified here, allowing extensibility.
239 */
240 __u64 size;
241};
242
243/**
244 * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE
245 */
246struct drm_asahi_vm_create {
247 /**
248 * @kernel_start: Start of the kernel-reserved address range. See
249 * drm_asahi_params_global::vm_kernel_min_size.
250 *
251 * Both @kernel_start and @kernel_end must be within the range of
252 * valid VAs given by drm_asahi_params_global::vm_start and
253 * drm_asahi_params_global::vm_end. The size of the kernel range
254 * (@kernel_end - @kernel_start) must be at least
255 * drm_asahi_params_global::vm_kernel_min_size.
256 *
257 * Userspace must not bind any memory on this VM into this reserved
258 * range, it is for kernel use only.
259 */
260 __u64 kernel_start;
261
262 /**
263 * @kernel_end: End of the kernel-reserved address range. See
264 * @kernel_start.
265 */
266 __u64 kernel_end;
267
268 /** @vm_id: Returned VM ID */
269 __u32 vm_id;
270
271 /** @pad: MBZ */
272 __u32 pad;
273};
274
275/**
276 * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY
277 */
278struct drm_asahi_vm_destroy {
279 /** @vm_id: VM ID to be destroyed */
280 __u32 vm_id;
281
282 /** @pad: MBZ */
283 __u32 pad;
284};
285
286/**
287 * enum drm_asahi_gem_flags - Flags for GEM creation
288 */
289enum drm_asahi_gem_flags {
290 /**
291 * @DRM_ASAHI_GEM_WRITEBACK: BO should be CPU-mapped as writeback.
292 *
293 * Map as writeback instead of write-combine. This optimizes for CPU
294 * reads.
295 */
296 DRM_ASAHI_GEM_WRITEBACK = (1L << 0),
297
298 /**
299 * @DRM_ASAHI_GEM_VM_PRIVATE: BO is private to this GPU VM (no exports).
300 */
301 DRM_ASAHI_GEM_VM_PRIVATE = (1L << 1),
302};
303
304/**
305 * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE
306 */
307struct drm_asahi_gem_create {
308 /** @size: Size of the BO */
309 __u64 size;
310
311 /** @flags: Combination of drm_asahi_gem_flags flags. */
312 __u32 flags;
313
314 /**
315 * @vm_id: VM ID to assign to the BO, if DRM_ASAHI_GEM_VM_PRIVATE is set
316 */
317 __u32 vm_id;
318
319 /** @handle: Returned GEM handle for the BO */
320 __u32 handle;
321
322 /** @pad: MBZ */
323 __u32 pad;
324};
325
326/**
327 * struct drm_asahi_gem_mmap_offset - Arguments passed to
328 * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET
329 */
330struct drm_asahi_gem_mmap_offset {
331 /** @handle: Handle for the object being mapped. */
332 __u32 handle;
333
334 /** @flags: Must be zero */
335 __u32 flags;
336
337 /** @offset: The fake offset to use for subsequent mmap call */
338 __u64 offset;
339};
340
341/**
342 * enum drm_asahi_bind_flags - Flags for GEM binding
343 */
344enum drm_asahi_bind_flags {
345 /**
346 * @DRM_ASAHI_BIND_UNBIND: Instead of binding a GEM object to the range,
347 * simply unbind the GPU VMA range.
348 */
349 DRM_ASAHI_BIND_UNBIND = (1L << 0),
350
351 /** @DRM_ASAHI_BIND_READ: Map BO with GPU read permission */
352 DRM_ASAHI_BIND_READ = (1L << 1),
353
354 /** @DRM_ASAHI_BIND_WRITE: Map BO with GPU write permission */
355 DRM_ASAHI_BIND_WRITE = (1L << 2),
356
357 /**
358 * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly
359 * across the VA range.
360 *
361 * This is useful to fill a VA range with scratch pages or zero pages.
362 * It is intended as a mechanism to accelerate sparse.
363 */
364 DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 3),
365};
366
367/**
368 * struct drm_asahi_gem_bind_op - Description of a single GEM bind operation.
369 */
370struct drm_asahi_gem_bind_op {
371 /** @flags: Combination of drm_asahi_bind_flags flags. */
372 __u32 flags;
373
374 /** @handle: GEM object to bind (except for UNBIND) */
375 __u32 handle;
376
377 /**
378 * @offset: Offset into the object (except for UNBIND).
379 *
380 * For a regular bind, this is the beginning of the region of the GEM
381 * object to bind.
382 *
383 * For a single-page bind, this is the offset to the single page that
384 * will be repeatedly bound.
385 *
386 * Must be page-size aligned.
387 */
388 __u64 offset;
389
390 /**
391 * @range: Number of bytes to bind/unbind to @addr.
392 *
393 * Must be page-size aligned.
394 */
395 __u64 range;
396
397 /**
398 * @addr: Address to bind to.
399 *
400 * Must be page-size aligned.
401 */
402 __u64 addr;
403};
404
405/**
406 * struct drm_asahi_vm_bind - Arguments passed to
407 * DRM_IOCTL_ASAHI_VM_BIND
408 */
409struct drm_asahi_vm_bind {
410 /** @vm_id: The ID of the VM to bind to */
411 __u32 vm_id;
412
413 /** @num_binds: number of binds in this IOCTL. */
414 __u32 num_binds;
415
416 /**
417 * @stride: Stride in bytes between consecutive binds. This allows
418 * extensibility of drm_asahi_gem_bind_op.
419 */
420 __u32 stride;
421
422 /** @pad: MBZ */
423 __u32 pad;
424
425 /**
426 * @userptr: User pointer to an array of @num_binds structures of type
427 * @drm_asahi_gem_bind_op and size @stride bytes.
428 */
429 __u64 userptr;
430};
431
432/**
433 * enum drm_asahi_bind_object_op - Special object bind operation
434 */
435enum drm_asahi_bind_object_op {
436 /** @DRM_ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */
437 DRM_ASAHI_BIND_OBJECT_OP_BIND = 0,
438
439 /** @DRM_ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */
440 DRM_ASAHI_BIND_OBJECT_OP_UNBIND = 1,
441};
442
443/**
444 * enum drm_asahi_bind_object_flags - Special object bind flags
445 */
446enum drm_asahi_bind_object_flags {
447 /**
448 * @DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS: Map a BO as a timestamp
449 * buffer.
450 */
451 DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS = (1L << 0),
452};
453
454/**
455 * struct drm_asahi_gem_bind_object - Arguments passed to
456 * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT
457 */
458struct drm_asahi_gem_bind_object {
459 /** @op: Bind operation (enum drm_asahi_bind_object_op) */
460 __u32 op;
461
462 /** @flags: Combination of drm_asahi_bind_object_flags flags. */
463 __u32 flags;
464
465 /** @handle: GEM object to bind/unbind (BIND) */
466 __u32 handle;
467
468 /** @vm_id: The ID of the VM to operate on (MBZ currently) */
469 __u32 vm_id;
470
471 /** @offset: Offset into the object (BIND only) */
472 __u64 offset;
473
474 /** @range: Number of bytes to bind/unbind (BIND only) */
475 __u64 range;
476
477 /** @object_handle: Object handle (out for BIND, in for UNBIND) */
478 __u32 object_handle;
479
480 /** @pad: MBZ */
481 __u32 pad;
482};
483
484/**
485 * enum drm_asahi_cmd_type - Command type
486 */
487enum drm_asahi_cmd_type {
488 /**
489 * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render
490 * subqueue. Combined vertex and fragment operation.
491 *
492 * Followed by a @drm_asahi_cmd_render payload.
493 */
494 DRM_ASAHI_CMD_RENDER = 0,
495
496 /**
497 * @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue.
498 *
499 * Followed by a @drm_asahi_cmd_compute payload.
500 */
501 DRM_ASAHI_CMD_COMPUTE = 1,
502
503 /**
504 * @DRM_ASAHI_SET_VERTEX_ATTACHMENTS: Software command to set
505 * attachments for subsequent vertex shaders in the same submit.
506 *
507 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
508 */
509 DRM_ASAHI_SET_VERTEX_ATTACHMENTS = 2,
510
511 /**
512 * @DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS: Software command to set
513 * attachments for subsequent fragment shaders in the same submit.
514 *
515 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
516 */
517 DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS = 3,
518
519 /**
520 * @DRM_ASAHI_SET_COMPUTE_ATTACHMENTS: Software command to set
521 * attachments for subsequent compute shaders in the same submit.
522 *
523 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
524 */
525 DRM_ASAHI_SET_COMPUTE_ATTACHMENTS = 4,
526};
527
528/**
529 * enum drm_asahi_priority - Scheduling queue priority.
530 *
531 * These priorities are forwarded to the firmware to influence firmware
532 * scheduling. The exact policy is ultimately decided by firmware, but
533 * these enums allow userspace to communicate the intentions.
534 */
535enum drm_asahi_priority {
536 /** @DRM_ASAHI_PRIORITY_LOW: Low priority queue. */
537 DRM_ASAHI_PRIORITY_LOW = 0,
538
539 /** @DRM_ASAHI_PRIORITY_MEDIUM: Medium priority queue. */
540 DRM_ASAHI_PRIORITY_MEDIUM = 1,
541
542 /**
543 * @DRM_ASAHI_PRIORITY_HIGH: High priority queue.
544 *
545 * Reserved for future extension.
546 */
547 DRM_ASAHI_PRIORITY_HIGH = 2,
548
549 /**
550 * @DRM_ASAHI_PRIORITY_REALTIME: Real-time priority queue.
551 *
552 * Reserved for future extension.
553 */
554 DRM_ASAHI_PRIORITY_REALTIME = 3,
555};
556
557/**
558 * struct drm_asahi_queue_create - Arguments passed to
559 * DRM_IOCTL_ASAHI_QUEUE_CREATE
560 */
561struct drm_asahi_queue_create {
562 /** @flags: MBZ */
563 __u32 flags;
564
565 /** @vm_id: The ID of the VM this queue is bound to */
566 __u32 vm_id;
567
568 /** @priority: One of drm_asahi_priority */
569 __u32 priority;
570
571 /** @queue_id: The returned queue ID */
572 __u32 queue_id;
573
574 /**
575 * @usc_exec_base: GPU base address for all USC binaries (shaders) on
576 * this queue. USC addresses are 32-bit relative to this 64-bit base.
577 *
578 * This sets the following registers on all queue commands:
579 *
580 * USC_EXEC_BASE_TA (vertex)
581 * USC_EXEC_BASE_ISP (fragment)
582 * USC_EXEC_BASE_CP (compute)
583 *
584 * While the hardware lets us configure these independently per command,
585 * we do not have a use case for this. Instead, we expect userspace to
586 * fix a 4GiB VA carveout for USC memory and pass its base address here.
587 */
588 __u64 usc_exec_base;
589};
590
591/**
592 * struct drm_asahi_queue_destroy - Arguments passed to
593 * DRM_IOCTL_ASAHI_QUEUE_DESTROY
594 */
595struct drm_asahi_queue_destroy {
596 /** @queue_id: The queue ID to be destroyed */
597 __u32 queue_id;
598
599 /** @pad: MBZ */
600 __u32 pad;
601};
602
603/**
604 * enum drm_asahi_sync_type - Sync item type
605 */
606enum drm_asahi_sync_type {
607 /** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */
608 DRM_ASAHI_SYNC_SYNCOBJ = 0,
609
610 /** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */
611 DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1,
612};
613
614/**
615 * struct drm_asahi_sync - Sync item
616 */
617struct drm_asahi_sync {
618 /** @sync_type: One of drm_asahi_sync_type */
619 __u32 sync_type;
620
621 /** @handle: The sync object handle */
622 __u32 handle;
623
624 /** @timeline_value: Timeline value for timeline sync objects */
625 __u64 timeline_value;
626};
627
628/**
629 * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier
630 *
631 * This special value may be passed in to drm_asahi_command::vdm_barrier or
632 * drm_asahi_command::cdm_barrier to indicate that the respective subqueue
633 * should not wait on any previous work.
634 */
635#define DRM_ASAHI_BARRIER_NONE (0xFFFFu)
636
637/**
638 * struct drm_asahi_cmd_header - Top level command structure
639 *
640 * This struct is core to the command buffer definition and therefore is not
641 * extensible.
642 */
643struct drm_asahi_cmd_header {
644 /** @cmd_type: One of drm_asahi_cmd_type */
645 __u16 cmd_type;
646
647 /**
648 * @size: Size of this command, not including this header.
649 *
650 * For hardware commands, this enables extensibility of commands without
651 * requiring extra command types. Passing a command that is shorter
652 * than expected is explicitly allowed for backwards-compatibility.
653 * Truncated fields will be zeroed.
654 *
655 * For the synthetic attachment setting commands, this implicitly
656 * encodes the number of attachments. These commands take multiple
657 * fixed-size @drm_asahi_attachment structures as their payload, so size
658 * equals number of attachments * sizeof(struct drm_asahi_attachment).
659 */
660 __u16 size;
661
662 /**
663 * @vdm_barrier: VDM (render) command index to wait on.
664 *
665 * Barriers are indices relative to the beginning of a given submit. A
666 * barrier of 0 waits on commands submitted to the respective subqueue
667 * in previous submit ioctls. A barrier of N waits on N previous
668 * commands on the subqueue within the current submit ioctl. As a
669 * special case, passing @DRM_ASAHI_BARRIER_NONE avoids waiting on any
670 * commands in the subqueue.
671 *
672 * Examples:
673 *
674 * 0: This waits on all previous work.
675 *
676 * NONE: This does not wait for anything on this subqueue.
677 *
678 * 1: This waits on the first render command in the submit.
679 * This is valid only if there are multiple render commands in the
680 * same submit.
681 *
682 * Barriers are valid only for hardware commands. Synthetic software
683 * commands to set attachments must pass NONE here.
684 */
685 __u16 vdm_barrier;
686
687 /**
688 * @cdm_barrier: CDM (compute) command index to wait on.
689 *
690 * See @vdm_barrier, and replace VDM/render with CDM/compute.
691 */
692 __u16 cdm_barrier;
693};
694
695/**
696 * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT
697 */
698struct drm_asahi_submit {
699 /**
700 * @syncs: An optional pointer to an array of drm_asahi_sync. The first
701 * @in_sync_count elements are in-syncs, then the remaining
702 * @out_sync_count elements are out-syncs. Using a single array with
703 * explicit partitioning simplifies handling.
704 */
705 __u64 syncs;
706
707 /**
708 * @cmdbuf: Pointer to the command buffer to submit.
709 *
710 * This is a flat command buffer. By design, it contains no CPU
711 * pointers, which makes it suitable for a virtgpu wire protocol without
712 * requiring any serializing/deserializing step.
713 *
714 * It consists of a series of commands. Each command begins with a
715 * fixed-size @drm_asahi_cmd_header header and is followed by a
716 * variable-length payload according to the type and size in the header.
717 *
718 * The combined count of "real" hardware commands must be nonzero and at
719 * most drm_asahi_params_global::max_commands_per_submission.
720 */
721 __u64 cmdbuf;
722
723 /** @flags: Flags for command submission (MBZ) */
724 __u32 flags;
725
726 /** @queue_id: The queue ID to be submitted to */
727 __u32 queue_id;
728
729 /**
730 * @in_sync_count: Number of sync objects to wait on before starting
731 * this job.
732 */
733 __u32 in_sync_count;
734
735 /**
736 * @out_sync_count: Number of sync objects to signal upon completion of
737 * this job.
738 */
739 __u32 out_sync_count;
740
741 /** @cmdbuf_size: Command buffer size in bytes */
742 __u32 cmdbuf_size;
743
744 /** @pad: MBZ */
745 __u32 pad;
746};
747
748/**
749 * struct drm_asahi_attachment - Describe an "attachment".
750 *
751 * Attachments are any memory written by shaders, notably including render
752 * target attachments written by the end-of-tile program. This is purely a hint
753 * about the accessed memory regions. It is optional to specify, which is
754 * fortunate as it cannot be specified precisely with bindless access anyway.
755 * But where possible, it's probably a good idea for userspace to include these
756 * hints, forwarded to the firmware.
757 *
758 * This struct is implicitly sized and therefore is not extensible.
759 */
760struct drm_asahi_attachment {
761 /** @pointer: Base address of the attachment */
762 __u64 pointer;
763
764 /** @size: Size of the attachment in bytes */
765 __u64 size;
766
767 /** @pad: MBZ */
768 __u32 pad;
769
770 /** @flags: MBZ */
771 __u32 flags;
772};
773
774enum drm_asahi_render_flags {
775 /**
776 * @DRM_ASAHI_RENDER_VERTEX_SCRATCH: A vertex stage shader uses scratch
777 * memory.
778 */
779 DRM_ASAHI_RENDER_VERTEX_SCRATCH = (1U << 0),
780
781 /**
782 * @DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES: Process even empty tiles.
783 * This must be set when clearing render targets.
784 */
785 DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES = (1U << 1),
786
787 /**
788 * @DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING: Run vertex stage on a single
789 * cluster (on multi-cluster GPUs)
790 *
791 * This harms performance but can workaround certain sync/coherency
792 * bugs, and therefore is useful for debugging.
793 */
794 DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING = (1U << 2),
795
796 /**
797 * @DRM_ASAHI_RENDER_DBIAS_IS_INT: Use integer depth bias formula.
798 *
799 * Graphics specifications contain two alternate formulas for depth
800 * bias, a float formula used with floating-point depth buffers and an
801 * integer formula using with unorm depth buffers. This flag specifies
802 * that the integer formula should be used. If omitted, the float
803 * formula is used instead.
804 *
805 * This corresponds to bit 18 of the relevant hardware control register,
806 * so we match that here for efficiency.
807 */
808 DRM_ASAHI_RENDER_DBIAS_IS_INT = (1U << 18),
809};
810
811/**
812 * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer.
813 *
814 * These fields correspond to hardware registers in the ZLS (Z Load/Store) unit.
815 * There are three hardware registers for each field respectively for loads,
816 * stores, and partial renders. In practice, it makes sense to set all to the
817 * same values, except in exceptional cases not yet implemented in userspace, so
818 * we do not duplicate here for simplicity/efficiency.
819 *
820 * This struct is embedded in other structs and therefore is not extensible.
821 */
822struct drm_asahi_zls_buffer {
823 /** @base: Base address of the buffer */
824 __u64 base;
825
826 /**
827 * @comp_base: If the load buffer is compressed, address of the
828 * compression metadata section.
829 */
830 __u64 comp_base;
831
832 /**
833 * @stride: If layered rendering is enabled, the number of bytes
834 * between each layer of the buffer.
835 */
836 __u32 stride;
837
838 /**
839 * @comp_stride: If layered rendering is enabled, the number of bytes
840 * between each layer of the compression metadata.
841 */
842 __u32 comp_stride;
843};
844
845/**
846 * struct drm_asahi_timestamp - Describe a timestamp write.
847 *
848 * The firmware can optionally write the GPU timestamp at render pass
849 * granularities, but it needs to be mapped specially via
850 * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to
851 * write as a handle-offset pair, rather than a GPU address like normal.
852 *
853 * This struct is embedded in other structs and therefore is not extensible.
854 */
855struct drm_asahi_timestamp {
856 /**
857 * @handle: Handle of the timestamp buffer, or 0 to skip this
858 * timestamp. If nonzero, this must equal the value returned in
859 * drm_asahi_gem_bind_object::object_handle.
860 */
861 __u32 handle;
862
863 /** @offset: Offset to write into the timestamp buffer */
864 __u32 offset;
865};
866
867/**
868 * struct drm_asahi_timestamps - Describe timestamp writes.
869 *
870 * Each operation that can be timestamped, can be timestamped at the start and
871 * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled
872 * together into drm_asahi_timestamps.
873 *
874 * This struct is embedded in other structs and therefore is not extensible.
875 */
876struct drm_asahi_timestamps {
877 /** @start: Timestamp recorded at the start of the operation */
878 struct drm_asahi_timestamp start;
879
880 /** @end: Timestamp recorded at the end of the operation */
881 struct drm_asahi_timestamp end;
882};
883
884/**
885 * struct drm_asahi_helper_program - Describe helper program configuration.
886 *
887 * The helper program is a compute-like kernel required for various hardware
888 * functionality. Its most important role is dynamically allocating
889 * scratch/stack memory for individual subgroups, by partitioning a static
890 * allocation shared for the whole device. It is supplied by userspace via
891 * drm_asahi_helper_program and internally dispatched by the hardware as needed.
892 *
893 * This struct is embedded in other structs and therefore is not extensible.
894 */
895struct drm_asahi_helper_program {
896 /**
897 * @binary: USC address to the helper program binary. This is a tagged
898 * pointer with configuration in the bottom bits.
899 */
900 __u32 binary;
901
902 /** @cfg: Additional configuration bits for the helper program. */
903 __u32 cfg;
904
905 /**
906 * @data: Data passed to the helper program. This value is not
907 * interpreted by the kernel, firmware, or hardware in any way. It is
908 * simply a sideband for userspace, set with the submit ioctl and read
909 * via special registers inside the helper program.
910 *
911 * In practice, userspace will pass a 64-bit GPU VA here pointing to the
912 * actual arguments, which presumably don't fit in 64-bits.
913 */
914 __u64 data;
915};
916
917/**
918 * struct drm_asahi_bg_eot - Describe a background or end-of-tile program.
919 *
920 * The background and end-of-tile programs are dispatched by the hardware at the
921 * beginning and end of rendering. As the hardware "tilebuffer" is simply local
922 * memory, these programs are necessary to implement API-level render targets.
923 * The fragment-like background program is responsible for loading either the
924 * clear colour or the existing render target contents, while the compute-like
925 * end-of-tile program stores the tilebuffer contents to memory.
926 *
927 * This struct is embedded in other structs and therefore is not extensible.
928 */
929struct drm_asahi_bg_eot {
930 /**
931 * @usc: USC address of the hardware USC words binding resources
932 * (including images and uniforms) and the program itself. Note this is
933 * an additional layer of indirection compared to the helper program,
934 * avoiding the need for a sideband for data. This is a tagged pointer
935 * with additional configuration in the bottom bits.
936 */
937 __u32 usc;
938
939 /**
940 * @rsrc_spec: Resource specifier for the program. This is a packed
941 * hardware data structure describing the required number of registers,
942 * uniforms, bound textures, and bound samplers.
943 */
944 __u32 rsrc_spec;
945};
946
947/**
948 * struct drm_asahi_cmd_render - Command to submit 3D
949 *
950 * This command submits a single render pass. The hardware control stream may
951 * include many draws and subpasses, but within the command, the framebuffer
952 * dimensions and attachments are fixed.
953 *
954 * The hardware requires the firmware to set a large number of Control Registers
955 * setting up state at render pass granularity before each command rendering 3D.
956 * The firmware bundles this state into data structures. Unfortunately, we
957 * cannot expose either any of that directly to userspace, because the
958 * kernel-firmware ABI is not stable. Although we can guarantee the firmware
959 * updates in tandem with the kernel, we cannot break old userspace when
960 * upgrading the firmware and kernel. Therefore, we need to abstract well the
961 * data structures to avoid tying our hands with future firmwares.
962 *
963 * The bulk of drm_asahi_cmd_render therefore consists of values of hardware
964 * control registers, marshalled via the firmware interface.
965 *
966 * The framebuffer/tilebuffer dimensions are also specified here. In addition to
967 * being passed to the firmware/hardware, the kernel requires these dimensions
968 * to calculate various essential tiling-related data structures. It is
969 * unfortunate that our submits are heavier than on vendors with saner
970 * hardware-software interfaces. The upshot is all of this information is
971 * readily available to userspace with all current APIs.
972 *
973 * It looks odd - but it's not overly burdensome and it ensures we can remain
974 * compatible with old userspace.
975 */
976struct drm_asahi_cmd_render {
977 /** @flags: Combination of drm_asahi_render_flags flags. */
978 __u32 flags;
979
980 /**
981 * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the
982 * depth/stencil width/height, which may differ from the framebuffer
983 * width/height.
984 */
985 __u32 isp_zls_pixels;
986
987 /**
988 * @vdm_ctrl_stream_base: VDM_CTRL_STREAM_BASE register value. GPU
989 * address to the beginning of the VDM control stream.
990 */
991 __u64 vdm_ctrl_stream_base;
992
993 /** @vertex_helper: Helper program used for the vertex shader */
994 struct drm_asahi_helper_program vertex_helper;
995
996 /** @fragment_helper: Helper program used for the fragment shader */
997 struct drm_asahi_helper_program fragment_helper;
998
999 /**
1000 * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an
1001 * array of scissor descriptors indexed in the render pass.
1002 */
1003 __u64 isp_scissor_base;
1004
1005 /**
1006 * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an
1007 * array of depth bias values indexed in the render pass.
1008 */
1009 __u64 isp_dbias_base;
1010
1011 /**
1012 * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an
1013 * array of occlusion query results written by the render pass.
1014 */
1015 __u64 isp_oclqry_base;
1016
1017 /** @depth: Depth buffer */
1018 struct drm_asahi_zls_buffer depth;
1019
1020 /** @stencil: Stencil buffer */
1021 struct drm_asahi_zls_buffer stencil;
1022
1023 /** @zls_ctrl: ZLS_CTRL register value */
1024 __u64 zls_ctrl;
1025
1026 /** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */
1027 __u64 ppp_multisamplectl;
1028
1029 /**
1030 * @sampler_heap: Base address of the sampler heap. This heap is used
1031 * for both vertex shaders and fragment shaders. The registers are
1032 * per-stage, but there is no known use case for separate heaps.
1033 */
1034 __u64 sampler_heap;
1035
1036 /** @ppp_ctrl: PPP_CTRL register value */
1037 __u32 ppp_ctrl;
1038
1039 /** @width_px: Framebuffer width in pixels */
1040 __u16 width_px;
1041
1042 /** @height_px: Framebuffer height in pixels */
1043 __u16 height_px;
1044
1045 /** @layers: Number of layers in the framebuffer */
1046 __u16 layers;
1047
1048 /** @sampler_count: Number of samplers in the sampler heap. */
1049 __u16 sampler_count;
1050
1051 /** @utile_width_px: Width of a logical tilebuffer tile in pixels */
1052 __u8 utile_width_px;
1053
1054 /** @utile_height_px: Height of a logical tilebuffer tile in pixels */
1055 __u8 utile_height_px;
1056
1057 /** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */
1058 __u8 samples;
1059
1060 /** @sample_size_B: # of bytes in the tilebuffer required per sample. */
1061 __u8 sample_size_B;
1062
1063 /**
1064 * @isp_merge_upper_x: 32-bit float used in the hardware triangle
1065 * merging. Calculate as: tan(60 deg) * width.
1066 *
1067 * Making these values UAPI avoids requiring floating-point calculations
1068 * in the kernel in the hot path.
1069 */
1070 __u32 isp_merge_upper_x;
1071
1072 /**
1073 * @isp_merge_upper_y: 32-bit float. Calculate as: tan(60 deg) * height.
1074 * See @isp_merge_upper_x.
1075 */
1076 __u32 isp_merge_upper_y;
1077
1078 /** @bg: Background program run for each tile at the start */
1079 struct drm_asahi_bg_eot bg;
1080
1081 /** @eot: End-of-tile program ran for each tile at the end */
1082 struct drm_asahi_bg_eot eot;
1083
1084 /**
1085 * @partial_bg: Background program ran at the start of each tile when
1086 * resuming the render pass during a partial render.
1087 */
1088 struct drm_asahi_bg_eot partial_bg;
1089
1090 /**
1091 * @partial_eot: End-of-tile program ran at the end of each tile when
1092 * pausing the render pass during a partial render.
1093 */
1094 struct drm_asahi_bg_eot partial_eot;
1095
1096 /**
1097 * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth
1098 * buffer clear value, encoded in the depth buffer's format: either a
1099 * 32-bit float or a 16-bit unorm (with upper bits zeroed).
1100 */
1101 __u32 isp_bgobjdepth;
1102
1103 /**
1104 * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits
1105 * contain the stencil buffer clear value.
1106 */
1107 __u32 isp_bgobjvals;
1108
1109 /** @ts_vtx: Timestamps for the vertex portion of the render */
1110 struct drm_asahi_timestamps ts_vtx;
1111
1112 /** @ts_frag: Timestamps for the fragment portion of the render */
1113 struct drm_asahi_timestamps ts_frag;
1114};
1115
1116/**
1117 * struct drm_asahi_cmd_compute - Command to submit compute
1118 *
1119 * This command submits a control stream consisting of compute dispatches. There
1120 * is essentially no limit on how many compute dispatches may be included in a
1121 * single compute command, although timestamps are at command granularity.
1122 */
1123struct drm_asahi_cmd_compute {
1124 /** @flags: MBZ */
1125 __u32 flags;
1126
1127 /** @sampler_count: Number of samplers in the sampler heap. */
1128 __u32 sampler_count;
1129
1130 /**
1131 * @cdm_ctrl_stream_base: CDM_CTRL_STREAM_BASE register value. GPU
1132 * address to the beginning of the CDM control stream.
1133 */
1134 __u64 cdm_ctrl_stream_base;
1135
1136 /**
1137 * @cdm_ctrl_stream_end: GPU base address to the end of the hardware
1138 * control stream. Note this only considers the first contiguous segment
1139 * of the control stream, as the stream might jump elsewhere.
1140 */
1141 __u64 cdm_ctrl_stream_end;
1142
1143 /** @sampler_heap: Base address of the sampler heap. */
1144 __u64 sampler_heap;
1145
1146 /** @helper: Helper program used for this compute command */
1147 struct drm_asahi_helper_program helper;
1148
1149 /** @ts: Timestamps for the compute command */
1150 struct drm_asahi_timestamps ts;
1151};
1152
1153/**
1154 * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME
1155 */
1156struct drm_asahi_get_time {
1157 /** @flags: MBZ. */
1158 __u64 flags;
1159
1160 /** @gpu_timestamp: On return, the GPU timestamp in nanoseconds. */
1161 __u64 gpu_timestamp;
1162};
1163
1164/**
1165 * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number
1166 * @__access: Access type. Must be R, W or RW.
1167 * @__id: One of the DRM_ASAHI_xxx id.
1168 * @__type: Suffix of the type being passed to the IOCTL.
1169 *
1170 * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx
1171 * values instead.
1172 *
1173 * Return: An IOCTL number to be passed to ioctl() from userspace.
1174 */
1175#define DRM_IOCTL_ASAHI(__access, __id, __type) \
1176 DRM_IO##__access(DRM_COMMAND_BASE + DRM_ASAHI_##__id, \
1177 struct drm_asahi_##__type)
1178
1179/* Note: this is an enum so that it can be resolved by Rust bindgen. */
1180enum {
1181 DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOCTL_ASAHI(W, GET_PARAMS, get_params),
1182 DRM_IOCTL_ASAHI_GET_TIME = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time),
1183 DRM_IOCTL_ASAHI_VM_CREATE = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create),
1184 DRM_IOCTL_ASAHI_VM_DESTROY = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy),
1185 DRM_IOCTL_ASAHI_VM_BIND = DRM_IOCTL_ASAHI(W, VM_BIND, vm_bind),
1186 DRM_IOCTL_ASAHI_GEM_CREATE = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create),
1187 DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset),
1188 DRM_IOCTL_ASAHI_GEM_BIND_OBJECT = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object),
1189 DRM_IOCTL_ASAHI_QUEUE_CREATE = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create),
1190 DRM_IOCTL_ASAHI_QUEUE_DESTROY = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy),
1191 DRM_IOCTL_ASAHI_SUBMIT = DRM_IOCTL_ASAHI(W, SUBMIT, submit),
1192};
1193
1194#if defined(__cplusplus)
1195}
1196#endif
1197
1198#endif /* _ASAHI_DRM_H_ */