blob: e797a9c5ceef3dff9cd2f8d7f99b2f3f6aef9bac [file] [log] [blame]
Chris Wilson5615ab22016-03-11 10:48:47 +00001/*
2 * Copyright © 2009 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
25/** @file gem_exec_whisper.c
26 *
27 * Pass around a value to write into a scratch buffer between lots of batches
28 */
29
30#include "igt.h"
31#include "igt_gt.h"
Chris Wilson58de7852017-03-24 18:11:08 +000032#include "igt_debugfs.h"
Chris Wilsonc6e26e42016-07-22 12:58:54 +010033#include "igt_sysfs.h"
Chris Wilson5615ab22016-03-11 10:48:47 +000034
35#define LOCAL_I915_EXEC_NO_RELOC (1<<11)
36#define LOCAL_I915_EXEC_HANDLE_LUT (1<<12)
37
38#define LOCAL_I915_EXEC_BSD_SHIFT (13)
39#define LOCAL_I915_EXEC_BSD_MASK (3 << LOCAL_I915_EXEC_BSD_SHIFT)
40
41#define ENGINE_MASK (I915_EXEC_RING_MASK | LOCAL_I915_EXEC_BSD_MASK)
42
Chris Wilson8f6ed9e2016-03-12 11:20:03 +000043#define VERIFY 0
44
Chris Wilson58de7852017-03-24 18:11:08 +000045static void write_seqno(int dir, unsigned offset)
Chris Wilson5615ab22016-03-11 10:48:47 +000046{
47 uint32_t seqno = UINT32_MAX - offset;
Chris Wilson5615ab22016-03-11 10:48:47 +000048
Chris Wilson58de7852017-03-24 18:11:08 +000049 igt_sysfs_printf(dir, "i915_next_seqno", "0x%x", seqno);
Chris Wilson5615ab22016-03-11 10:48:47 +000050
51 igt_debug("next seqno set to: 0x%x\n", seqno);
52}
53
54static void check_bo(int fd, uint32_t handle)
55{
56 uint32_t *map;
57 int i;
58
59 igt_debug("Verifying result\n");
60 map = gem_mmap__cpu(fd, handle, 0, 4096, PROT_READ);
61 gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, 0);
62 for (i = 0; i < 1024; i++)
63 igt_assert_eq(map[i], i);
64 munmap(map, 4096);
65}
66
Chris Wilson8f6ed9e2016-03-12 11:20:03 +000067static void verify_reloc(int fd, uint32_t handle,
68 const struct drm_i915_gem_relocation_entry *reloc)
69{
70 if (VERIFY) {
71 uint64_t target = 0;
72 if (intel_gen(intel_get_drm_devid(fd)) >= 8)
73 gem_read(fd, handle, reloc->offset, &target, 8);
74 else
75 gem_read(fd, handle, reloc->offset, &target, 4);
76 igt_assert_eq_u64(target,
77 reloc->presumed_offset + reloc->delta);
78 }
79}
80
Chris Wilson5615ab22016-03-11 10:48:47 +000081static int __gem_context_create(int fd, uint32_t *ctx_id)
82{
83 struct drm_i915_gem_context_create arg;
84 int ret = 0;
85
86 memset(&arg, 0, sizeof(arg));
87 if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &arg))
88 ret = -errno;
89
90 *ctx_id = arg.ctx_id;
91 return ret;
92}
93
Chris Wilsonbc787762017-05-18 12:11:59 +010094static bool ignore_engine(int fd, unsigned engine)
Chris Wilson5615ab22016-03-11 10:48:47 +000095{
Chris Wilson5df2de72016-03-15 09:52:57 +000096 if (engine == 0)
97 return true;
98
Chris Wilsonbc787762017-05-18 12:11:59 +010099 if (!gem_can_store_dword(fd, engine))
Chris Wilson5df2de72016-03-15 09:52:57 +0000100 return true;
101
102 return false;
Chris Wilson5615ab22016-03-11 10:48:47 +0000103}
104
105#define CONTEXTS 0x1
Chris Wilson9eacbd22016-03-11 14:31:56 +0000106#define FDS 0x2
Chris Wilson83cfed82016-03-19 14:21:34 +0000107#define INTERRUPTIBLE 0x4
Chris Wilson7b34c512016-06-04 16:12:28 +0100108#define CHAIN 0x8
Chris Wilson587753b2016-09-12 16:06:48 +0100109#define FORKED 0x10
Chris Wilson1a76d882016-10-01 16:50:51 +0100110#define HANG 0x20
Chris Wilson38dc1582017-04-05 17:09:15 +0100111#define SYNC 0x40
Chris Wilson1a76d882016-10-01 16:50:51 +0100112
113struct hang {
114 struct drm_i915_gem_exec_object2 obj;
115 struct drm_i915_gem_relocation_entry reloc;
116 struct drm_i915_gem_execbuffer2 execbuf;
117 int fd;
118};
119
120static void init_hang(struct hang *h)
121{
122 uint32_t *batch;
123 int i, gen;
124
125 h->fd = drm_open_driver(DRIVER_INTEL);
126 igt_allow_hang(h->fd, 0, 0);
127
128 gen = intel_gen(intel_get_drm_devid(h->fd));
129
130 memset(&h->execbuf, 0, sizeof(h->execbuf));
Chris Wilson4de67b22017-01-02 11:05:21 +0000131 h->execbuf.buffers_ptr = to_user_pointer(&h->obj);
Chris Wilson1a76d882016-10-01 16:50:51 +0100132 h->execbuf.buffer_count = 1;
133
134 memset(&h->obj, 0, sizeof(h->obj));
135 h->obj.handle = gem_create(h->fd, 4096);
136
Chris Wilson4de67b22017-01-02 11:05:21 +0000137 h->obj.relocs_ptr = to_user_pointer(&h->reloc);
Chris Wilson1a76d882016-10-01 16:50:51 +0100138 h->obj.relocation_count = 1;
139 memset(&h->reloc, 0, sizeof(h->reloc));
140
141 batch = gem_mmap__cpu(h->fd, h->obj.handle, 0, 4096, PROT_WRITE);
142 gem_set_domain(h->fd, h->obj.handle,
143 I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
144
145 h->reloc.target_handle = h->obj.handle; /* recurse */
146 h->reloc.presumed_offset = 0;
147 h->reloc.offset = 5*sizeof(uint32_t);
148 h->reloc.delta = 0;
149 h->reloc.read_domains = I915_GEM_DOMAIN_COMMAND;
150 h->reloc.write_domain = 0;
151
152 i = 0;
153 batch[i++] = 0xffffffff;
154 batch[i++] = 0xdeadbeef;
155 batch[i++] = 0xc00fee00;
156 batch[i++] = 0x00c00fee;
157 batch[i] = MI_BATCH_BUFFER_START;
158 if (gen >= 8) {
159 batch[i] |= 1 << 8 | 1;
160 batch[++i] = 0;
161 batch[++i] = 0;
162 } else if (gen >= 6) {
163 batch[i] |= 1 << 8;
164 batch[++i] = 0;
165 } else {
166 batch[i] |= 2 << 6;
167 batch[++i] = 0;
168 if (gen < 4) {
169 batch[i] |= 1;
170 h->reloc.delta = 1;
171 }
172 }
173 munmap(batch, 4096);
174}
175
Chris Wilson38dc1582017-04-05 17:09:15 +0100176static void submit_hang(struct hang *h, unsigned *engines, int nengine, unsigned flags)
Chris Wilson1a76d882016-10-01 16:50:51 +0100177{
178 while (nengine--) {
179 h->execbuf.flags &= ~ENGINE_MASK;
180 h->execbuf.flags |= *engines++;
181 gem_execbuf(h->fd, &h->execbuf);
182 }
Chris Wilson38dc1582017-04-05 17:09:15 +0100183 if (flags & SYNC)
184 gem_sync(h->fd, h->obj.handle);
Chris Wilson1a76d882016-10-01 16:50:51 +0100185}
186
187static void fini_hang(struct hang *h)
188{
189 close(h->fd);
190}
Chris Wilson5615ab22016-03-11 10:48:47 +0000191
Chris Wilson2fdf5ac2016-03-14 13:41:15 +0000192static void whisper(int fd, unsigned engine, unsigned flags)
Chris Wilson5615ab22016-03-11 10:48:47 +0000193{
Chris Wilson3e765842016-07-02 11:51:29 +0100194 const uint32_t bbe = MI_BATCH_BUFFER_END;
Chris Wilson5615ab22016-03-11 10:48:47 +0000195 const int gen = intel_gen(intel_get_drm_devid(fd));
196 struct drm_i915_gem_exec_object2 batches[1024];
197 struct drm_i915_gem_relocation_entry inter[1024];
198 struct drm_i915_gem_relocation_entry reloc;
Chris Wilson8f6ed9e2016-03-12 11:20:03 +0000199 struct drm_i915_gem_exec_object2 store, scratch;
200 struct drm_i915_gem_exec_object2 tmp[2];
201 struct drm_i915_gem_execbuffer2 execbuf;
Chris Wilson1a76d882016-10-01 16:50:51 +0100202 struct hang hang;
Chris Wilson9eacbd22016-03-11 14:31:56 +0000203 int fds[64];
Chris Wilson5615ab22016-03-11 10:48:47 +0000204 uint32_t contexts[64];
Chris Wilson5615ab22016-03-11 10:48:47 +0000205 unsigned engines[16];
206 unsigned nengine;
Chris Wilson5615ab22016-03-11 10:48:47 +0000207 uint32_t batch[16];
208 int i, n, pass, loc;
Chris Wilson5dcb0262016-03-26 09:48:16 +0000209 unsigned int relocations = 0;
Chris Wilson488dc3b2016-03-15 09:16:30 +0000210 unsigned int reloc_migrations = 0;
Chris Wilsond5e550f2016-03-21 11:58:21 +0000211 unsigned int reloc_interruptions = 0;
Chris Wilson488dc3b2016-03-15 09:16:30 +0000212 unsigned int eb_migrations = 0;
Chris Wilson5dcb0262016-03-26 09:48:16 +0000213 uint64_t old_offset;
Chris Wilson58de7852017-03-24 18:11:08 +0000214 int debugfs;
215
216 debugfs = igt_debugfs_dir(fd);
Chris Wilson5615ab22016-03-11 10:48:47 +0000217
218 nengine = 0;
Chris Wilson2fdf5ac2016-03-14 13:41:15 +0000219 if (engine == -1) {
220 for_each_engine(fd, engine) {
Chris Wilsonbc787762017-05-18 12:11:59 +0100221 if (!ignore_engine(fd, engine))
Chris Wilson2fdf5ac2016-03-14 13:41:15 +0000222 engines[nengine++] = engine;
223 }
224 } else {
225 igt_require(gem_has_ring(fd, engine));
Chris Wilsonbc787762017-05-18 12:11:59 +0100226 igt_require(gem_can_store_dword(fd, engine));
Chris Wilson2fdf5ac2016-03-14 13:41:15 +0000227 engines[nengine++] = engine;
228 }
Chris Wilson5615ab22016-03-11 10:48:47 +0000229 igt_require(nengine);
230
Chris Wilson875c27c2017-04-08 13:54:12 +0100231 if (flags & FDS)
232 igt_require(gen >= 6);
233
Chris Wilsonfe97e032017-03-23 10:48:32 +0000234 if (flags & CONTEXTS) {
235 igt_require(__gem_context_create(fd, &contexts[0]) == 0);
236 gem_context_destroy(fd, contexts[0]);
237 }
238
Chris Wilson1a76d882016-10-01 16:50:51 +0100239 if (flags & HANG)
240 init_hang(&hang);
241
Chris Wilson587753b2016-09-12 16:06:48 +0100242 intel_detect_and_clear_missed_interrupts(fd);
243 igt_fork(child, flags & FORKED ? sysconf(_SC_NPROCESSORS_ONLN) : 1) {
244 memset(&scratch, 0, sizeof(scratch));
245 scratch.handle = gem_create(fd, 4096);
246 scratch.flags = EXEC_OBJECT_WRITE;
Chris Wilson8f6ed9e2016-03-12 11:20:03 +0000247
Chris Wilson587753b2016-09-12 16:06:48 +0100248 memset(&store, 0, sizeof(store));
249 store.handle = gem_create(fd, 4096);
Chris Wilson4de67b22017-01-02 11:05:21 +0000250 store.relocs_ptr = to_user_pointer(&reloc);
Chris Wilson587753b2016-09-12 16:06:48 +0100251 store.relocation_count = 1;
Chris Wilson5615ab22016-03-11 10:48:47 +0000252
Chris Wilson587753b2016-09-12 16:06:48 +0100253 memset(&reloc, 0, sizeof(reloc));
254 reloc.offset = sizeof(uint32_t);
255 if (gen < 8 && gen >= 4)
256 reloc.offset += sizeof(uint32_t);
257 loc = 8;
258 if (gen >= 4)
259 loc += 4;
260 reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
261 reloc.write_domain = I915_GEM_DOMAIN_INSTRUCTION;
Chris Wilson5615ab22016-03-11 10:48:47 +0000262
Chris Wilson587753b2016-09-12 16:06:48 +0100263 {
264 tmp[0] = scratch;
265 tmp[1] = store;
266 gem_write(fd, store.handle, 0, &bbe, sizeof(bbe));
Chris Wilson8f6ed9e2016-03-12 11:20:03 +0000267
Chris Wilson587753b2016-09-12 16:06:48 +0100268 memset(&execbuf, 0, sizeof(execbuf));
Chris Wilson4de67b22017-01-02 11:05:21 +0000269 execbuf.buffers_ptr = to_user_pointer(tmp);
Chris Wilson587753b2016-09-12 16:06:48 +0100270 execbuf.buffer_count = 2;
271 execbuf.flags = LOCAL_I915_EXEC_HANDLE_LUT;
272 execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
273 if (gen < 6)
274 execbuf.flags |= I915_EXEC_SECURE;
275 igt_require(__gem_execbuf(fd, &execbuf) == 0);
276 scratch = tmp[0];
277 store = tmp[1];
Chris Wilson3e765842016-07-02 11:51:29 +0100278 }
279
Chris Wilson587753b2016-09-12 16:06:48 +0100280 i = 0;
281 batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
282 if (gen >= 8) {
283 batch[++i] = store.offset + loc;
284 batch[++i] = (store.offset + loc) >> 32;
285 } else if (gen >= 4) {
286 batch[++i] = 0;
287 batch[++i] = store.offset + loc;
288 } else {
289 batch[i]--;
290 batch[++i] = store.offset + loc;
291 }
292 batch[++i] = 0xc0ffee;
293 igt_assert(loc == sizeof(uint32_t) * i);
294 batch[++i] = MI_BATCH_BUFFER_END;
Chris Wilson3e765842016-07-02 11:51:29 +0100295
Chris Wilson587753b2016-09-12 16:06:48 +0100296 if (flags & CONTEXTS) {
Chris Wilsonfe97e032017-03-23 10:48:32 +0000297 for (n = 0; n < 64; n++)
Chris Wilson587753b2016-09-12 16:06:48 +0100298 contexts[n] = gem_context_create(fd);
299 }
300 if (flags & FDS) {
Chris Wilson587753b2016-09-12 16:06:48 +0100301 for (n = 0; n < 64; n++)
302 fds[n] = drm_open_driver(DRIVER_INTEL);
303 }
Chris Wilson5615ab22016-03-11 10:48:47 +0000304
Chris Wilson587753b2016-09-12 16:06:48 +0100305 memset(batches, 0, sizeof(batches));
306 for (n = 0; n < 1024; n++) {
307 batches[n].handle = gem_create(fd, 4096);
308 gem_write(fd, batches[n].handle, 0, &bbe, sizeof(bbe));
309 }
Chris Wilson4de67b22017-01-02 11:05:21 +0000310 execbuf.buffers_ptr = to_user_pointer(batches);
Chris Wilson587753b2016-09-12 16:06:48 +0100311 execbuf.buffer_count = 1024;
312 gem_execbuf(fd, &execbuf);
Chris Wilson5615ab22016-03-11 10:48:47 +0000313
Chris Wilson4de67b22017-01-02 11:05:21 +0000314 execbuf.buffers_ptr = to_user_pointer(tmp);
Chris Wilson587753b2016-09-12 16:06:48 +0100315 execbuf.buffer_count = 2;
Chris Wilson5615ab22016-03-11 10:48:47 +0000316
Chris Wilson587753b2016-09-12 16:06:48 +0100317 old_offset = store.offset;
318 for (n = 0; n < 1024; n++) {
Chris Wilson83cfed82016-03-19 14:21:34 +0000319 if (gen >= 8) {
Chris Wilson587753b2016-09-12 16:06:48 +0100320 batch[1] = old_offset + loc;
321 batch[2] = (old_offset + loc) >> 32;
Chris Wilson83cfed82016-03-19 14:21:34 +0000322 } else if (gen >= 4) {
Chris Wilson587753b2016-09-12 16:06:48 +0100323 batch[2] = old_offset + loc;
Chris Wilson83cfed82016-03-19 14:21:34 +0000324 } else {
Chris Wilson587753b2016-09-12 16:06:48 +0100325 batch[1] = old_offset + loc;
Chris Wilson9eacbd22016-03-11 14:31:56 +0000326 }
327
Chris Wilson587753b2016-09-12 16:06:48 +0100328 inter[n] = reloc;
329 inter[n].presumed_offset = old_offset;
330 inter[n].delta = loc;
Chris Wilson4de67b22017-01-02 11:05:21 +0000331 batches[n].relocs_ptr = to_user_pointer(&inter[n]);
Chris Wilson587753b2016-09-12 16:06:48 +0100332 batches[n].relocation_count = 1;
333 gem_write(fd, batches[n].handle, 0, batch, sizeof(batch));
Chris Wilson83cfed82016-03-19 14:21:34 +0000334
Chris Wilson587753b2016-09-12 16:06:48 +0100335 old_offset = batches[n].offset;
336 }
Chris Wilson83cfed82016-03-19 14:21:34 +0000337
Chris Wilson587753b2016-09-12 16:06:48 +0100338 igt_while_interruptible(flags & INTERRUPTIBLE) {
339 for (pass = 0; pass < 1024; pass++) {
340 uint64_t offset;
Chris Wilson83cfed82016-03-19 14:21:34 +0000341
Chris Wilson125e27e2016-10-05 17:25:20 +0100342 if (!(flags & FORKED))
Chris Wilson58de7852017-03-24 18:11:08 +0000343 write_seqno(debugfs, pass);
Chris Wilson83cfed82016-03-19 14:21:34 +0000344
Chris Wilson1a76d882016-10-01 16:50:51 +0100345 if (flags & HANG)
Chris Wilson38dc1582017-04-05 17:09:15 +0100346 submit_hang(&hang, engines, nengine, flags);
Chris Wilson1a76d882016-10-01 16:50:51 +0100347
Chris Wilson587753b2016-09-12 16:06:48 +0100348 if (flags & CHAIN) {
Chris Wilson7b34c512016-06-04 16:12:28 +0100349 execbuf.flags &= ~ENGINE_MASK;
350 execbuf.flags |= engines[rand() % nengine];
351 }
Chris Wilson587753b2016-09-12 16:06:48 +0100352
353 reloc.presumed_offset = scratch.offset;
354 reloc.delta = 4*pass;
355 offset = reloc.presumed_offset + reloc.delta;
356
357 i = 0;
358 if (gen >= 8) {
359 batch[++i] = offset;
360 batch[++i] = offset >> 32;
361 } else if (gen >= 4) {
362 batch[++i] = 0;
363 batch[++i] = offset;
364 } else {
365 batch[++i] = offset;
366 }
367 batch[++i] = ~pass;
368 gem_write(fd, store.handle, 0, batch, sizeof(batch));
369
370 tmp[0] = scratch;
371 igt_assert(tmp[0].flags & EXEC_OBJECT_WRITE);
372 tmp[1] = store;
373 verify_reloc(fd, store.handle, &reloc);
Chris Wilson4de67b22017-01-02 11:05:21 +0000374 execbuf.buffers_ptr = to_user_pointer(tmp);
Chris Wilson587753b2016-09-12 16:06:48 +0100375 gem_execbuf(fd, &execbuf);
376 igt_assert_eq_u64(reloc.presumed_offset, tmp[0].offset);
Chris Wilson38dc1582017-04-05 17:09:15 +0100377 if (flags & SYNC)
378 gem_sync(fd, tmp[0].handle);
Chris Wilson587753b2016-09-12 16:06:48 +0100379 scratch = tmp[0];
380
381 gem_write(fd, batches[1023].handle, loc, &pass, sizeof(pass));
382 for (n = 1024; --n >= 1; ) {
383 int this_fd = fd;
384 uint32_t handle[2];
385
Chris Wilson4de67b22017-01-02 11:05:21 +0000386 execbuf.buffers_ptr = to_user_pointer(&batches[n-1]);
Chris Wilson587753b2016-09-12 16:06:48 +0100387 reloc_migrations += batches[n-1].offset != inter[n].presumed_offset;
388 batches[n-1].offset = inter[n].presumed_offset;
389 old_offset = inter[n].presumed_offset;
390 batches[n-1].relocation_count = 0;
391 batches[n-1].flags |= EXEC_OBJECT_WRITE;
392 verify_reloc(fd, batches[n].handle, &inter[n]);
393
394 if (flags & FDS) {
395 this_fd = fds[rand() % 64];
396 handle[0] = batches[n-1].handle;
397 handle[1] = batches[n].handle;
398 batches[n-1].handle =
399 gem_open(this_fd,
400 gem_flink(fd, handle[0]));
401 batches[n].handle =
402 gem_open(this_fd,
403 gem_flink(fd, handle[1]));
404 }
405
406 if (!(flags & CHAIN)) {
407 execbuf.flags &= ~ENGINE_MASK;
408 execbuf.flags |= engines[rand() % nengine];
409 }
410 if (flags & CONTEXTS)
411 execbuf.rsvd1 = contexts[rand() % 64];
412 gem_execbuf(this_fd, &execbuf);
413 if (inter[n].presumed_offset == -1) {
414 reloc_interruptions++;
415 inter[n].presumed_offset = batches[n-1].offset;
416 }
417 igt_assert_eq_u64(inter[n].presumed_offset, batches[n-1].offset);
Chris Wilson38dc1582017-04-05 17:09:15 +0100418
419 if (flags & SYNC)
420 gem_sync(this_fd, batches[n-1].handle);
Chris Wilson587753b2016-09-12 16:06:48 +0100421 relocations += inter[n].presumed_offset != old_offset;
422
423 batches[n-1].relocation_count = 1;
424 batches[n-1].flags &= ~EXEC_OBJECT_WRITE;
425
426 if (this_fd != fd) {
427 gem_close(this_fd, batches[n-1].handle);
428 batches[n-1].handle = handle[0];
429
430 gem_close(this_fd, batches[n].handle);
431 batches[n].handle = handle[1];
432 }
433 }
434 execbuf.flags &= ~ENGINE_MASK;
435 execbuf.rsvd1 = 0;
Chris Wilson4de67b22017-01-02 11:05:21 +0000436 execbuf.buffers_ptr = to_user_pointer(&tmp);
Chris Wilson587753b2016-09-12 16:06:48 +0100437
438 tmp[0] = tmp[1];
439 tmp[0].relocation_count = 0;
440 tmp[0].flags = EXEC_OBJECT_WRITE;
441 reloc_migrations += tmp[0].offset != inter[0].presumed_offset;
442 tmp[0].offset = inter[0].presumed_offset;
443 old_offset = tmp[0].offset;
444 tmp[1] = batches[0];
445 verify_reloc(fd, batches[0].handle, &inter[0]);
446 gem_execbuf(fd, &execbuf);
447 if (inter[0].presumed_offset == -1) {
Chris Wilson5dcb0262016-03-26 09:48:16 +0000448 reloc_interruptions++;
Chris Wilson587753b2016-09-12 16:06:48 +0100449 inter[0].presumed_offset = tmp[0].offset;
Chris Wilson5dcb0262016-03-26 09:48:16 +0000450 }
Chris Wilson587753b2016-09-12 16:06:48 +0100451 igt_assert_eq_u64(inter[0].presumed_offset, tmp[0].offset);
452 relocations += inter[0].presumed_offset != old_offset;
453 batches[0] = tmp[1];
Chris Wilson83cfed82016-03-19 14:21:34 +0000454
Chris Wilson587753b2016-09-12 16:06:48 +0100455 tmp[1] = tmp[0];
456 tmp[0] = scratch;
457 igt_assert(tmp[0].flags & EXEC_OBJECT_WRITE);
458 igt_assert_eq_u64(reloc.presumed_offset, tmp[0].offset);
Chris Wilson4de67b22017-01-02 11:05:21 +0000459 igt_assert(tmp[1].relocs_ptr == to_user_pointer(&reloc));
Chris Wilson587753b2016-09-12 16:06:48 +0100460 tmp[1].relocation_count = 1;
461 tmp[1].flags &= ~EXEC_OBJECT_WRITE;
462 verify_reloc(fd, store.handle, &reloc);
463 gem_execbuf(fd, &execbuf);
464 eb_migrations += tmp[0].offset != scratch.offset;
465 eb_migrations += tmp[1].offset != store.offset;
466 igt_assert_eq_u64(reloc.presumed_offset, tmp[0].offset);
Chris Wilson38dc1582017-04-05 17:09:15 +0100467 if (flags & SYNC)
468 gem_sync(fd, tmp[0].handle);
469
Chris Wilson587753b2016-09-12 16:06:48 +0100470 store = tmp[1];
471 scratch = tmp[0];
Chris Wilson83cfed82016-03-19 14:21:34 +0000472 }
Chris Wilson62916782016-03-11 14:16:13 +0000473 }
Chris Wilson587753b2016-09-12 16:06:48 +0100474 igt_info("Number of migrations for execbuf: %d\n", eb_migrations);
475 igt_info("Number of migrations for reloc: %d, interrupted %d, patched %d\n", reloc_migrations, reloc_interruptions, relocations);
Chris Wilson5615ab22016-03-11 10:48:47 +0000476
Chris Wilson587753b2016-09-12 16:06:48 +0100477 check_bo(fd, scratch.handle);
478 gem_close(fd, scratch.handle);
479 gem_close(fd, store.handle);
480
481 if (flags & FDS) {
482 for (n = 0; n < 64; n++)
483 close(fds[n]);
484 }
485 if (flags & CONTEXTS) {
486 for (n = 0; n < 64; n++)
487 gem_context_destroy(fd, contexts[n]);
488 }
489 for (n = 0; n < 1024; n++)
490 gem_close(fd, batches[n].handle);
491 }
492
493 igt_waitchildren();
Chris Wilson1a76d882016-10-01 16:50:51 +0100494
495 if (flags & HANG)
496 fini_hang(&hang);
497 else
498 igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
Chris Wilson58de7852017-03-24 18:11:08 +0000499
500 close(debugfs);
Chris Wilson5615ab22016-03-11 10:48:47 +0000501}
502
Chris Wilsonc6e26e42016-07-22 12:58:54 +0100503static void print_welcome(int fd)
504{
505 bool active;
Chris Wilsonc6e26e42016-07-22 12:58:54 +0100506 int dir;
507
508 dir = igt_sysfs_open_parameters(fd);
509 if (dir < 0)
510 return;
511
Chris Wilsonb64d10c2016-07-22 17:53:51 +0100512 active = igt_sysfs_get_boolean(dir, "enable_guc_submission");
Chris Wilsonc6e26e42016-07-22 12:58:54 +0100513 if (active) {
514 igt_info("Using GuC submission\n");
515 goto out;
516 }
517
Chris Wilsonb64d10c2016-07-22 17:53:51 +0100518 active = igt_sysfs_get_boolean(dir, "enable_execlists");
Chris Wilsonc6e26e42016-07-22 12:58:54 +0100519 if (active) {
520 igt_info("Using Execlists submission\n");
521 goto out;
522 }
523
Chris Wilsonb64d10c2016-07-22 17:53:51 +0100524 active = igt_sysfs_get_boolean(dir, "semaphores");
Chris Wilsonf565b6c2016-09-08 20:59:55 +0100525 igt_info("Using Legacy submission%s\n",
Chris Wilsonc6e26e42016-07-22 12:58:54 +0100526 active ? ", with semaphores" : "");
527
528out:
529 close(dir);
530}
531
Chris Wilson5615ab22016-03-11 10:48:47 +0000532igt_main
533{
Chris Wilson83cfed82016-03-19 14:21:34 +0000534 const struct mode {
535 const char *name;
536 unsigned flags;
537 } modes[] = {
Chris Wilson2b4c35e2016-05-20 11:20:49 +0100538 { "normal", 0 },
Chris Wilson1a722fa2016-03-26 10:54:43 +0000539 { "interruptible", INTERRUPTIBLE },
Chris Wilson587753b2016-09-12 16:06:48 +0100540 { "forked", FORKED },
Chris Wilson38dc1582017-04-05 17:09:15 +0100541 { "sync", SYNC },
Chris Wilson7b34c512016-06-04 16:12:28 +0100542 { "chain", CHAIN },
Chris Wilson587753b2016-09-12 16:06:48 +0100543 { "chain-forked", CHAIN | FORKED },
544 { "chain-interruptible", CHAIN | INTERRUPTIBLE },
Chris Wilson38dc1582017-04-05 17:09:15 +0100545 { "chain-sync", CHAIN | SYNC },
Chris Wilson83cfed82016-03-19 14:21:34 +0000546 { "contexts", CONTEXTS },
547 { "contexts-interruptible", CONTEXTS | INTERRUPTIBLE},
Chris Wilson587753b2016-09-12 16:06:48 +0100548 { "contexts-forked", CONTEXTS | FORKED},
Chris Wilson7b34c512016-06-04 16:12:28 +0100549 { "contexts-chain", CONTEXTS | CHAIN },
Chris Wilson38dc1582017-04-05 17:09:15 +0100550 { "contexts-sync", CONTEXTS | SYNC },
Chris Wilson83cfed82016-03-19 14:21:34 +0000551 { "fds", FDS },
552 { "fds-interruptible", FDS | INTERRUPTIBLE},
Chris Wilson587753b2016-09-12 16:06:48 +0100553 { "fds-forked", FDS | FORKED},
Chris Wilson7b34c512016-06-04 16:12:28 +0100554 { "fds-chain", FDS | CHAIN},
Chris Wilson38dc1582017-04-05 17:09:15 +0100555 { "fds-sync", FDS | SYNC},
Chris Wilson83cfed82016-03-19 14:21:34 +0000556 { NULL }
557 };
Chris Wilson5615ab22016-03-11 10:48:47 +0000558 int fd;
559
Daniel Vetterbe21fc02016-06-17 16:04:09 +0200560 igt_fixture {
Chris Wilson5615ab22016-03-11 10:48:47 +0000561 fd = drm_open_driver_master(DRIVER_INTEL);
Chris Wilson9518cb52017-02-22 15:24:54 +0000562 igt_require_gem(fd);
Chris Wilsonbc787762017-05-18 12:11:59 +0100563 igt_require(gem_can_store_dword(fd, 0));
Chris Wilsonc6e26e42016-07-22 12:58:54 +0100564 print_welcome(fd);
Chris Wilson5615ab22016-03-11 10:48:47 +0000565
Daniel Vetterbe21fc02016-06-17 16:04:09 +0200566 igt_fork_hang_detector(fd);
567 }
Chris Wilson756f3e02016-03-22 11:33:41 +0000568
Chris Wilson83cfed82016-03-19 14:21:34 +0000569 for (const struct mode *m = modes; m->name; m++)
Chris Wilson2b4c35e2016-05-20 11:20:49 +0100570 igt_subtest_f("%s", m->name)
Chris Wilson83cfed82016-03-19 14:21:34 +0000571 whisper(fd, -1, m->flags);
Chris Wilson2fdf5ac2016-03-14 13:41:15 +0000572
573 for (const struct intel_execution_engine *e = intel_execution_engines;
574 e->name; e++) {
Chris Wilson7b34c512016-06-04 16:12:28 +0100575 for (const struct mode *m = modes; m->name; m++) {
576 if (m->flags & CHAIN)
577 continue;
578
Chris Wilson2b4c35e2016-05-20 11:20:49 +0100579 igt_subtest_f("%s-%s", e->name, m->name)
Chris Wilson83cfed82016-03-19 14:21:34 +0000580 whisper(fd, e->exec_id | e->flags, m->flags);
Chris Wilson7b34c512016-06-04 16:12:28 +0100581 }
Chris Wilson2fdf5ac2016-03-14 13:41:15 +0000582 }
Chris Wilson9eacbd22016-03-11 14:31:56 +0000583
Daniel Vetterbe21fc02016-06-17 16:04:09 +0200584 igt_fixture {
585 igt_stop_hang_detector();
Chris Wilson1a76d882016-10-01 16:50:51 +0100586 }
587
588 igt_subtest_group {
589 for (const struct mode *m = modes; m->name; m++) {
590 if (m->flags & INTERRUPTIBLE)
591 continue;
592 igt_subtest_f("hang-%s", m->name)
593 whisper(fd, -1, m->flags | HANG);
594 }
595 }
596
597 igt_fixture {
Chris Wilson5615ab22016-03-11 10:48:47 +0000598 close(fd);
Daniel Vetterbe21fc02016-06-17 16:04:09 +0200599 }
Chris Wilson5615ab22016-03-11 10:48:47 +0000600}