xref: /aosp_15_r20/external/mesa3d/src/asahi/lib/agx_device.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2021 Alyssa Rosenzweig
3*61046927SAndroid Build Coastguard Worker  * Copyright 2019 Collabora, Ltd.
4*61046927SAndroid Build Coastguard Worker  * Copyright 2020 Igalia S.L.
5*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
6*61046927SAndroid Build Coastguard Worker  */
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #include "agx_device.h"
9*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
10*61046927SAndroid Build Coastguard Worker #include "util/ralloc.h"
11*61046927SAndroid Build Coastguard Worker #include "util/timespec.h"
12*61046927SAndroid Build Coastguard Worker #include "agx_bo.h"
13*61046927SAndroid Build Coastguard Worker #include "agx_compile.h"
14*61046927SAndroid Build Coastguard Worker #include "agx_device_virtio.h"
15*61046927SAndroid Build Coastguard Worker #include "agx_scratch.h"
16*61046927SAndroid Build Coastguard Worker #include "decode.h"
17*61046927SAndroid Build Coastguard Worker #include "glsl_types.h"
18*61046927SAndroid Build Coastguard Worker #include "libagx_shaders.h"
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
21*61046927SAndroid Build Coastguard Worker #include <xf86drm.h>
22*61046927SAndroid Build Coastguard Worker #include "drm-uapi/dma-buf.h"
23*61046927SAndroid Build Coastguard Worker #include "util/blob.h"
24*61046927SAndroid Build Coastguard Worker #include "util/log.h"
25*61046927SAndroid Build Coastguard Worker #include "util/mesa-sha1.h"
26*61046927SAndroid Build Coastguard Worker #include "util/os_file.h"
27*61046927SAndroid Build Coastguard Worker #include "util/os_mman.h"
28*61046927SAndroid Build Coastguard Worker #include "util/os_time.h"
29*61046927SAndroid Build Coastguard Worker #include "util/simple_mtx.h"
30*61046927SAndroid Build Coastguard Worker #include "git_sha1.h"
31*61046927SAndroid Build Coastguard Worker #include "nir_serialize.h"
32*61046927SAndroid Build Coastguard Worker #include "unstable_asahi_drm.h"
33*61046927SAndroid Build Coastguard Worker #include "vdrm.h"
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker static inline int
asahi_simple_ioctl(struct agx_device * dev,unsigned cmd,void * req)36*61046927SAndroid Build Coastguard Worker asahi_simple_ioctl(struct agx_device *dev, unsigned cmd, void *req)
37*61046927SAndroid Build Coastguard Worker {
38*61046927SAndroid Build Coastguard Worker    if (dev->is_virtio) {
39*61046927SAndroid Build Coastguard Worker       return agx_virtio_simple_ioctl(dev, cmd, req);
40*61046927SAndroid Build Coastguard Worker    } else {
41*61046927SAndroid Build Coastguard Worker       return drmIoctl(dev->fd, cmd, req);
42*61046927SAndroid Build Coastguard Worker    }
43*61046927SAndroid Build Coastguard Worker }
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker /* clang-format off */
46*61046927SAndroid Build Coastguard Worker static const struct debug_named_value agx_debug_options[] = {
47*61046927SAndroid Build Coastguard Worker    {"trace",     AGX_DBG_TRACE,    "Trace the command stream"},
48*61046927SAndroid Build Coastguard Worker    {"no16",      AGX_DBG_NO16,     "Disable 16-bit support"},
49*61046927SAndroid Build Coastguard Worker    {"perf",      AGX_DBG_PERF,     "Print performance warnings"},
50*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
51*61046927SAndroid Build Coastguard Worker    {"dirty",     AGX_DBG_DIRTY,    "Disable dirty tracking"},
52*61046927SAndroid Build Coastguard Worker #endif
53*61046927SAndroid Build Coastguard Worker    {"precompile",AGX_DBG_PRECOMPILE,"Precompile shaders for shader-db"},
54*61046927SAndroid Build Coastguard Worker    {"nocompress",AGX_DBG_NOCOMPRESS,"Disable lossless compression"},
55*61046927SAndroid Build Coastguard Worker    {"nocluster", AGX_DBG_NOCLUSTER,"Disable vertex clustering"},
56*61046927SAndroid Build Coastguard Worker    {"sync",      AGX_DBG_SYNC,     "Synchronously wait for all submissions"},
57*61046927SAndroid Build Coastguard Worker    {"stats",     AGX_DBG_STATS,    "Show command execution statistics"},
58*61046927SAndroid Build Coastguard Worker    {"resource",  AGX_DBG_RESOURCE, "Log resource operations"},
59*61046927SAndroid Build Coastguard Worker    {"batch",     AGX_DBG_BATCH,    "Log batches"},
60*61046927SAndroid Build Coastguard Worker    {"nowc",      AGX_DBG_NOWC,     "Disable write-combining"},
61*61046927SAndroid Build Coastguard Worker    {"synctvb",   AGX_DBG_SYNCTVB,  "Synchronous TVB growth"},
62*61046927SAndroid Build Coastguard Worker    {"smalltile", AGX_DBG_SMALLTILE,"Force 16x16 tiles"},
63*61046927SAndroid Build Coastguard Worker    {"feedback",  AGX_DBG_FEEDBACK, "Debug feedback loops"},
64*61046927SAndroid Build Coastguard Worker    {"nomsaa",    AGX_DBG_NOMSAA,   "Force disable MSAA"},
65*61046927SAndroid Build Coastguard Worker    {"noshadow",  AGX_DBG_NOSHADOW, "Force disable resource shadowing"},
66*61046927SAndroid Build Coastguard Worker    {"scratch",   AGX_DBG_SCRATCH,  "Debug scratch memory usage"},
67*61046927SAndroid Build Coastguard Worker    {"1queue",    AGX_DBG_1QUEUE,   "Force usage of a single queue for multiple contexts"},
68*61046927SAndroid Build Coastguard Worker    DEBUG_NAMED_VALUE_END
69*61046927SAndroid Build Coastguard Worker };
70*61046927SAndroid Build Coastguard Worker /* clang-format on */
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker void
agx_bo_free(struct agx_device * dev,struct agx_bo * bo)73*61046927SAndroid Build Coastguard Worker agx_bo_free(struct agx_device *dev, struct agx_bo *bo)
74*61046927SAndroid Build Coastguard Worker {
75*61046927SAndroid Build Coastguard Worker    const uint64_t handle = bo->handle;
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker    if (bo->map)
78*61046927SAndroid Build Coastguard Worker       munmap(bo->map, bo->size);
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker    /* Free the VA. No need to unmap the BO, as the kernel will take care of that
81*61046927SAndroid Build Coastguard Worker     * when we close it.
82*61046927SAndroid Build Coastguard Worker     */
83*61046927SAndroid Build Coastguard Worker    agx_va_free(dev, bo->va);
84*61046927SAndroid Build Coastguard Worker 
85*61046927SAndroid Build Coastguard Worker    if (bo->prime_fd != -1)
86*61046927SAndroid Build Coastguard Worker       close(bo->prime_fd);
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker    /* Reset the handle. This has to happen before the GEM close to avoid a race.
89*61046927SAndroid Build Coastguard Worker     */
90*61046927SAndroid Build Coastguard Worker    memset(bo, 0, sizeof(*bo));
91*61046927SAndroid Build Coastguard Worker    __sync_synchronize();
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker    struct drm_gem_close args = {.handle = handle};
94*61046927SAndroid Build Coastguard Worker    drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &args);
95*61046927SAndroid Build Coastguard Worker }
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker static int
agx_bo_bind(struct agx_device * dev,struct agx_bo * bo,uint64_t addr,size_t size_B,uint64_t offset_B,uint32_t flags,bool unbind)98*61046927SAndroid Build Coastguard Worker agx_bo_bind(struct agx_device *dev, struct agx_bo *bo, uint64_t addr,
99*61046927SAndroid Build Coastguard Worker             size_t size_B, uint64_t offset_B, uint32_t flags, bool unbind)
100*61046927SAndroid Build Coastguard Worker {
101*61046927SAndroid Build Coastguard Worker    struct drm_asahi_gem_bind gem_bind = {
102*61046927SAndroid Build Coastguard Worker       .op = unbind ? ASAHI_BIND_OP_UNBIND : ASAHI_BIND_OP_BIND,
103*61046927SAndroid Build Coastguard Worker       .flags = flags,
104*61046927SAndroid Build Coastguard Worker       .handle = bo->handle,
105*61046927SAndroid Build Coastguard Worker       .vm_id = dev->vm_id,
106*61046927SAndroid Build Coastguard Worker       .offset = offset_B,
107*61046927SAndroid Build Coastguard Worker       .range = size_B,
108*61046927SAndroid Build Coastguard Worker       .addr = addr,
109*61046927SAndroid Build Coastguard Worker    };
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker    int ret = drmIoctl(dev->fd, DRM_IOCTL_ASAHI_GEM_BIND, &gem_bind);
112*61046927SAndroid Build Coastguard Worker    if (ret) {
113*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "DRM_IOCTL_ASAHI_GEM_BIND failed: %m (handle=%d)\n",
114*61046927SAndroid Build Coastguard Worker               bo->handle);
115*61046927SAndroid Build Coastguard Worker    }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    return ret;
118*61046927SAndroid Build Coastguard Worker }
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker static struct agx_bo *
agx_bo_alloc(struct agx_device * dev,size_t size,size_t align,enum agx_bo_flags flags)121*61046927SAndroid Build Coastguard Worker agx_bo_alloc(struct agx_device *dev, size_t size, size_t align,
122*61046927SAndroid Build Coastguard Worker              enum agx_bo_flags flags)
123*61046927SAndroid Build Coastguard Worker {
124*61046927SAndroid Build Coastguard Worker    struct agx_bo *bo;
125*61046927SAndroid Build Coastguard Worker    unsigned handle = 0;
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker    assert(size > 0);
128*61046927SAndroid Build Coastguard Worker    size = ALIGN_POT(size, dev->params.vm_page_size);
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker    /* executable implies low va */
131*61046927SAndroid Build Coastguard Worker    assert(!(flags & AGX_BO_EXEC) || (flags & AGX_BO_LOW_VA));
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker    struct drm_asahi_gem_create gem_create = {.size = size};
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker    if (flags & AGX_BO_WRITEBACK)
136*61046927SAndroid Build Coastguard Worker       gem_create.flags |= ASAHI_GEM_WRITEBACK;
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker    if (!(flags & (AGX_BO_SHARED | AGX_BO_SHAREABLE))) {
139*61046927SAndroid Build Coastguard Worker       gem_create.flags |= ASAHI_GEM_VM_PRIVATE;
140*61046927SAndroid Build Coastguard Worker       gem_create.vm_id = dev->vm_id;
141*61046927SAndroid Build Coastguard Worker    }
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker    int ret = drmIoctl(dev->fd, DRM_IOCTL_ASAHI_GEM_CREATE, &gem_create);
144*61046927SAndroid Build Coastguard Worker    if (ret) {
145*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "DRM_IOCTL_ASAHI_GEM_CREATE failed: %m\n");
146*61046927SAndroid Build Coastguard Worker       return NULL;
147*61046927SAndroid Build Coastguard Worker    }
148*61046927SAndroid Build Coastguard Worker 
149*61046927SAndroid Build Coastguard Worker    handle = gem_create.handle;
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    pthread_mutex_lock(&dev->bo_map_lock);
152*61046927SAndroid Build Coastguard Worker    bo = agx_lookup_bo(dev, handle);
153*61046927SAndroid Build Coastguard Worker    dev->max_handle = MAX2(dev->max_handle, handle);
154*61046927SAndroid Build Coastguard Worker    pthread_mutex_unlock(&dev->bo_map_lock);
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    /* Fresh handle */
157*61046927SAndroid Build Coastguard Worker    assert(!memcmp(bo, &((struct agx_bo){}), sizeof(*bo)));
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker    bo->size = gem_create.size;
160*61046927SAndroid Build Coastguard Worker    bo->align = MAX2(dev->params.vm_page_size, align);
161*61046927SAndroid Build Coastguard Worker    bo->flags = flags;
162*61046927SAndroid Build Coastguard Worker    bo->handle = handle;
163*61046927SAndroid Build Coastguard Worker    bo->prime_fd = -1;
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    enum agx_va_flags va_flags = flags & AGX_BO_LOW_VA ? AGX_VA_USC : 0;
166*61046927SAndroid Build Coastguard Worker    bo->va = agx_va_alloc(dev, size, bo->align, va_flags, 0);
167*61046927SAndroid Build Coastguard Worker    if (!bo->va) {
168*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Failed to allocate BO VMA\n");
169*61046927SAndroid Build Coastguard Worker       agx_bo_free(dev, bo);
170*61046927SAndroid Build Coastguard Worker       return NULL;
171*61046927SAndroid Build Coastguard Worker    }
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker    uint32_t bind = ASAHI_BIND_READ;
174*61046927SAndroid Build Coastguard Worker    if (!(flags & AGX_BO_READONLY)) {
175*61046927SAndroid Build Coastguard Worker       bind |= ASAHI_BIND_WRITE;
176*61046927SAndroid Build Coastguard Worker    }
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker    ret = dev->ops.bo_bind(dev, bo, bo->va->addr, bo->size, 0, bind, false);
179*61046927SAndroid Build Coastguard Worker    if (ret) {
180*61046927SAndroid Build Coastguard Worker       agx_bo_free(dev, bo);
181*61046927SAndroid Build Coastguard Worker       return NULL;
182*61046927SAndroid Build Coastguard Worker    }
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker    dev->ops.bo_mmap(dev, bo);
185*61046927SAndroid Build Coastguard Worker    return bo;
186*61046927SAndroid Build Coastguard Worker }
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker static void
agx_bo_mmap(struct agx_device * dev,struct agx_bo * bo)189*61046927SAndroid Build Coastguard Worker agx_bo_mmap(struct agx_device *dev, struct agx_bo *bo)
190*61046927SAndroid Build Coastguard Worker {
191*61046927SAndroid Build Coastguard Worker    struct drm_asahi_gem_mmap_offset gem_mmap_offset = {.handle = bo->handle};
192*61046927SAndroid Build Coastguard Worker    int ret;
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker    if (bo->map)
195*61046927SAndroid Build Coastguard Worker       return;
196*61046927SAndroid Build Coastguard Worker 
197*61046927SAndroid Build Coastguard Worker    ret = drmIoctl(dev->fd, DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET, &gem_mmap_offset);
198*61046927SAndroid Build Coastguard Worker    if (ret) {
199*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "DRM_IOCTL_ASAHI_MMAP_BO failed: %m\n");
200*61046927SAndroid Build Coastguard Worker       assert(0);
201*61046927SAndroid Build Coastguard Worker    }
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker    bo->map = os_mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
204*61046927SAndroid Build Coastguard Worker                      dev->fd, gem_mmap_offset.offset);
205*61046927SAndroid Build Coastguard Worker    if (bo->map == MAP_FAILED) {
206*61046927SAndroid Build Coastguard Worker       bo->map = NULL;
207*61046927SAndroid Build Coastguard Worker       fprintf(stderr,
208*61046927SAndroid Build Coastguard Worker               "mmap failed: result=%p size=0x%llx fd=%i offset=0x%llx %m\n",
209*61046927SAndroid Build Coastguard Worker               bo->map, (long long)bo->size, dev->fd,
210*61046927SAndroid Build Coastguard Worker               (long long)gem_mmap_offset.offset);
211*61046927SAndroid Build Coastguard Worker    }
212*61046927SAndroid Build Coastguard Worker }
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker struct agx_bo *
agx_bo_import(struct agx_device * dev,int fd)215*61046927SAndroid Build Coastguard Worker agx_bo_import(struct agx_device *dev, int fd)
216*61046927SAndroid Build Coastguard Worker {
217*61046927SAndroid Build Coastguard Worker    struct agx_bo *bo;
218*61046927SAndroid Build Coastguard Worker    ASSERTED int ret;
219*61046927SAndroid Build Coastguard Worker    unsigned gem_handle;
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker    pthread_mutex_lock(&dev->bo_map_lock);
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker    ret = drmPrimeFDToHandle(dev->fd, fd, &gem_handle);
224*61046927SAndroid Build Coastguard Worker    if (ret) {
225*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "import failed: Could not map fd %d to handle\n", fd);
226*61046927SAndroid Build Coastguard Worker       pthread_mutex_unlock(&dev->bo_map_lock);
227*61046927SAndroid Build Coastguard Worker       return NULL;
228*61046927SAndroid Build Coastguard Worker    }
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker    bo = agx_lookup_bo(dev, gem_handle);
231*61046927SAndroid Build Coastguard Worker    dev->max_handle = MAX2(dev->max_handle, gem_handle);
232*61046927SAndroid Build Coastguard Worker 
233*61046927SAndroid Build Coastguard Worker    if (!bo->size) {
234*61046927SAndroid Build Coastguard Worker       bo->size = lseek(fd, 0, SEEK_END);
235*61046927SAndroid Build Coastguard Worker       bo->align = dev->params.vm_page_size;
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker       /* Sometimes this can fail and return -1. size of -1 is not
238*61046927SAndroid Build Coastguard Worker        * a nice thing for mmap to try mmap. Be more robust also
239*61046927SAndroid Build Coastguard Worker        * for zero sized maps and fail nicely too
240*61046927SAndroid Build Coastguard Worker        */
241*61046927SAndroid Build Coastguard Worker       if ((bo->size == 0) || (bo->size == (size_t)-1)) {
242*61046927SAndroid Build Coastguard Worker          pthread_mutex_unlock(&dev->bo_map_lock);
243*61046927SAndroid Build Coastguard Worker          return NULL;
244*61046927SAndroid Build Coastguard Worker       }
245*61046927SAndroid Build Coastguard Worker       if (bo->size & (dev->params.vm_page_size - 1)) {
246*61046927SAndroid Build Coastguard Worker          fprintf(
247*61046927SAndroid Build Coastguard Worker             stderr,
248*61046927SAndroid Build Coastguard Worker             "import failed: BO is not a multiple of the page size (0x%llx bytes)\n",
249*61046927SAndroid Build Coastguard Worker             (long long)bo->size);
250*61046927SAndroid Build Coastguard Worker          goto error;
251*61046927SAndroid Build Coastguard Worker       }
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker       bo->flags = AGX_BO_SHARED | AGX_BO_SHAREABLE;
254*61046927SAndroid Build Coastguard Worker       bo->handle = gem_handle;
255*61046927SAndroid Build Coastguard Worker       bo->prime_fd = os_dupfd_cloexec(fd);
256*61046927SAndroid Build Coastguard Worker       bo->label = "Imported BO";
257*61046927SAndroid Build Coastguard Worker       assert(bo->prime_fd >= 0);
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker       p_atomic_set(&bo->refcnt, 1);
260*61046927SAndroid Build Coastguard Worker       bo->va = agx_va_alloc(dev, bo->size, bo->align, 0, 0);
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker       if (!bo->va) {
263*61046927SAndroid Build Coastguard Worker          fprintf(
264*61046927SAndroid Build Coastguard Worker             stderr,
265*61046927SAndroid Build Coastguard Worker             "import failed: Could not allocate from VMA heap (0x%llx bytes)\n",
266*61046927SAndroid Build Coastguard Worker             (long long)bo->size);
267*61046927SAndroid Build Coastguard Worker          abort();
268*61046927SAndroid Build Coastguard Worker       }
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker       if (dev->is_virtio) {
271*61046927SAndroid Build Coastguard Worker          bo->vbo_res_id = vdrm_handle_to_res_id(dev->vdrm, bo->handle);
272*61046927SAndroid Build Coastguard Worker       }
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker       ret = dev->ops.bo_bind(dev, bo, bo->va->addr, bo->size, 0,
275*61046927SAndroid Build Coastguard Worker                              ASAHI_BIND_READ | ASAHI_BIND_WRITE, false);
276*61046927SAndroid Build Coastguard Worker       if (ret) {
277*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "import failed: Could not bind BO at 0x%llx\n",
278*61046927SAndroid Build Coastguard Worker                  (long long)bo->va->addr);
279*61046927SAndroid Build Coastguard Worker          abort();
280*61046927SAndroid Build Coastguard Worker       }
281*61046927SAndroid Build Coastguard Worker    } else {
282*61046927SAndroid Build Coastguard Worker       /* bo->refcnt == 0 can happen if the BO
283*61046927SAndroid Build Coastguard Worker        * was being released but agx_bo_import() acquired the
284*61046927SAndroid Build Coastguard Worker        * lock before agx_bo_unreference(). In that case, refcnt
285*61046927SAndroid Build Coastguard Worker        * is 0 and we can't use agx_bo_reference() directly, we
286*61046927SAndroid Build Coastguard Worker        * have to re-initialize the refcnt().
287*61046927SAndroid Build Coastguard Worker        * Note that agx_bo_unreference() checks
288*61046927SAndroid Build Coastguard Worker        * refcnt value just after acquiring the lock to
289*61046927SAndroid Build Coastguard Worker        * make sure the object is not freed if agx_bo_import()
290*61046927SAndroid Build Coastguard Worker        * acquired it in the meantime.
291*61046927SAndroid Build Coastguard Worker        */
292*61046927SAndroid Build Coastguard Worker       if (p_atomic_read(&bo->refcnt) == 0)
293*61046927SAndroid Build Coastguard Worker          p_atomic_set(&bo->refcnt, 1);
294*61046927SAndroid Build Coastguard Worker       else
295*61046927SAndroid Build Coastguard Worker          agx_bo_reference(bo);
296*61046927SAndroid Build Coastguard Worker    }
297*61046927SAndroid Build Coastguard Worker    pthread_mutex_unlock(&dev->bo_map_lock);
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker    if (dev->debug & AGX_DBG_TRACE)
300*61046927SAndroid Build Coastguard Worker       agxdecode_track_alloc(dev->agxdecode, bo);
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker    return bo;
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker error:
305*61046927SAndroid Build Coastguard Worker    memset(bo, 0, sizeof(*bo));
306*61046927SAndroid Build Coastguard Worker    pthread_mutex_unlock(&dev->bo_map_lock);
307*61046927SAndroid Build Coastguard Worker    return NULL;
308*61046927SAndroid Build Coastguard Worker }
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker int
agx_bo_export(struct agx_device * dev,struct agx_bo * bo)311*61046927SAndroid Build Coastguard Worker agx_bo_export(struct agx_device *dev, struct agx_bo *bo)
312*61046927SAndroid Build Coastguard Worker {
313*61046927SAndroid Build Coastguard Worker    int fd;
314*61046927SAndroid Build Coastguard Worker 
315*61046927SAndroid Build Coastguard Worker    assert(bo->flags & AGX_BO_SHAREABLE);
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker    if (drmPrimeHandleToFD(dev->fd, bo->handle, DRM_CLOEXEC, &fd))
318*61046927SAndroid Build Coastguard Worker       return -1;
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker    if (!(bo->flags & AGX_BO_SHARED)) {
321*61046927SAndroid Build Coastguard Worker       bo->flags |= AGX_BO_SHARED;
322*61046927SAndroid Build Coastguard Worker       assert(bo->prime_fd == -1);
323*61046927SAndroid Build Coastguard Worker       bo->prime_fd = os_dupfd_cloexec(fd);
324*61046927SAndroid Build Coastguard Worker 
325*61046927SAndroid Build Coastguard Worker       /* If there is a pending writer to this BO, import it into the buffer
326*61046927SAndroid Build Coastguard Worker        * for implicit sync.
327*61046927SAndroid Build Coastguard Worker        */
328*61046927SAndroid Build Coastguard Worker       uint64_t writer = p_atomic_read_relaxed(&bo->writer);
329*61046927SAndroid Build Coastguard Worker       if (writer) {
330*61046927SAndroid Build Coastguard Worker          int out_sync_fd = -1;
331*61046927SAndroid Build Coastguard Worker          int ret = drmSyncobjExportSyncFile(
332*61046927SAndroid Build Coastguard Worker             dev->fd, agx_bo_writer_syncobj(writer), &out_sync_fd);
333*61046927SAndroid Build Coastguard Worker          assert(ret >= 0);
334*61046927SAndroid Build Coastguard Worker          assert(out_sync_fd >= 0);
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker          ret = agx_import_sync_file(dev, bo, out_sync_fd);
337*61046927SAndroid Build Coastguard Worker          assert(ret >= 0);
338*61046927SAndroid Build Coastguard Worker          close(out_sync_fd);
339*61046927SAndroid Build Coastguard Worker       }
340*61046927SAndroid Build Coastguard Worker    }
341*61046927SAndroid Build Coastguard Worker 
342*61046927SAndroid Build Coastguard Worker    assert(bo->prime_fd >= 0);
343*61046927SAndroid Build Coastguard Worker    return fd;
344*61046927SAndroid Build Coastguard Worker }
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker static void
agx_get_global_ids(struct agx_device * dev)347*61046927SAndroid Build Coastguard Worker agx_get_global_ids(struct agx_device *dev)
348*61046927SAndroid Build Coastguard Worker {
349*61046927SAndroid Build Coastguard Worker    dev->next_global_id = 0;
350*61046927SAndroid Build Coastguard Worker    dev->last_global_id = 0x1000000;
351*61046927SAndroid Build Coastguard Worker }
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker uint64_t
agx_get_global_id(struct agx_device * dev)354*61046927SAndroid Build Coastguard Worker agx_get_global_id(struct agx_device *dev)
355*61046927SAndroid Build Coastguard Worker {
356*61046927SAndroid Build Coastguard Worker    if (unlikely(dev->next_global_id >= dev->last_global_id)) {
357*61046927SAndroid Build Coastguard Worker       agx_get_global_ids(dev);
358*61046927SAndroid Build Coastguard Worker    }
359*61046927SAndroid Build Coastguard Worker 
360*61046927SAndroid Build Coastguard Worker    return dev->next_global_id++;
361*61046927SAndroid Build Coastguard Worker }
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker static ssize_t
agx_get_params(struct agx_device * dev,void * buf,size_t size)364*61046927SAndroid Build Coastguard Worker agx_get_params(struct agx_device *dev, void *buf, size_t size)
365*61046927SAndroid Build Coastguard Worker {
366*61046927SAndroid Build Coastguard Worker    struct drm_asahi_get_params get_param = {
367*61046927SAndroid Build Coastguard Worker       .param_group = 0,
368*61046927SAndroid Build Coastguard Worker       .pointer = (uint64_t)(uintptr_t)buf,
369*61046927SAndroid Build Coastguard Worker       .size = size,
370*61046927SAndroid Build Coastguard Worker    };
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker    memset(buf, 0, size);
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker    int ret = drmIoctl(dev->fd, DRM_IOCTL_ASAHI_GET_PARAMS, &get_param);
375*61046927SAndroid Build Coastguard Worker    if (ret) {
376*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "DRM_IOCTL_ASAHI_GET_PARAMS failed: %m\n");
377*61046927SAndroid Build Coastguard Worker       return -EINVAL;
378*61046927SAndroid Build Coastguard Worker    }
379*61046927SAndroid Build Coastguard Worker 
380*61046927SAndroid Build Coastguard Worker    return get_param.size;
381*61046927SAndroid Build Coastguard Worker }
382*61046927SAndroid Build Coastguard Worker 
383*61046927SAndroid Build Coastguard Worker static int
agx_submit(struct agx_device * dev,struct drm_asahi_submit * submit,uint32_t vbo_res_id)384*61046927SAndroid Build Coastguard Worker agx_submit(struct agx_device *dev, struct drm_asahi_submit *submit,
385*61046927SAndroid Build Coastguard Worker            uint32_t vbo_res_id)
386*61046927SAndroid Build Coastguard Worker {
387*61046927SAndroid Build Coastguard Worker    return drmIoctl(dev->fd, DRM_IOCTL_ASAHI_SUBMIT, submit);
388*61046927SAndroid Build Coastguard Worker }
389*61046927SAndroid Build Coastguard Worker 
390*61046927SAndroid Build Coastguard Worker const agx_device_ops_t agx_device_drm_ops = {
391*61046927SAndroid Build Coastguard Worker    .bo_alloc = agx_bo_alloc,
392*61046927SAndroid Build Coastguard Worker    .bo_bind = agx_bo_bind,
393*61046927SAndroid Build Coastguard Worker    .bo_mmap = agx_bo_mmap,
394*61046927SAndroid Build Coastguard Worker    .get_params = agx_get_params,
395*61046927SAndroid Build Coastguard Worker    .submit = agx_submit,
396*61046927SAndroid Build Coastguard Worker };
397*61046927SAndroid Build Coastguard Worker 
398*61046927SAndroid Build Coastguard Worker bool
agx_open_device(void * memctx,struct agx_device * dev)399*61046927SAndroid Build Coastguard Worker agx_open_device(void *memctx, struct agx_device *dev)
400*61046927SAndroid Build Coastguard Worker {
401*61046927SAndroid Build Coastguard Worker    dev->debug =
402*61046927SAndroid Build Coastguard Worker       debug_get_flags_option("ASAHI_MESA_DEBUG", agx_debug_options, 0);
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker    dev->ops = agx_device_drm_ops;
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker    ssize_t params_size = -1;
407*61046927SAndroid Build Coastguard Worker    drmVersionPtr version;
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker    version = drmGetVersion(dev->fd);
410*61046927SAndroid Build Coastguard Worker    if (!version) {
411*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "cannot get version: %s", strerror(errno));
412*61046927SAndroid Build Coastguard Worker       return NULL;
413*61046927SAndroid Build Coastguard Worker    }
414*61046927SAndroid Build Coastguard Worker 
415*61046927SAndroid Build Coastguard Worker    if (!strcmp(version->name, "asahi")) {
416*61046927SAndroid Build Coastguard Worker       dev->is_virtio = false;
417*61046927SAndroid Build Coastguard Worker       dev->ops = agx_device_drm_ops;
418*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(version->name, "virtio_gpu")) {
419*61046927SAndroid Build Coastguard Worker       dev->is_virtio = true;
420*61046927SAndroid Build Coastguard Worker       if (!agx_virtio_open_device(dev)) {
421*61046927SAndroid Build Coastguard Worker          fprintf(stderr,
422*61046927SAndroid Build Coastguard Worker                  "Error opening virtio-gpu device for Asahi native context\n");
423*61046927SAndroid Build Coastguard Worker          return false;
424*61046927SAndroid Build Coastguard Worker       }
425*61046927SAndroid Build Coastguard Worker    } else {
426*61046927SAndroid Build Coastguard Worker       return false;
427*61046927SAndroid Build Coastguard Worker    }
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker    params_size = dev->ops.get_params(dev, &dev->params, sizeof(dev->params));
430*61046927SAndroid Build Coastguard Worker    if (params_size <= 0) {
431*61046927SAndroid Build Coastguard Worker       assert(0);
432*61046927SAndroid Build Coastguard Worker       return false;
433*61046927SAndroid Build Coastguard Worker    }
434*61046927SAndroid Build Coastguard Worker    assert(params_size >= sizeof(dev->params));
435*61046927SAndroid Build Coastguard Worker 
436*61046927SAndroid Build Coastguard Worker    /* Refuse to probe. */
437*61046927SAndroid Build Coastguard Worker    if (dev->params.unstable_uabi_version != DRM_ASAHI_UNSTABLE_UABI_VERSION) {
438*61046927SAndroid Build Coastguard Worker       fprintf(
439*61046927SAndroid Build Coastguard Worker          stderr,
440*61046927SAndroid Build Coastguard Worker          "You are attempting to use upstream Mesa with a downstream kernel!\n"
441*61046927SAndroid Build Coastguard Worker          "This WILL NOT work.\n"
442*61046927SAndroid Build Coastguard Worker          "The Asahi UABI is unstable and NOT SUPPORTED in upstream Mesa.\n"
443*61046927SAndroid Build Coastguard Worker          "UABI related code in upstream Mesa is not for use!\n"
444*61046927SAndroid Build Coastguard Worker          "\n"
445*61046927SAndroid Build Coastguard Worker          "Do NOT attempt to patch out checks, you WILL break your system.\n"
446*61046927SAndroid Build Coastguard Worker          "Do NOT report bugs.\n"
447*61046927SAndroid Build Coastguard Worker          "Do NOT ask Mesa developers for support.\n"
448*61046927SAndroid Build Coastguard Worker          "Do NOT write guides about how to patch out these checks.\n"
449*61046927SAndroid Build Coastguard Worker          "Do NOT package patches to Mesa to bypass this.\n"
450*61046927SAndroid Build Coastguard Worker          "\n"
451*61046927SAndroid Build Coastguard Worker          "~~~\n"
452*61046927SAndroid Build Coastguard Worker          "This is not a place of honor.\n"
453*61046927SAndroid Build Coastguard Worker          "No highly esteemed deed is commemorated here.\n"
454*61046927SAndroid Build Coastguard Worker          "Nothing valued is here.\n"
455*61046927SAndroid Build Coastguard Worker          "\n"
456*61046927SAndroid Build Coastguard Worker          "What is here was dangerous and repulsive to us.\n"
457*61046927SAndroid Build Coastguard Worker          "This message is a warning about danger.\n"
458*61046927SAndroid Build Coastguard Worker          "\n"
459*61046927SAndroid Build Coastguard Worker          "The danger is still present, in your time, as it was in ours.\n"
460*61046927SAndroid Build Coastguard Worker          "The danger is unleashed only if you substantially disturb this place physically.\n"
461*61046927SAndroid Build Coastguard Worker          "This place is best shunned and left uninhabited.\n"
462*61046927SAndroid Build Coastguard Worker          "~~~\n"
463*61046927SAndroid Build Coastguard Worker          "\n"
464*61046927SAndroid Build Coastguard Worker          "THIS IS NOT A BUG. THIS IS YOU DOING SOMETHING BROKEN!\n");
465*61046927SAndroid Build Coastguard Worker       abort();
466*61046927SAndroid Build Coastguard Worker    }
467*61046927SAndroid Build Coastguard Worker 
468*61046927SAndroid Build Coastguard Worker    uint64_t incompat =
469*61046927SAndroid Build Coastguard Worker       dev->params.feat_incompat & (~AGX_SUPPORTED_INCOMPAT_FEATURES);
470*61046927SAndroid Build Coastguard Worker    if (incompat) {
471*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Missing GPU incompat features: 0x%" PRIx64 "\n",
472*61046927SAndroid Build Coastguard Worker               incompat);
473*61046927SAndroid Build Coastguard Worker       assert(0);
474*61046927SAndroid Build Coastguard Worker       return false;
475*61046927SAndroid Build Coastguard Worker    }
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker    assert(dev->params.gpu_generation >= 13);
478*61046927SAndroid Build Coastguard Worker    const char *variant = " Unknown";
479*61046927SAndroid Build Coastguard Worker    switch (dev->params.gpu_variant) {
480*61046927SAndroid Build Coastguard Worker    case 'G':
481*61046927SAndroid Build Coastguard Worker       variant = "";
482*61046927SAndroid Build Coastguard Worker       break;
483*61046927SAndroid Build Coastguard Worker    case 'S':
484*61046927SAndroid Build Coastguard Worker       variant = " Pro";
485*61046927SAndroid Build Coastguard Worker       break;
486*61046927SAndroid Build Coastguard Worker    case 'C':
487*61046927SAndroid Build Coastguard Worker       variant = " Max";
488*61046927SAndroid Build Coastguard Worker       break;
489*61046927SAndroid Build Coastguard Worker    case 'D':
490*61046927SAndroid Build Coastguard Worker       variant = " Ultra";
491*61046927SAndroid Build Coastguard Worker       break;
492*61046927SAndroid Build Coastguard Worker    }
493*61046927SAndroid Build Coastguard Worker    snprintf(dev->name, sizeof(dev->name), "Apple M%d%s (G%d%c %02X)",
494*61046927SAndroid Build Coastguard Worker             dev->params.gpu_generation - 12, variant,
495*61046927SAndroid Build Coastguard Worker             dev->params.gpu_generation, dev->params.gpu_variant,
496*61046927SAndroid Build Coastguard Worker             dev->params.gpu_revision + 0xA0);
497*61046927SAndroid Build Coastguard Worker 
498*61046927SAndroid Build Coastguard Worker    dev->guard_size = dev->params.vm_page_size;
499*61046927SAndroid Build Coastguard Worker    if (dev->params.vm_usc_start) {
500*61046927SAndroid Build Coastguard Worker       dev->shader_base = dev->params.vm_usc_start;
501*61046927SAndroid Build Coastguard Worker    } else {
502*61046927SAndroid Build Coastguard Worker       // Put the USC heap at the bottom of the user address space, 4GiB aligned
503*61046927SAndroid Build Coastguard Worker       dev->shader_base = ALIGN_POT(dev->params.vm_user_start, 0x100000000ull);
504*61046927SAndroid Build Coastguard Worker    }
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker    uint64_t shader_size = 0x100000000ull;
507*61046927SAndroid Build Coastguard Worker    // Put the user heap after the USC heap
508*61046927SAndroid Build Coastguard Worker    uint64_t user_start = dev->shader_base + shader_size;
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker    assert(dev->shader_base >= dev->params.vm_user_start);
511*61046927SAndroid Build Coastguard Worker    assert(user_start < dev->params.vm_user_end);
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker    dev->agxdecode = agxdecode_new_context(dev->shader_base);
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker    util_sparse_array_init(&dev->bo_map, sizeof(struct agx_bo), 512);
516*61046927SAndroid Build Coastguard Worker    pthread_mutex_init(&dev->bo_map_lock, NULL);
517*61046927SAndroid Build Coastguard Worker 
518*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&dev->bo_cache.lock, mtx_plain);
519*61046927SAndroid Build Coastguard Worker    list_inithead(&dev->bo_cache.lru);
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ARRAY_SIZE(dev->bo_cache.buckets); ++i)
522*61046927SAndroid Build Coastguard Worker       list_inithead(&dev->bo_cache.buckets[i]);
523*61046927SAndroid Build Coastguard Worker 
524*61046927SAndroid Build Coastguard Worker    // Put the kernel heap at the top of the address space.
525*61046927SAndroid Build Coastguard Worker    // Give it 32GB of address space, should be more than enough for any
526*61046927SAndroid Build Coastguard Worker    // reasonable use case.
527*61046927SAndroid Build Coastguard Worker    uint64_t kernel_size = MAX2(dev->params.vm_kernel_min_size, 32ull << 30);
528*61046927SAndroid Build Coastguard Worker    struct drm_asahi_vm_create vm_create = {
529*61046927SAndroid Build Coastguard Worker       .kernel_start = dev->params.vm_user_end - kernel_size,
530*61046927SAndroid Build Coastguard Worker       .kernel_end = dev->params.vm_user_end,
531*61046927SAndroid Build Coastguard Worker    };
532*61046927SAndroid Build Coastguard Worker 
533*61046927SAndroid Build Coastguard Worker    uint64_t user_size = vm_create.kernel_start - user_start;
534*61046927SAndroid Build Coastguard Worker 
535*61046927SAndroid Build Coastguard Worker    int ret = asahi_simple_ioctl(dev, DRM_IOCTL_ASAHI_VM_CREATE, &vm_create);
536*61046927SAndroid Build Coastguard Worker    if (ret) {
537*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "DRM_IOCTL_ASAHI_VM_CREATE failed: %m\n");
538*61046927SAndroid Build Coastguard Worker       assert(0);
539*61046927SAndroid Build Coastguard Worker       return false;
540*61046927SAndroid Build Coastguard Worker    }
541*61046927SAndroid Build Coastguard Worker 
542*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&dev->vma_lock, mtx_plain);
543*61046927SAndroid Build Coastguard Worker    util_vma_heap_init(&dev->main_heap, user_start, user_size);
544*61046927SAndroid Build Coastguard Worker    util_vma_heap_init(&dev->usc_heap, dev->shader_base, shader_size);
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker    dev->vm_id = vm_create.vm_id;
547*61046927SAndroid Build Coastguard Worker 
548*61046927SAndroid Build Coastguard Worker    agx_get_global_ids(dev);
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker    glsl_type_singleton_init_or_ref();
551*61046927SAndroid Build Coastguard Worker    struct blob_reader blob;
552*61046927SAndroid Build Coastguard Worker    blob_reader_init(&blob, (void *)libagx_shaders_nir,
553*61046927SAndroid Build Coastguard Worker                     sizeof(libagx_shaders_nir));
554*61046927SAndroid Build Coastguard Worker    dev->libagx = nir_deserialize(memctx, &agx_nir_options, &blob);
555*61046927SAndroid Build Coastguard Worker 
556*61046927SAndroid Build Coastguard Worker    dev->helper = agx_build_helper(dev);
557*61046927SAndroid Build Coastguard Worker 
558*61046927SAndroid Build Coastguard Worker    return true;
559*61046927SAndroid Build Coastguard Worker }
560*61046927SAndroid Build Coastguard Worker 
561*61046927SAndroid Build Coastguard Worker void
agx_close_device(struct agx_device * dev)562*61046927SAndroid Build Coastguard Worker agx_close_device(struct agx_device *dev)
563*61046927SAndroid Build Coastguard Worker {
564*61046927SAndroid Build Coastguard Worker    ralloc_free((void *)dev->libagx);
565*61046927SAndroid Build Coastguard Worker    agx_bo_unreference(dev, dev->helper);
566*61046927SAndroid Build Coastguard Worker    agx_bo_cache_evict_all(dev);
567*61046927SAndroid Build Coastguard Worker    util_sparse_array_finish(&dev->bo_map);
568*61046927SAndroid Build Coastguard Worker    agxdecode_destroy_context(dev->agxdecode);
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker    util_vma_heap_finish(&dev->main_heap);
571*61046927SAndroid Build Coastguard Worker    util_vma_heap_finish(&dev->usc_heap);
572*61046927SAndroid Build Coastguard Worker    glsl_type_singleton_decref();
573*61046927SAndroid Build Coastguard Worker 
574*61046927SAndroid Build Coastguard Worker    close(dev->fd);
575*61046927SAndroid Build Coastguard Worker }
576*61046927SAndroid Build Coastguard Worker 
577*61046927SAndroid Build Coastguard Worker uint32_t
agx_create_command_queue(struct agx_device * dev,uint32_t caps,uint32_t priority)578*61046927SAndroid Build Coastguard Worker agx_create_command_queue(struct agx_device *dev, uint32_t caps,
579*61046927SAndroid Build Coastguard Worker                          uint32_t priority)
580*61046927SAndroid Build Coastguard Worker {
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker    if (dev->debug & AGX_DBG_1QUEUE) {
583*61046927SAndroid Build Coastguard Worker       // Abuse this lock for this, it's debug only anyway
584*61046927SAndroid Build Coastguard Worker       simple_mtx_lock(&dev->vma_lock);
585*61046927SAndroid Build Coastguard Worker       if (dev->queue_id) {
586*61046927SAndroid Build Coastguard Worker          simple_mtx_unlock(&dev->vma_lock);
587*61046927SAndroid Build Coastguard Worker          return dev->queue_id;
588*61046927SAndroid Build Coastguard Worker       }
589*61046927SAndroid Build Coastguard Worker    }
590*61046927SAndroid Build Coastguard Worker 
591*61046927SAndroid Build Coastguard Worker    struct drm_asahi_queue_create queue_create = {
592*61046927SAndroid Build Coastguard Worker       .vm_id = dev->vm_id,
593*61046927SAndroid Build Coastguard Worker       .queue_caps = caps,
594*61046927SAndroid Build Coastguard Worker       .priority = priority,
595*61046927SAndroid Build Coastguard Worker       .flags = 0,
596*61046927SAndroid Build Coastguard Worker    };
597*61046927SAndroid Build Coastguard Worker 
598*61046927SAndroid Build Coastguard Worker    int ret =
599*61046927SAndroid Build Coastguard Worker       asahi_simple_ioctl(dev, DRM_IOCTL_ASAHI_QUEUE_CREATE, &queue_create);
600*61046927SAndroid Build Coastguard Worker    if (ret) {
601*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "DRM_IOCTL_ASAHI_QUEUE_CREATE failed: %m\n");
602*61046927SAndroid Build Coastguard Worker       assert(0);
603*61046927SAndroid Build Coastguard Worker    }
604*61046927SAndroid Build Coastguard Worker 
605*61046927SAndroid Build Coastguard Worker    if (dev->debug & AGX_DBG_1QUEUE) {
606*61046927SAndroid Build Coastguard Worker       dev->queue_id = queue_create.queue_id;
607*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&dev->vma_lock);
608*61046927SAndroid Build Coastguard Worker    }
609*61046927SAndroid Build Coastguard Worker 
610*61046927SAndroid Build Coastguard Worker    return queue_create.queue_id;
611*61046927SAndroid Build Coastguard Worker }
612*61046927SAndroid Build Coastguard Worker 
613*61046927SAndroid Build Coastguard Worker int
agx_destroy_command_queue(struct agx_device * dev,uint32_t queue_id)614*61046927SAndroid Build Coastguard Worker agx_destroy_command_queue(struct agx_device *dev, uint32_t queue_id)
615*61046927SAndroid Build Coastguard Worker {
616*61046927SAndroid Build Coastguard Worker    if (dev->debug & AGX_DBG_1QUEUE)
617*61046927SAndroid Build Coastguard Worker       return 0;
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker    struct drm_asahi_queue_destroy queue_destroy = {
620*61046927SAndroid Build Coastguard Worker       .queue_id = queue_id,
621*61046927SAndroid Build Coastguard Worker    };
622*61046927SAndroid Build Coastguard Worker 
623*61046927SAndroid Build Coastguard Worker    return drmIoctl(dev->fd, DRM_IOCTL_ASAHI_QUEUE_DESTROY, &queue_destroy);
624*61046927SAndroid Build Coastguard Worker }
625*61046927SAndroid Build Coastguard Worker 
626*61046927SAndroid Build Coastguard Worker int
agx_import_sync_file(struct agx_device * dev,struct agx_bo * bo,int fd)627*61046927SAndroid Build Coastguard Worker agx_import_sync_file(struct agx_device *dev, struct agx_bo *bo, int fd)
628*61046927SAndroid Build Coastguard Worker {
629*61046927SAndroid Build Coastguard Worker    struct dma_buf_import_sync_file import_sync_file_ioctl = {
630*61046927SAndroid Build Coastguard Worker       .flags = DMA_BUF_SYNC_WRITE,
631*61046927SAndroid Build Coastguard Worker       .fd = fd,
632*61046927SAndroid Build Coastguard Worker    };
633*61046927SAndroid Build Coastguard Worker 
634*61046927SAndroid Build Coastguard Worker    assert(fd >= 0);
635*61046927SAndroid Build Coastguard Worker    assert(bo->prime_fd != -1);
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker    int ret = drmIoctl(bo->prime_fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE,
638*61046927SAndroid Build Coastguard Worker                       &import_sync_file_ioctl);
639*61046927SAndroid Build Coastguard Worker    assert(ret >= 0);
640*61046927SAndroid Build Coastguard Worker 
641*61046927SAndroid Build Coastguard Worker    return ret;
642*61046927SAndroid Build Coastguard Worker }
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker int
agx_export_sync_file(struct agx_device * dev,struct agx_bo * bo)645*61046927SAndroid Build Coastguard Worker agx_export_sync_file(struct agx_device *dev, struct agx_bo *bo)
646*61046927SAndroid Build Coastguard Worker {
647*61046927SAndroid Build Coastguard Worker    struct dma_buf_export_sync_file export_sync_file_ioctl = {
648*61046927SAndroid Build Coastguard Worker       .flags = DMA_BUF_SYNC_RW,
649*61046927SAndroid Build Coastguard Worker       .fd = -1,
650*61046927SAndroid Build Coastguard Worker    };
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker    assert(bo->prime_fd != -1);
653*61046927SAndroid Build Coastguard Worker 
654*61046927SAndroid Build Coastguard Worker    int ret = drmIoctl(bo->prime_fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE,
655*61046927SAndroid Build Coastguard Worker                       &export_sync_file_ioctl);
656*61046927SAndroid Build Coastguard Worker    assert(ret >= 0);
657*61046927SAndroid Build Coastguard Worker    assert(export_sync_file_ioctl.fd >= 0);
658*61046927SAndroid Build Coastguard Worker 
659*61046927SAndroid Build Coastguard Worker    return ret >= 0 ? export_sync_file_ioctl.fd : ret;
660*61046927SAndroid Build Coastguard Worker }
661*61046927SAndroid Build Coastguard Worker 
662*61046927SAndroid Build Coastguard Worker void
agx_debug_fault(struct agx_device * dev,uint64_t addr)663*61046927SAndroid Build Coastguard Worker agx_debug_fault(struct agx_device *dev, uint64_t addr)
664*61046927SAndroid Build Coastguard Worker {
665*61046927SAndroid Build Coastguard Worker    pthread_mutex_lock(&dev->bo_map_lock);
666*61046927SAndroid Build Coastguard Worker 
667*61046927SAndroid Build Coastguard Worker    struct agx_bo *best = NULL;
668*61046927SAndroid Build Coastguard Worker 
669*61046927SAndroid Build Coastguard Worker    for (uint32_t handle = 0; handle < dev->max_handle; handle++) {
670*61046927SAndroid Build Coastguard Worker       struct agx_bo *bo = agx_lookup_bo(dev, handle);
671*61046927SAndroid Build Coastguard Worker       if (!bo->va)
672*61046927SAndroid Build Coastguard Worker          continue;
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker       uint64_t bo_addr = bo->va->addr;
675*61046927SAndroid Build Coastguard Worker       if (bo->flags & AGX_BO_LOW_VA)
676*61046927SAndroid Build Coastguard Worker          bo_addr += dev->shader_base;
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker       if (!bo->size || bo_addr > addr)
679*61046927SAndroid Build Coastguard Worker          continue;
680*61046927SAndroid Build Coastguard Worker 
681*61046927SAndroid Build Coastguard Worker       if (!best || bo_addr > best->va->addr)
682*61046927SAndroid Build Coastguard Worker          best = bo;
683*61046927SAndroid Build Coastguard Worker    }
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker    if (!best) {
686*61046927SAndroid Build Coastguard Worker       mesa_logw("Address 0x%" PRIx64 " is unknown\n", addr);
687*61046927SAndroid Build Coastguard Worker    } else {
688*61046927SAndroid Build Coastguard Worker       uint64_t start = best->va->addr;
689*61046927SAndroid Build Coastguard Worker       uint64_t end = best->va->addr + best->size;
690*61046927SAndroid Build Coastguard Worker       if (addr > (end + 1024 * 1024 * 1024)) {
691*61046927SAndroid Build Coastguard Worker          /* 1GiB max as a sanity check */
692*61046927SAndroid Build Coastguard Worker          mesa_logw("Address 0x%" PRIx64 " is unknown\n", addr);
693*61046927SAndroid Build Coastguard Worker       } else if (addr > end) {
694*61046927SAndroid Build Coastguard Worker          mesa_logw("Address 0x%" PRIx64 " is 0x%" PRIx64
695*61046927SAndroid Build Coastguard Worker                    " bytes beyond an object at 0x%" PRIx64 "..0x%" PRIx64
696*61046927SAndroid Build Coastguard Worker                    " (%s)\n",
697*61046927SAndroid Build Coastguard Worker                    addr, addr - end, start, end - 1, best->label);
698*61046927SAndroid Build Coastguard Worker       } else {
699*61046927SAndroid Build Coastguard Worker          mesa_logw("Address 0x%" PRIx64 " is 0x%" PRIx64
700*61046927SAndroid Build Coastguard Worker                    " bytes into an object at 0x%" PRIx64 "..0x%" PRIx64
701*61046927SAndroid Build Coastguard Worker                    " (%s)\n",
702*61046927SAndroid Build Coastguard Worker                    addr, addr - start, start, end - 1, best->label);
703*61046927SAndroid Build Coastguard Worker       }
704*61046927SAndroid Build Coastguard Worker    }
705*61046927SAndroid Build Coastguard Worker 
706*61046927SAndroid Build Coastguard Worker    pthread_mutex_unlock(&dev->bo_map_lock);
707*61046927SAndroid Build Coastguard Worker }
708*61046927SAndroid Build Coastguard Worker 
709*61046927SAndroid Build Coastguard Worker uint64_t
agx_get_gpu_timestamp(struct agx_device * dev)710*61046927SAndroid Build Coastguard Worker agx_get_gpu_timestamp(struct agx_device *dev)
711*61046927SAndroid Build Coastguard Worker {
712*61046927SAndroid Build Coastguard Worker #if DETECT_ARCH_AARCH64
713*61046927SAndroid Build Coastguard Worker    uint64_t ret;
714*61046927SAndroid Build Coastguard Worker    __asm__ volatile("mrs \t%0, cntvct_el0" : "=r"(ret));
715*61046927SAndroid Build Coastguard Worker    return ret;
716*61046927SAndroid Build Coastguard Worker #elif DETECT_ARCH_X86 || DETECT_ARCH_X86_64
717*61046927SAndroid Build Coastguard Worker    /* Maps to the above when run under FEX without thunking */
718*61046927SAndroid Build Coastguard Worker    uint32_t high, low;
719*61046927SAndroid Build Coastguard Worker    __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
720*61046927SAndroid Build Coastguard Worker    return (uint64_t)low | ((uint64_t)high << 32);
721*61046927SAndroid Build Coastguard Worker #else
722*61046927SAndroid Build Coastguard Worker #error "invalid architecture for asahi"
723*61046927SAndroid Build Coastguard Worker #endif
724*61046927SAndroid Build Coastguard Worker }
725*61046927SAndroid Build Coastguard Worker 
726*61046927SAndroid Build Coastguard Worker /* (Re)define UUID_SIZE to avoid including vulkan.h (or p_defines.h) here. */
727*61046927SAndroid Build Coastguard Worker #define UUID_SIZE 16
728*61046927SAndroid Build Coastguard Worker 
729*61046927SAndroid Build Coastguard Worker void
agx_get_device_uuid(const struct agx_device * dev,void * uuid)730*61046927SAndroid Build Coastguard Worker agx_get_device_uuid(const struct agx_device *dev, void *uuid)
731*61046927SAndroid Build Coastguard Worker {
732*61046927SAndroid Build Coastguard Worker    struct mesa_sha1 sha1_ctx;
733*61046927SAndroid Build Coastguard Worker    _mesa_sha1_init(&sha1_ctx);
734*61046927SAndroid Build Coastguard Worker 
735*61046927SAndroid Build Coastguard Worker    /* The device UUID uniquely identifies the given device within the machine.
736*61046927SAndroid Build Coastguard Worker     * Since we never have more than one device, this doesn't need to be a real
737*61046927SAndroid Build Coastguard Worker     * UUID, so we use SHA1("agx" + gpu_generation + gpu_variant + gpu_revision).
738*61046927SAndroid Build Coastguard Worker     */
739*61046927SAndroid Build Coastguard Worker    static const char *device_name = "agx";
740*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&sha1_ctx, device_name, strlen(device_name));
741*61046927SAndroid Build Coastguard Worker 
742*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&sha1_ctx, &dev->params.gpu_generation,
743*61046927SAndroid Build Coastguard Worker                      sizeof(dev->params.gpu_generation));
744*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&sha1_ctx, &dev->params.gpu_variant,
745*61046927SAndroid Build Coastguard Worker                      sizeof(dev->params.gpu_variant));
746*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&sha1_ctx, &dev->params.gpu_revision,
747*61046927SAndroid Build Coastguard Worker                      sizeof(dev->params.gpu_revision));
748*61046927SAndroid Build Coastguard Worker 
749*61046927SAndroid Build Coastguard Worker    uint8_t sha1[SHA1_DIGEST_LENGTH];
750*61046927SAndroid Build Coastguard Worker    _mesa_sha1_final(&sha1_ctx, sha1);
751*61046927SAndroid Build Coastguard Worker 
752*61046927SAndroid Build Coastguard Worker    assert(SHA1_DIGEST_LENGTH >= UUID_SIZE);
753*61046927SAndroid Build Coastguard Worker    memcpy(uuid, sha1, UUID_SIZE);
754*61046927SAndroid Build Coastguard Worker }
755*61046927SAndroid Build Coastguard Worker 
756*61046927SAndroid Build Coastguard Worker void
agx_get_driver_uuid(void * uuid)757*61046927SAndroid Build Coastguard Worker agx_get_driver_uuid(void *uuid)
758*61046927SAndroid Build Coastguard Worker {
759*61046927SAndroid Build Coastguard Worker    const char *driver_id = PACKAGE_VERSION MESA_GIT_SHA1;
760*61046927SAndroid Build Coastguard Worker 
761*61046927SAndroid Build Coastguard Worker    /* The driver UUID is used for determining sharability of images and memory
762*61046927SAndroid Build Coastguard Worker     * between two Vulkan instances in separate processes, but also to
763*61046927SAndroid Build Coastguard Worker     * determining memory objects and sharability between Vulkan and OpenGL
764*61046927SAndroid Build Coastguard Worker     * driver. People who want to share memory need to also check the device
765*61046927SAndroid Build Coastguard Worker     * UUID.
766*61046927SAndroid Build Coastguard Worker     */
767*61046927SAndroid Build Coastguard Worker    struct mesa_sha1 sha1_ctx;
768*61046927SAndroid Build Coastguard Worker    _mesa_sha1_init(&sha1_ctx);
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&sha1_ctx, driver_id, strlen(driver_id));
771*61046927SAndroid Build Coastguard Worker 
772*61046927SAndroid Build Coastguard Worker    uint8_t sha1[SHA1_DIGEST_LENGTH];
773*61046927SAndroid Build Coastguard Worker    _mesa_sha1_final(&sha1_ctx, sha1);
774*61046927SAndroid Build Coastguard Worker 
775*61046927SAndroid Build Coastguard Worker    assert(SHA1_DIGEST_LENGTH >= UUID_SIZE);
776*61046927SAndroid Build Coastguard Worker    memcpy(uuid, sha1, UUID_SIZE);
777*61046927SAndroid Build Coastguard Worker }
778