1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <stdlib.h>
25bf215546Sopenharmony_ci#include <stdio.h>
26bf215546Sopenharmony_ci#include <string.h>
27bf215546Sopenharmony_ci#include <stdint.h>
28bf215546Sopenharmony_ci#include <stdbool.h>
29bf215546Sopenharmony_ci#include <signal.h>
30bf215546Sopenharmony_ci#include <stdarg.h>
31bf215546Sopenharmony_ci#include <fcntl.h>
32bf215546Sopenharmony_ci#include <sys/types.h>
33bf215546Sopenharmony_ci#include <sys/sysmacros.h>
34bf215546Sopenharmony_ci#include <sys/stat.h>
35bf215546Sopenharmony_ci#include <sys/ioctl.h>
36bf215546Sopenharmony_ci#include <unistd.h>
37bf215546Sopenharmony_ci#include <errno.h>
38bf215546Sopenharmony_ci#include <sys/mman.h>
39bf215546Sopenharmony_ci#include <dlfcn.h>
40bf215546Sopenharmony_ci#include "drm-uapi/i915_drm.h"
41bf215546Sopenharmony_ci#include <inttypes.h>
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci#include "intel_aub.h"
44bf215546Sopenharmony_ci#include "aub_write.h"
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci#include "dev/intel_debug.h"
47bf215546Sopenharmony_ci#include "dev/intel_device_info.h"
48bf215546Sopenharmony_ci#include "util/macros.h"
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_cistatic int close_init_helper(int fd);
51bf215546Sopenharmony_cistatic int ioctl_init_helper(int fd, unsigned long request, ...);
52bf215546Sopenharmony_cistatic int munmap_init_helper(void *addr, size_t length);
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_cistatic int (*libc_close)(int fd) = close_init_helper;
55bf215546Sopenharmony_cistatic int (*libc_ioctl)(int fd, unsigned long request, ...) = ioctl_init_helper;
56bf215546Sopenharmony_cistatic int (*libc_munmap)(void *addr, size_t length) = munmap_init_helper;
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_cistatic int drm_fd = -1;
59bf215546Sopenharmony_cistatic char *output_filename = NULL;
60bf215546Sopenharmony_cistatic FILE *output_file = NULL;
61bf215546Sopenharmony_cistatic int verbose = 0;
62bf215546Sopenharmony_cistatic bool device_override = false;
63bf215546Sopenharmony_cistatic bool capture_only = false;
64bf215546Sopenharmony_cistatic int64_t frame_id = -1;
65bf215546Sopenharmony_cistatic bool capture_finished = false;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci#define MAX_FD_COUNT 64
68bf215546Sopenharmony_ci#define MAX_BO_COUNT 64 * 1024
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_cistruct bo {
71bf215546Sopenharmony_ci   uint32_t size;
72bf215546Sopenharmony_ci   uint64_t offset;
73bf215546Sopenharmony_ci   void *map;
74bf215546Sopenharmony_ci   /* Whether the buffer has been positioned in the GTT already. */
75bf215546Sopenharmony_ci   bool gtt_mapped : 1;
76bf215546Sopenharmony_ci   /* Tracks userspace mmapping of the buffer */
77bf215546Sopenharmony_ci   bool user_mapped : 1;
78bf215546Sopenharmony_ci   /* Using the i915-gem mmapping ioctl & execbuffer ioctl, track whether a
79bf215546Sopenharmony_ci    * buffer has been updated.
80bf215546Sopenharmony_ci    */
81bf215546Sopenharmony_ci   bool dirty : 1;
82bf215546Sopenharmony_ci};
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_cistatic struct bo *bos;
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci#define DRM_MAJOR 226
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci/* We set bit 0 in the map pointer for userptr BOs so we know not to
89bf215546Sopenharmony_ci * munmap them on DRM_IOCTL_GEM_CLOSE.
90bf215546Sopenharmony_ci */
91bf215546Sopenharmony_ci#define USERPTR_FLAG 1
92bf215546Sopenharmony_ci#define IS_USERPTR(p) ((uintptr_t) (p) & USERPTR_FLAG)
93bf215546Sopenharmony_ci#define GET_PTR(p) ( (void *) ((uintptr_t) p & ~(uintptr_t) 1) )
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci#define fail_if(cond, ...) _fail_if(cond, "intel_dump_gpu", __VA_ARGS__)
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_cistatic struct bo *
98bf215546Sopenharmony_ciget_bo(unsigned fd, uint32_t handle)
99bf215546Sopenharmony_ci{
100bf215546Sopenharmony_ci   struct bo *bo;
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   fail_if(handle >= MAX_BO_COUNT, "bo handle too large\n");
103bf215546Sopenharmony_ci   fail_if(fd >= MAX_FD_COUNT, "bo fd too large\n");
104bf215546Sopenharmony_ci   bo = &bos[handle + fd * MAX_BO_COUNT];
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   return bo;
107bf215546Sopenharmony_ci}
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_cistatic inline uint32_t
110bf215546Sopenharmony_cialign_u32(uint32_t v, uint32_t a)
111bf215546Sopenharmony_ci{
112bf215546Sopenharmony_ci   return (v + a - 1) & ~(a - 1);
113bf215546Sopenharmony_ci}
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_cistatic struct intel_device_info devinfo = {0};
116bf215546Sopenharmony_cistatic int device = 0;
117bf215546Sopenharmony_cistatic struct aub_file aub_file;
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_cistatic void
120bf215546Sopenharmony_ciensure_device_info(int fd)
121bf215546Sopenharmony_ci{
122bf215546Sopenharmony_ci   /* We can't do this at open time as we're not yet authenticated. */
123bf215546Sopenharmony_ci   if (device == 0) {
124bf215546Sopenharmony_ci      fail_if(!intel_get_device_info_from_fd(fd, &devinfo),
125bf215546Sopenharmony_ci              "failed to identify chipset.\n");
126bf215546Sopenharmony_ci      device = devinfo.pci_device_id;
127bf215546Sopenharmony_ci   } else if (devinfo.ver == 0) {
128bf215546Sopenharmony_ci      fail_if(!intel_get_device_info_from_pci_id(device, &devinfo),
129bf215546Sopenharmony_ci              "failed to identify chipset.\n");
130bf215546Sopenharmony_ci   }
131bf215546Sopenharmony_ci}
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_cistatic void *
134bf215546Sopenharmony_cirelocate_bo(int fd, struct bo *bo, const struct drm_i915_gem_execbuffer2 *execbuffer2,
135bf215546Sopenharmony_ci            const struct drm_i915_gem_exec_object2 *obj)
136bf215546Sopenharmony_ci{
137bf215546Sopenharmony_ci   const struct drm_i915_gem_exec_object2 *exec_objects =
138bf215546Sopenharmony_ci      (struct drm_i915_gem_exec_object2 *) (uintptr_t) execbuffer2->buffers_ptr;
139bf215546Sopenharmony_ci   const struct drm_i915_gem_relocation_entry *relocs =
140bf215546Sopenharmony_ci      (const struct drm_i915_gem_relocation_entry *) (uintptr_t) obj->relocs_ptr;
141bf215546Sopenharmony_ci   void *relocated;
142bf215546Sopenharmony_ci   int handle;
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   relocated = malloc(bo->size);
145bf215546Sopenharmony_ci   fail_if(relocated == NULL, "out of memory\n");
146bf215546Sopenharmony_ci   memcpy(relocated, GET_PTR(bo->map), bo->size);
147bf215546Sopenharmony_ci   for (size_t i = 0; i < obj->relocation_count; i++) {
148bf215546Sopenharmony_ci      fail_if(relocs[i].offset >= bo->size, "reloc outside bo\n");
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci      if (execbuffer2->flags & I915_EXEC_HANDLE_LUT)
151bf215546Sopenharmony_ci         handle = exec_objects[relocs[i].target_handle].handle;
152bf215546Sopenharmony_ci      else
153bf215546Sopenharmony_ci         handle = relocs[i].target_handle;
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci      aub_write_reloc(&devinfo, ((char *)relocated) + relocs[i].offset,
156bf215546Sopenharmony_ci                      get_bo(fd, handle)->offset + relocs[i].delta);
157bf215546Sopenharmony_ci   }
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   return relocated;
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_cistatic int
163bf215546Sopenharmony_cigem_ioctl(int fd, unsigned long request, void *argp)
164bf215546Sopenharmony_ci{
165bf215546Sopenharmony_ci   int ret;
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci   do {
168bf215546Sopenharmony_ci      ret = libc_ioctl(fd, request, argp);
169bf215546Sopenharmony_ci   } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   return ret;
172bf215546Sopenharmony_ci}
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_cistatic void *
175bf215546Sopenharmony_cigem_mmap(int fd, uint32_t handle, uint64_t offset, uint64_t size)
176bf215546Sopenharmony_ci{
177bf215546Sopenharmony_ci   struct drm_i915_gem_mmap mmap = {
178bf215546Sopenharmony_ci      .handle = handle,
179bf215546Sopenharmony_ci      .offset = offset,
180bf215546Sopenharmony_ci      .size = size
181bf215546Sopenharmony_ci   };
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci   if (gem_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &mmap) == -1)
184bf215546Sopenharmony_ci      return MAP_FAILED;
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   return (void *)(uintptr_t) mmap.addr_ptr;
187bf215546Sopenharmony_ci}
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_cistatic enum drm_i915_gem_engine_class
190bf215546Sopenharmony_ciengine_class_from_ring_flag(uint32_t ring_flag)
191bf215546Sopenharmony_ci{
192bf215546Sopenharmony_ci   switch (ring_flag) {
193bf215546Sopenharmony_ci   case I915_EXEC_DEFAULT:
194bf215546Sopenharmony_ci   case I915_EXEC_RENDER:
195bf215546Sopenharmony_ci      return I915_ENGINE_CLASS_RENDER;
196bf215546Sopenharmony_ci   case I915_EXEC_BSD:
197bf215546Sopenharmony_ci      return I915_ENGINE_CLASS_VIDEO;
198bf215546Sopenharmony_ci   case I915_EXEC_BLT:
199bf215546Sopenharmony_ci      return I915_ENGINE_CLASS_COPY;
200bf215546Sopenharmony_ci   case I915_EXEC_VEBOX:
201bf215546Sopenharmony_ci      return I915_ENGINE_CLASS_VIDEO_ENHANCE;
202bf215546Sopenharmony_ci   default:
203bf215546Sopenharmony_ci      return I915_ENGINE_CLASS_INVALID;
204bf215546Sopenharmony_ci   }
205bf215546Sopenharmony_ci}
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_cistatic void
208bf215546Sopenharmony_cidump_execbuffer2(int fd, struct drm_i915_gem_execbuffer2 *execbuffer2)
209bf215546Sopenharmony_ci{
210bf215546Sopenharmony_ci   struct drm_i915_gem_exec_object2 *exec_objects =
211bf215546Sopenharmony_ci      (struct drm_i915_gem_exec_object2 *) (uintptr_t) execbuffer2->buffers_ptr;
212bf215546Sopenharmony_ci   uint32_t ring_flag = execbuffer2->flags & I915_EXEC_RING_MASK;
213bf215546Sopenharmony_ci   uint32_t offset;
214bf215546Sopenharmony_ci   struct drm_i915_gem_exec_object2 *obj;
215bf215546Sopenharmony_ci   struct bo *bo, *batch_bo;
216bf215546Sopenharmony_ci   int batch_index;
217bf215546Sopenharmony_ci   void *data;
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci   ensure_device_info(fd);
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci   if (capture_finished)
222bf215546Sopenharmony_ci      return;
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci   if (!aub_file.file) {
225bf215546Sopenharmony_ci      aub_file_init(&aub_file, output_file,
226bf215546Sopenharmony_ci                    verbose == 2 ? stdout : NULL,
227bf215546Sopenharmony_ci                    device, program_invocation_short_name);
228bf215546Sopenharmony_ci      aub_write_default_setup(&aub_file);
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci      if (verbose)
231bf215546Sopenharmony_ci         printf("[running, output file %s, chipset id 0x%04x, gen %d]\n",
232bf215546Sopenharmony_ci                output_filename, device, devinfo.ver);
233bf215546Sopenharmony_ci   }
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   if (aub_use_execlists(&aub_file))
236bf215546Sopenharmony_ci      offset = 0x1000;
237bf215546Sopenharmony_ci   else
238bf215546Sopenharmony_ci      offset = aub_gtt_size(&aub_file);
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci   for (uint32_t i = 0; i < execbuffer2->buffer_count; i++) {
241bf215546Sopenharmony_ci      obj = &exec_objects[i];
242bf215546Sopenharmony_ci      bo = get_bo(fd, obj->handle);
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci      /* If bo->size == 0, this means they passed us an invalid
245bf215546Sopenharmony_ci       * buffer.  The kernel will reject it and so should we.
246bf215546Sopenharmony_ci       */
247bf215546Sopenharmony_ci      if (bo->size == 0) {
248bf215546Sopenharmony_ci         if (verbose)
249bf215546Sopenharmony_ci            printf("BO #%d is invalid!\n", obj->handle);
250bf215546Sopenharmony_ci         return;
251bf215546Sopenharmony_ci      }
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci      if (obj->flags & EXEC_OBJECT_PINNED) {
254bf215546Sopenharmony_ci         if (bo->offset != obj->offset)
255bf215546Sopenharmony_ci            bo->gtt_mapped = false;
256bf215546Sopenharmony_ci         bo->offset = obj->offset;
257bf215546Sopenharmony_ci      } else {
258bf215546Sopenharmony_ci         if (obj->alignment != 0)
259bf215546Sopenharmony_ci            offset = align_u32(offset, obj->alignment);
260bf215546Sopenharmony_ci         bo->offset = offset;
261bf215546Sopenharmony_ci         offset = align_u32(offset + bo->size + 4095, 4096);
262bf215546Sopenharmony_ci      }
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci      if (bo->map == NULL && bo->size > 0)
265bf215546Sopenharmony_ci         bo->map = gem_mmap(fd, obj->handle, 0, bo->size);
266bf215546Sopenharmony_ci      fail_if(bo->map == MAP_FAILED, "bo mmap failed\n");
267bf215546Sopenharmony_ci   }
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci   uint64_t current_frame_id = 0;
270bf215546Sopenharmony_ci   if (frame_id >= 0) {
271bf215546Sopenharmony_ci      for (uint32_t i = 0; i < execbuffer2->buffer_count; i++) {
272bf215546Sopenharmony_ci         obj = &exec_objects[i];
273bf215546Sopenharmony_ci         bo = get_bo(fd, obj->handle);
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci         /* Check against frame_id requirements. */
276bf215546Sopenharmony_ci         if (memcmp(bo->map, intel_debug_identifier(),
277bf215546Sopenharmony_ci                    intel_debug_identifier_size()) == 0) {
278bf215546Sopenharmony_ci            const struct intel_debug_block_frame *frame_desc =
279bf215546Sopenharmony_ci               intel_debug_get_identifier_block(bo->map, bo->size,
280bf215546Sopenharmony_ci                                                INTEL_DEBUG_BLOCK_TYPE_FRAME);
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci            current_frame_id = frame_desc ? frame_desc->frame_id : 0;
283bf215546Sopenharmony_ci            break;
284bf215546Sopenharmony_ci         }
285bf215546Sopenharmony_ci      }
286bf215546Sopenharmony_ci   }
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci   if (verbose)
289bf215546Sopenharmony_ci      printf("Dumping execbuffer2 (frame_id=%"PRIu64", buffers=%u):\n",
290bf215546Sopenharmony_ci             current_frame_id, execbuffer2->buffer_count);
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   /* Check whether we can stop right now. */
293bf215546Sopenharmony_ci   if (frame_id >= 0) {
294bf215546Sopenharmony_ci      if (current_frame_id < frame_id)
295bf215546Sopenharmony_ci         return;
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_ci      if (current_frame_id > frame_id) {
298bf215546Sopenharmony_ci         aub_file_finish(&aub_file);
299bf215546Sopenharmony_ci         capture_finished = true;
300bf215546Sopenharmony_ci         return;
301bf215546Sopenharmony_ci      }
302bf215546Sopenharmony_ci   }
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci   /* Map buffers into the PPGTT. */
306bf215546Sopenharmony_ci   for (uint32_t i = 0; i < execbuffer2->buffer_count; i++) {
307bf215546Sopenharmony_ci      obj = &exec_objects[i];
308bf215546Sopenharmony_ci      bo = get_bo(fd, obj->handle);
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci      if (verbose) {
311bf215546Sopenharmony_ci         printf("BO #%d (%dB) @ 0x%" PRIx64 "\n",
312bf215546Sopenharmony_ci                obj->handle, bo->size, bo->offset);
313bf215546Sopenharmony_ci      }
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci      if (aub_use_execlists(&aub_file) && !bo->gtt_mapped) {
316bf215546Sopenharmony_ci         aub_map_ppgtt(&aub_file, bo->offset, bo->size);
317bf215546Sopenharmony_ci         bo->gtt_mapped = true;
318bf215546Sopenharmony_ci      }
319bf215546Sopenharmony_ci   }
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   /* Write the buffer content into the Aub. */
322bf215546Sopenharmony_ci   batch_index = (execbuffer2->flags & I915_EXEC_BATCH_FIRST) ? 0 :
323bf215546Sopenharmony_ci      execbuffer2->buffer_count - 1;
324bf215546Sopenharmony_ci   batch_bo = get_bo(fd, exec_objects[batch_index].handle);
325bf215546Sopenharmony_ci   for (uint32_t i = 0; i < execbuffer2->buffer_count; i++) {
326bf215546Sopenharmony_ci      obj = &exec_objects[i];
327bf215546Sopenharmony_ci      bo = get_bo(fd, obj->handle);
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci      if (obj->relocation_count > 0)
330bf215546Sopenharmony_ci         data = relocate_bo(fd, bo, execbuffer2, obj);
331bf215546Sopenharmony_ci      else
332bf215546Sopenharmony_ci         data = bo->map;
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci      bool write = !capture_only || (obj->flags & EXEC_OBJECT_CAPTURE);
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci      if (write && bo->dirty) {
337bf215546Sopenharmony_ci         if (bo == batch_bo) {
338bf215546Sopenharmony_ci            aub_write_trace_block(&aub_file, AUB_TRACE_TYPE_BATCH,
339bf215546Sopenharmony_ci                                  GET_PTR(data), bo->size, bo->offset);
340bf215546Sopenharmony_ci         } else {
341bf215546Sopenharmony_ci            aub_write_trace_block(&aub_file, AUB_TRACE_TYPE_NOTYPE,
342bf215546Sopenharmony_ci                                  GET_PTR(data), bo->size, bo->offset);
343bf215546Sopenharmony_ci         }
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci         if (!bo->user_mapped)
346bf215546Sopenharmony_ci            bo->dirty = false;
347bf215546Sopenharmony_ci      }
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci      if (data != bo->map)
350bf215546Sopenharmony_ci         free(data);
351bf215546Sopenharmony_ci   }
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci   uint32_t ctx_id = execbuffer2->rsvd1;
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   aub_write_exec(&aub_file, ctx_id,
356bf215546Sopenharmony_ci                  batch_bo->offset + execbuffer2->batch_start_offset,
357bf215546Sopenharmony_ci                  offset, engine_class_from_ring_flag(ring_flag));
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci   if (device_override &&
360bf215546Sopenharmony_ci       (execbuffer2->flags & I915_EXEC_FENCE_ARRAY) != 0) {
361bf215546Sopenharmony_ci      struct drm_i915_gem_exec_fence *fences =
362bf215546Sopenharmony_ci         (void*)(uintptr_t)execbuffer2->cliprects_ptr;
363bf215546Sopenharmony_ci      for (uint32_t i = 0; i < execbuffer2->num_cliprects; i++) {
364bf215546Sopenharmony_ci         if ((fences[i].flags & I915_EXEC_FENCE_SIGNAL) != 0) {
365bf215546Sopenharmony_ci            struct drm_syncobj_array arg = {
366bf215546Sopenharmony_ci               .handles = (uintptr_t)&fences[i].handle,
367bf215546Sopenharmony_ci               .count_handles = 1,
368bf215546Sopenharmony_ci               .pad = 0,
369bf215546Sopenharmony_ci            };
370bf215546Sopenharmony_ci            libc_ioctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &arg);
371bf215546Sopenharmony_ci         }
372bf215546Sopenharmony_ci      }
373bf215546Sopenharmony_ci   }
374bf215546Sopenharmony_ci}
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_cistatic void
377bf215546Sopenharmony_ciadd_new_bo(unsigned fd, int handle, uint64_t size, void *map)
378bf215546Sopenharmony_ci{
379bf215546Sopenharmony_ci   struct bo *bo = &bos[handle + fd * MAX_BO_COUNT];
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   fail_if(handle >= MAX_BO_COUNT, "bo handle out of range\n");
382bf215546Sopenharmony_ci   fail_if(fd >= MAX_FD_COUNT, "bo fd out of range\n");
383bf215546Sopenharmony_ci   fail_if(size == 0, "bo size is invalid\n");
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   bo->size = size;
386bf215546Sopenharmony_ci   bo->map = map;
387bf215546Sopenharmony_ci   bo->user_mapped = false;
388bf215546Sopenharmony_ci   bo->gtt_mapped = false;
389bf215546Sopenharmony_ci}
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_cistatic void
392bf215546Sopenharmony_ciremove_bo(int fd, int handle)
393bf215546Sopenharmony_ci{
394bf215546Sopenharmony_ci   struct bo *bo = get_bo(fd, handle);
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci   if (bo->map && !IS_USERPTR(bo->map))
397bf215546Sopenharmony_ci      munmap(bo->map, bo->size);
398bf215546Sopenharmony_ci   memset(bo, 0, sizeof(*bo));
399bf215546Sopenharmony_ci}
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci__attribute__ ((visibility ("default"))) int
402bf215546Sopenharmony_ciclose(int fd)
403bf215546Sopenharmony_ci{
404bf215546Sopenharmony_ci   if (fd == drm_fd)
405bf215546Sopenharmony_ci      drm_fd = -1;
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci   return libc_close(fd);
408bf215546Sopenharmony_ci}
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_cistatic int
411bf215546Sopenharmony_ciget_pci_id(int fd, int *pci_id)
412bf215546Sopenharmony_ci{
413bf215546Sopenharmony_ci   struct drm_i915_getparam gparam;
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci   if (device_override) {
416bf215546Sopenharmony_ci      *pci_id = device;
417bf215546Sopenharmony_ci      return 0;
418bf215546Sopenharmony_ci   }
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   gparam.param = I915_PARAM_CHIPSET_ID;
421bf215546Sopenharmony_ci   gparam.value = pci_id;
422bf215546Sopenharmony_ci   return libc_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gparam);
423bf215546Sopenharmony_ci}
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_cistatic void
426bf215546Sopenharmony_cimaybe_init(int fd)
427bf215546Sopenharmony_ci{
428bf215546Sopenharmony_ci   static bool initialized = false;
429bf215546Sopenharmony_ci   FILE *config;
430bf215546Sopenharmony_ci   char *key, *value;
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci   if (initialized)
433bf215546Sopenharmony_ci      return;
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci   initialized = true;
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci   const char *config_path = getenv("INTEL_DUMP_GPU_CONFIG");
438bf215546Sopenharmony_ci   fail_if(config_path == NULL, "INTEL_DUMP_GPU_CONFIG is not set\n");
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   config = fopen(config_path, "r");
441bf215546Sopenharmony_ci   fail_if(config == NULL, "failed to open file %s\n", config_path);
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci   while (fscanf(config, "%m[^=]=%m[^\n]\n", &key, &value) != EOF) {
444bf215546Sopenharmony_ci      if (!strcmp(key, "verbose")) {
445bf215546Sopenharmony_ci         if (!strcmp(value, "1")) {
446bf215546Sopenharmony_ci            verbose = 1;
447bf215546Sopenharmony_ci         } else if (!strcmp(value, "2")) {
448bf215546Sopenharmony_ci            verbose = 2;
449bf215546Sopenharmony_ci         }
450bf215546Sopenharmony_ci      } else if (!strcmp(key, "device")) {
451bf215546Sopenharmony_ci         fail_if(device != 0, "Device/Platform override specified multiple times.\n");
452bf215546Sopenharmony_ci         fail_if(sscanf(value, "%i", &device) != 1,
453bf215546Sopenharmony_ci                 "failed to parse device id '%s'\n",
454bf215546Sopenharmony_ci                 value);
455bf215546Sopenharmony_ci         device_override = true;
456bf215546Sopenharmony_ci      } else if (!strcmp(key, "platform")) {
457bf215546Sopenharmony_ci         fail_if(device != 0, "Device/Platform override specified multiple times.\n");
458bf215546Sopenharmony_ci         device = intel_device_name_to_pci_device_id(value);
459bf215546Sopenharmony_ci         fail_if(device == -1, "Unknown platform '%s'\n", value);
460bf215546Sopenharmony_ci         device_override = true;
461bf215546Sopenharmony_ci      } else if (!strcmp(key, "file")) {
462bf215546Sopenharmony_ci         free(output_filename);
463bf215546Sopenharmony_ci         if (output_file)
464bf215546Sopenharmony_ci            fclose(output_file);
465bf215546Sopenharmony_ci         output_filename = strdup(value);
466bf215546Sopenharmony_ci         output_file = fopen(output_filename, "w+");
467bf215546Sopenharmony_ci         fail_if(output_file == NULL,
468bf215546Sopenharmony_ci                 "failed to open file '%s'\n",
469bf215546Sopenharmony_ci                 output_filename);
470bf215546Sopenharmony_ci      } else if (!strcmp(key, "capture_only")) {
471bf215546Sopenharmony_ci         capture_only = atoi(value);
472bf215546Sopenharmony_ci      } else if (!strcmp(key, "frame")) {
473bf215546Sopenharmony_ci         frame_id = atol(value);
474bf215546Sopenharmony_ci      } else {
475bf215546Sopenharmony_ci         fprintf(stderr, "unknown option '%s'\n", key);
476bf215546Sopenharmony_ci      }
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci      free(key);
479bf215546Sopenharmony_ci      free(value);
480bf215546Sopenharmony_ci   }
481bf215546Sopenharmony_ci   fclose(config);
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci   bos = calloc(MAX_FD_COUNT * MAX_BO_COUNT, sizeof(bos[0]));
484bf215546Sopenharmony_ci   fail_if(bos == NULL, "out of memory\n");
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci   ASSERTED int ret = get_pci_id(fd, &device);
487bf215546Sopenharmony_ci   assert(ret == 0);
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_ci   aub_file_init(&aub_file, output_file,
490bf215546Sopenharmony_ci                 verbose == 2 ? stdout : NULL,
491bf215546Sopenharmony_ci                 device, program_invocation_short_name);
492bf215546Sopenharmony_ci   aub_write_default_setup(&aub_file);
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci   if (verbose)
495bf215546Sopenharmony_ci      printf("[running, output file %s, chipset id 0x%04x, gen %d]\n",
496bf215546Sopenharmony_ci             output_filename, device, devinfo.ver);
497bf215546Sopenharmony_ci}
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci__attribute__ ((visibility ("default"))) int
500bf215546Sopenharmony_ciioctl(int fd, unsigned long request, ...)
501bf215546Sopenharmony_ci{
502bf215546Sopenharmony_ci   va_list args;
503bf215546Sopenharmony_ci   void *argp;
504bf215546Sopenharmony_ci   int ret;
505bf215546Sopenharmony_ci   struct stat buf;
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci   va_start(args, request);
508bf215546Sopenharmony_ci   argp = va_arg(args, void *);
509bf215546Sopenharmony_ci   va_end(args);
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   if (_IOC_TYPE(request) == DRM_IOCTL_BASE &&
512bf215546Sopenharmony_ci       drm_fd != fd && fstat(fd, &buf) == 0 &&
513bf215546Sopenharmony_ci       (buf.st_mode & S_IFMT) == S_IFCHR && major(buf.st_rdev) == DRM_MAJOR) {
514bf215546Sopenharmony_ci      drm_fd = fd;
515bf215546Sopenharmony_ci      if (verbose)
516bf215546Sopenharmony_ci         printf("[intercept drm ioctl on fd %d]\n", fd);
517bf215546Sopenharmony_ci   }
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_ci   if (fd == drm_fd) {
520bf215546Sopenharmony_ci      maybe_init(fd);
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_ci      switch (request) {
523bf215546Sopenharmony_ci      case DRM_IOCTL_SYNCOBJ_WAIT:
524bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_WAIT: {
525bf215546Sopenharmony_ci         if (device_override)
526bf215546Sopenharmony_ci            return 0;
527bf215546Sopenharmony_ci         return libc_ioctl(fd, request, argp);
528bf215546Sopenharmony_ci      }
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GET_RESET_STATS: {
531bf215546Sopenharmony_ci         if (device_override) {
532bf215546Sopenharmony_ci            struct drm_i915_reset_stats *stats = argp;
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci            stats->reset_count = 0;
535bf215546Sopenharmony_ci            stats->batch_active = 0;
536bf215546Sopenharmony_ci            stats->batch_pending = 0;
537bf215546Sopenharmony_ci            return 0;
538bf215546Sopenharmony_ci         }
539bf215546Sopenharmony_ci         return libc_ioctl(fd, request, argp);
540bf215546Sopenharmony_ci      }
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GETPARAM: {
543bf215546Sopenharmony_ci         struct drm_i915_getparam *getparam = argp;
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci         ensure_device_info(fd);
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ci         if (getparam->param == I915_PARAM_CHIPSET_ID)
548bf215546Sopenharmony_ci            return get_pci_id(fd, getparam->value);
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci         if (device_override) {
551bf215546Sopenharmony_ci            switch (getparam->param) {
552bf215546Sopenharmony_ci            case I915_PARAM_CS_TIMESTAMP_FREQUENCY:
553bf215546Sopenharmony_ci               *getparam->value = devinfo.timestamp_frequency;
554bf215546Sopenharmony_ci               return 0;
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci            case I915_PARAM_HAS_WAIT_TIMEOUT:
557bf215546Sopenharmony_ci            case I915_PARAM_HAS_EXECBUF2:
558bf215546Sopenharmony_ci            case I915_PARAM_MMAP_VERSION:
559bf215546Sopenharmony_ci            case I915_PARAM_HAS_EXEC_ASYNC:
560bf215546Sopenharmony_ci            case I915_PARAM_HAS_EXEC_FENCE:
561bf215546Sopenharmony_ci            case I915_PARAM_HAS_EXEC_FENCE_ARRAY:
562bf215546Sopenharmony_ci               *getparam->value = 1;
563bf215546Sopenharmony_ci               return 0;
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_ci            case I915_PARAM_HAS_EXEC_SOFTPIN:
566bf215546Sopenharmony_ci               *getparam->value = devinfo.ver >= 8 && devinfo.platform != INTEL_PLATFORM_CHV;
567bf215546Sopenharmony_ci               return 0;
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ci            default:
570bf215546Sopenharmony_ci               return -1;
571bf215546Sopenharmony_ci            }
572bf215546Sopenharmony_ci         }
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci         return libc_ioctl(fd, request, argp);
575bf215546Sopenharmony_ci      }
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM: {
578bf215546Sopenharmony_ci         struct drm_i915_gem_context_param *getparam = argp;
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ci         ensure_device_info(fd);
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci         if (device_override) {
583bf215546Sopenharmony_ci            switch (getparam->param) {
584bf215546Sopenharmony_ci            case I915_CONTEXT_PARAM_GTT_SIZE:
585bf215546Sopenharmony_ci               if (devinfo.platform == INTEL_PLATFORM_EHL)
586bf215546Sopenharmony_ci                  getparam->value = 1ull << 36;
587bf215546Sopenharmony_ci               else if (devinfo.ver >= 8 && devinfo.platform != INTEL_PLATFORM_CHV)
588bf215546Sopenharmony_ci                  getparam->value = 1ull << 48;
589bf215546Sopenharmony_ci               else
590bf215546Sopenharmony_ci                  getparam->value = 1ull << 31;
591bf215546Sopenharmony_ci               return 0;
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci            default:
594bf215546Sopenharmony_ci               return -1;
595bf215546Sopenharmony_ci            }
596bf215546Sopenharmony_ci         }
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci         return libc_ioctl(fd, request, argp);
599bf215546Sopenharmony_ci      }
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_EXECBUFFER: {
602bf215546Sopenharmony_ci         static bool once;
603bf215546Sopenharmony_ci         if (!once) {
604bf215546Sopenharmony_ci            fprintf(stderr,
605bf215546Sopenharmony_ci                    "application uses DRM_IOCTL_I915_GEM_EXECBUFFER, not handled\n");
606bf215546Sopenharmony_ci            once = true;
607bf215546Sopenharmony_ci         }
608bf215546Sopenharmony_ci         return libc_ioctl(fd, request, argp);
609bf215546Sopenharmony_ci      }
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_EXECBUFFER2:
612bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_EXECBUFFER2_WR: {
613bf215546Sopenharmony_ci         dump_execbuffer2(fd, argp);
614bf215546Sopenharmony_ci         if (device_override)
615bf215546Sopenharmony_ci            return 0;
616bf215546Sopenharmony_ci
617bf215546Sopenharmony_ci         return libc_ioctl(fd, request, argp);
618bf215546Sopenharmony_ci      }
619bf215546Sopenharmony_ci
620bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_CONTEXT_CREATE: {
621bf215546Sopenharmony_ci         uint32_t *ctx_id = NULL;
622bf215546Sopenharmony_ci         struct drm_i915_gem_context_create *create = argp;
623bf215546Sopenharmony_ci         ret = 0;
624bf215546Sopenharmony_ci         if (!device_override) {
625bf215546Sopenharmony_ci            ret = libc_ioctl(fd, request, argp);
626bf215546Sopenharmony_ci            ctx_id = &create->ctx_id;
627bf215546Sopenharmony_ci         }
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_ci         if (ret == 0)
630bf215546Sopenharmony_ci            create->ctx_id = aub_write_context_create(&aub_file, ctx_id);
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci         return ret;
633bf215546Sopenharmony_ci      }
634bf215546Sopenharmony_ci
635bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT: {
636bf215546Sopenharmony_ci         uint32_t *ctx_id = NULL;
637bf215546Sopenharmony_ci         struct drm_i915_gem_context_create_ext *create = argp;
638bf215546Sopenharmony_ci         ret = 0;
639bf215546Sopenharmony_ci         if (!device_override) {
640bf215546Sopenharmony_ci            ret = libc_ioctl(fd, request, argp);
641bf215546Sopenharmony_ci            ctx_id = &create->ctx_id;
642bf215546Sopenharmony_ci         }
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci         if (ret == 0)
645bf215546Sopenharmony_ci            create->ctx_id = aub_write_context_create(&aub_file, ctx_id);
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci         return ret;
648bf215546Sopenharmony_ci      }
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_CREATE: {
651bf215546Sopenharmony_ci         struct drm_i915_gem_create *create = argp;
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci         ret = libc_ioctl(fd, request, argp);
654bf215546Sopenharmony_ci         if (ret == 0)
655bf215546Sopenharmony_ci            add_new_bo(fd, create->handle, create->size, NULL);
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci         return ret;
658bf215546Sopenharmony_ci      }
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_CREATE_EXT: {
661bf215546Sopenharmony_ci         struct drm_i915_gem_create_ext *create = argp;
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci         ret = libc_ioctl(fd, request, argp);
664bf215546Sopenharmony_ci         if (ret == 0)
665bf215546Sopenharmony_ci            add_new_bo(fd, create->handle, create->size, NULL);
666bf215546Sopenharmony_ci
667bf215546Sopenharmony_ci         return ret;
668bf215546Sopenharmony_ci      }
669bf215546Sopenharmony_ci
670bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_USERPTR: {
671bf215546Sopenharmony_ci         struct drm_i915_gem_userptr *userptr = argp;
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci         ret = libc_ioctl(fd, request, argp);
674bf215546Sopenharmony_ci         if (ret == 0)
675bf215546Sopenharmony_ci            add_new_bo(fd, userptr->handle, userptr->user_size,
676bf215546Sopenharmony_ci                       (void *) (uintptr_t) (userptr->user_ptr | USERPTR_FLAG));
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci         return ret;
679bf215546Sopenharmony_ci      }
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_ci      case DRM_IOCTL_GEM_CLOSE: {
682bf215546Sopenharmony_ci         struct drm_gem_close *close = argp;
683bf215546Sopenharmony_ci
684bf215546Sopenharmony_ci         remove_bo(fd, close->handle);
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci         return libc_ioctl(fd, request, argp);
687bf215546Sopenharmony_ci      }
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ci      case DRM_IOCTL_GEM_OPEN: {
690bf215546Sopenharmony_ci         struct drm_gem_open *open = argp;
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci         ret = libc_ioctl(fd, request, argp);
693bf215546Sopenharmony_ci         if (ret == 0)
694bf215546Sopenharmony_ci            add_new_bo(fd, open->handle, open->size, NULL);
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ci         return ret;
697bf215546Sopenharmony_ci      }
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci      case DRM_IOCTL_PRIME_FD_TO_HANDLE: {
700bf215546Sopenharmony_ci         struct drm_prime_handle *prime = argp;
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_ci         ret = libc_ioctl(fd, request, argp);
703bf215546Sopenharmony_ci         if (ret == 0) {
704bf215546Sopenharmony_ci            off_t size;
705bf215546Sopenharmony_ci
706bf215546Sopenharmony_ci            size = lseek(prime->fd, 0, SEEK_END);
707bf215546Sopenharmony_ci            fail_if(size == -1, "failed to get prime bo size\n");
708bf215546Sopenharmony_ci            add_new_bo(fd, prime->handle, size, NULL);
709bf215546Sopenharmony_ci
710bf215546Sopenharmony_ci         }
711bf215546Sopenharmony_ci
712bf215546Sopenharmony_ci         return ret;
713bf215546Sopenharmony_ci      }
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_MMAP: {
716bf215546Sopenharmony_ci         ret = libc_ioctl(fd, request, argp);
717bf215546Sopenharmony_ci         if (ret == 0) {
718bf215546Sopenharmony_ci            struct drm_i915_gem_mmap *mmap = argp;
719bf215546Sopenharmony_ci            struct bo *bo = get_bo(fd, mmap->handle);
720bf215546Sopenharmony_ci            bo->user_mapped = true;
721bf215546Sopenharmony_ci            bo->dirty = true;
722bf215546Sopenharmony_ci         }
723bf215546Sopenharmony_ci         return ret;
724bf215546Sopenharmony_ci      }
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_ci      case DRM_IOCTL_I915_GEM_MMAP_OFFSET: {
727bf215546Sopenharmony_ci         ret = libc_ioctl(fd, request, argp);
728bf215546Sopenharmony_ci         if (ret == 0) {
729bf215546Sopenharmony_ci            struct drm_i915_gem_mmap_offset *mmap = argp;
730bf215546Sopenharmony_ci            struct bo *bo = get_bo(fd, mmap->handle);
731bf215546Sopenharmony_ci            bo->user_mapped = true;
732bf215546Sopenharmony_ci            bo->dirty = true;
733bf215546Sopenharmony_ci         }
734bf215546Sopenharmony_ci         return ret;
735bf215546Sopenharmony_ci      }
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci      default:
738bf215546Sopenharmony_ci         return libc_ioctl(fd, request, argp);
739bf215546Sopenharmony_ci      }
740bf215546Sopenharmony_ci   } else {
741bf215546Sopenharmony_ci      return libc_ioctl(fd, request, argp);
742bf215546Sopenharmony_ci   }
743bf215546Sopenharmony_ci}
744bf215546Sopenharmony_ci
745bf215546Sopenharmony_cistatic void
746bf215546Sopenharmony_ciinit(void)
747bf215546Sopenharmony_ci{
748bf215546Sopenharmony_ci   libc_close = dlsym(RTLD_NEXT, "close");
749bf215546Sopenharmony_ci   libc_ioctl = dlsym(RTLD_NEXT, "ioctl");
750bf215546Sopenharmony_ci   libc_munmap = dlsym(RTLD_NEXT, "munmap");
751bf215546Sopenharmony_ci   fail_if(libc_close == NULL || libc_ioctl == NULL,
752bf215546Sopenharmony_ci           "failed to get libc ioctl or close\n");
753bf215546Sopenharmony_ci}
754bf215546Sopenharmony_ci
755bf215546Sopenharmony_cistatic int
756bf215546Sopenharmony_ciclose_init_helper(int fd)
757bf215546Sopenharmony_ci{
758bf215546Sopenharmony_ci   init();
759bf215546Sopenharmony_ci   return libc_close(fd);
760bf215546Sopenharmony_ci}
761bf215546Sopenharmony_ci
762bf215546Sopenharmony_cistatic int
763bf215546Sopenharmony_ciioctl_init_helper(int fd, unsigned long request, ...)
764bf215546Sopenharmony_ci{
765bf215546Sopenharmony_ci   va_list args;
766bf215546Sopenharmony_ci   void *argp;
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci   va_start(args, request);
769bf215546Sopenharmony_ci   argp = va_arg(args, void *);
770bf215546Sopenharmony_ci   va_end(args);
771bf215546Sopenharmony_ci
772bf215546Sopenharmony_ci   init();
773bf215546Sopenharmony_ci   return libc_ioctl(fd, request, argp);
774bf215546Sopenharmony_ci}
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_cistatic int
777bf215546Sopenharmony_cimunmap_init_helper(void *addr, size_t length)
778bf215546Sopenharmony_ci{
779bf215546Sopenharmony_ci   init();
780bf215546Sopenharmony_ci   for (uint32_t i = 0; i < MAX_FD_COUNT * MAX_BO_COUNT; i++) {
781bf215546Sopenharmony_ci      struct bo *bo = &bos[i];
782bf215546Sopenharmony_ci      if (bo->map == addr) {
783bf215546Sopenharmony_ci         bo->user_mapped = false;
784bf215546Sopenharmony_ci         break;
785bf215546Sopenharmony_ci      }
786bf215546Sopenharmony_ci   }
787bf215546Sopenharmony_ci   return libc_munmap(addr, length);
788bf215546Sopenharmony_ci}
789bf215546Sopenharmony_ci
790bf215546Sopenharmony_cistatic void __attribute__ ((destructor))
791bf215546Sopenharmony_cifini(void)
792bf215546Sopenharmony_ci{
793bf215546Sopenharmony_ci   if (devinfo.ver != 0) {
794bf215546Sopenharmony_ci      free(output_filename);
795bf215546Sopenharmony_ci      if (!capture_finished)
796bf215546Sopenharmony_ci         aub_file_finish(&aub_file);
797bf215546Sopenharmony_ci      free(bos);
798bf215546Sopenharmony_ci   }
799bf215546Sopenharmony_ci}
800