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