1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2015 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include <stdlib.h> 25b8e80941Smrg#include <stdio.h> 26b8e80941Smrg#include <string.h> 27b8e80941Smrg#include <stdint.h> 28b8e80941Smrg#include <stdbool.h> 29b8e80941Smrg#include <signal.h> 30b8e80941Smrg#include <stdarg.h> 31b8e80941Smrg#include <fcntl.h> 32b8e80941Smrg#include <sys/types.h> 33b8e80941Smrg#include <sys/sysmacros.h> 34b8e80941Smrg#include <sys/stat.h> 35b8e80941Smrg#include <sys/ioctl.h> 36b8e80941Smrg#include <unistd.h> 37b8e80941Smrg#include <errno.h> 38b8e80941Smrg#include <sys/mman.h> 39b8e80941Smrg#include <dlfcn.h> 40b8e80941Smrg#include "drm-uapi/i915_drm.h" 41b8e80941Smrg#include <inttypes.h> 42b8e80941Smrg 43b8e80941Smrg#include "intel_aub.h" 44b8e80941Smrg#include "aub_write.h" 45b8e80941Smrg 46b8e80941Smrg#include "dev/gen_device_info.h" 47b8e80941Smrg#include "util/macros.h" 48b8e80941Smrg 49b8e80941Smrgstatic int close_init_helper(int fd); 50b8e80941Smrgstatic int ioctl_init_helper(int fd, unsigned long request, ...); 51b8e80941Smrg 52b8e80941Smrgstatic int (*libc_close)(int fd) = close_init_helper; 53b8e80941Smrgstatic int (*libc_ioctl)(int fd, unsigned long request, ...) = ioctl_init_helper; 54b8e80941Smrg 55b8e80941Smrgstatic int drm_fd = -1; 56b8e80941Smrgstatic char *output_filename = NULL; 57b8e80941Smrgstatic FILE *output_file = NULL; 58b8e80941Smrgstatic int verbose = 0; 59b8e80941Smrgstatic bool device_override; 60b8e80941Smrg 61b8e80941Smrg#define MAX_FD_COUNT 64 62b8e80941Smrg#define MAX_BO_COUNT 64 * 1024 63b8e80941Smrg 64b8e80941Smrgstruct bo { 65b8e80941Smrg uint32_t size; 66b8e80941Smrg uint64_t offset; 67b8e80941Smrg void *map; 68b8e80941Smrg}; 69b8e80941Smrg 70b8e80941Smrgstatic struct bo *bos; 71b8e80941Smrg 72b8e80941Smrg#define DRM_MAJOR 226 73b8e80941Smrg 74b8e80941Smrg/* We set bit 0 in the map pointer for userptr BOs so we know not to 75b8e80941Smrg * munmap them on DRM_IOCTL_GEM_CLOSE. 76b8e80941Smrg */ 77b8e80941Smrg#define USERPTR_FLAG 1 78b8e80941Smrg#define IS_USERPTR(p) ((uintptr_t) (p) & USERPTR_FLAG) 79b8e80941Smrg#define GET_PTR(p) ( (void *) ((uintptr_t) p & ~(uintptr_t) 1) ) 80b8e80941Smrg 81b8e80941Smrgstatic void __attribute__ ((format(__printf__, 2, 3))) 82b8e80941Smrgfail_if(int cond, const char *format, ...) 83b8e80941Smrg{ 84b8e80941Smrg va_list args; 85b8e80941Smrg 86b8e80941Smrg if (!cond) 87b8e80941Smrg return; 88b8e80941Smrg 89b8e80941Smrg va_start(args, format); 90b8e80941Smrg fprintf(stderr, "intel_dump_gpu: "); 91b8e80941Smrg vfprintf(stderr, format, args); 92b8e80941Smrg va_end(args); 93b8e80941Smrg 94b8e80941Smrg raise(SIGTRAP); 95b8e80941Smrg} 96b8e80941Smrg 97b8e80941Smrgstatic struct bo * 98b8e80941Smrgget_bo(unsigned fd, uint32_t handle) 99b8e80941Smrg{ 100b8e80941Smrg struct bo *bo; 101b8e80941Smrg 102b8e80941Smrg fail_if(handle >= MAX_BO_COUNT, "bo handle too large\n"); 103b8e80941Smrg fail_if(fd >= MAX_FD_COUNT, "bo fd too large\n"); 104b8e80941Smrg bo = &bos[handle + fd * MAX_BO_COUNT]; 105b8e80941Smrg 106b8e80941Smrg return bo; 107b8e80941Smrg} 108b8e80941Smrg 109b8e80941Smrgstatic inline uint32_t 110b8e80941Smrgalign_u32(uint32_t v, uint32_t a) 111b8e80941Smrg{ 112b8e80941Smrg return (v + a - 1) & ~(a - 1); 113b8e80941Smrg} 114b8e80941Smrg 115b8e80941Smrgstatic struct gen_device_info devinfo = {0}; 116b8e80941Smrgstatic uint32_t device = 0; 117b8e80941Smrgstatic struct aub_file aub_file; 118b8e80941Smrg 119b8e80941Smrgstatic void * 120b8e80941Smrgrelocate_bo(int fd, struct bo *bo, const struct drm_i915_gem_execbuffer2 *execbuffer2, 121b8e80941Smrg const struct drm_i915_gem_exec_object2 *obj) 122b8e80941Smrg{ 123b8e80941Smrg const struct drm_i915_gem_exec_object2 *exec_objects = 124b8e80941Smrg (struct drm_i915_gem_exec_object2 *) (uintptr_t) execbuffer2->buffers_ptr; 125b8e80941Smrg const struct drm_i915_gem_relocation_entry *relocs = 126b8e80941Smrg (const struct drm_i915_gem_relocation_entry *) (uintptr_t) obj->relocs_ptr; 127b8e80941Smrg void *relocated; 128b8e80941Smrg int handle; 129b8e80941Smrg 130b8e80941Smrg relocated = malloc(bo->size); 131b8e80941Smrg fail_if(relocated == NULL, "out of memory\n"); 132b8e80941Smrg memcpy(relocated, GET_PTR(bo->map), bo->size); 133b8e80941Smrg for (size_t i = 0; i < obj->relocation_count; i++) { 134b8e80941Smrg fail_if(relocs[i].offset >= bo->size, "reloc outside bo\n"); 135b8e80941Smrg 136b8e80941Smrg if (execbuffer2->flags & I915_EXEC_HANDLE_LUT) 137b8e80941Smrg handle = exec_objects[relocs[i].target_handle].handle; 138b8e80941Smrg else 139b8e80941Smrg handle = relocs[i].target_handle; 140b8e80941Smrg 141b8e80941Smrg aub_write_reloc(&devinfo, ((char *)relocated) + relocs[i].offset, 142b8e80941Smrg get_bo(fd, handle)->offset + relocs[i].delta); 143b8e80941Smrg } 144b8e80941Smrg 145b8e80941Smrg return relocated; 146b8e80941Smrg} 147b8e80941Smrg 148b8e80941Smrgstatic int 149b8e80941Smrggem_ioctl(int fd, unsigned long request, void *argp) 150b8e80941Smrg{ 151b8e80941Smrg int ret; 152b8e80941Smrg 153b8e80941Smrg do { 154b8e80941Smrg ret = libc_ioctl(fd, request, argp); 155b8e80941Smrg } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 156b8e80941Smrg 157b8e80941Smrg return ret; 158b8e80941Smrg} 159b8e80941Smrg 160b8e80941Smrgstatic void * 161b8e80941Smrggem_mmap(int fd, uint32_t handle, uint64_t offset, uint64_t size) 162b8e80941Smrg{ 163b8e80941Smrg struct drm_i915_gem_mmap mmap = { 164b8e80941Smrg .handle = handle, 165b8e80941Smrg .offset = offset, 166b8e80941Smrg .size = size 167b8e80941Smrg }; 168b8e80941Smrg 169b8e80941Smrg if (gem_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &mmap) == -1) 170b8e80941Smrg return MAP_FAILED; 171b8e80941Smrg 172b8e80941Smrg return (void *)(uintptr_t) mmap.addr_ptr; 173b8e80941Smrg} 174b8e80941Smrg 175b8e80941Smrgstatic int 176b8e80941Smrggem_get_param(int fd, uint32_t param) 177b8e80941Smrg{ 178b8e80941Smrg int value; 179b8e80941Smrg drm_i915_getparam_t gp = { 180b8e80941Smrg .param = param, 181b8e80941Smrg .value = &value 182b8e80941Smrg }; 183b8e80941Smrg 184b8e80941Smrg if (gem_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) == -1) 185b8e80941Smrg return 0; 186b8e80941Smrg 187b8e80941Smrg return value; 188b8e80941Smrg} 189b8e80941Smrg 190b8e80941Smrgstatic enum drm_i915_gem_engine_class 191b8e80941Smrgengine_class_from_ring_flag(uint32_t ring_flag) 192b8e80941Smrg{ 193b8e80941Smrg switch (ring_flag) { 194b8e80941Smrg case I915_EXEC_DEFAULT: 195b8e80941Smrg case I915_EXEC_RENDER: 196b8e80941Smrg return I915_ENGINE_CLASS_RENDER; 197b8e80941Smrg case I915_EXEC_BSD: 198b8e80941Smrg return I915_ENGINE_CLASS_VIDEO; 199b8e80941Smrg case I915_EXEC_BLT: 200b8e80941Smrg return I915_ENGINE_CLASS_COPY; 201b8e80941Smrg case I915_EXEC_VEBOX: 202b8e80941Smrg return I915_ENGINE_CLASS_VIDEO_ENHANCE; 203b8e80941Smrg default: 204b8e80941Smrg return I915_ENGINE_CLASS_INVALID; 205b8e80941Smrg } 206b8e80941Smrg} 207b8e80941Smrg 208b8e80941Smrgstatic void 209b8e80941Smrgdump_execbuffer2(int fd, struct drm_i915_gem_execbuffer2 *execbuffer2) 210b8e80941Smrg{ 211b8e80941Smrg struct drm_i915_gem_exec_object2 *exec_objects = 212b8e80941Smrg (struct drm_i915_gem_exec_object2 *) (uintptr_t) execbuffer2->buffers_ptr; 213b8e80941Smrg uint32_t ring_flag = execbuffer2->flags & I915_EXEC_RING_MASK; 214b8e80941Smrg uint32_t offset; 215b8e80941Smrg struct drm_i915_gem_exec_object2 *obj; 216b8e80941Smrg struct bo *bo, *batch_bo; 217b8e80941Smrg int batch_index; 218b8e80941Smrg void *data; 219b8e80941Smrg 220b8e80941Smrg /* We can't do this at open time as we're not yet authenticated. */ 221b8e80941Smrg if (device == 0) { 222b8e80941Smrg device = gem_get_param(fd, I915_PARAM_CHIPSET_ID); 223b8e80941Smrg fail_if(device == 0 || devinfo.gen == 0, "failed to identify chipset\n"); 224b8e80941Smrg } 225b8e80941Smrg if (devinfo.gen == 0) { 226b8e80941Smrg fail_if(!gen_get_device_info(device, &devinfo), 227b8e80941Smrg "failed to identify chipset=0x%x\n", device); 228b8e80941Smrg 229b8e80941Smrg aub_file_init(&aub_file, output_file, 230b8e80941Smrg verbose == 2 ? stdout : NULL, 231b8e80941Smrg device, program_invocation_short_name); 232b8e80941Smrg aub_write_default_setup(&aub_file); 233b8e80941Smrg 234b8e80941Smrg if (verbose) 235b8e80941Smrg printf("[running, output file %s, chipset id 0x%04x, gen %d]\n", 236b8e80941Smrg output_filename, device, devinfo.gen); 237b8e80941Smrg } 238b8e80941Smrg 239b8e80941Smrg if (aub_use_execlists(&aub_file)) 240b8e80941Smrg offset = 0x1000; 241b8e80941Smrg else 242b8e80941Smrg offset = aub_gtt_size(&aub_file); 243b8e80941Smrg 244b8e80941Smrg if (verbose) 245b8e80941Smrg printf("Dumping execbuffer2:\n"); 246b8e80941Smrg 247b8e80941Smrg for (uint32_t i = 0; i < execbuffer2->buffer_count; i++) { 248b8e80941Smrg obj = &exec_objects[i]; 249b8e80941Smrg bo = get_bo(fd, obj->handle); 250b8e80941Smrg 251b8e80941Smrg /* If bo->size == 0, this means they passed us an invalid 252b8e80941Smrg * buffer. The kernel will reject it and so should we. 253b8e80941Smrg */ 254b8e80941Smrg if (bo->size == 0) { 255b8e80941Smrg if (verbose) 256b8e80941Smrg printf("BO #%d is invalid!\n", obj->handle); 257b8e80941Smrg return; 258b8e80941Smrg } 259b8e80941Smrg 260b8e80941Smrg if (obj->flags & EXEC_OBJECT_PINNED) { 261b8e80941Smrg bo->offset = obj->offset; 262b8e80941Smrg if (verbose) 263b8e80941Smrg printf("BO #%d (%dB) pinned @ 0x%lx\n", 264b8e80941Smrg obj->handle, bo->size, bo->offset); 265b8e80941Smrg } else { 266b8e80941Smrg if (obj->alignment != 0) 267b8e80941Smrg offset = align_u32(offset, obj->alignment); 268b8e80941Smrg bo->offset = offset; 269b8e80941Smrg if (verbose) 270b8e80941Smrg printf("BO #%d (%dB) @ 0x%lx\n", obj->handle, 271b8e80941Smrg bo->size, bo->offset); 272b8e80941Smrg offset = align_u32(offset + bo->size + 4095, 4096); 273b8e80941Smrg } 274b8e80941Smrg 275b8e80941Smrg if (bo->map == NULL && bo->size > 0) 276b8e80941Smrg bo->map = gem_mmap(fd, obj->handle, 0, bo->size); 277b8e80941Smrg fail_if(bo->map == MAP_FAILED, "bo mmap failed\n"); 278b8e80941Smrg 279b8e80941Smrg if (aub_use_execlists(&aub_file)) 280b8e80941Smrg aub_map_ppgtt(&aub_file, bo->offset, bo->size); 281b8e80941Smrg } 282b8e80941Smrg 283b8e80941Smrg batch_index = (execbuffer2->flags & I915_EXEC_BATCH_FIRST) ? 0 : 284b8e80941Smrg execbuffer2->buffer_count - 1; 285b8e80941Smrg batch_bo = get_bo(fd, exec_objects[batch_index].handle); 286b8e80941Smrg for (uint32_t i = 0; i < execbuffer2->buffer_count; i++) { 287b8e80941Smrg obj = &exec_objects[i]; 288b8e80941Smrg bo = get_bo(fd, obj->handle); 289b8e80941Smrg 290b8e80941Smrg if (obj->relocation_count > 0) 291b8e80941Smrg data = relocate_bo(fd, bo, execbuffer2, obj); 292b8e80941Smrg else 293b8e80941Smrg data = bo->map; 294b8e80941Smrg 295b8e80941Smrg if (bo == batch_bo) { 296b8e80941Smrg aub_write_trace_block(&aub_file, AUB_TRACE_TYPE_BATCH, 297b8e80941Smrg GET_PTR(data), bo->size, bo->offset); 298b8e80941Smrg } else { 299b8e80941Smrg aub_write_trace_block(&aub_file, AUB_TRACE_TYPE_NOTYPE, 300b8e80941Smrg GET_PTR(data), bo->size, bo->offset); 301b8e80941Smrg } 302b8e80941Smrg 303b8e80941Smrg if (data != bo->map) 304b8e80941Smrg free(data); 305b8e80941Smrg } 306b8e80941Smrg 307b8e80941Smrg aub_write_exec(&aub_file, 308b8e80941Smrg batch_bo->offset + execbuffer2->batch_start_offset, 309b8e80941Smrg offset, engine_class_from_ring_flag(ring_flag)); 310b8e80941Smrg 311b8e80941Smrg if (device_override && 312b8e80941Smrg (execbuffer2->flags & I915_EXEC_FENCE_ARRAY) != 0) { 313b8e80941Smrg struct drm_i915_gem_exec_fence *fences = 314b8e80941Smrg (void*)(uintptr_t)execbuffer2->cliprects_ptr; 315b8e80941Smrg for (uint32_t i = 0; i < execbuffer2->num_cliprects; i++) { 316b8e80941Smrg if ((fences[i].flags & I915_EXEC_FENCE_SIGNAL) != 0) { 317b8e80941Smrg struct drm_syncobj_array arg = { 318b8e80941Smrg .handles = (uintptr_t)&fences[i].handle, 319b8e80941Smrg .count_handles = 1, 320b8e80941Smrg .pad = 0, 321b8e80941Smrg }; 322b8e80941Smrg libc_ioctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &arg); 323b8e80941Smrg } 324b8e80941Smrg } 325b8e80941Smrg } 326b8e80941Smrg} 327b8e80941Smrg 328b8e80941Smrgstatic void 329b8e80941Smrgadd_new_bo(unsigned fd, int handle, uint64_t size, void *map) 330b8e80941Smrg{ 331b8e80941Smrg struct bo *bo = &bos[handle + fd * MAX_BO_COUNT]; 332b8e80941Smrg 333b8e80941Smrg fail_if(handle >= MAX_BO_COUNT, "bo handle out of range\n"); 334b8e80941Smrg fail_if(fd >= MAX_FD_COUNT, "bo fd out of range\n"); 335b8e80941Smrg fail_if(size == 0, "bo size is invalid\n"); 336b8e80941Smrg 337b8e80941Smrg bo->size = size; 338b8e80941Smrg bo->map = map; 339b8e80941Smrg} 340b8e80941Smrg 341b8e80941Smrgstatic void 342b8e80941Smrgremove_bo(int fd, int handle) 343b8e80941Smrg{ 344b8e80941Smrg struct bo *bo = get_bo(fd, handle); 345b8e80941Smrg 346b8e80941Smrg if (bo->map && !IS_USERPTR(bo->map)) 347b8e80941Smrg munmap(bo->map, bo->size); 348b8e80941Smrg bo->size = 0; 349b8e80941Smrg bo->map = NULL; 350b8e80941Smrg} 351b8e80941Smrg 352b8e80941Smrg__attribute__ ((visibility ("default"))) int 353b8e80941Smrgclose(int fd) 354b8e80941Smrg{ 355b8e80941Smrg if (fd == drm_fd) 356b8e80941Smrg drm_fd = -1; 357b8e80941Smrg 358b8e80941Smrg return libc_close(fd); 359b8e80941Smrg} 360b8e80941Smrg 361b8e80941Smrgstatic void 362b8e80941Smrgmaybe_init(void) 363b8e80941Smrg{ 364b8e80941Smrg static bool initialized = false; 365b8e80941Smrg FILE *config; 366b8e80941Smrg char *key, *value; 367b8e80941Smrg 368b8e80941Smrg if (initialized) 369b8e80941Smrg return; 370b8e80941Smrg 371b8e80941Smrg initialized = true; 372b8e80941Smrg 373b8e80941Smrg config = fopen(getenv("INTEL_DUMP_GPU_CONFIG"), "r"); 374b8e80941Smrg while (fscanf(config, "%m[^=]=%m[^\n]\n", &key, &value) != EOF) { 375b8e80941Smrg if (!strcmp(key, "verbose")) { 376b8e80941Smrg if (!strcmp(value, "1")) { 377b8e80941Smrg verbose = 1; 378b8e80941Smrg } else if (!strcmp(value, "2")) { 379b8e80941Smrg verbose = 2; 380b8e80941Smrg } 381b8e80941Smrg } else if (!strcmp(key, "device")) { 382b8e80941Smrg fail_if(device != 0, "Device/Platform override specified multiple times."); 383b8e80941Smrg fail_if(sscanf(value, "%i", &device) != 1, 384b8e80941Smrg "failed to parse device id '%s'", 385b8e80941Smrg value); 386b8e80941Smrg device_override = true; 387b8e80941Smrg } else if (!strcmp(key, "platform")) { 388b8e80941Smrg fail_if(device != 0, "Device/Platform override specified multiple times."); 389b8e80941Smrg device = gen_device_name_to_pci_device_id(value); 390b8e80941Smrg fail_if(device == -1, "Unknown platform '%s'", value); 391b8e80941Smrg device_override = true; 392b8e80941Smrg } else if (!strcmp(key, "file")) { 393b8e80941Smrg output_filename = strdup(value); 394b8e80941Smrg output_file = fopen(output_filename, "w+"); 395b8e80941Smrg fail_if(output_file == NULL, 396b8e80941Smrg "failed to open file '%s'\n", 397b8e80941Smrg output_filename); 398b8e80941Smrg } else { 399b8e80941Smrg fprintf(stderr, "unknown option '%s'\n", key); 400b8e80941Smrg } 401b8e80941Smrg 402b8e80941Smrg free(key); 403b8e80941Smrg free(value); 404b8e80941Smrg } 405b8e80941Smrg fclose(config); 406b8e80941Smrg 407b8e80941Smrg bos = calloc(MAX_FD_COUNT * MAX_BO_COUNT, sizeof(bos[0])); 408b8e80941Smrg fail_if(bos == NULL, "out of memory\n"); 409b8e80941Smrg} 410b8e80941Smrg 411b8e80941Smrg__attribute__ ((visibility ("default"))) int 412b8e80941Smrgioctl(int fd, unsigned long request, ...) 413b8e80941Smrg{ 414b8e80941Smrg va_list args; 415b8e80941Smrg void *argp; 416b8e80941Smrg int ret; 417b8e80941Smrg struct stat buf; 418b8e80941Smrg 419b8e80941Smrg va_start(args, request); 420b8e80941Smrg argp = va_arg(args, void *); 421b8e80941Smrg va_end(args); 422b8e80941Smrg 423b8e80941Smrg if (_IOC_TYPE(request) == DRM_IOCTL_BASE && 424b8e80941Smrg drm_fd != fd && fstat(fd, &buf) == 0 && 425b8e80941Smrg (buf.st_mode & S_IFMT) == S_IFCHR && major(buf.st_rdev) == DRM_MAJOR) { 426b8e80941Smrg drm_fd = fd; 427b8e80941Smrg if (verbose) 428b8e80941Smrg printf("[intercept drm ioctl on fd %d]\n", fd); 429b8e80941Smrg } 430b8e80941Smrg 431b8e80941Smrg if (fd == drm_fd) { 432b8e80941Smrg maybe_init(); 433b8e80941Smrg 434b8e80941Smrg switch (request) { 435b8e80941Smrg case DRM_IOCTL_I915_GETPARAM: { 436b8e80941Smrg struct drm_i915_getparam *getparam = argp; 437b8e80941Smrg 438b8e80941Smrg if (device_override && getparam->param == I915_PARAM_CHIPSET_ID) { 439b8e80941Smrg *getparam->value = device; 440b8e80941Smrg return 0; 441b8e80941Smrg } 442b8e80941Smrg 443b8e80941Smrg ret = libc_ioctl(fd, request, argp); 444b8e80941Smrg 445b8e80941Smrg /* If the application looks up chipset_id 446b8e80941Smrg * (they typically do), we'll piggy-back on 447b8e80941Smrg * their ioctl and store the id for later 448b8e80941Smrg * use. */ 449b8e80941Smrg if (ret == 0 && getparam->param == I915_PARAM_CHIPSET_ID) 450b8e80941Smrg device = *getparam->value; 451b8e80941Smrg 452b8e80941Smrg return ret; 453b8e80941Smrg } 454b8e80941Smrg 455b8e80941Smrg case DRM_IOCTL_I915_GEM_EXECBUFFER: { 456b8e80941Smrg static bool once; 457b8e80941Smrg if (!once) { 458b8e80941Smrg fprintf(stderr, 459b8e80941Smrg "application uses DRM_IOCTL_I915_GEM_EXECBUFFER, not handled\n"); 460b8e80941Smrg once = true; 461b8e80941Smrg } 462b8e80941Smrg return libc_ioctl(fd, request, argp); 463b8e80941Smrg } 464b8e80941Smrg 465b8e80941Smrg case DRM_IOCTL_I915_GEM_EXECBUFFER2: 466b8e80941Smrg case DRM_IOCTL_I915_GEM_EXECBUFFER2_WR: { 467b8e80941Smrg dump_execbuffer2(fd, argp); 468b8e80941Smrg if (device_override) 469b8e80941Smrg return 0; 470b8e80941Smrg 471b8e80941Smrg return libc_ioctl(fd, request, argp); 472b8e80941Smrg } 473b8e80941Smrg 474b8e80941Smrg case DRM_IOCTL_I915_GEM_CREATE: { 475b8e80941Smrg struct drm_i915_gem_create *create = argp; 476b8e80941Smrg 477b8e80941Smrg ret = libc_ioctl(fd, request, argp); 478b8e80941Smrg if (ret == 0) 479b8e80941Smrg add_new_bo(fd, create->handle, create->size, NULL); 480b8e80941Smrg 481b8e80941Smrg return ret; 482b8e80941Smrg } 483b8e80941Smrg 484b8e80941Smrg case DRM_IOCTL_I915_GEM_USERPTR: { 485b8e80941Smrg struct drm_i915_gem_userptr *userptr = argp; 486b8e80941Smrg 487b8e80941Smrg ret = libc_ioctl(fd, request, argp); 488b8e80941Smrg if (ret == 0) 489b8e80941Smrg add_new_bo(fd, userptr->handle, userptr->user_size, 490b8e80941Smrg (void *) (uintptr_t) (userptr->user_ptr | USERPTR_FLAG)); 491b8e80941Smrg 492b8e80941Smrg return ret; 493b8e80941Smrg } 494b8e80941Smrg 495b8e80941Smrg case DRM_IOCTL_GEM_CLOSE: { 496b8e80941Smrg struct drm_gem_close *close = argp; 497b8e80941Smrg 498b8e80941Smrg remove_bo(fd, close->handle); 499b8e80941Smrg 500b8e80941Smrg return libc_ioctl(fd, request, argp); 501b8e80941Smrg } 502b8e80941Smrg 503b8e80941Smrg case DRM_IOCTL_GEM_OPEN: { 504b8e80941Smrg struct drm_gem_open *open = argp; 505b8e80941Smrg 506b8e80941Smrg ret = libc_ioctl(fd, request, argp); 507b8e80941Smrg if (ret == 0) 508b8e80941Smrg add_new_bo(fd, open->handle, open->size, NULL); 509b8e80941Smrg 510b8e80941Smrg return ret; 511b8e80941Smrg } 512b8e80941Smrg 513b8e80941Smrg case DRM_IOCTL_PRIME_FD_TO_HANDLE: { 514b8e80941Smrg struct drm_prime_handle *prime = argp; 515b8e80941Smrg 516b8e80941Smrg ret = libc_ioctl(fd, request, argp); 517b8e80941Smrg if (ret == 0) { 518b8e80941Smrg off_t size; 519b8e80941Smrg 520b8e80941Smrg size = lseek(prime->fd, 0, SEEK_END); 521b8e80941Smrg fail_if(size == -1, "failed to get prime bo size\n"); 522b8e80941Smrg add_new_bo(fd, prime->handle, size, NULL); 523b8e80941Smrg 524b8e80941Smrg } 525b8e80941Smrg 526b8e80941Smrg return ret; 527b8e80941Smrg } 528b8e80941Smrg 529b8e80941Smrg default: 530b8e80941Smrg return libc_ioctl(fd, request, argp); 531b8e80941Smrg } 532b8e80941Smrg } else { 533b8e80941Smrg return libc_ioctl(fd, request, argp); 534b8e80941Smrg } 535b8e80941Smrg} 536b8e80941Smrg 537b8e80941Smrgstatic void 538b8e80941Smrginit(void) 539b8e80941Smrg{ 540b8e80941Smrg libc_close = dlsym(RTLD_NEXT, "close"); 541b8e80941Smrg libc_ioctl = dlsym(RTLD_NEXT, "ioctl"); 542b8e80941Smrg fail_if(libc_close == NULL || libc_ioctl == NULL, 543b8e80941Smrg "failed to get libc ioctl or close\n"); 544b8e80941Smrg} 545b8e80941Smrg 546b8e80941Smrgstatic int 547b8e80941Smrgclose_init_helper(int fd) 548b8e80941Smrg{ 549b8e80941Smrg init(); 550b8e80941Smrg return libc_close(fd); 551b8e80941Smrg} 552b8e80941Smrg 553b8e80941Smrgstatic int 554b8e80941Smrgioctl_init_helper(int fd, unsigned long request, ...) 555b8e80941Smrg{ 556b8e80941Smrg va_list args; 557b8e80941Smrg void *argp; 558b8e80941Smrg 559b8e80941Smrg va_start(args, request); 560b8e80941Smrg argp = va_arg(args, void *); 561b8e80941Smrg va_end(args); 562b8e80941Smrg 563b8e80941Smrg init(); 564b8e80941Smrg return libc_ioctl(fd, request, argp); 565b8e80941Smrg} 566b8e80941Smrg 567b8e80941Smrgstatic void __attribute__ ((destructor)) 568b8e80941Smrgfini(void) 569b8e80941Smrg{ 570b8e80941Smrg if (devinfo.gen != 0) { 571b8e80941Smrg free(output_filename); 572b8e80941Smrg aub_file_finish(&aub_file); 573b8e80941Smrg free(bos); 574b8e80941Smrg } 575b8e80941Smrg} 576