blob: f0057942150fbcca86548fd42c96bf191573219e [file] [log] [blame]
Chris Wilson0393e722015-08-09 17:39:41 +01001/*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#define _GNU_SOURCE /* for RTLD_NEXT */
25
26#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
29#include <stdint.h>
30#include <stdbool.h>
31#include <stdarg.h>
32#include <fcntl.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/ioctl.h>
36#include <unistd.h>
37#include <errno.h>
38#include <sys/mman.h>
39#include <dlfcn.h>
40#include <i915_drm.h>
41
42#include "intel_aub.h"
43#include "intel_chipset.h"
44
45static int (*libc_close)(int fd);
46static int (*libc_ioctl)(int fd, unsigned long request, void *argp);
47
48static int drm_fd = -1;
49static FILE *file;
50
51#define DRM_MAJOR 226
52
53enum {
54 ADD_BO = 0,
55 DEL_BO,
56 EXEC,
57};
58
59struct trace_add_bo {
60 uint8_t cmd;
61 uint32_t handle;
62 uint64_t size;
63} __attribute__((packed));
64struct trace_del_bo {
65 uint8_t cmd;
66 uint32_t handle;
67}__attribute__((packed));
68
69struct trace_exec {
70 uint8_t cmd;
71 uint32_t object_count;
72 uint64_t flags;
73}__attribute__((packed));
74
75struct trace_exec_object {
76 uint32_t handle;
77 uint32_t relocation_count;
78 uint64_t alignment;
79 uint64_t flags;
80 uint64_t rsvd1;
81 uint64_t rsvd2;
82}__attribute__((packed));
83
84struct trace_exec_relocation {
85 uint32_t target_handle;
86 uint32_t delta;
87 uint64_t offset;
88 uint32_t read_domains;
89 uint32_t write_domain;
90}__attribute__((packed));
91
92static void __attribute__ ((format(__printf__, 2, 3)))
93fail_if(int cond, const char *format, ...)
94{
95 va_list args;
96
97 if (!cond)
98 return;
99
100 va_start(args, format);
101 vfprintf(stderr, format, args);
102 va_end(args);
103
104 exit(1);
105}
106
107static void
108trace_exec(int fd, const struct drm_i915_gem_execbuffer2 *execbuffer2)
109{
110 const struct drm_i915_gem_exec_object2 *exec_objects =
111 (struct drm_i915_gem_exec_object2 *)(uintptr_t)execbuffer2->buffers_ptr;
112
113 {
114 struct trace_exec t = {
Chris Wilson39116212015-08-10 18:17:47 +0100115 EXEC, execbuffer2->buffer_count, execbuffer2->flags
116 };
Chris Wilson0393e722015-08-09 17:39:41 +0100117 fwrite(&t, sizeof(t), 1, file);
118 }
119
120 for (uint32_t i = 0; i < execbuffer2->buffer_count; i++) {
121 const struct drm_i915_gem_exec_object2 *obj = &exec_objects[i];
122 const struct drm_i915_gem_relocation_entry *relocs =
123 (struct drm_i915_gem_relocation_entry *)(uintptr_t)obj->relocs_ptr;
124 {
125 struct trace_exec_object t = {
126 obj->handle,
127 obj->relocation_count,
128 obj->alignment,
129 obj->flags,
130 obj->rsvd1,
131 obj->rsvd2
132 };
133 fwrite(&t, sizeof(t), 1, file);
134 }
135 for (uint32_t j = 0; j < obj->relocation_count; j++) {
136 struct trace_exec_relocation t = {
137 relocs[j].target_handle,
138 relocs[j].delta,
139 relocs[j].offset,
140 relocs[j].read_domains,
141 relocs[j].write_domain,
142 };
143 fwrite(&t, sizeof(t), 1, file);
144 }
145 }
146
147 fflush(file);
148}
149
150static void
151trace_add(uint32_t handle, uint64_t size)
152{
153 struct trace_add_bo t = { ADD_BO, handle, size };
154 fwrite(&t, sizeof(t), 1, file);
155}
156
157static void
158trace_del(uint32_t handle)
159{
160 struct trace_del_bo t = { DEL_BO, handle };
161 fwrite(&t, sizeof(t), 1, file);
162}
163
164int
165close(int fd)
166{
167 if (fd == drm_fd)
168 drm_fd = -1;
169
170 return libc_close(fd);
171}
172
Chris Wilsona64e6c32015-08-14 20:31:48 +0100173static unsigned long
174size_for_fb(const struct drm_mode_fb_cmd *cmd)
175{
176 unsigned long size;
177
178#ifndef ALIGN
179#define ALIGN(x, y) (((x) + (y) - 1) & -(y))
180#endif
181
182 size = ALIGN(cmd->width * cmd->bpp, 64);
183 size *= cmd->height;
184 return ALIGN(size, 4096);
185}
186
187static int is_i915(int fd)
188{
189 drm_version_t version;
190 char name[5] = "";
191
192 memset(&version, 0, sizeof(version));
193 version.name_len = 4;
194 version.name = name;
195
196 if (libc_ioctl(fd, DRM_IOCTL_VERSION, &version))
197 return 0;
198
199 return strcmp(name, "i915") == 0;
200}
201
Chris Wilson0393e722015-08-09 17:39:41 +0100202int
203ioctl(int fd, unsigned long request, ...)
204{
205 va_list args;
206 void *argp;
207 int ret;
208
209 va_start(args, request);
210 argp = va_arg(args, void *);
211 va_end(args);
212
Chris Wilsona64e6c32015-08-14 20:31:48 +0100213 ret = libc_ioctl(fd, request, argp);
214 if (ret)
215 return ret;
216
217 if (_IOC_TYPE(request) != DRM_IOCTL_BASE)
218 return 0;
219
220 if (drm_fd != fd) {
Chris Wilson0393e722015-08-09 17:39:41 +0100221 char filename[80];
Chris Wilsona64e6c32015-08-14 20:31:48 +0100222
223 if (!is_i915(fd))
224 return 0;
225
Chris Wilson0393e722015-08-09 17:39:41 +0100226 if (file)
227 fclose(file);
Chris Wilsona64e6c32015-08-14 20:31:48 +0100228
Chris Wilson0393e722015-08-09 17:39:41 +0100229 sprintf(filename, "/tmp/trace.%d", fd);
230 file = fopen(filename, "w+");
231 drm_fd = fd;
232 }
233
Chris Wilsona64e6c32015-08-14 20:31:48 +0100234 switch (request) {
235 case DRM_IOCTL_I915_GEM_EXECBUFFER2:
236 trace_exec(fd, argp);
237 break;
Chris Wilson0393e722015-08-09 17:39:41 +0100238
Chris Wilsona64e6c32015-08-14 20:31:48 +0100239 case DRM_IOCTL_I915_GEM_CREATE: {
240 struct drm_i915_gem_create *create = argp;
241 trace_add(create->handle, create->size);
242 break;
Chris Wilson0393e722015-08-09 17:39:41 +0100243 }
Chris Wilsona64e6c32015-08-14 20:31:48 +0100244
245 case DRM_IOCTL_I915_GEM_USERPTR: {
246 struct drm_i915_gem_userptr *userptr = argp;
247 trace_add(userptr->handle, userptr->user_size);
248 break;
249 }
250
251 case DRM_IOCTL_GEM_CLOSE: {
252 struct drm_gem_close *close = argp;
253 trace_del(close->handle);
254 break;
255 }
256
257 case DRM_IOCTL_GEM_OPEN: {
258 struct drm_gem_open *open = argp;
259 trace_add(open->handle, open->size);
260 break;
261 }
262
263 case DRM_IOCTL_PRIME_FD_TO_HANDLE: {
264 struct drm_prime_handle *prime = argp;
265 off_t size = lseek(prime->fd, 0, SEEK_END);
266 fail_if(size == -1, "failed to get prime bo size\n");
267 trace_add(prime->handle, size);
268 break;
269 }
270
271 case DRM_IOCTL_MODE_GETFB: {
272 struct drm_mode_fb_cmd *cmd = argp;
273 trace_add(cmd->handle, size_for_fb(cmd));
274 break;
275 }
276 }
277
278 return 0;
Chris Wilson0393e722015-08-09 17:39:41 +0100279}
280
281static void __attribute__ ((constructor))
282init(void)
283{
284 libc_close = dlsym(RTLD_NEXT, "close");
285 libc_ioctl = dlsym(RTLD_NEXT, "ioctl");
286 fail_if(libc_close == NULL || libc_ioctl == NULL,
287 "failed to get libc ioctl or close\n");
288}