xref: /aosp_15_r20/external/mesa3d/src/asahi/lib/agx_iokit.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2021 Alyssa Rosenzweig
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #pragma once
7 
8 #include <stdbool.h>
9 #include "agx_bo.h"
10 
11 #if __APPLE__
12 #include <IOKit/IODataQueueClient.h>
13 #include <mach/mach.h>
14 #endif
15 
16 /*
17  * This file contains necessary defines for the macOS (IOKit) interface to the
18  * AGX accelerator, required to build a userspace graphics driver on macOS.
19  *
20  * They are not used under Linux.
21  *
22  * Information is this file was originally determined independently. More
23  * recently, names have been augmented via the oob_timestamp code sample from
24  * Project Zero [1]
25  *
26  * [1] https://bugs.chromium.org/p/project-zero/issues/detail?id=1986
27  */
28 
29 #define AGX_SERVICE_TYPE 0x100005
30 
31 enum agx_selector {
32    AGX_SELECTOR_GET_GLOBAL_IDS = 0x6,
33    AGX_SELECTOR_SET_API = 0x7,
34    AGX_SELECTOR_CREATE_COMMAND_QUEUE = 0x8,
35    AGX_SELECTOR_FREE_COMMAND_QUEUE = 0x9,
36    AGX_SELECTOR_ALLOCATE_MEM = 0xA,
37    AGX_SELECTOR_FREE_MEM = 0xB,
38    AGX_SELECTOR_CREATE_SHMEM = 0xF,
39    AGX_SELECTOR_FREE_SHMEM = 0x10,
40    AGX_SELECTOR_CREATE_NOTIFICATION_QUEUE = 0x11,
41    AGX_SELECTOR_FREE_NOTIFICATION_QUEUE = 0x12,
42    AGX_SELECTOR_SUBMIT_COMMAND_BUFFERS = 0x1E,
43    AGX_SELECTOR_GET_VERSION = 0x23,
44    AGX_NUM_SELECTORS = 0x32
45 };
46 
47 static const char *selector_table[AGX_NUM_SELECTORS] = {
48    "unk0",
49    "unk1",
50    "unk2",
51    "unk3",
52    "unk4",
53    "unk5",
54    "GET_GLOBAL_IDS",
55    "SET_API",
56    "CREATE_COMMAND_QUEUE",
57    "FREE_COMMAND_QUEUE",
58    "ALLOCATE_MEM",
59    "FREE_MEM",
60    "unkC",
61    "unkD",
62    "unkE",
63    "CREATE_SHMEM",
64    "FREE_SHMEM",
65    "CREATE_NOTIFICATION_QUEUE",
66    "FREE_NOTIFICATION_QUEUE",
67    "unk13",
68    "unk14",
69    "unk15",
70    "unk16",
71    "unk17",
72    "unk18",
73    "unk19",
74    "unk1A",
75    "unk1B",
76    "unk1C",
77    "unk1D",
78    "SUBMIT_COMMAND_BUFFERS",
79    "unk1F",
80    "unk20",
81    "unk21",
82    "unk22",
83    "GET_VERSION",
84    "unk24",
85    "unk25",
86    "unk26",
87    "unk27",
88    "unk28",
89    "unk29",
90    "unk2A",
91    "unk2B",
92    "unk2C",
93    "unk2D",
94    "unk2E",
95    "unk2F",
96    "unk30",
97    "unk31"};
98 
99 static inline const char *
wrap_selector_name(uint32_t selector)100 wrap_selector_name(uint32_t selector)
101 {
102    return (selector < AGX_NUM_SELECTORS) ? selector_table[selector] : "unk??";
103 }
104 
105 struct agx_create_command_queue_resp {
106    uint64_t id;
107    uint32_t unk2; // 90 0A 08 27
108    uint32_t unk3; // 0
109 } __attribute__((packed));
110 
111 struct agx_create_shmem_resp {
112    /* IOAccelDeviceShmemData */
113    void *map;
114    uint32_t size;
115    uint32_t id;
116 } __attribute__((packed));
117 
118 struct agx_create_notification_queue_resp {
119 #ifdef __APPLE__
120    IODataQueueMemory *queue;
121 #else
122    void *queue;
123 #endif
124    uint32_t unk2; // 1
125    uint32_t unk3; // 0
126 } __attribute__((packed));
127 
128 struct IOAccelCommandQueueSubmitArgs_Header {
129    uint32_t unk0;
130    uint32_t count;
131 };
132 
133 struct IOAccelCommandQueueSubmitArgs_Command {
134    uint32_t command_buffer_shmem_id;
135    uint32_t segment_list_shmem_id;
136    uint64_t unk1B; // 0, new in 12.x
137    uint64_t notify_1;
138    uint64_t notify_2;
139    uint32_t unk2;
140    uint32_t unk3;
141 } __attribute__((packed));
142 
143 /* Memory allocation isn't really understood yet. By comparing SHADER/CMDBUF_32
144  * vs everything else, it appears the 0x40000000 bit indicates the GPU VA must
145  * be be in the first 4GiB */
146 
147 enum agx_memory_type {
148    AGX_MEMORY_TYPE_NORMAL = 0x00000000,    /* used for user allocations */
149    AGX_MEMORY_TYPE_UNK = 0x08000000,       /* unknown */
150    AGX_MEMORY_TYPE_CMDBUF_64 = 0x18000000, /* used for command buffer storage */
151    AGX_MEMORY_TYPE_SHADER =
152       0x48000000, /* used for shader memory, with VA = 0 */
153    AGX_MEMORY_TYPE_CMDBUF_32 =
154       0x58000000, /* used for command buffers, with VA < 32-bit */
155    AGX_MEMORY_TYPE_FRAMEBUFFER = 0x00888F00, /* used for framebuffer backing */
156 };
157 
158 static inline const char *
agx_memory_type_name(uint32_t type)159 agx_memory_type_name(uint32_t type)
160 {
161    switch (type) {
162    case AGX_MEMORY_TYPE_NORMAL:
163       return "normal";
164    case AGX_MEMORY_TYPE_UNK:
165       return "unk";
166    case AGX_MEMORY_TYPE_CMDBUF_64:
167       return "cmdbuf_64";
168    case AGX_MEMORY_TYPE_SHADER:
169       return "shader";
170    case AGX_MEMORY_TYPE_CMDBUF_32:
171       return "cmdbuf_32";
172    case AGX_MEMORY_TYPE_FRAMEBUFFER:
173       return "framebuffer";
174    default:
175       return NULL;
176    }
177 }
178 
179 struct agx_allocate_resource_req {
180    uint32_t unk0[5];
181    uint32_t mode;
182    uint32_t unk6[6];
183    uint64_t cpu_fixed;
184    uint64_t cpu_fixed_parent;
185    uint32_t size;
186    uint32_t unk17;
187 
188    /* Handle of the parent resource when a suballocation is requested.
189     * Based on an assertion failure, this corresponds to:
190     *
191     * -[IOGPUMetalBuffer
192     * initWithPrimaryBuffer:heapIndex:bufferIndex:bufferOffset:length:args:argsSize:]
193     */
194    uint32_t parent;
195 
196    uint32_t unk19;
197    uint32_t flags;
198    uint32_t unk21[3];
199 } __attribute__((packed));
200 
201 struct agx_allocate_resource_resp {
202    /* Returned GPU virtual address */
203    uint64_t gpu_va;
204 
205    /* Returned CPU virtual address */
206    uint64_t cpu;
207 
208    uint32_t unk4[3];
209 
210    /* Handle used to identify the resource in the segment list */
211    uint32_t handle;
212 
213    /* Size of the root resource from which we are allocated. If this is not a
214     * suballocation, this is equal to the size.
215     */
216    uint64_t root_size;
217 
218    /* Globally unique identifier for the resource, shown in Instruments */
219    uint32_t guid;
220 
221    uint32_t unk11[7];
222 
223    /* Maximum size of the suballocation. For a suballocation, this equals:
224     *
225     *    sub_size = root_size - (sub_cpu - root_cpu)
226     *
227     * For root allocations, this equals the size.
228     */
229    uint64_t sub_size;
230 } __attribute__((packed));
231 
232 struct agx_notification_queue {
233 #ifdef __APPLE__
234    mach_port_t port;
235    IODataQueueMemory *queue;
236 #else
237    unsigned port;
238    void *queue;
239 #endif
240    unsigned id;
241 };
242 
243 struct agx_command_queue {
244    unsigned id;
245    struct agx_notification_queue notif;
246 };
247 
248 struct agx_map_header {
249    /* IOAccelSegmentListHeader */
250    uint64_t cmdbuf_id; // GUID
251    uint32_t segment_count;
252    uint16_t length;
253    uint16_t unk;        // 0x8000
254    uint64_t encoder_id; // GUID
255 
256    /* IOAccelSegmentResourceListHeader */
257    uint32_t kernel_commands_start_offset;
258    uint32_t kernel_commands_end_offset;
259    uint32_t padding[2];
260    uint32_t total_resources;
261    uint32_t resource_group_count;
262 } __attribute__((packed));
263 
264 /* IOAccelSegmentResourceList_ResourceGroup */
265 struct agx_map_entry {
266    uint32_t resource_id[6];
267    uint32_t resource_unk[6];
268    uint16_t resource_flags[6];
269    uint16_t unka; // ff ff
270    uint16_t resource_count;
271 } __attribute__((packed));
272 
273 uint64_t agx_get_global_id(struct agx_device *dev);
274