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