xref: /aosp_15_r20/external/mesa3d/src/freedreno/decode/replay.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Igalia S.L.
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include <assert.h>
7*61046927SAndroid Build Coastguard Worker #include <ctype.h>
8*61046927SAndroid Build Coastguard Worker #include <err.h>
9*61046927SAndroid Build Coastguard Worker #include <errno.h>
10*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
11*61046927SAndroid Build Coastguard Worker #include <getopt.h>
12*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
13*61046927SAndroid Build Coastguard Worker #include <signal.h>
14*61046927SAndroid Build Coastguard Worker #include <stdarg.h>
15*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
16*61046927SAndroid Build Coastguard Worker #include <stdint.h>
17*61046927SAndroid Build Coastguard Worker #include <stdio.h>
18*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
19*61046927SAndroid Build Coastguard Worker #include <string.h>
20*61046927SAndroid Build Coastguard Worker #include <unistd.h>
21*61046927SAndroid Build Coastguard Worker #include <libgen.h>
22*61046927SAndroid Build Coastguard Worker #if FD_REPLAY_KGSL
23*61046927SAndroid Build Coastguard Worker #include "../vulkan/msm_kgsl.h"
24*61046927SAndroid Build Coastguard Worker #elif FD_REPLAY_MSM
25*61046927SAndroid Build Coastguard Worker #include <xf86drm.h>
26*61046927SAndroid Build Coastguard Worker #include "drm-uapi/msm_drm.h"
27*61046927SAndroid Build Coastguard Worker #elif FD_REPLAY_WSL
28*61046927SAndroid Build Coastguard Worker #define __KERNEL__
29*61046927SAndroid Build Coastguard Worker #include "drm-uapi/d3dkmthk.h"
30*61046927SAndroid Build Coastguard Worker #endif
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker #include <sys/ioctl.h>
33*61046927SAndroid Build Coastguard Worker #include <sys/mman.h>
34*61046927SAndroid Build Coastguard Worker #include <sys/stat.h>
35*61046927SAndroid Build Coastguard Worker #include <sys/types.h>
36*61046927SAndroid Build Coastguard Worker #include <sys/wait.h>
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker #include "util/os_time.h"
39*61046927SAndroid Build Coastguard Worker #include "util/rb_tree.h"
40*61046927SAndroid Build Coastguard Worker #include "util/u_vector.h"
41*61046927SAndroid Build Coastguard Worker #include "util/vma.h"
42*61046927SAndroid Build Coastguard Worker #include "buffers.h"
43*61046927SAndroid Build Coastguard Worker #include "cffdec.h"
44*61046927SAndroid Build Coastguard Worker #include "io.h"
45*61046927SAndroid Build Coastguard Worker #include "redump.h"
46*61046927SAndroid Build Coastguard Worker #include "rdutil.h"
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker /**
49*61046927SAndroid Build Coastguard Worker  * Replay command stream obtained from:
50*61046927SAndroid Build Coastguard Worker  * - /sys/kernel/debug/dri/0/rd
51*61046927SAndroid Build Coastguard Worker  * - /sys/kernel/debug/dri/0/hangrd
52*61046927SAndroid Build Coastguard Worker  * !!! Command stream capture should be done with ALL buffers:
53*61046927SAndroid Build Coastguard Worker  * - echo 1 > /sys/module/msm/parameters/rd_full
54*61046927SAndroid Build Coastguard Worker  *
55*61046927SAndroid Build Coastguard Worker  * Requires kernel with MSM_INFO_SET_IOVA support.
56*61046927SAndroid Build Coastguard Worker  * In case userspace IOVAs are not supported, like on KGSL, we have to
57*61046927SAndroid Build Coastguard Worker  * pre-allocate a single buffer and hope it always allocated starting
58*61046927SAndroid Build Coastguard Worker  * from the same address.
59*61046927SAndroid Build Coastguard Worker  *
60*61046927SAndroid Build Coastguard Worker  * TODO: Misrendering, would require marking framebuffer images
61*61046927SAndroid Build Coastguard Worker  *       at each renderpass in order to fetch and decode them.
62*61046927SAndroid Build Coastguard Worker  *
63*61046927SAndroid Build Coastguard Worker  * Code from Freedreno/Turnip is not re-used here since the relevant
64*61046927SAndroid Build Coastguard Worker  * pieces may introduce additional allocations which cannot be allowed
65*61046927SAndroid Build Coastguard Worker  * during the replay.
66*61046927SAndroid Build Coastguard Worker  *
67*61046927SAndroid Build Coastguard Worker  * For how-to see freedreno.rst
68*61046927SAndroid Build Coastguard Worker  */
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker static const char *exename = NULL;
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker static const uint64_t FAKE_ADDRESS_SPACE_SIZE = 1024 * 1024 * 1024;
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker static int handle_file(const char *filename, uint32_t first_submit,
75*61046927SAndroid Build Coastguard Worker                        uint32_t last_submit, uint32_t submit_to_override,
76*61046927SAndroid Build Coastguard Worker                        uint64_t base_addr, const char *cmdstreamgen);
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker static void
print_usage(const char * name,const char * default_csgen)79*61046927SAndroid Build Coastguard Worker print_usage(const char *name, const char *default_csgen)
80*61046927SAndroid Build Coastguard Worker {
81*61046927SAndroid Build Coastguard Worker    /* clang-format off */
82*61046927SAndroid Build Coastguard Worker    fprintf(stderr, "Usage:\n\n"
83*61046927SAndroid Build Coastguard Worker            "\t%s [OPTIONS]... FILE...\n\n"
84*61046927SAndroid Build Coastguard Worker            "Options:\n"
85*61046927SAndroid Build Coastguard Worker            "\t-e, --exe=NAME         - only use cmdstream from named process\n"
86*61046927SAndroid Build Coastguard Worker            "\t-o  --override=submit  - № of the submit to override\n"
87*61046927SAndroid Build Coastguard Worker            "\t-g  --generator=path   - executable which generate cmdstream for override (default: %s)\n"
88*61046927SAndroid Build Coastguard Worker            "\t-f  --first=submit     - first submit № to replay\n"
89*61046927SAndroid Build Coastguard Worker            "\t-l  --last=submit      - last submit № to replay\n"
90*61046927SAndroid Build Coastguard Worker            "\t-a  --address=address  - base iova address on WSL\n"
91*61046927SAndroid Build Coastguard Worker            "\t-h, --help             - show this message\n"
92*61046927SAndroid Build Coastguard Worker            , name, default_csgen);
93*61046927SAndroid Build Coastguard Worker    /* clang-format on */
94*61046927SAndroid Build Coastguard Worker    exit(2);
95*61046927SAndroid Build Coastguard Worker }
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker /* clang-format off */
98*61046927SAndroid Build Coastguard Worker static const struct option opts[] = {
99*61046927SAndroid Build Coastguard Worker       { "exe",       required_argument, 0, 'e' },
100*61046927SAndroid Build Coastguard Worker       { "override",  required_argument, 0, 'o' },
101*61046927SAndroid Build Coastguard Worker       { "generator", required_argument, 0, 'g' },
102*61046927SAndroid Build Coastguard Worker       { "first",     required_argument, 0, 'f' },
103*61046927SAndroid Build Coastguard Worker       { "last",      required_argument, 0, 'l' },
104*61046927SAndroid Build Coastguard Worker       { "address",   required_argument, 0, 'a' },
105*61046927SAndroid Build Coastguard Worker       { "help",      no_argument,       0, 'h' },
106*61046927SAndroid Build Coastguard Worker };
107*61046927SAndroid Build Coastguard Worker /* clang-format on */
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker int
main(int argc,char ** argv)110*61046927SAndroid Build Coastguard Worker main(int argc, char **argv)
111*61046927SAndroid Build Coastguard Worker {
112*61046927SAndroid Build Coastguard Worker    int ret = -1;
113*61046927SAndroid Build Coastguard Worker    int c;
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker    uint32_t submit_to_override = -1;
116*61046927SAndroid Build Coastguard Worker    uint32_t first_submit = 0;
117*61046927SAndroid Build Coastguard Worker    uint32_t last_submit = -1;
118*61046927SAndroid Build Coastguard Worker    uint64_t base_addr = 0;
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker    char *default_csgen = malloc(PATH_MAX);
121*61046927SAndroid Build Coastguard Worker    snprintf(default_csgen, PATH_MAX, "%s/generate_rd", dirname(argv[0]));
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker    const char *csgen = default_csgen;
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker    while ((c = getopt_long(argc, argv, "e:o:g:f:l:a:h", opts, NULL)) != -1) {
126*61046927SAndroid Build Coastguard Worker       switch (c) {
127*61046927SAndroid Build Coastguard Worker       case 0:
128*61046927SAndroid Build Coastguard Worker          /* option that set a flag, nothing to do */
129*61046927SAndroid Build Coastguard Worker          break;
130*61046927SAndroid Build Coastguard Worker       case 'e':
131*61046927SAndroid Build Coastguard Worker          exename = optarg;
132*61046927SAndroid Build Coastguard Worker          break;
133*61046927SAndroid Build Coastguard Worker       case 'o':
134*61046927SAndroid Build Coastguard Worker          submit_to_override = strtoul(optarg, NULL, 0);
135*61046927SAndroid Build Coastguard Worker          break;
136*61046927SAndroid Build Coastguard Worker       case 'g':
137*61046927SAndroid Build Coastguard Worker          csgen = optarg;
138*61046927SAndroid Build Coastguard Worker          break;
139*61046927SAndroid Build Coastguard Worker       case 'f':
140*61046927SAndroid Build Coastguard Worker          first_submit = strtoul(optarg, NULL, 0);
141*61046927SAndroid Build Coastguard Worker          break;
142*61046927SAndroid Build Coastguard Worker       case 'l':
143*61046927SAndroid Build Coastguard Worker          last_submit = strtoul(optarg, NULL, 0);
144*61046927SAndroid Build Coastguard Worker          break;
145*61046927SAndroid Build Coastguard Worker       case 'a':
146*61046927SAndroid Build Coastguard Worker          base_addr = strtoull(optarg, NULL, 0);
147*61046927SAndroid Build Coastguard Worker          break;
148*61046927SAndroid Build Coastguard Worker       case 'h':
149*61046927SAndroid Build Coastguard Worker       default:
150*61046927SAndroid Build Coastguard Worker          print_usage(argv[0], default_csgen);
151*61046927SAndroid Build Coastguard Worker       }
152*61046927SAndroid Build Coastguard Worker    }
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker    while (optind < argc) {
155*61046927SAndroid Build Coastguard Worker       ret = handle_file(argv[optind], first_submit, last_submit,
156*61046927SAndroid Build Coastguard Worker                         submit_to_override, base_addr, csgen);
157*61046927SAndroid Build Coastguard Worker       if (ret) {
158*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "error reading: %s\n", argv[optind]);
159*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "continuing..\n");
160*61046927SAndroid Build Coastguard Worker       }
161*61046927SAndroid Build Coastguard Worker       optind++;
162*61046927SAndroid Build Coastguard Worker    }
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker    if (ret)
165*61046927SAndroid Build Coastguard Worker       print_usage(argv[0], default_csgen);
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker    return ret;
168*61046927SAndroid Build Coastguard Worker }
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker struct buffer {
171*61046927SAndroid Build Coastguard Worker    struct rb_node node;
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker    uint32_t gem_handle;
174*61046927SAndroid Build Coastguard Worker    uint64_t size;
175*61046927SAndroid Build Coastguard Worker    uint64_t iova;
176*61046927SAndroid Build Coastguard Worker    void *map;
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker    bool used;
179*61046927SAndroid Build Coastguard Worker    uint32_t flags;
180*61046927SAndroid Build Coastguard Worker };
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker struct cmdstream {
183*61046927SAndroid Build Coastguard Worker    uint64_t iova;
184*61046927SAndroid Build Coastguard Worker    uint64_t size;
185*61046927SAndroid Build Coastguard Worker };
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker struct wrbuf {
188*61046927SAndroid Build Coastguard Worker    uint64_t iova;
189*61046927SAndroid Build Coastguard Worker    uint64_t size;
190*61046927SAndroid Build Coastguard Worker    char* name;
191*61046927SAndroid Build Coastguard Worker };
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker struct device {
194*61046927SAndroid Build Coastguard Worker    int fd;
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker    struct rb_tree buffers;
197*61046927SAndroid Build Coastguard Worker    struct util_vma_heap vma;
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker    struct u_vector cmdstreams;
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker    uint64_t shader_log_iova;
202*61046927SAndroid Build Coastguard Worker    uint64_t cp_log_iova;
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    bool has_set_iova;
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker    uint32_t va_id;
207*61046927SAndroid Build Coastguard Worker    void *va_map;
208*61046927SAndroid Build Coastguard Worker    uint64_t va_iova;
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker    struct u_vector wrbufs;
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker #ifdef FD_REPLAY_MSM
213*61046927SAndroid Build Coastguard Worker    uint32_t queue_id;
214*61046927SAndroid Build Coastguard Worker #endif
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker #ifdef FD_REPLAY_KGSL
217*61046927SAndroid Build Coastguard Worker    uint32_t context_id;
218*61046927SAndroid Build Coastguard Worker #endif
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker #ifdef FD_REPLAY_WSL
221*61046927SAndroid Build Coastguard Worker    struct d3dkmthandle device;
222*61046927SAndroid Build Coastguard Worker    struct d3dkmthandle context;
223*61046927SAndroid Build Coastguard Worker 
224*61046927SAndroid Build Coastguard Worker    /* We don't know at the moment a good way to wait for submission to complete
225*61046927SAndroid Build Coastguard Worker     * on WSL, so we could use our own fences.
226*61046927SAndroid Build Coastguard Worker     */
227*61046927SAndroid Build Coastguard Worker    uint64_t fence_iova;
228*61046927SAndroid Build Coastguard Worker    uint64_t fence_ib_iova;
229*61046927SAndroid Build Coastguard Worker    volatile uint32_t *fence;
230*61046927SAndroid Build Coastguard Worker    uint32_t *fence_ib;
231*61046927SAndroid Build Coastguard Worker #endif
232*61046927SAndroid Build Coastguard Worker };
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker void buffer_mem_free(struct device *dev, struct buffer *buf);
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker static int
rb_buffer_insert_cmp(const struct rb_node * n1,const struct rb_node * n2)237*61046927SAndroid Build Coastguard Worker rb_buffer_insert_cmp(const struct rb_node *n1, const struct rb_node *n2)
238*61046927SAndroid Build Coastguard Worker {
239*61046927SAndroid Build Coastguard Worker    const struct buffer *buf1 = (const struct buffer *)n1;
240*61046927SAndroid Build Coastguard Worker    const struct buffer *buf2 = (const struct buffer *)n2;
241*61046927SAndroid Build Coastguard Worker    /* Note that gpuaddr comparisions can overflow an int: */
242*61046927SAndroid Build Coastguard Worker    if (buf1->iova > buf2->iova)
243*61046927SAndroid Build Coastguard Worker       return 1;
244*61046927SAndroid Build Coastguard Worker    else if (buf1->iova < buf2->iova)
245*61046927SAndroid Build Coastguard Worker       return -1;
246*61046927SAndroid Build Coastguard Worker    return 0;
247*61046927SAndroid Build Coastguard Worker }
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker static int
rb_buffer_search_cmp(const struct rb_node * node,const void * addrptr)250*61046927SAndroid Build Coastguard Worker rb_buffer_search_cmp(const struct rb_node *node, const void *addrptr)
251*61046927SAndroid Build Coastguard Worker {
252*61046927SAndroid Build Coastguard Worker    const struct buffer *buf = (const struct buffer *)node;
253*61046927SAndroid Build Coastguard Worker    uint64_t iova = *(uint64_t *)addrptr;
254*61046927SAndroid Build Coastguard Worker    if (buf->iova + buf->size <= iova)
255*61046927SAndroid Build Coastguard Worker       return -1;
256*61046927SAndroid Build Coastguard Worker    else if (buf->iova > iova)
257*61046927SAndroid Build Coastguard Worker       return 1;
258*61046927SAndroid Build Coastguard Worker    return 0;
259*61046927SAndroid Build Coastguard Worker }
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker static struct buffer *
device_get_buffer(struct device * dev,uint64_t iova)262*61046927SAndroid Build Coastguard Worker device_get_buffer(struct device *dev, uint64_t iova)
263*61046927SAndroid Build Coastguard Worker {
264*61046927SAndroid Build Coastguard Worker    if (iova == 0)
265*61046927SAndroid Build Coastguard Worker       return NULL;
266*61046927SAndroid Build Coastguard Worker    return (struct buffer *)rb_tree_search(&dev->buffers, &iova,
267*61046927SAndroid Build Coastguard Worker                                           rb_buffer_search_cmp);
268*61046927SAndroid Build Coastguard Worker }
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker static void
device_mark_buffers(struct device * dev)271*61046927SAndroid Build Coastguard Worker device_mark_buffers(struct device *dev)
272*61046927SAndroid Build Coastguard Worker {
273*61046927SAndroid Build Coastguard Worker    rb_tree_foreach_safe (struct buffer, buf, &dev->buffers, node) {
274*61046927SAndroid Build Coastguard Worker       buf->used = false;
275*61046927SAndroid Build Coastguard Worker    }
276*61046927SAndroid Build Coastguard Worker }
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker static void
device_free_buffers(struct device * dev)279*61046927SAndroid Build Coastguard Worker device_free_buffers(struct device *dev)
280*61046927SAndroid Build Coastguard Worker {
281*61046927SAndroid Build Coastguard Worker    rb_tree_foreach_safe (struct buffer, buf, &dev->buffers, node) {
282*61046927SAndroid Build Coastguard Worker       buffer_mem_free(dev, buf);
283*61046927SAndroid Build Coastguard Worker       rb_tree_remove(&dev->buffers, &buf->node);
284*61046927SAndroid Build Coastguard Worker       free(buf);
285*61046927SAndroid Build Coastguard Worker    }
286*61046927SAndroid Build Coastguard Worker }
287*61046927SAndroid Build Coastguard Worker 
288*61046927SAndroid Build Coastguard Worker static void
device_print_shader_log(struct device * dev)289*61046927SAndroid Build Coastguard Worker device_print_shader_log(struct device *dev)
290*61046927SAndroid Build Coastguard Worker {
291*61046927SAndroid Build Coastguard Worker    struct shader_log {
292*61046927SAndroid Build Coastguard Worker       uint64_t cur_iova;
293*61046927SAndroid Build Coastguard Worker       union {
294*61046927SAndroid Build Coastguard Worker          uint32_t entries_u32[0];
295*61046927SAndroid Build Coastguard Worker          float entries_float[0];
296*61046927SAndroid Build Coastguard Worker       };
297*61046927SAndroid Build Coastguard Worker    };
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker    if (dev->shader_log_iova != 0)
300*61046927SAndroid Build Coastguard Worker    {
301*61046927SAndroid Build Coastguard Worker       struct buffer *buf = device_get_buffer(dev, dev->shader_log_iova);
302*61046927SAndroid Build Coastguard Worker       if (buf) {
303*61046927SAndroid Build Coastguard Worker          struct shader_log *log = buf->map + (dev->shader_log_iova - buf->iova);
304*61046927SAndroid Build Coastguard Worker          uint32_t count = (log->cur_iova - dev->shader_log_iova -
305*61046927SAndroid Build Coastguard Worker                            offsetof(struct shader_log, entries_u32)) / 4;
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker          printf("Shader Log Entries: %u\n", count);
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; i < count; i++) {
310*61046927SAndroid Build Coastguard Worker             printf("[%u] %08x %.4f\n", i, log->entries_u32[i],
311*61046927SAndroid Build Coastguard Worker                    log->entries_float[i]);
312*61046927SAndroid Build Coastguard Worker          }
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker          printf("========================================\n");
315*61046927SAndroid Build Coastguard Worker       }
316*61046927SAndroid Build Coastguard Worker    }
317*61046927SAndroid Build Coastguard Worker }
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker static void
device_print_cp_log(struct device * dev)320*61046927SAndroid Build Coastguard Worker device_print_cp_log(struct device *dev)
321*61046927SAndroid Build Coastguard Worker {
322*61046927SAndroid Build Coastguard Worker    struct cp_log {
323*61046927SAndroid Build Coastguard Worker       uint64_t cur_iova;
324*61046927SAndroid Build Coastguard Worker       uint64_t tmp;
325*61046927SAndroid Build Coastguard Worker       uint64_t first_entry_size;
326*61046927SAndroid Build Coastguard Worker    };
327*61046927SAndroid Build Coastguard Worker 
328*61046927SAndroid Build Coastguard Worker    struct cp_log_entry {
329*61046927SAndroid Build Coastguard Worker       uint64_t size;
330*61046927SAndroid Build Coastguard Worker       uint32_t data[0];
331*61046927SAndroid Build Coastguard Worker    };
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker    if (dev->cp_log_iova == 0)
334*61046927SAndroid Build Coastguard Worker       return;
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker    struct buffer *buf = device_get_buffer(dev, dev->cp_log_iova);
337*61046927SAndroid Build Coastguard Worker    if (!buf)
338*61046927SAndroid Build Coastguard Worker       return;
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker    struct cp_log *log = buf->map + (dev->cp_log_iova - buf->iova);
341*61046927SAndroid Build Coastguard Worker    if (log->first_entry_size == 0)
342*61046927SAndroid Build Coastguard Worker       return;
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker    struct cp_log_entry *log_entry =
345*61046927SAndroid Build Coastguard Worker       buf->map + offsetof(struct cp_log, first_entry_size);
346*61046927SAndroid Build Coastguard Worker    uint32_t idx = 0;
347*61046927SAndroid Build Coastguard Worker    while (log_entry->size != 0) {
348*61046927SAndroid Build Coastguard Worker       printf("\nCP Log [%u]:\n", idx++);
349*61046927SAndroid Build Coastguard Worker       uint32_t dwords = log_entry->size / 4;
350*61046927SAndroid Build Coastguard Worker 
351*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < dwords; i++) {
352*61046927SAndroid Build Coastguard Worker          if (i % 8 == 0)
353*61046927SAndroid Build Coastguard Worker             printf("\t");
354*61046927SAndroid Build Coastguard Worker          printf("%08x ", log_entry->data[i]);
355*61046927SAndroid Build Coastguard Worker          if (i % 8 == 7)
356*61046927SAndroid Build Coastguard Worker             printf("\n");
357*61046927SAndroid Build Coastguard Worker       }
358*61046927SAndroid Build Coastguard Worker       printf("\n");
359*61046927SAndroid Build Coastguard Worker 
360*61046927SAndroid Build Coastguard Worker       log_entry = (void *)log_entry + log_entry->size +
361*61046927SAndroid Build Coastguard Worker                   offsetof(struct cp_log_entry, data);
362*61046927SAndroid Build Coastguard Worker    }
363*61046927SAndroid Build Coastguard Worker }
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker static void
device_dump_wrbuf(struct device * dev)366*61046927SAndroid Build Coastguard Worker device_dump_wrbuf(struct device *dev)
367*61046927SAndroid Build Coastguard Worker {
368*61046927SAndroid Build Coastguard Worker    if (!u_vector_length(&dev->wrbufs))
369*61046927SAndroid Build Coastguard Worker       return;
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker    char buffer_dir[PATH_MAX];
372*61046927SAndroid Build Coastguard Worker    getcwd(buffer_dir, sizeof(buffer_dir));
373*61046927SAndroid Build Coastguard Worker    strcat(buffer_dir, "/buffers");
374*61046927SAndroid Build Coastguard Worker    rmdir(buffer_dir);
375*61046927SAndroid Build Coastguard Worker    mkdir(buffer_dir, 0777);
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker    struct wrbuf *wrbuf;
378*61046927SAndroid Build Coastguard Worker    u_vector_foreach(wrbuf, &dev->wrbufs) {
379*61046927SAndroid Build Coastguard Worker       char buffer_path[PATH_MAX];
380*61046927SAndroid Build Coastguard Worker       snprintf(buffer_path, sizeof(buffer_path), "%s/%s", buffer_dir, wrbuf->name);
381*61046927SAndroid Build Coastguard Worker       FILE *f = fopen(buffer_path, "wb");
382*61046927SAndroid Build Coastguard Worker       if (!f) {
383*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Error opening %s\n", buffer_path);
384*61046927SAndroid Build Coastguard Worker          goto end_it;
385*61046927SAndroid Build Coastguard Worker       }
386*61046927SAndroid Build Coastguard Worker 
387*61046927SAndroid Build Coastguard Worker       struct buffer *buf = device_get_buffer(dev, wrbuf->iova);
388*61046927SAndroid Build Coastguard Worker       if (!buf) {
389*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Error getting buffer for %s\n", buffer_path);
390*61046927SAndroid Build Coastguard Worker          goto end_it;
391*61046927SAndroid Build Coastguard Worker       }
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker       uint64_t offset = wrbuf->iova - buf->iova;
394*61046927SAndroid Build Coastguard Worker       uint64_t size = MIN2(wrbuf->size, buf->size - offset);
395*61046927SAndroid Build Coastguard Worker       if (size != wrbuf->size) {
396*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Warning: Clamping buffer %s as it's smaller than expected (0x%" PRIx64 " < 0x%" PRIx64 ")\n", wrbuf->name, size, wrbuf->size);
397*61046927SAndroid Build Coastguard Worker       }
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker       printf("Dumping %s (0x%" PRIx64 " - 0x%" PRIx64 ")\n", wrbuf->name, wrbuf->iova, wrbuf->iova + size);
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker       fwrite(buf->map + offset, size, 1, f);
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker       end_it:
404*61046927SAndroid Build Coastguard Worker       fclose(f);
405*61046927SAndroid Build Coastguard Worker    }
406*61046927SAndroid Build Coastguard Worker }
407*61046927SAndroid Build Coastguard Worker 
408*61046927SAndroid Build Coastguard Worker #if FD_REPLAY_MSM
409*61046927SAndroid Build Coastguard Worker static inline void
get_abs_timeout(struct drm_msm_timespec * tv,uint64_t ns)410*61046927SAndroid Build Coastguard Worker get_abs_timeout(struct drm_msm_timespec *tv, uint64_t ns)
411*61046927SAndroid Build Coastguard Worker {
412*61046927SAndroid Build Coastguard Worker    struct timespec t;
413*61046927SAndroid Build Coastguard Worker    clock_gettime(CLOCK_MONOTONIC, &t);
414*61046927SAndroid Build Coastguard Worker    tv->tv_sec = t.tv_sec + ns / 1000000000;
415*61046927SAndroid Build Coastguard Worker    tv->tv_nsec = t.tv_nsec + ns % 1000000000;
416*61046927SAndroid Build Coastguard Worker }
417*61046927SAndroid Build Coastguard Worker 
418*61046927SAndroid Build Coastguard Worker static struct device *
device_create(uint64_t base_addr)419*61046927SAndroid Build Coastguard Worker device_create(uint64_t base_addr)
420*61046927SAndroid Build Coastguard Worker {
421*61046927SAndroid Build Coastguard Worker    struct device *dev = calloc(sizeof(struct device), 1);
422*61046927SAndroid Build Coastguard Worker 
423*61046927SAndroid Build Coastguard Worker    dev->fd = drmOpenWithType("msm", NULL, DRM_NODE_RENDER);
424*61046927SAndroid Build Coastguard Worker    if (dev->fd < 0) {
425*61046927SAndroid Build Coastguard Worker       errx(1, "Cannot open MSM fd!");
426*61046927SAndroid Build Coastguard Worker    }
427*61046927SAndroid Build Coastguard Worker 
428*61046927SAndroid Build Coastguard Worker    uint64_t va_start, va_size;
429*61046927SAndroid Build Coastguard Worker 
430*61046927SAndroid Build Coastguard Worker    struct drm_msm_param req = {
431*61046927SAndroid Build Coastguard Worker       .pipe = MSM_PIPE_3D0,
432*61046927SAndroid Build Coastguard Worker       .param = MSM_PARAM_VA_START,
433*61046927SAndroid Build Coastguard Worker    };
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker    int ret = drmCommandWriteRead(dev->fd, DRM_MSM_GET_PARAM, &req, sizeof(req));
436*61046927SAndroid Build Coastguard Worker    va_start = req.value;
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker    if (!ret) {
439*61046927SAndroid Build Coastguard Worker       req.param = MSM_PARAM_VA_SIZE;
440*61046927SAndroid Build Coastguard Worker       ret = drmCommandWriteRead(dev->fd, DRM_MSM_GET_PARAM, &req, sizeof(req));
441*61046927SAndroid Build Coastguard Worker       va_size = req.value;
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker       dev->has_set_iova = true;
444*61046927SAndroid Build Coastguard Worker    }
445*61046927SAndroid Build Coastguard Worker 
446*61046927SAndroid Build Coastguard Worker    if (ret) {
447*61046927SAndroid Build Coastguard Worker       printf("MSM_INFO_SET_IOVA is not supported!\n");
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker       struct drm_msm_gem_new req_new = {.size = FAKE_ADDRESS_SPACE_SIZE, .flags = MSM_BO_CACHED_COHERENT};
450*61046927SAndroid Build Coastguard Worker       drmCommandWriteRead(dev->fd, DRM_MSM_GEM_NEW, &req_new, sizeof(req_new));
451*61046927SAndroid Build Coastguard Worker       dev->va_id = req_new.handle;
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker       struct drm_msm_gem_info req_info = {
454*61046927SAndroid Build Coastguard Worker          .handle = req_new.handle,
455*61046927SAndroid Build Coastguard Worker          .info = MSM_INFO_GET_IOVA,
456*61046927SAndroid Build Coastguard Worker       };
457*61046927SAndroid Build Coastguard Worker 
458*61046927SAndroid Build Coastguard Worker       drmCommandWriteRead(dev->fd,
459*61046927SAndroid Build Coastguard Worker                                  DRM_MSM_GEM_INFO, &req_info, sizeof(req_info));
460*61046927SAndroid Build Coastguard Worker       dev->va_iova = req_info.value;
461*61046927SAndroid Build Coastguard Worker 
462*61046927SAndroid Build Coastguard Worker       struct drm_msm_gem_info req_offset = {
463*61046927SAndroid Build Coastguard Worker          .handle = req_new.handle,
464*61046927SAndroid Build Coastguard Worker          .info = MSM_INFO_GET_OFFSET,
465*61046927SAndroid Build Coastguard Worker       };
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker       drmCommandWriteRead(dev->fd, DRM_MSM_GEM_INFO, &req_offset, sizeof(req_offset));
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker       dev->va_map = mmap(0, FAKE_ADDRESS_SPACE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
470*61046927SAndroid Build Coastguard Worker                        dev->fd, req_offset.value);
471*61046927SAndroid Build Coastguard Worker       if (dev->va_map == MAP_FAILED) {
472*61046927SAndroid Build Coastguard Worker          err(1, "mmap failure");
473*61046927SAndroid Build Coastguard Worker       }
474*61046927SAndroid Build Coastguard Worker 
475*61046927SAndroid Build Coastguard Worker       va_start = dev->va_iova;
476*61046927SAndroid Build Coastguard Worker       va_size = FAKE_ADDRESS_SPACE_SIZE;
477*61046927SAndroid Build Coastguard Worker 
478*61046927SAndroid Build Coastguard Worker       printf("Allocated iova %" PRIx64 "\n", dev->va_iova);
479*61046927SAndroid Build Coastguard Worker    }
480*61046927SAndroid Build Coastguard Worker 
481*61046927SAndroid Build Coastguard Worker    struct drm_msm_submitqueue req_queue = {
482*61046927SAndroid Build Coastguard Worker       .flags = 0,
483*61046927SAndroid Build Coastguard Worker       .prio = 0,
484*61046927SAndroid Build Coastguard Worker    };
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker    ret = drmCommandWriteRead(dev->fd, DRM_MSM_SUBMITQUEUE_NEW, &req_queue,
487*61046927SAndroid Build Coastguard Worker                              sizeof(req_queue));
488*61046927SAndroid Build Coastguard Worker    if (ret) {
489*61046927SAndroid Build Coastguard Worker       err(1, "DRM_MSM_SUBMITQUEUE_NEW failure");
490*61046927SAndroid Build Coastguard Worker    }
491*61046927SAndroid Build Coastguard Worker 
492*61046927SAndroid Build Coastguard Worker    dev->queue_id = req_queue.id;
493*61046927SAndroid Build Coastguard Worker 
494*61046927SAndroid Build Coastguard Worker    rb_tree_init(&dev->buffers);
495*61046927SAndroid Build Coastguard Worker    util_vma_heap_init(&dev->vma, va_start, ROUND_DOWN_TO(va_size, 4096));
496*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->cmdstreams, 8, sizeof(struct cmdstream));
497*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->wrbufs, 8, sizeof(struct wrbuf));
498*61046927SAndroid Build Coastguard Worker 
499*61046927SAndroid Build Coastguard Worker    return dev;
500*61046927SAndroid Build Coastguard Worker }
501*61046927SAndroid Build Coastguard Worker 
502*61046927SAndroid Build Coastguard Worker static void
device_submit_cmdstreams(struct device * dev)503*61046927SAndroid Build Coastguard Worker device_submit_cmdstreams(struct device *dev)
504*61046927SAndroid Build Coastguard Worker {
505*61046927SAndroid Build Coastguard Worker    if (!u_vector_length(&dev->cmdstreams)) {
506*61046927SAndroid Build Coastguard Worker       device_free_buffers(dev);
507*61046927SAndroid Build Coastguard Worker       return;
508*61046927SAndroid Build Coastguard Worker    }
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker    struct drm_msm_gem_submit_cmd cmds[u_vector_length(&dev->cmdstreams)];
511*61046927SAndroid Build Coastguard Worker 
512*61046927SAndroid Build Coastguard Worker    uint32_t idx = 0;
513*61046927SAndroid Build Coastguard Worker    struct cmdstream *cmd;
514*61046927SAndroid Build Coastguard Worker    u_vector_foreach(cmd, &dev->cmdstreams) {
515*61046927SAndroid Build Coastguard Worker       struct buffer *cmdstream_buf = device_get_buffer(dev, cmd->iova);
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker       uint32_t bo_idx = 0;
518*61046927SAndroid Build Coastguard Worker       rb_tree_foreach (struct buffer, buf, &dev->buffers, node) {
519*61046927SAndroid Build Coastguard Worker          if (buf == cmdstream_buf)
520*61046927SAndroid Build Coastguard Worker             break;
521*61046927SAndroid Build Coastguard Worker 
522*61046927SAndroid Build Coastguard Worker          bo_idx++;
523*61046927SAndroid Build Coastguard Worker       }
524*61046927SAndroid Build Coastguard Worker 
525*61046927SAndroid Build Coastguard Worker       if (cmdstream_buf)
526*61046927SAndroid Build Coastguard Worker          cmdstream_buf->flags = MSM_SUBMIT_BO_DUMP;
527*61046927SAndroid Build Coastguard Worker 
528*61046927SAndroid Build Coastguard Worker       struct drm_msm_gem_submit_cmd *submit_cmd = &cmds[idx];
529*61046927SAndroid Build Coastguard Worker       submit_cmd->type = MSM_SUBMIT_CMD_BUF;
530*61046927SAndroid Build Coastguard Worker       submit_cmd->submit_idx = dev->has_set_iova ? bo_idx : 0;
531*61046927SAndroid Build Coastguard Worker       if (dev->has_set_iova) {
532*61046927SAndroid Build Coastguard Worker          submit_cmd->submit_offset = cmd->iova - cmdstream_buf->iova;
533*61046927SAndroid Build Coastguard Worker       } else {
534*61046927SAndroid Build Coastguard Worker          submit_cmd->submit_offset = cmd->iova - dev->va_iova;
535*61046927SAndroid Build Coastguard Worker       }
536*61046927SAndroid Build Coastguard Worker       submit_cmd->size = cmd->size;
537*61046927SAndroid Build Coastguard Worker       submit_cmd->pad = 0;
538*61046927SAndroid Build Coastguard Worker       submit_cmd->nr_relocs = 0;
539*61046927SAndroid Build Coastguard Worker       submit_cmd->relocs = 0;
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker       idx++;
542*61046927SAndroid Build Coastguard Worker    }
543*61046927SAndroid Build Coastguard Worker 
544*61046927SAndroid Build Coastguard Worker    uint32_t bo_count = 0;
545*61046927SAndroid Build Coastguard Worker    rb_tree_foreach (struct buffer, buf, &dev->buffers, node) {
546*61046927SAndroid Build Coastguard Worker       if (buf)
547*61046927SAndroid Build Coastguard Worker          bo_count++;
548*61046927SAndroid Build Coastguard Worker    }
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker    if (!dev->has_set_iova) {
551*61046927SAndroid Build Coastguard Worker       bo_count = 1;
552*61046927SAndroid Build Coastguard Worker    }
553*61046927SAndroid Build Coastguard Worker 
554*61046927SAndroid Build Coastguard Worker    struct drm_msm_gem_submit_bo *bo_list =
555*61046927SAndroid Build Coastguard Worker       calloc(sizeof(struct drm_msm_gem_submit_bo), bo_count);
556*61046927SAndroid Build Coastguard Worker 
557*61046927SAndroid Build Coastguard Worker    if (dev->has_set_iova) {
558*61046927SAndroid Build Coastguard Worker       uint32_t bo_idx = 0;
559*61046927SAndroid Build Coastguard Worker       rb_tree_foreach (struct buffer, buf, &dev->buffers, node) {
560*61046927SAndroid Build Coastguard Worker          struct drm_msm_gem_submit_bo *submit_bo = &bo_list[bo_idx++];
561*61046927SAndroid Build Coastguard Worker          submit_bo->handle = buf->gem_handle;
562*61046927SAndroid Build Coastguard Worker          submit_bo->flags =
563*61046927SAndroid Build Coastguard Worker             buf->flags | MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE;
564*61046927SAndroid Build Coastguard Worker          submit_bo->presumed = buf->iova;
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker          buf->flags = 0;
567*61046927SAndroid Build Coastguard Worker       }
568*61046927SAndroid Build Coastguard Worker    } else {
569*61046927SAndroid Build Coastguard Worker       bo_list[0].handle = dev->va_id;
570*61046927SAndroid Build Coastguard Worker       bo_list[0].flags =
571*61046927SAndroid Build Coastguard Worker          MSM_SUBMIT_BO_DUMP | MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE;
572*61046927SAndroid Build Coastguard Worker       bo_list[0].presumed = dev->va_iova;
573*61046927SAndroid Build Coastguard Worker    }
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker    struct drm_msm_gem_submit submit_req = {
576*61046927SAndroid Build Coastguard Worker       .flags = MSM_PIPE_3D0,
577*61046927SAndroid Build Coastguard Worker       .queueid = dev->queue_id,
578*61046927SAndroid Build Coastguard Worker       .bos = (uint64_t)(uintptr_t)bo_list,
579*61046927SAndroid Build Coastguard Worker       .nr_bos = bo_count,
580*61046927SAndroid Build Coastguard Worker       .cmds = (uint64_t)(uintptr_t)cmds,
581*61046927SAndroid Build Coastguard Worker       .nr_cmds = u_vector_length(&dev->cmdstreams),
582*61046927SAndroid Build Coastguard Worker       .in_syncobjs = 0,
583*61046927SAndroid Build Coastguard Worker       .out_syncobjs = 0,
584*61046927SAndroid Build Coastguard Worker       .nr_in_syncobjs = 0,
585*61046927SAndroid Build Coastguard Worker       .nr_out_syncobjs = 0,
586*61046927SAndroid Build Coastguard Worker       .syncobj_stride = sizeof(struct drm_msm_gem_submit_syncobj),
587*61046927SAndroid Build Coastguard Worker    };
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker    int ret = drmCommandWriteRead(dev->fd, DRM_MSM_GEM_SUBMIT, &submit_req,
590*61046927SAndroid Build Coastguard Worker                                  sizeof(submit_req));
591*61046927SAndroid Build Coastguard Worker 
592*61046927SAndroid Build Coastguard Worker    if (ret) {
593*61046927SAndroid Build Coastguard Worker       err(1, "DRM_MSM_GEM_SUBMIT failure %d", ret);
594*61046927SAndroid Build Coastguard Worker    }
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker    /* Wait for submission to complete in order to be sure that
597*61046927SAndroid Build Coastguard Worker     * freeing buffers would free their VMAs in the kernel.
598*61046927SAndroid Build Coastguard Worker     * Makes sure that new allocations won't clash with old ones.
599*61046927SAndroid Build Coastguard Worker     */
600*61046927SAndroid Build Coastguard Worker    struct drm_msm_wait_fence wait_req = {
601*61046927SAndroid Build Coastguard Worker       .fence = submit_req.fence,
602*61046927SAndroid Build Coastguard Worker       .queueid = dev->queue_id,
603*61046927SAndroid Build Coastguard Worker    };
604*61046927SAndroid Build Coastguard Worker    get_abs_timeout(&wait_req.timeout, 1000000000);
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker    ret =
607*61046927SAndroid Build Coastguard Worker       drmCommandWrite(dev->fd, DRM_MSM_WAIT_FENCE, &wait_req, sizeof(wait_req));
608*61046927SAndroid Build Coastguard Worker    if (ret && (ret != -ETIMEDOUT)) {
609*61046927SAndroid Build Coastguard Worker       err(1, "DRM_MSM_WAIT_FENCE failure %d", ret);
610*61046927SAndroid Build Coastguard Worker    }
611*61046927SAndroid Build Coastguard Worker 
612*61046927SAndroid Build Coastguard Worker    u_vector_finish(&dev->cmdstreams);
613*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->cmdstreams, 8, sizeof(struct cmdstream));
614*61046927SAndroid Build Coastguard Worker 
615*61046927SAndroid Build Coastguard Worker    device_print_shader_log(dev);
616*61046927SAndroid Build Coastguard Worker    device_print_cp_log(dev);
617*61046927SAndroid Build Coastguard Worker 
618*61046927SAndroid Build Coastguard Worker    device_dump_wrbuf(dev);
619*61046927SAndroid Build Coastguard Worker    u_vector_finish(&dev->wrbufs);
620*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->wrbufs, 8, sizeof(struct wrbuf));
621*61046927SAndroid Build Coastguard Worker 
622*61046927SAndroid Build Coastguard Worker    device_free_buffers(dev);
623*61046927SAndroid Build Coastguard Worker }
624*61046927SAndroid Build Coastguard Worker 
625*61046927SAndroid Build Coastguard Worker static void
buffer_mem_alloc(struct device * dev,struct buffer * buf)626*61046927SAndroid Build Coastguard Worker buffer_mem_alloc(struct device *dev, struct buffer *buf)
627*61046927SAndroid Build Coastguard Worker {
628*61046927SAndroid Build Coastguard Worker    bool success = util_vma_heap_alloc_addr(&dev->vma, buf->iova, buf->size);
629*61046927SAndroid Build Coastguard Worker    if (!success)
630*61046927SAndroid Build Coastguard Worker       errx(1, "Failed to allocate buffer");
631*61046927SAndroid Build Coastguard Worker 
632*61046927SAndroid Build Coastguard Worker    if (!dev->has_set_iova) {
633*61046927SAndroid Build Coastguard Worker       uint64_t offset = buf->iova - dev->va_iova;
634*61046927SAndroid Build Coastguard Worker       assert(offset < FAKE_ADDRESS_SPACE_SIZE && (offset + buf->size) <= FAKE_ADDRESS_SPACE_SIZE);
635*61046927SAndroid Build Coastguard Worker       buf->map = ((uint8_t*)dev->va_map) + offset;
636*61046927SAndroid Build Coastguard Worker       return;
637*61046927SAndroid Build Coastguard Worker    }
638*61046927SAndroid Build Coastguard Worker 
639*61046927SAndroid Build Coastguard Worker    {
640*61046927SAndroid Build Coastguard Worker       struct drm_msm_gem_new req = {.size = buf->size, .flags = MSM_BO_WC};
641*61046927SAndroid Build Coastguard Worker 
642*61046927SAndroid Build Coastguard Worker       int ret =
643*61046927SAndroid Build Coastguard Worker          drmCommandWriteRead(dev->fd, DRM_MSM_GEM_NEW, &req, sizeof(req));
644*61046927SAndroid Build Coastguard Worker       if (ret) {
645*61046927SAndroid Build Coastguard Worker          err(1, "DRM_MSM_GEM_NEW failure %d", ret);
646*61046927SAndroid Build Coastguard Worker       }
647*61046927SAndroid Build Coastguard Worker 
648*61046927SAndroid Build Coastguard Worker       buf->gem_handle = req.handle;
649*61046927SAndroid Build Coastguard Worker    }
650*61046927SAndroid Build Coastguard Worker 
651*61046927SAndroid Build Coastguard Worker    {
652*61046927SAndroid Build Coastguard Worker       struct drm_msm_gem_info req = {
653*61046927SAndroid Build Coastguard Worker          .handle = buf->gem_handle,
654*61046927SAndroid Build Coastguard Worker          .info = MSM_INFO_SET_IOVA,
655*61046927SAndroid Build Coastguard Worker          .value = buf->iova,
656*61046927SAndroid Build Coastguard Worker       };
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker       int ret =
659*61046927SAndroid Build Coastguard Worker          drmCommandWriteRead(dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
660*61046927SAndroid Build Coastguard Worker 
661*61046927SAndroid Build Coastguard Worker       if (ret) {
662*61046927SAndroid Build Coastguard Worker          err(1, "MSM_INFO_SET_IOVA failure %d", ret);
663*61046927SAndroid Build Coastguard Worker       }
664*61046927SAndroid Build Coastguard Worker    }
665*61046927SAndroid Build Coastguard Worker 
666*61046927SAndroid Build Coastguard Worker    {
667*61046927SAndroid Build Coastguard Worker       struct drm_msm_gem_info req = {
668*61046927SAndroid Build Coastguard Worker          .handle = buf->gem_handle,
669*61046927SAndroid Build Coastguard Worker          .info = MSM_INFO_GET_OFFSET,
670*61046927SAndroid Build Coastguard Worker       };
671*61046927SAndroid Build Coastguard Worker 
672*61046927SAndroid Build Coastguard Worker       int ret =
673*61046927SAndroid Build Coastguard Worker          drmCommandWriteRead(dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
674*61046927SAndroid Build Coastguard Worker       if (ret) {
675*61046927SAndroid Build Coastguard Worker          err(1, "MSM_INFO_GET_OFFSET failure %d", ret);
676*61046927SAndroid Build Coastguard Worker       }
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker       void *map = mmap(0, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED,
679*61046927SAndroid Build Coastguard Worker                        dev->fd, req.value);
680*61046927SAndroid Build Coastguard Worker       if (map == MAP_FAILED) {
681*61046927SAndroid Build Coastguard Worker          err(1, "mmap failure");
682*61046927SAndroid Build Coastguard Worker       }
683*61046927SAndroid Build Coastguard Worker 
684*61046927SAndroid Build Coastguard Worker       buf->map = map;
685*61046927SAndroid Build Coastguard Worker    }
686*61046927SAndroid Build Coastguard Worker }
687*61046927SAndroid Build Coastguard Worker 
688*61046927SAndroid Build Coastguard Worker void
buffer_mem_free(struct device * dev,struct buffer * buf)689*61046927SAndroid Build Coastguard Worker buffer_mem_free(struct device *dev, struct buffer *buf)
690*61046927SAndroid Build Coastguard Worker {
691*61046927SAndroid Build Coastguard Worker    if (dev->has_set_iova) {
692*61046927SAndroid Build Coastguard Worker       munmap(buf->map, buf->size);
693*61046927SAndroid Build Coastguard Worker 
694*61046927SAndroid Build Coastguard Worker       struct drm_msm_gem_info req_iova = {
695*61046927SAndroid Build Coastguard Worker          .handle = buf->gem_handle,
696*61046927SAndroid Build Coastguard Worker          .info = MSM_INFO_SET_IOVA,
697*61046927SAndroid Build Coastguard Worker          .value = 0,
698*61046927SAndroid Build Coastguard Worker       };
699*61046927SAndroid Build Coastguard Worker 
700*61046927SAndroid Build Coastguard Worker       int ret = drmCommandWriteRead(dev->fd, DRM_MSM_GEM_INFO, &req_iova,
701*61046927SAndroid Build Coastguard Worker                                     sizeof(req_iova));
702*61046927SAndroid Build Coastguard Worker       if (ret < 0) {
703*61046927SAndroid Build Coastguard Worker          err(1, "MSM_INFO_SET_IOVA(0) failed! %d", ret);
704*61046927SAndroid Build Coastguard Worker          return;
705*61046927SAndroid Build Coastguard Worker       }
706*61046927SAndroid Build Coastguard Worker 
707*61046927SAndroid Build Coastguard Worker       struct drm_gem_close req = {
708*61046927SAndroid Build Coastguard Worker          .handle = buf->gem_handle,
709*61046927SAndroid Build Coastguard Worker       };
710*61046927SAndroid Build Coastguard Worker       drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
711*61046927SAndroid Build Coastguard Worker    }
712*61046927SAndroid Build Coastguard Worker 
713*61046927SAndroid Build Coastguard Worker    util_vma_heap_free(&dev->vma, buf->iova, buf->size);
714*61046927SAndroid Build Coastguard Worker }
715*61046927SAndroid Build Coastguard Worker 
716*61046927SAndroid Build Coastguard Worker #elif FD_REPLAY_KGSL
717*61046927SAndroid Build Coastguard Worker static int
safe_ioctl(int fd,unsigned long request,void * arg)718*61046927SAndroid Build Coastguard Worker safe_ioctl(int fd, unsigned long request, void *arg)
719*61046927SAndroid Build Coastguard Worker {
720*61046927SAndroid Build Coastguard Worker    int ret;
721*61046927SAndroid Build Coastguard Worker 
722*61046927SAndroid Build Coastguard Worker    do {
723*61046927SAndroid Build Coastguard Worker       ret = ioctl(fd, request, arg);
724*61046927SAndroid Build Coastguard Worker    } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
725*61046927SAndroid Build Coastguard Worker 
726*61046927SAndroid Build Coastguard Worker    return ret;
727*61046927SAndroid Build Coastguard Worker }
728*61046927SAndroid Build Coastguard Worker 
729*61046927SAndroid Build Coastguard Worker static struct device *
device_create(uint64_t base_addr)730*61046927SAndroid Build Coastguard Worker device_create(uint64_t base_addr)
731*61046927SAndroid Build Coastguard Worker {
732*61046927SAndroid Build Coastguard Worker    struct device *dev = calloc(sizeof(struct device), 1);
733*61046927SAndroid Build Coastguard Worker 
734*61046927SAndroid Build Coastguard Worker    static const char path[] = "/dev/kgsl-3d0";
735*61046927SAndroid Build Coastguard Worker 
736*61046927SAndroid Build Coastguard Worker    dev->fd = open(path, O_RDWR | O_CLOEXEC);
737*61046927SAndroid Build Coastguard Worker    if (dev->fd < 0) {
738*61046927SAndroid Build Coastguard Worker       errx(1, "Cannot open KGSL fd!");
739*61046927SAndroid Build Coastguard Worker    }
740*61046927SAndroid Build Coastguard Worker 
741*61046927SAndroid Build Coastguard Worker    struct kgsl_gpumem_alloc_id req = {
742*61046927SAndroid Build Coastguard Worker       .size = FAKE_ADDRESS_SPACE_SIZE,
743*61046927SAndroid Build Coastguard Worker       .flags = KGSL_MEMFLAGS_IOCOHERENT,
744*61046927SAndroid Build Coastguard Worker    };
745*61046927SAndroid Build Coastguard Worker 
746*61046927SAndroid Build Coastguard Worker    int ret = safe_ioctl(dev->fd, IOCTL_KGSL_GPUMEM_ALLOC_ID, &req);
747*61046927SAndroid Build Coastguard Worker    if (ret) {
748*61046927SAndroid Build Coastguard Worker       err(1, "IOCTL_KGSL_GPUMEM_ALLOC_ID failure");
749*61046927SAndroid Build Coastguard Worker    }
750*61046927SAndroid Build Coastguard Worker 
751*61046927SAndroid Build Coastguard Worker    dev->va_id = req.id;
752*61046927SAndroid Build Coastguard Worker    dev->va_iova = req.gpuaddr;
753*61046927SAndroid Build Coastguard Worker    dev->va_map = mmap(0, FAKE_ADDRESS_SPACE_SIZE, PROT_READ | PROT_WRITE,
754*61046927SAndroid Build Coastguard Worker                       MAP_SHARED, dev->fd, req.id << 12);
755*61046927SAndroid Build Coastguard Worker 
756*61046927SAndroid Build Coastguard Worker    rb_tree_init(&dev->buffers);
757*61046927SAndroid Build Coastguard Worker    util_vma_heap_init(&dev->vma, req.gpuaddr, ROUND_DOWN_TO(FAKE_ADDRESS_SPACE_SIZE, 4096));
758*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->cmdstreams, 8, sizeof(struct cmdstream));
759*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->wrbufs, 8, sizeof(struct wrbuf));
760*61046927SAndroid Build Coastguard Worker 
761*61046927SAndroid Build Coastguard Worker    struct kgsl_drawctxt_create drawctxt_req = {
762*61046927SAndroid Build Coastguard Worker       .flags = KGSL_CONTEXT_SAVE_GMEM |
763*61046927SAndroid Build Coastguard Worker               KGSL_CONTEXT_NO_GMEM_ALLOC |
764*61046927SAndroid Build Coastguard Worker               KGSL_CONTEXT_PREAMBLE,
765*61046927SAndroid Build Coastguard Worker    };
766*61046927SAndroid Build Coastguard Worker 
767*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, IOCTL_KGSL_DRAWCTXT_CREATE, &drawctxt_req);
768*61046927SAndroid Build Coastguard Worker    if (ret) {
769*61046927SAndroid Build Coastguard Worker       err(1, "IOCTL_KGSL_DRAWCTXT_CREATE failure");
770*61046927SAndroid Build Coastguard Worker    }
771*61046927SAndroid Build Coastguard Worker 
772*61046927SAndroid Build Coastguard Worker    printf("Allocated iova %" PRIx64 "\n", dev->va_iova);
773*61046927SAndroid Build Coastguard Worker 
774*61046927SAndroid Build Coastguard Worker    dev->context_id = drawctxt_req.drawctxt_id;
775*61046927SAndroid Build Coastguard Worker 
776*61046927SAndroid Build Coastguard Worker    return dev;
777*61046927SAndroid Build Coastguard Worker }
778*61046927SAndroid Build Coastguard Worker 
779*61046927SAndroid Build Coastguard Worker static void
device_submit_cmdstreams(struct device * dev)780*61046927SAndroid Build Coastguard Worker device_submit_cmdstreams(struct device *dev)
781*61046927SAndroid Build Coastguard Worker {
782*61046927SAndroid Build Coastguard Worker    if (!u_vector_length(&dev->cmdstreams)) {
783*61046927SAndroid Build Coastguard Worker       device_free_buffers(dev);
784*61046927SAndroid Build Coastguard Worker       return;
785*61046927SAndroid Build Coastguard Worker    }
786*61046927SAndroid Build Coastguard Worker 
787*61046927SAndroid Build Coastguard Worker    struct kgsl_command_object cmds[u_vector_length(&dev->cmdstreams)];
788*61046927SAndroid Build Coastguard Worker 
789*61046927SAndroid Build Coastguard Worker    uint32_t idx = 0;
790*61046927SAndroid Build Coastguard Worker    struct cmdstream *cmd;
791*61046927SAndroid Build Coastguard Worker    u_vector_foreach(cmd, &dev->cmdstreams) {
792*61046927SAndroid Build Coastguard Worker       struct kgsl_command_object *submit_cmd = &cmds[idx++];
793*61046927SAndroid Build Coastguard Worker       submit_cmd->gpuaddr = cmd->iova;
794*61046927SAndroid Build Coastguard Worker       submit_cmd->size = cmd->size;
795*61046927SAndroid Build Coastguard Worker       submit_cmd->flags = KGSL_CMDLIST_IB;
796*61046927SAndroid Build Coastguard Worker       submit_cmd->id = dev->va_id;
797*61046927SAndroid Build Coastguard Worker    }
798*61046927SAndroid Build Coastguard Worker 
799*61046927SAndroid Build Coastguard Worker    struct kgsl_gpu_command submit_req = {
800*61046927SAndroid Build Coastguard Worker       .flags = KGSL_CMDBATCH_SUBMIT_IB_LIST,
801*61046927SAndroid Build Coastguard Worker       .cmdlist = (uintptr_t) &cmds,
802*61046927SAndroid Build Coastguard Worker       .cmdsize = sizeof(struct kgsl_command_object),
803*61046927SAndroid Build Coastguard Worker       .numcmds = u_vector_length(&dev->cmdstreams),
804*61046927SAndroid Build Coastguard Worker       .numsyncs = 0,
805*61046927SAndroid Build Coastguard Worker       .context_id = dev->context_id,
806*61046927SAndroid Build Coastguard Worker    };
807*61046927SAndroid Build Coastguard Worker 
808*61046927SAndroid Build Coastguard Worker    int ret = safe_ioctl(dev->fd, IOCTL_KGSL_GPU_COMMAND, &submit_req);
809*61046927SAndroid Build Coastguard Worker 
810*61046927SAndroid Build Coastguard Worker    if (ret) {
811*61046927SAndroid Build Coastguard Worker       err(1, "IOCTL_KGSL_GPU_COMMAND failure %d", ret);
812*61046927SAndroid Build Coastguard Worker    }
813*61046927SAndroid Build Coastguard Worker 
814*61046927SAndroid Build Coastguard Worker    struct kgsl_device_waittimestamp_ctxtid wait = {
815*61046927SAndroid Build Coastguard Worker       .context_id = dev->context_id,
816*61046927SAndroid Build Coastguard Worker       .timestamp = submit_req.timestamp,
817*61046927SAndroid Build Coastguard Worker       .timeout = 3000,
818*61046927SAndroid Build Coastguard Worker    };
819*61046927SAndroid Build Coastguard Worker 
820*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID, &wait);
821*61046927SAndroid Build Coastguard Worker 
822*61046927SAndroid Build Coastguard Worker    if (ret) {
823*61046927SAndroid Build Coastguard Worker       err(1, "IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID failure %d", ret);
824*61046927SAndroid Build Coastguard Worker    }
825*61046927SAndroid Build Coastguard Worker 
826*61046927SAndroid Build Coastguard Worker    u_vector_finish(&dev->cmdstreams);
827*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->cmdstreams, 8, sizeof(struct cmdstream));
828*61046927SAndroid Build Coastguard Worker 
829*61046927SAndroid Build Coastguard Worker    device_print_shader_log(dev);
830*61046927SAndroid Build Coastguard Worker    device_print_cp_log(dev);
831*61046927SAndroid Build Coastguard Worker 
832*61046927SAndroid Build Coastguard Worker    device_dump_wrbuf(dev);
833*61046927SAndroid Build Coastguard Worker    u_vector_finish(&dev->wrbufs);
834*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->wrbufs, 8, sizeof(struct wrbuf));
835*61046927SAndroid Build Coastguard Worker 
836*61046927SAndroid Build Coastguard Worker    device_free_buffers(dev);
837*61046927SAndroid Build Coastguard Worker }
838*61046927SAndroid Build Coastguard Worker 
839*61046927SAndroid Build Coastguard Worker static void
buffer_mem_alloc(struct device * dev,struct buffer * buf)840*61046927SAndroid Build Coastguard Worker buffer_mem_alloc(struct device *dev, struct buffer *buf)
841*61046927SAndroid Build Coastguard Worker {
842*61046927SAndroid Build Coastguard Worker    bool success = util_vma_heap_alloc_addr(&dev->vma, buf->iova, buf->size);
843*61046927SAndroid Build Coastguard Worker    if (!success)
844*61046927SAndroid Build Coastguard Worker       errx(1, "Failed to allocate buffer");
845*61046927SAndroid Build Coastguard Worker 
846*61046927SAndroid Build Coastguard Worker    buf->map = ((uint8_t*)dev->va_map) + (buf->iova - dev->va_iova);
847*61046927SAndroid Build Coastguard Worker }
848*61046927SAndroid Build Coastguard Worker 
849*61046927SAndroid Build Coastguard Worker void
buffer_mem_free(struct device * dev,struct buffer * buf)850*61046927SAndroid Build Coastguard Worker buffer_mem_free(struct device *dev, struct buffer *buf)
851*61046927SAndroid Build Coastguard Worker {
852*61046927SAndroid Build Coastguard Worker    util_vma_heap_free(&dev->vma, buf->iova, buf->size);
853*61046927SAndroid Build Coastguard Worker }
854*61046927SAndroid Build Coastguard Worker #else
855*61046927SAndroid Build Coastguard Worker 
856*61046927SAndroid Build Coastguard Worker static int
safe_ioctl(int fd,unsigned long request,void * arg)857*61046927SAndroid Build Coastguard Worker safe_ioctl(int fd, unsigned long request, void *arg)
858*61046927SAndroid Build Coastguard Worker {
859*61046927SAndroid Build Coastguard Worker    int ret;
860*61046927SAndroid Build Coastguard Worker 
861*61046927SAndroid Build Coastguard Worker    do {
862*61046927SAndroid Build Coastguard Worker       ret = ioctl(fd, request, arg);
863*61046927SAndroid Build Coastguard Worker    } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
864*61046927SAndroid Build Coastguard Worker 
865*61046927SAndroid Build Coastguard Worker    return ret;
866*61046927SAndroid Build Coastguard Worker }
867*61046927SAndroid Build Coastguard Worker 
868*61046927SAndroid Build Coastguard Worker struct alloc_priv_info {
869*61046927SAndroid Build Coastguard Worker    __u32 struct_size;
870*61046927SAndroid Build Coastguard Worker    char _pad0[4];
871*61046927SAndroid Build Coastguard Worker    __u32 unk0; // 1
872*61046927SAndroid Build Coastguard Worker    char _pad1[4];
873*61046927SAndroid Build Coastguard Worker    __u64 size;
874*61046927SAndroid Build Coastguard Worker    __u32 alignment;
875*61046927SAndroid Build Coastguard Worker    char _pad2[20];
876*61046927SAndroid Build Coastguard Worker    __u64 allocated_size;
877*61046927SAndroid Build Coastguard Worker    __u32 unk1;   // 1
878*61046927SAndroid Build Coastguard Worker    char _pad4[8]; /* offset: 60*/
879*61046927SAndroid Build Coastguard Worker    __u32 unk2;   // 61
880*61046927SAndroid Build Coastguard Worker    char _pad5[76];
881*61046927SAndroid Build Coastguard Worker    __u32 unk3; /* offset: 148 */ // 1
882*61046927SAndroid Build Coastguard Worker    char _pad6[8];
883*61046927SAndroid Build Coastguard Worker    __u32 unk4; /* offset: 160 */ // 1
884*61046927SAndroid Build Coastguard Worker    char _pad7[44];
885*61046927SAndroid Build Coastguard Worker    __u32 unk5; /* offset: 208 */ // 3
886*61046927SAndroid Build Coastguard Worker    char _pad8[16];
887*61046927SAndroid Build Coastguard Worker    __u32 size_2; /* offset: 228 */
888*61046927SAndroid Build Coastguard Worker    __u32 unk6;   // 1
889*61046927SAndroid Build Coastguard Worker    __u32 size_3;
890*61046927SAndroid Build Coastguard Worker    __u32 size_4;
891*61046927SAndroid Build Coastguard Worker    __u32 unk7; /* offset: 244 */ // 1
892*61046927SAndroid Build Coastguard Worker    char _pad9[56];
893*61046927SAndroid Build Coastguard Worker };
894*61046927SAndroid Build Coastguard Worker static_assert(sizeof(struct alloc_priv_info) == 304);
895*61046927SAndroid Build Coastguard Worker static_assert(offsetof(struct alloc_priv_info, unk1) == 56);
896*61046927SAndroid Build Coastguard Worker static_assert(offsetof(struct alloc_priv_info, unk3) == 148);
897*61046927SAndroid Build Coastguard Worker static_assert(offsetof(struct alloc_priv_info, unk5) == 208);
898*61046927SAndroid Build Coastguard Worker 
899*61046927SAndroid Build Coastguard Worker struct submit_priv_ib_info {
900*61046927SAndroid Build Coastguard Worker    char _pad5[4];
901*61046927SAndroid Build Coastguard Worker    __u32 size_dwords;
902*61046927SAndroid Build Coastguard Worker    __u64 iova;
903*61046927SAndroid Build Coastguard Worker    char _pad6[8];
904*61046927SAndroid Build Coastguard Worker } __attribute__((packed));
905*61046927SAndroid Build Coastguard Worker 
906*61046927SAndroid Build Coastguard Worker struct submit_priv_data {
907*61046927SAndroid Build Coastguard Worker    __u32 magic0;
908*61046927SAndroid Build Coastguard Worker    char _pad0[4];
909*61046927SAndroid Build Coastguard Worker    __u32 struct_size;
910*61046927SAndroid Build Coastguard Worker    char _pad1[4];
911*61046927SAndroid Build Coastguard Worker    /* It seems that priv data can have several sub-datas
912*61046927SAndroid Build Coastguard Worker     * cmdbuf is one of them, after it there is another 8 byte struct
913*61046927SAndroid Build Coastguard Worker     * without anything useful in it. That second data doesn't seem
914*61046927SAndroid Build Coastguard Worker     * important for replaying.
915*61046927SAndroid Build Coastguard Worker     */
916*61046927SAndroid Build Coastguard Worker    __u32 datas_count;
917*61046927SAndroid Build Coastguard Worker    char _pad2[32];
918*61046927SAndroid Build Coastguard Worker    struct {
919*61046927SAndroid Build Coastguard Worker       __u32 magic1;
920*61046927SAndroid Build Coastguard Worker       __u32 data_size;
921*61046927SAndroid Build Coastguard Worker 
922*61046927SAndroid Build Coastguard Worker       struct {
923*61046927SAndroid Build Coastguard Worker          __u32 unk1;
924*61046927SAndroid Build Coastguard Worker          __u32 cmdbuf_size;
925*61046927SAndroid Build Coastguard Worker          char _pad3[32];
926*61046927SAndroid Build Coastguard Worker          __u32 ib_count;
927*61046927SAndroid Build Coastguard Worker          char _pad4[36];
928*61046927SAndroid Build Coastguard Worker 
929*61046927SAndroid Build Coastguard Worker          struct submit_priv_ib_info ibs[];
930*61046927SAndroid Build Coastguard Worker       } cmdbuf;
931*61046927SAndroid Build Coastguard Worker    } data0;
932*61046927SAndroid Build Coastguard Worker 
933*61046927SAndroid Build Coastguard Worker    //    unsigned char magic2[8];
934*61046927SAndroid Build Coastguard Worker } __attribute__((packed));
935*61046927SAndroid Build Coastguard Worker static_assert(offsetof(struct submit_priv_data, data0) == 0x34);
936*61046927SAndroid Build Coastguard Worker static_assert(offsetof(struct submit_priv_data, data0.cmdbuf.ibs) == 0x8c);
937*61046927SAndroid Build Coastguard Worker 
938*61046927SAndroid Build Coastguard Worker static struct device *
device_create(uint64_t base_addr)939*61046927SAndroid Build Coastguard Worker device_create(uint64_t base_addr)
940*61046927SAndroid Build Coastguard Worker {
941*61046927SAndroid Build Coastguard Worker    struct device *dev = calloc(sizeof(struct device), 1);
942*61046927SAndroid Build Coastguard Worker 
943*61046927SAndroid Build Coastguard Worker    static const char path[] = "/dev/dxg";
944*61046927SAndroid Build Coastguard Worker 
945*61046927SAndroid Build Coastguard Worker    dev->fd = open(path, O_RDWR | O_CLOEXEC);
946*61046927SAndroid Build Coastguard Worker    if (dev->fd < 0) {
947*61046927SAndroid Build Coastguard Worker       errx(1, "Cannot open /dev/dxg fd");
948*61046927SAndroid Build Coastguard Worker    }
949*61046927SAndroid Build Coastguard Worker 
950*61046927SAndroid Build Coastguard Worker    struct d3dkmt_adapterinfo adapters[1];
951*61046927SAndroid Build Coastguard Worker    struct d3dkmt_enumadapters3 enum_adapters = {
952*61046927SAndroid Build Coastguard Worker       .adapter_count = 1,
953*61046927SAndroid Build Coastguard Worker       .adapters = adapters,
954*61046927SAndroid Build Coastguard Worker    };
955*61046927SAndroid Build Coastguard Worker    int ret = safe_ioctl(dev->fd, LX_DXENUMADAPTERS3, &enum_adapters);
956*61046927SAndroid Build Coastguard Worker    if (ret) {
957*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXENUMADAPTERS3 failure");
958*61046927SAndroid Build Coastguard Worker    }
959*61046927SAndroid Build Coastguard Worker 
960*61046927SAndroid Build Coastguard Worker    if (enum_adapters.adapter_count == 0) {
961*61046927SAndroid Build Coastguard Worker       errx(1, "No adapters found");
962*61046927SAndroid Build Coastguard Worker    }
963*61046927SAndroid Build Coastguard Worker 
964*61046927SAndroid Build Coastguard Worker    struct winluid adapter_luid = enum_adapters.adapters[0].adapter_luid;
965*61046927SAndroid Build Coastguard Worker 
966*61046927SAndroid Build Coastguard Worker    struct d3dkmt_openadapterfromluid open_adapter = {
967*61046927SAndroid Build Coastguard Worker       .adapter_luid = adapter_luid,
968*61046927SAndroid Build Coastguard Worker    };
969*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, LX_DXOPENADAPTERFROMLUID, &open_adapter);
970*61046927SAndroid Build Coastguard Worker    if (ret) {
971*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXOPENADAPTERFROMLUID failure");
972*61046927SAndroid Build Coastguard Worker    }
973*61046927SAndroid Build Coastguard Worker 
974*61046927SAndroid Build Coastguard Worker    struct d3dkmthandle adapter = open_adapter.adapter_handle;
975*61046927SAndroid Build Coastguard Worker 
976*61046927SAndroid Build Coastguard Worker    struct d3dkmt_createdevice create_device = {
977*61046927SAndroid Build Coastguard Worker       .adapter = adapter,
978*61046927SAndroid Build Coastguard Worker    };
979*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, LX_DXCREATEDEVICE, &create_device);
980*61046927SAndroid Build Coastguard Worker    if (ret) {
981*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXCREATEDEVICE failure");
982*61046927SAndroid Build Coastguard Worker    }
983*61046927SAndroid Build Coastguard Worker 
984*61046927SAndroid Build Coastguard Worker    struct d3dkmthandle device = create_device.device;
985*61046927SAndroid Build Coastguard Worker    dev->device = device;
986*61046927SAndroid Build Coastguard Worker 
987*61046927SAndroid Build Coastguard Worker    unsigned char create_context_priv_data[] = {
988*61046927SAndroid Build Coastguard Worker       0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
989*61046927SAndroid Build Coastguard Worker       0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
990*61046927SAndroid Build Coastguard Worker       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x00, 0x00, 0x00,
991*61046927SAndroid Build Coastguard Worker       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992*61046927SAndroid Build Coastguard Worker       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
993*61046927SAndroid Build Coastguard Worker       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
994*61046927SAndroid Build Coastguard Worker    };
995*61046927SAndroid Build Coastguard Worker 
996*61046927SAndroid Build Coastguard Worker    struct d3dkmt_createcontextvirtual create_context = {
997*61046927SAndroid Build Coastguard Worker       .device = device,
998*61046927SAndroid Build Coastguard Worker       .node_ordinal = 0,
999*61046927SAndroid Build Coastguard Worker       .engine_affinity = 1,
1000*61046927SAndroid Build Coastguard Worker       .priv_drv_data = create_context_priv_data,
1001*61046927SAndroid Build Coastguard Worker       .priv_drv_data_size = sizeof(create_context_priv_data),
1002*61046927SAndroid Build Coastguard Worker       .client_hint = 16,
1003*61046927SAndroid Build Coastguard Worker    };
1004*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, LX_DXCREATECONTEXTVIRTUAL, &create_context);
1005*61046927SAndroid Build Coastguard Worker    if (ret) {
1006*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXCREATECONTEXTVIRTUAL failure");
1007*61046927SAndroid Build Coastguard Worker    }
1008*61046927SAndroid Build Coastguard Worker 
1009*61046927SAndroid Build Coastguard Worker    dev->context = create_context.context;
1010*61046927SAndroid Build Coastguard Worker 
1011*61046927SAndroid Build Coastguard Worker    struct d3dkmt_createpagingqueue create_paging_queue = {
1012*61046927SAndroid Build Coastguard Worker       .device = device,
1013*61046927SAndroid Build Coastguard Worker       .priority = _D3DDDI_PAGINGQUEUE_PRIORITY_NORMAL,
1014*61046927SAndroid Build Coastguard Worker       .physical_adapter_index = 0,
1015*61046927SAndroid Build Coastguard Worker    };
1016*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, LX_DXCREATEPAGINGQUEUE, &create_paging_queue);
1017*61046927SAndroid Build Coastguard Worker    if (ret) {
1018*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXCREATEPAGINGQUEUE failure");
1019*61046927SAndroid Build Coastguard Worker    }
1020*61046927SAndroid Build Coastguard Worker    struct d3dkmthandle paging_queue = create_paging_queue.paging_queue;
1021*61046927SAndroid Build Coastguard Worker 
1022*61046927SAndroid Build Coastguard Worker 
1023*61046927SAndroid Build Coastguard Worker    uint32_t alloc_size = FAKE_ADDRESS_SPACE_SIZE;
1024*61046927SAndroid Build Coastguard Worker    struct alloc_priv_info priv_alloc_info = {
1025*61046927SAndroid Build Coastguard Worker       .struct_size = sizeof(struct alloc_priv_info),
1026*61046927SAndroid Build Coastguard Worker       .unk0 = 1,
1027*61046927SAndroid Build Coastguard Worker       .size = alloc_size,
1028*61046927SAndroid Build Coastguard Worker       .alignment = 4096,
1029*61046927SAndroid Build Coastguard Worker       .unk1 = 1,
1030*61046927SAndroid Build Coastguard Worker       .unk2 = 61,
1031*61046927SAndroid Build Coastguard Worker       .unk3 = 1,
1032*61046927SAndroid Build Coastguard Worker       .unk4 = 1,
1033*61046927SAndroid Build Coastguard Worker       .unk5 = 3,
1034*61046927SAndroid Build Coastguard Worker       .size_2 = alloc_size,
1035*61046927SAndroid Build Coastguard Worker       .unk6 = 1,
1036*61046927SAndroid Build Coastguard Worker       .size_3 = alloc_size,
1037*61046927SAndroid Build Coastguard Worker       .size_4 = alloc_size,
1038*61046927SAndroid Build Coastguard Worker       .unk7 = 1,
1039*61046927SAndroid Build Coastguard Worker    };
1040*61046927SAndroid Build Coastguard Worker 
1041*61046927SAndroid Build Coastguard Worker    struct d3dddi_allocationinfo2 alloc_info = {
1042*61046927SAndroid Build Coastguard Worker       .priv_drv_data = &priv_alloc_info,
1043*61046927SAndroid Build Coastguard Worker       .priv_drv_data_size = sizeof(struct alloc_priv_info),
1044*61046927SAndroid Build Coastguard Worker    };
1045*61046927SAndroid Build Coastguard Worker 
1046*61046927SAndroid Build Coastguard Worker    struct d3dkmt_createallocation create_allocation = {
1047*61046927SAndroid Build Coastguard Worker       .device = device,
1048*61046927SAndroid Build Coastguard Worker       .alloc_count = 1,
1049*61046927SAndroid Build Coastguard Worker       .allocation_info = &alloc_info,
1050*61046927SAndroid Build Coastguard Worker    };
1051*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, LX_DXCREATEALLOCATION, &create_allocation);
1052*61046927SAndroid Build Coastguard Worker    if (ret) {
1053*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXCREATEALLOCATION failure");
1054*61046927SAndroid Build Coastguard Worker    }
1055*61046927SAndroid Build Coastguard Worker 
1056*61046927SAndroid Build Coastguard Worker    assert(priv_alloc_info.allocated_size == alloc_size);
1057*61046927SAndroid Build Coastguard Worker 
1058*61046927SAndroid Build Coastguard Worker    struct d3dddi_mapgpuvirtualaddress map_virtual_address = {
1059*61046927SAndroid Build Coastguard Worker       .paging_queue = paging_queue,
1060*61046927SAndroid Build Coastguard Worker       .base_address = base_addr,
1061*61046927SAndroid Build Coastguard Worker       .maximum_address = 18446744073709551615ull,
1062*61046927SAndroid Build Coastguard Worker       .allocation = create_allocation.allocation_info[0].allocation,
1063*61046927SAndroid Build Coastguard Worker       .size_in_pages = MAX2(alloc_size / 4096, 1),
1064*61046927SAndroid Build Coastguard Worker       .protection = {
1065*61046927SAndroid Build Coastguard Worker          .write = 1,
1066*61046927SAndroid Build Coastguard Worker          .execute = 1,
1067*61046927SAndroid Build Coastguard Worker       },
1068*61046927SAndroid Build Coastguard Worker    };
1069*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, LX_DXMAPGPUVIRTUALADDRESS, &map_virtual_address);
1070*61046927SAndroid Build Coastguard Worker    if (ret != 259) {
1071*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXMAPGPUVIRTUALADDRESS failure");
1072*61046927SAndroid Build Coastguard Worker    }
1073*61046927SAndroid Build Coastguard Worker 
1074*61046927SAndroid Build Coastguard Worker    __u32 priority = 0;
1075*61046927SAndroid Build Coastguard Worker    struct d3dddi_makeresident make_resident = {
1076*61046927SAndroid Build Coastguard Worker       .paging_queue = paging_queue,
1077*61046927SAndroid Build Coastguard Worker       .alloc_count = 1,
1078*61046927SAndroid Build Coastguard Worker       .allocation_list = &create_allocation.allocation_info[0].allocation,
1079*61046927SAndroid Build Coastguard Worker       .priority_list = &priority,
1080*61046927SAndroid Build Coastguard Worker    };
1081*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, LX_DXMAKERESIDENT, &make_resident);
1082*61046927SAndroid Build Coastguard Worker    if (ret != 259) {
1083*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXMAKERESIDENT failure");
1084*61046927SAndroid Build Coastguard Worker    }
1085*61046927SAndroid Build Coastguard Worker 
1086*61046927SAndroid Build Coastguard Worker    struct d3dkmt_lock2 lock = {
1087*61046927SAndroid Build Coastguard Worker       .device = device,
1088*61046927SAndroid Build Coastguard Worker       .allocation = create_allocation.allocation_info[0].allocation,
1089*61046927SAndroid Build Coastguard Worker    };
1090*61046927SAndroid Build Coastguard Worker    ret = safe_ioctl(dev->fd, LX_DXLOCK2, &lock);
1091*61046927SAndroid Build Coastguard Worker    if (ret) {
1092*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXLOCK2 failure");
1093*61046927SAndroid Build Coastguard Worker    }
1094*61046927SAndroid Build Coastguard Worker 
1095*61046927SAndroid Build Coastguard Worker    dev->va_iova = map_virtual_address.virtual_address;
1096*61046927SAndroid Build Coastguard Worker    dev->va_map = lock.data;
1097*61046927SAndroid Build Coastguard Worker 
1098*61046927SAndroid Build Coastguard Worker    rb_tree_init(&dev->buffers);
1099*61046927SAndroid Build Coastguard Worker    util_vma_heap_init(&dev->vma, dev->va_iova, ROUND_DOWN_TO(alloc_size, 4096));
1100*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->cmdstreams, 8, sizeof(struct cmdstream));
1101*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->wrbufs, 8, sizeof(struct wrbuf));
1102*61046927SAndroid Build Coastguard Worker 
1103*61046927SAndroid Build Coastguard Worker    printf("Allocated iova at 0x%" PRIx64 "\n", dev->va_iova);
1104*61046927SAndroid Build Coastguard Worker 
1105*61046927SAndroid Build Coastguard Worker    uint64_t hole_size = 4096;
1106*61046927SAndroid Build Coastguard Worker    dev->vma.alloc_high = true;
1107*61046927SAndroid Build Coastguard Worker    dev->fence_iova = util_vma_heap_alloc(&dev->vma, hole_size, 4096);
1108*61046927SAndroid Build Coastguard Worker    dev->fence_ib_iova = dev->fence_iova + 8;
1109*61046927SAndroid Build Coastguard Worker    dev->fence = (uint32_t *) ((uint8_t*)dev->va_map + (dev->fence_iova - dev->va_iova));
1110*61046927SAndroid Build Coastguard Worker    dev->fence_ib = (uint32_t *) ((uint8_t*)dev->va_map + (dev->fence_ib_iova - dev->va_iova));
1111*61046927SAndroid Build Coastguard Worker    dev->vma.alloc_high = false;
1112*61046927SAndroid Build Coastguard Worker 
1113*61046927SAndroid Build Coastguard Worker    return dev;
1114*61046927SAndroid Build Coastguard Worker }
1115*61046927SAndroid Build Coastguard Worker 
1116*61046927SAndroid Build Coastguard Worker static void
device_submit_cmdstreams(struct device * dev)1117*61046927SAndroid Build Coastguard Worker device_submit_cmdstreams(struct device *dev)
1118*61046927SAndroid Build Coastguard Worker {
1119*61046927SAndroid Build Coastguard Worker    if (!u_vector_length(&dev->cmdstreams)) {
1120*61046927SAndroid Build Coastguard Worker       device_free_buffers(dev);
1121*61046927SAndroid Build Coastguard Worker       return;
1122*61046927SAndroid Build Coastguard Worker    }
1123*61046927SAndroid Build Coastguard Worker 
1124*61046927SAndroid Build Coastguard Worker    uint32_t cmdstream_count = u_vector_length(&dev->cmdstreams) + 1;
1125*61046927SAndroid Build Coastguard Worker 
1126*61046927SAndroid Build Coastguard Worker    uint32_t priv_data_size =
1127*61046927SAndroid Build Coastguard Worker       sizeof(struct submit_priv_data) +
1128*61046927SAndroid Build Coastguard Worker       cmdstream_count * sizeof(struct submit_priv_ib_info);
1129*61046927SAndroid Build Coastguard Worker 
1130*61046927SAndroid Build Coastguard Worker    struct submit_priv_data *priv_data = calloc(1, priv_data_size);
1131*61046927SAndroid Build Coastguard Worker    priv_data->magic0 = 0xccaabbee;
1132*61046927SAndroid Build Coastguard Worker    priv_data->struct_size = priv_data_size;
1133*61046927SAndroid Build Coastguard Worker    priv_data->datas_count = 1;
1134*61046927SAndroid Build Coastguard Worker 
1135*61046927SAndroid Build Coastguard Worker    priv_data->data0.magic1 = 0xfadcab02;
1136*61046927SAndroid Build Coastguard Worker    priv_data->data0.data_size =
1137*61046927SAndroid Build Coastguard Worker       sizeof(priv_data->data0) +
1138*61046927SAndroid Build Coastguard Worker       cmdstream_count * sizeof(struct submit_priv_ib_info);
1139*61046927SAndroid Build Coastguard Worker    priv_data->data0.cmdbuf.unk1 = 0xcccc0001;
1140*61046927SAndroid Build Coastguard Worker    priv_data->data0.cmdbuf.cmdbuf_size = sizeof(priv_data->data0.cmdbuf) +
1141*61046927SAndroid Build Coastguard Worker       cmdstream_count * sizeof(struct submit_priv_ib_info);
1142*61046927SAndroid Build Coastguard Worker    priv_data->data0.cmdbuf.ib_count = cmdstream_count;
1143*61046927SAndroid Build Coastguard Worker 
1144*61046927SAndroid Build Coastguard Worker    struct cmdstream *cmd;
1145*61046927SAndroid Build Coastguard Worker    uint32_t idx = 0;
1146*61046927SAndroid Build Coastguard Worker    u_vector_foreach(cmd, &dev->cmdstreams) {
1147*61046927SAndroid Build Coastguard Worker       priv_data->data0.cmdbuf.ibs[idx].size_dwords = cmd->size / 4;
1148*61046927SAndroid Build Coastguard Worker       priv_data->data0.cmdbuf.ibs[idx].iova = cmd->iova;
1149*61046927SAndroid Build Coastguard Worker       idx++;
1150*61046927SAndroid Build Coastguard Worker    }
1151*61046927SAndroid Build Coastguard Worker 
1152*61046927SAndroid Build Coastguard Worker    priv_data->data0.cmdbuf.ibs[idx].size_dwords = 4;
1153*61046927SAndroid Build Coastguard Worker    priv_data->data0.cmdbuf.ibs[idx].iova = dev->fence_ib_iova;
1154*61046927SAndroid Build Coastguard Worker 
1155*61046927SAndroid Build Coastguard Worker    *dev->fence = 0x00000000;
1156*61046927SAndroid Build Coastguard Worker    dev->fence_ib[0] = pm4_pkt7_hdr(0x3d, 3); // CP_MEM_WRITE
1157*61046927SAndroid Build Coastguard Worker    dev->fence_ib[1] = dev->fence_iova;
1158*61046927SAndroid Build Coastguard Worker    dev->fence_ib[2] = dev->fence_iova >> 32;
1159*61046927SAndroid Build Coastguard Worker    dev->fence_ib[3] = 0xababfcfc;
1160*61046927SAndroid Build Coastguard Worker 
1161*61046927SAndroid Build Coastguard Worker    // Fill second (empty) data block
1162*61046927SAndroid Build Coastguard Worker    // uint32_t *magic_end = (uint32_t *)(((char *) priv_data) + priv_data_size - 8);
1163*61046927SAndroid Build Coastguard Worker    // magic_end[0] = 0xfadcab00;
1164*61046927SAndroid Build Coastguard Worker    // magic_end[1] = 0x00000008;
1165*61046927SAndroid Build Coastguard Worker 
1166*61046927SAndroid Build Coastguard Worker    struct d3dkmt_submitcommand submission = {
1167*61046927SAndroid Build Coastguard Worker       .command_buffer = priv_data->data0.cmdbuf.ibs[0].iova,
1168*61046927SAndroid Build Coastguard Worker       .command_length = priv_data->data0.cmdbuf.ibs[0].size_dwords * sizeof(uint32_t),
1169*61046927SAndroid Build Coastguard Worker       .broadcast_context_count = 1,
1170*61046927SAndroid Build Coastguard Worker       .broadcast_context[0] = dev->context,
1171*61046927SAndroid Build Coastguard Worker       .priv_drv_data_size = priv_data_size,
1172*61046927SAndroid Build Coastguard Worker       .priv_drv_data = priv_data,
1173*61046927SAndroid Build Coastguard Worker    };
1174*61046927SAndroid Build Coastguard Worker 
1175*61046927SAndroid Build Coastguard Worker    int ret = safe_ioctl(dev->fd, LX_DXSUBMITCOMMAND, &submission);
1176*61046927SAndroid Build Coastguard Worker    if (ret) {
1177*61046927SAndroid Build Coastguard Worker       errx(1, "LX_DXSUBMITCOMMAND failure");
1178*61046927SAndroid Build Coastguard Worker    }
1179*61046927SAndroid Build Coastguard Worker 
1180*61046927SAndroid Build Coastguard Worker    free(priv_data);
1181*61046927SAndroid Build Coastguard Worker 
1182*61046927SAndroid Build Coastguard Worker    u_vector_finish(&dev->cmdstreams);
1183*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->cmdstreams, 8, sizeof(struct cmdstream));
1184*61046927SAndroid Build Coastguard Worker 
1185*61046927SAndroid Build Coastguard Worker    // TODO: better way to wait
1186*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < 1000; i++) {
1187*61046927SAndroid Build Coastguard Worker       usleep(1000);
1188*61046927SAndroid Build Coastguard Worker       if (*dev->fence != 0)
1189*61046927SAndroid Build Coastguard Worker          break;
1190*61046927SAndroid Build Coastguard Worker    }
1191*61046927SAndroid Build Coastguard Worker    if (*dev->fence == 0) {
1192*61046927SAndroid Build Coastguard Worker       errx(1, "Waiting for submission failed! GPU faulted or kernel did not execute this submission.");
1193*61046927SAndroid Build Coastguard Worker    }
1194*61046927SAndroid Build Coastguard Worker 
1195*61046927SAndroid Build Coastguard Worker    device_print_shader_log(dev);
1196*61046927SAndroid Build Coastguard Worker    device_print_cp_log(dev);
1197*61046927SAndroid Build Coastguard Worker 
1198*61046927SAndroid Build Coastguard Worker    device_dump_wrbuf(dev);
1199*61046927SAndroid Build Coastguard Worker    u_vector_finish(&dev->wrbufs);
1200*61046927SAndroid Build Coastguard Worker    u_vector_init(&dev->wrbufs, 8, sizeof(struct wrbuf));
1201*61046927SAndroid Build Coastguard Worker 
1202*61046927SAndroid Build Coastguard Worker    device_free_buffers(dev);
1203*61046927SAndroid Build Coastguard Worker }
1204*61046927SAndroid Build Coastguard Worker 
1205*61046927SAndroid Build Coastguard Worker static void
buffer_mem_alloc(struct device * dev,struct buffer * buf)1206*61046927SAndroid Build Coastguard Worker buffer_mem_alloc(struct device *dev, struct buffer *buf)
1207*61046927SAndroid Build Coastguard Worker {
1208*61046927SAndroid Build Coastguard Worker    bool success = util_vma_heap_alloc_addr(&dev->vma, buf->iova, buf->size);
1209*61046927SAndroid Build Coastguard Worker    if (!success)
1210*61046927SAndroid Build Coastguard Worker       errx(1, "Failed to allocate buffer");
1211*61046927SAndroid Build Coastguard Worker 
1212*61046927SAndroid Build Coastguard Worker    buf->map = ((uint8_t*)dev->va_map) + (buf->iova - dev->va_iova);
1213*61046927SAndroid Build Coastguard Worker }
1214*61046927SAndroid Build Coastguard Worker 
1215*61046927SAndroid Build Coastguard Worker void
buffer_mem_free(struct device * dev,struct buffer * buf)1216*61046927SAndroid Build Coastguard Worker buffer_mem_free(struct device *dev, struct buffer *buf)
1217*61046927SAndroid Build Coastguard Worker {
1218*61046927SAndroid Build Coastguard Worker    util_vma_heap_free(&dev->vma, buf->iova, buf->size);
1219*61046927SAndroid Build Coastguard Worker }
1220*61046927SAndroid Build Coastguard Worker 
1221*61046927SAndroid Build Coastguard Worker #endif
1222*61046927SAndroid Build Coastguard Worker 
1223*61046927SAndroid Build Coastguard Worker static void
upload_buffer(struct device * dev,uint64_t iova,unsigned int size,void * hostptr)1224*61046927SAndroid Build Coastguard Worker upload_buffer(struct device *dev, uint64_t iova, unsigned int size,
1225*61046927SAndroid Build Coastguard Worker               void *hostptr)
1226*61046927SAndroid Build Coastguard Worker {
1227*61046927SAndroid Build Coastguard Worker    struct buffer *buf = device_get_buffer(dev, iova);
1228*61046927SAndroid Build Coastguard Worker 
1229*61046927SAndroid Build Coastguard Worker    if (!buf) {
1230*61046927SAndroid Build Coastguard Worker       buf = calloc(sizeof(struct buffer), 1);
1231*61046927SAndroid Build Coastguard Worker       buf->iova = iova;
1232*61046927SAndroid Build Coastguard Worker       buf->size = size;
1233*61046927SAndroid Build Coastguard Worker 
1234*61046927SAndroid Build Coastguard Worker       rb_tree_insert(&dev->buffers, &buf->node, rb_buffer_insert_cmp);
1235*61046927SAndroid Build Coastguard Worker 
1236*61046927SAndroid Build Coastguard Worker       buffer_mem_alloc(dev, buf);
1237*61046927SAndroid Build Coastguard Worker    } else if (buf->size != size) {
1238*61046927SAndroid Build Coastguard Worker       buffer_mem_free(dev, buf);
1239*61046927SAndroid Build Coastguard Worker       buf->size = size;
1240*61046927SAndroid Build Coastguard Worker       buffer_mem_alloc(dev, buf);
1241*61046927SAndroid Build Coastguard Worker    }
1242*61046927SAndroid Build Coastguard Worker 
1243*61046927SAndroid Build Coastguard Worker    memcpy(buf->map, hostptr, size);
1244*61046927SAndroid Build Coastguard Worker 
1245*61046927SAndroid Build Coastguard Worker    buf->used = true;
1246*61046927SAndroid Build Coastguard Worker }
1247*61046927SAndroid Build Coastguard Worker 
1248*61046927SAndroid Build Coastguard Worker static int
override_cmdstream(struct device * dev,struct cmdstream * cs,const char * cmdstreamgen)1249*61046927SAndroid Build Coastguard Worker override_cmdstream(struct device *dev, struct cmdstream *cs,
1250*61046927SAndroid Build Coastguard Worker                    const char *cmdstreamgen)
1251*61046927SAndroid Build Coastguard Worker {
1252*61046927SAndroid Build Coastguard Worker #if FD_REPLAY_KGSL
1253*61046927SAndroid Build Coastguard Worker    static const char *tmpfilename = "/sdcard/Download/cmdstream_override.rd";
1254*61046927SAndroid Build Coastguard Worker #elif FD_REPLAY_MSM || FD_REPLAY_WSL
1255*61046927SAndroid Build Coastguard Worker    static const char *tmpfilename = "/tmp/cmdstream_override.rd";
1256*61046927SAndroid Build Coastguard Worker #endif
1257*61046927SAndroid Build Coastguard Worker 
1258*61046927SAndroid Build Coastguard Worker 
1259*61046927SAndroid Build Coastguard Worker    /* Find a free space for the new cmdstreams and resources we will use
1260*61046927SAndroid Build Coastguard Worker     * when overriding existing cmdstream.
1261*61046927SAndroid Build Coastguard Worker     */
1262*61046927SAndroid Build Coastguard Worker    uint64_t hole_size = util_vma_heap_get_max_free_continuous_size(&dev->vma);
1263*61046927SAndroid Build Coastguard Worker    uint64_t hole_iova = util_vma_heap_alloc(&dev->vma, hole_size, 1);
1264*61046927SAndroid Build Coastguard Worker    util_vma_heap_free(&dev->vma, hole_iova, hole_size);
1265*61046927SAndroid Build Coastguard Worker 
1266*61046927SAndroid Build Coastguard Worker    char cmd[2048];
1267*61046927SAndroid Build Coastguard Worker    snprintf(cmd, sizeof(cmd),
1268*61046927SAndroid Build Coastguard Worker             "%s --vastart=%" PRIu64 " --vasize=%" PRIu64 " %s", cmdstreamgen,
1269*61046927SAndroid Build Coastguard Worker             hole_iova, hole_size, tmpfilename);
1270*61046927SAndroid Build Coastguard Worker 
1271*61046927SAndroid Build Coastguard Worker    printf("generating cmdstream '%s'\n", cmd);
1272*61046927SAndroid Build Coastguard Worker 
1273*61046927SAndroid Build Coastguard Worker    int ret = system(cmd);
1274*61046927SAndroid Build Coastguard Worker    if (ret) {
1275*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Error executing %s\n", cmd);
1276*61046927SAndroid Build Coastguard Worker       return -1;
1277*61046927SAndroid Build Coastguard Worker    }
1278*61046927SAndroid Build Coastguard Worker 
1279*61046927SAndroid Build Coastguard Worker    struct io *io;
1280*61046927SAndroid Build Coastguard Worker    struct rd_parsed_section ps = {0};
1281*61046927SAndroid Build Coastguard Worker 
1282*61046927SAndroid Build Coastguard Worker    io = io_open(tmpfilename);
1283*61046927SAndroid Build Coastguard Worker    if (!io) {
1284*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "could not open: %s\n", tmpfilename);
1285*61046927SAndroid Build Coastguard Worker       return -1;
1286*61046927SAndroid Build Coastguard Worker    }
1287*61046927SAndroid Build Coastguard Worker 
1288*61046927SAndroid Build Coastguard Worker    struct {
1289*61046927SAndroid Build Coastguard Worker       unsigned int len;
1290*61046927SAndroid Build Coastguard Worker       uint64_t gpuaddr;
1291*61046927SAndroid Build Coastguard Worker    } gpuaddr = {0};
1292*61046927SAndroid Build Coastguard Worker 
1293*61046927SAndroid Build Coastguard Worker    while (parse_rd_section(io, &ps)) {
1294*61046927SAndroid Build Coastguard Worker       switch (ps.type) {
1295*61046927SAndroid Build Coastguard Worker       case RD_GPUADDR:
1296*61046927SAndroid Build Coastguard Worker          parse_addr(ps.buf, ps.sz, &gpuaddr.len, &gpuaddr.gpuaddr);
1297*61046927SAndroid Build Coastguard Worker          /* no-op */
1298*61046927SAndroid Build Coastguard Worker          break;
1299*61046927SAndroid Build Coastguard Worker       case RD_BUFFER_CONTENTS:
1300*61046927SAndroid Build Coastguard Worker          upload_buffer(dev, gpuaddr.gpuaddr, gpuaddr.len, ps.buf);
1301*61046927SAndroid Build Coastguard Worker          ps.buf = NULL;
1302*61046927SAndroid Build Coastguard Worker          break;
1303*61046927SAndroid Build Coastguard Worker       case RD_CMDSTREAM_ADDR: {
1304*61046927SAndroid Build Coastguard Worker          unsigned int sizedwords;
1305*61046927SAndroid Build Coastguard Worker          uint64_t gpuaddr;
1306*61046927SAndroid Build Coastguard Worker          parse_addr(ps.buf, ps.sz, &sizedwords, &gpuaddr);
1307*61046927SAndroid Build Coastguard Worker          printf("override cmdstream: %d dwords\n", sizedwords);
1308*61046927SAndroid Build Coastguard Worker 
1309*61046927SAndroid Build Coastguard Worker          cs->iova = gpuaddr;
1310*61046927SAndroid Build Coastguard Worker          cs->size = sizedwords * sizeof(uint32_t);
1311*61046927SAndroid Build Coastguard Worker          break;
1312*61046927SAndroid Build Coastguard Worker       }
1313*61046927SAndroid Build Coastguard Worker       case RD_SHADER_LOG_BUFFER: {
1314*61046927SAndroid Build Coastguard Worker          unsigned int sizedwords;
1315*61046927SAndroid Build Coastguard Worker          parse_addr(ps.buf, ps.sz, &sizedwords, &dev->shader_log_iova);
1316*61046927SAndroid Build Coastguard Worker          break;
1317*61046927SAndroid Build Coastguard Worker       }
1318*61046927SAndroid Build Coastguard Worker       case RD_CP_LOG_BUFFER: {
1319*61046927SAndroid Build Coastguard Worker          unsigned int sizedwords;
1320*61046927SAndroid Build Coastguard Worker          parse_addr(ps.buf, ps.sz, &sizedwords, &dev->cp_log_iova);
1321*61046927SAndroid Build Coastguard Worker          break;
1322*61046927SAndroid Build Coastguard Worker       }
1323*61046927SAndroid Build Coastguard Worker       case RD_WRBUFFER: {
1324*61046927SAndroid Build Coastguard Worker          struct wrbuf *wrbuf = u_vector_add(&dev->wrbufs);
1325*61046927SAndroid Build Coastguard Worker          uint64_t *p = (uint64_t *)ps.buf;
1326*61046927SAndroid Build Coastguard Worker          wrbuf->iova = p[0];
1327*61046927SAndroid Build Coastguard Worker          wrbuf->size = p[1];
1328*61046927SAndroid Build Coastguard Worker          bool clear = p[2];
1329*61046927SAndroid Build Coastguard Worker          int name_len = ps.sz - (3 * sizeof(uint64_t));
1330*61046927SAndroid Build Coastguard Worker          wrbuf->name = calloc(sizeof(char), name_len);
1331*61046927SAndroid Build Coastguard Worker          memcpy(wrbuf->name, (char*)(p + 3), name_len); // includes null terminator
1332*61046927SAndroid Build Coastguard Worker 
1333*61046927SAndroid Build Coastguard Worker          if (clear) {
1334*61046927SAndroid Build Coastguard Worker             struct buffer *buf = device_get_buffer(dev, wrbuf->iova);
1335*61046927SAndroid Build Coastguard Worker             assert(buf);
1336*61046927SAndroid Build Coastguard Worker 
1337*61046927SAndroid Build Coastguard Worker             uint64_t offset = wrbuf->iova - buf->iova;
1338*61046927SAndroid Build Coastguard Worker             uint64_t end = MIN2(offset + wrbuf->size, buf->size);
1339*61046927SAndroid Build Coastguard Worker             while (offset < end) {
1340*61046927SAndroid Build Coastguard Worker                static const uint64_t clear_value = 0xdeadbeefdeadbeef;
1341*61046927SAndroid Build Coastguard Worker                memcpy(buf->map + offset, &clear_value,
1342*61046927SAndroid Build Coastguard Worker                       MIN2(sizeof(clear_value), end - offset));
1343*61046927SAndroid Build Coastguard Worker                offset += sizeof(clear_value);
1344*61046927SAndroid Build Coastguard Worker             }
1345*61046927SAndroid Build Coastguard Worker          }
1346*61046927SAndroid Build Coastguard Worker 
1347*61046927SAndroid Build Coastguard Worker          break;
1348*61046927SAndroid Build Coastguard Worker       }
1349*61046927SAndroid Build Coastguard Worker       default:
1350*61046927SAndroid Build Coastguard Worker          break;
1351*61046927SAndroid Build Coastguard Worker       }
1352*61046927SAndroid Build Coastguard Worker    }
1353*61046927SAndroid Build Coastguard Worker 
1354*61046927SAndroid Build Coastguard Worker    io_close(io);
1355*61046927SAndroid Build Coastguard Worker    if (ps.ret < 0) {
1356*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "corrupt file %s\n", tmpfilename);
1357*61046927SAndroid Build Coastguard Worker    }
1358*61046927SAndroid Build Coastguard Worker 
1359*61046927SAndroid Build Coastguard Worker    return ps.ret;
1360*61046927SAndroid Build Coastguard Worker }
1361*61046927SAndroid Build Coastguard Worker 
1362*61046927SAndroid Build Coastguard Worker static int
handle_file(const char * filename,uint32_t first_submit,uint32_t last_submit,uint32_t submit_to_override,uint64_t base_addr,const char * cmdstreamgen)1363*61046927SAndroid Build Coastguard Worker handle_file(const char *filename, uint32_t first_submit, uint32_t last_submit,
1364*61046927SAndroid Build Coastguard Worker             uint32_t submit_to_override, uint64_t base_addr, const char *cmdstreamgen)
1365*61046927SAndroid Build Coastguard Worker {
1366*61046927SAndroid Build Coastguard Worker    struct io *io;
1367*61046927SAndroid Build Coastguard Worker    int submit = 0;
1368*61046927SAndroid Build Coastguard Worker    bool skip = false;
1369*61046927SAndroid Build Coastguard Worker    bool need_submit = false;
1370*61046927SAndroid Build Coastguard Worker    struct rd_parsed_section ps = {0};
1371*61046927SAndroid Build Coastguard Worker 
1372*61046927SAndroid Build Coastguard Worker    printf("Reading %s...\n", filename);
1373*61046927SAndroid Build Coastguard Worker 
1374*61046927SAndroid Build Coastguard Worker    if (!strcmp(filename, "-"))
1375*61046927SAndroid Build Coastguard Worker       io = io_openfd(0);
1376*61046927SAndroid Build Coastguard Worker    else
1377*61046927SAndroid Build Coastguard Worker       io = io_open(filename);
1378*61046927SAndroid Build Coastguard Worker 
1379*61046927SAndroid Build Coastguard Worker    if (!io) {
1380*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "could not open: %s\n", filename);
1381*61046927SAndroid Build Coastguard Worker       return -1;
1382*61046927SAndroid Build Coastguard Worker    }
1383*61046927SAndroid Build Coastguard Worker 
1384*61046927SAndroid Build Coastguard Worker    struct device *dev = device_create(base_addr);
1385*61046927SAndroid Build Coastguard Worker 
1386*61046927SAndroid Build Coastguard Worker    struct {
1387*61046927SAndroid Build Coastguard Worker       unsigned int len;
1388*61046927SAndroid Build Coastguard Worker       uint64_t gpuaddr;
1389*61046927SAndroid Build Coastguard Worker    } gpuaddr = {0};
1390*61046927SAndroid Build Coastguard Worker 
1391*61046927SAndroid Build Coastguard Worker    while (parse_rd_section(io, &ps)) {
1392*61046927SAndroid Build Coastguard Worker       switch (ps.type) {
1393*61046927SAndroid Build Coastguard Worker       case RD_TEST:
1394*61046927SAndroid Build Coastguard Worker       case RD_VERT_SHADER:
1395*61046927SAndroid Build Coastguard Worker       case RD_FRAG_SHADER:
1396*61046927SAndroid Build Coastguard Worker          /* no-op */
1397*61046927SAndroid Build Coastguard Worker          break;
1398*61046927SAndroid Build Coastguard Worker       case RD_CMD:
1399*61046927SAndroid Build Coastguard Worker          skip = false;
1400*61046927SAndroid Build Coastguard Worker          if (exename) {
1401*61046927SAndroid Build Coastguard Worker             skip |= (strstr(ps.buf, exename) != ps.buf);
1402*61046927SAndroid Build Coastguard Worker          } else {
1403*61046927SAndroid Build Coastguard Worker             skip |= (strstr(ps.buf, "fdperf") == ps.buf);
1404*61046927SAndroid Build Coastguard Worker             skip |= (strstr(ps.buf, "chrome") == ps.buf);
1405*61046927SAndroid Build Coastguard Worker             skip |= (strstr(ps.buf, "surfaceflinger") == ps.buf);
1406*61046927SAndroid Build Coastguard Worker             skip |= ((char *)ps.buf)[0] == 'X';
1407*61046927SAndroid Build Coastguard Worker          }
1408*61046927SAndroid Build Coastguard Worker          break;
1409*61046927SAndroid Build Coastguard Worker 
1410*61046927SAndroid Build Coastguard Worker       case RD_GPUADDR:
1411*61046927SAndroid Build Coastguard Worker          if (need_submit) {
1412*61046927SAndroid Build Coastguard Worker             need_submit = false;
1413*61046927SAndroid Build Coastguard Worker             device_submit_cmdstreams(dev);
1414*61046927SAndroid Build Coastguard Worker          }
1415*61046927SAndroid Build Coastguard Worker 
1416*61046927SAndroid Build Coastguard Worker          parse_addr(ps.buf, ps.sz, &gpuaddr.len, &gpuaddr.gpuaddr);
1417*61046927SAndroid Build Coastguard Worker          /* no-op */
1418*61046927SAndroid Build Coastguard Worker          break;
1419*61046927SAndroid Build Coastguard Worker       case RD_BUFFER_CONTENTS:
1420*61046927SAndroid Build Coastguard Worker          /* TODO: skip buffer uploading and even reading if this buffer
1421*61046927SAndroid Build Coastguard Worker           * is used for submit outside of [first_submit, last_submit]
1422*61046927SAndroid Build Coastguard Worker           * range. A set of buffers is shared between several cmdstreams,
1423*61046927SAndroid Build Coastguard Worker           * so we'd have to find starting from which RD_CMD to upload
1424*61046927SAndroid Build Coastguard Worker           * the buffers.
1425*61046927SAndroid Build Coastguard Worker           */
1426*61046927SAndroid Build Coastguard Worker          upload_buffer(dev, gpuaddr.gpuaddr, gpuaddr.len, ps.buf);
1427*61046927SAndroid Build Coastguard Worker          break;
1428*61046927SAndroid Build Coastguard Worker       case RD_CMDSTREAM_ADDR: {
1429*61046927SAndroid Build Coastguard Worker          unsigned int sizedwords;
1430*61046927SAndroid Build Coastguard Worker          uint64_t gpuaddr;
1431*61046927SAndroid Build Coastguard Worker          parse_addr(ps.buf, ps.sz, &sizedwords, &gpuaddr);
1432*61046927SAndroid Build Coastguard Worker 
1433*61046927SAndroid Build Coastguard Worker          bool add_submit = !skip && (submit >= first_submit) && (submit <= last_submit);
1434*61046927SAndroid Build Coastguard Worker          printf("%scmdstream %d: %d dwords\n", add_submit ? "" : "skipped ",
1435*61046927SAndroid Build Coastguard Worker                 submit, sizedwords);
1436*61046927SAndroid Build Coastguard Worker 
1437*61046927SAndroid Build Coastguard Worker          if (add_submit) {
1438*61046927SAndroid Build Coastguard Worker             struct cmdstream *cs = u_vector_add(&dev->cmdstreams);
1439*61046927SAndroid Build Coastguard Worker 
1440*61046927SAndroid Build Coastguard Worker             if (submit == submit_to_override) {
1441*61046927SAndroid Build Coastguard Worker                if (override_cmdstream(dev, cs, cmdstreamgen) < 0)
1442*61046927SAndroid Build Coastguard Worker                   break;
1443*61046927SAndroid Build Coastguard Worker             } else {
1444*61046927SAndroid Build Coastguard Worker                cs->iova = gpuaddr;
1445*61046927SAndroid Build Coastguard Worker                cs->size = sizedwords * sizeof(uint32_t);
1446*61046927SAndroid Build Coastguard Worker             }
1447*61046927SAndroid Build Coastguard Worker          }
1448*61046927SAndroid Build Coastguard Worker 
1449*61046927SAndroid Build Coastguard Worker          need_submit = true;
1450*61046927SAndroid Build Coastguard Worker 
1451*61046927SAndroid Build Coastguard Worker          submit++;
1452*61046927SAndroid Build Coastguard Worker          break;
1453*61046927SAndroid Build Coastguard Worker       }
1454*61046927SAndroid Build Coastguard Worker       case RD_GPU_ID: {
1455*61046927SAndroid Build Coastguard Worker          uint32_t gpu_id = parse_gpu_id(ps.buf);
1456*61046927SAndroid Build Coastguard Worker          if (gpu_id)
1457*61046927SAndroid Build Coastguard Worker             printf("gpuid: %d\n", gpu_id);
1458*61046927SAndroid Build Coastguard Worker          break;
1459*61046927SAndroid Build Coastguard Worker       }
1460*61046927SAndroid Build Coastguard Worker       case RD_CHIP_ID: {
1461*61046927SAndroid Build Coastguard Worker          uint64_t chip_id = parse_chip_id(ps.buf);
1462*61046927SAndroid Build Coastguard Worker          printf("chip_id: 0x%" PRIx64 "\n", chip_id);
1463*61046927SAndroid Build Coastguard Worker          break;
1464*61046927SAndroid Build Coastguard Worker       }
1465*61046927SAndroid Build Coastguard Worker       default:
1466*61046927SAndroid Build Coastguard Worker          break;
1467*61046927SAndroid Build Coastguard Worker       }
1468*61046927SAndroid Build Coastguard Worker    }
1469*61046927SAndroid Build Coastguard Worker 
1470*61046927SAndroid Build Coastguard Worker    if (need_submit)
1471*61046927SAndroid Build Coastguard Worker       device_submit_cmdstreams(dev);
1472*61046927SAndroid Build Coastguard Worker 
1473*61046927SAndroid Build Coastguard Worker    close(dev->fd);
1474*61046927SAndroid Build Coastguard Worker 
1475*61046927SAndroid Build Coastguard Worker    io_close(io);
1476*61046927SAndroid Build Coastguard Worker    fflush(stdout);
1477*61046927SAndroid Build Coastguard Worker 
1478*61046927SAndroid Build Coastguard Worker    if (ps.ret < 0) {
1479*61046927SAndroid Build Coastguard Worker       printf("corrupt file\n");
1480*61046927SAndroid Build Coastguard Worker    }
1481*61046927SAndroid Build Coastguard Worker    return 0;
1482*61046927SAndroid Build Coastguard Worker }
1483