blob: c151d487eb9cb02600fa4e4392ede13a7d8defd1 [file] [log] [blame]
Chris Wilson721d8742016-10-27 11:32:47 +01001/*
2 * Copyright © 2016 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#include <sys/poll.h>
Chris Wilsona19ef052017-07-31 14:15:59 +010025#include <sys/ioctl.h>
Chris Wilson721d8742016-10-27 11:32:47 +010026
27#include "igt.h"
28#include "igt_vgem.h"
Chris Wilson61f8de72017-07-20 10:08:28 +010029#include "igt_rand.h"
Chris Wilson721d8742016-10-27 11:32:47 +010030
Chris Wilson49f44c72016-11-14 21:24:52 +000031#define LOCAL_PARAM_HAS_SCHEDULER 41
Chris Wilsonaf0e1c52017-02-21 18:25:58 +000032#define LOCAL_CONTEXT_PARAM_PRIORITY 6
Chris Wilson721d8742016-10-27 11:32:47 +010033
34#define LO 0
35#define HI 1
36#define NOISE 2
37
38#define MAX_PRIO 1023
39
40#define BUSY_QLEN 8
41
42IGT_TEST_DESCRIPTION("Check that we can control the order of execution");
43
Chris Wilsonaf0e1c52017-02-21 18:25:58 +000044static int __ctx_set_priority(int fd, uint32_t ctx, int prio)
Chris Wilson721d8742016-10-27 11:32:47 +010045{
46 struct local_i915_gem_context_param param;
47
48 memset(&param, 0, sizeof(param));
49 param.context = ctx;
50 param.size = 0;
51 param.param = LOCAL_CONTEXT_PARAM_PRIORITY;
52 param.value = prio;
53
Chris Wilsonaf0e1c52017-02-21 18:25:58 +000054 return __gem_context_set_param(fd, &param);
55}
56
57static void ctx_set_priority(int fd, uint32_t ctx, int prio)
58{
59 igt_assert_eq(__ctx_set_priority(fd, ctx, prio), 0);
60}
61
62static void ctx_has_priority(int fd)
63{
64 igt_require(__ctx_set_priority(fd, 0, MAX_PRIO) == 0);
Chris Wilson721d8742016-10-27 11:32:47 +010065}
66
67static void store_dword(int fd, uint32_t ctx, unsigned ring,
68 uint32_t target, uint32_t offset, uint32_t value,
69 uint32_t cork, unsigned write_domain)
70{
71 const int gen = intel_gen(intel_get_drm_devid(fd));
72 struct drm_i915_gem_exec_object2 obj[3];
73 struct drm_i915_gem_relocation_entry reloc;
74 struct drm_i915_gem_execbuffer2 execbuf;
75 uint32_t batch[16];
76 int i;
77
78 memset(&execbuf, 0, sizeof(execbuf));
Chris Wilson4de67b22017-01-02 11:05:21 +000079 execbuf.buffers_ptr = to_user_pointer(obj + !cork);
Chris Wilson721d8742016-10-27 11:32:47 +010080 execbuf.buffer_count = 2 + !!cork;
81 execbuf.flags = ring;
82 if (gen < 6)
83 execbuf.flags |= I915_EXEC_SECURE;
84 execbuf.rsvd1 = ctx;
85
86 memset(obj, 0, sizeof(obj));
87 obj[0].handle = cork;
88 obj[1].handle = target;
89 obj[2].handle = gem_create(fd, 4096);
90
91 memset(&reloc, 0, sizeof(reloc));
92 reloc.target_handle = obj[1].handle;
93 reloc.presumed_offset = 0;
94 reloc.offset = sizeof(uint32_t);
95 reloc.delta = offset;
96 reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
97 reloc.write_domain = write_domain;
Chris Wilson4de67b22017-01-02 11:05:21 +000098 obj[2].relocs_ptr = to_user_pointer(&reloc);
Chris Wilson721d8742016-10-27 11:32:47 +010099 obj[2].relocation_count = 1;
100
101 i = 0;
102 batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
103 if (gen >= 8) {
104 batch[++i] = offset;
105 batch[++i] = 0;
106 } else if (gen >= 4) {
107 batch[++i] = 0;
108 batch[++i] = offset;
109 reloc.offset += sizeof(uint32_t);
110 } else {
111 batch[i]--;
112 batch[++i] = offset;
113 }
114 batch[++i] = value;
115 batch[++i] = MI_BATCH_BUFFER_END;
116 gem_write(fd, obj[2].handle, 0, batch, sizeof(batch));
117 gem_execbuf(fd, &execbuf);
118 gem_close(fd, obj[2].handle);
119}
120
121static uint32_t *make_busy(int fd, uint32_t target, unsigned ring)
122{
123 const int gen = intel_gen(intel_get_drm_devid(fd));
124 struct drm_i915_gem_exec_object2 obj[2];
125 struct drm_i915_gem_relocation_entry reloc[2];
126 struct drm_i915_gem_execbuffer2 execbuf;
127 uint32_t *batch;
128 int i;
129
130 memset(&execbuf, 0, sizeof(execbuf));
Chris Wilson4de67b22017-01-02 11:05:21 +0000131 execbuf.buffers_ptr = to_user_pointer(obj + !target);
Chris Wilson721d8742016-10-27 11:32:47 +0100132 execbuf.buffer_count = 1 + !!target;
133
134 memset(obj, 0, sizeof(obj));
135 obj[0].handle = target;
136 obj[1].handle = gem_create(fd, 4096);
137 batch = gem_mmap__wc(fd, obj[1].handle, 0, 4096, PROT_WRITE);
138 gem_set_domain(fd, obj[1].handle,
139 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
140
Chris Wilson4de67b22017-01-02 11:05:21 +0000141 obj[1].relocs_ptr = to_user_pointer(reloc);
Chris Wilson721d8742016-10-27 11:32:47 +0100142 obj[1].relocation_count = 1 + !!target;
143 memset(reloc, 0, sizeof(reloc));
144
145 reloc[0].target_handle = obj[1].handle; /* recurse */
146 reloc[0].presumed_offset = 0;
147 reloc[0].offset = sizeof(uint32_t);
148 reloc[0].delta = 0;
149 reloc[0].read_domains = I915_GEM_DOMAIN_COMMAND;
150 reloc[0].write_domain = 0;
151
152 reloc[1].target_handle = target;
153 reloc[1].presumed_offset = 0;
154 reloc[1].offset = 1024;
155 reloc[1].delta = 0;
156 reloc[1].read_domains = I915_GEM_DOMAIN_COMMAND;
157 reloc[1].write_domain = 0;
158
159 i = 0;
160 batch[i] = MI_BATCH_BUFFER_START;
161 if (gen >= 8) {
162 batch[i] |= 1 << 8 | 1;
163 batch[++i] = 0;
164 batch[++i] = 0;
165 } else if (gen >= 6) {
166 batch[i] |= 1 << 8;
167 batch[++i] = 0;
168 } else {
169 batch[i] |= 2 << 6;
170 batch[++i] = 0;
171 if (gen < 4) {
172 batch[i] |= 1;
173 reloc[0].delta = 1;
174 }
175 }
176 i++;
177
178 if (ring != -1) {
179 execbuf.flags = ring;
180 for (int n = 0; n < BUSY_QLEN; n++)
181 gem_execbuf(fd, &execbuf);
182 } else {
183 for_each_engine(fd, ring) {
184 if (ring == 0)
185 continue;
186
187 execbuf.flags = ring;
188 for (int n = 0; n < BUSY_QLEN; n++)
189 gem_execbuf(fd, &execbuf);
190 igt_assert(execbuf.flags == ring);
191 }
192 }
193
194 if (target) {
195 execbuf.flags = 0;
196 reloc[1].write_domain = I915_GEM_DOMAIN_COMMAND;
197 gem_execbuf(fd, &execbuf);
198 }
199
200 gem_close(fd, obj[1].handle);
201
202 return batch;
203}
204
205static void finish_busy(uint32_t *busy)
206{
207 *busy = MI_BATCH_BUFFER_END;
208 munmap(busy, 4096);
209}
210
211struct cork {
212 int device;
213 uint32_t handle;
214 uint32_t fence;
215};
216
217static void plug(int fd, struct cork *c)
218{
219 struct vgem_bo bo;
220 int dmabuf;
221
222 c->device = drm_open_driver(DRIVER_VGEM);
223
224 bo.width = bo.height = 1;
225 bo.bpp = 4;
226 vgem_create(c->device, &bo);
227 c->fence = vgem_fence_attach(c->device, &bo, VGEM_FENCE_WRITE);
228
229 dmabuf = prime_handle_to_fd(c->device, bo.handle);
230 c->handle = prime_fd_to_handle(fd, dmabuf);
231 close(dmabuf);
232}
233
234static void unplug(struct cork *c)
235{
236 vgem_fence_signal(c->device, c->fence);
237 close(c->device);
238}
239
240static void fifo(int fd, unsigned ring)
241{
242 struct cork cork;
243 uint32_t *busy;
244 uint32_t scratch;
245 uint32_t *ptr;
246
247 scratch = gem_create(fd, 4096);
248
249 busy = make_busy(fd, scratch, ring);
250 plug(fd, &cork);
251
252 /* Same priority, same timeline, final result will be the second eb */
253 store_dword(fd, 0, ring, scratch, 0, 1, cork.handle, 0);
254 store_dword(fd, 0, ring, scratch, 0, 2, cork.handle, 0);
255
256 unplug(&cork); /* only now submit our batches */
257 igt_debugfs_dump(fd, "i915_engine_info");
258 finish_busy(busy);
259
260 ptr = gem_mmap__gtt(fd, scratch, 4096, PROT_READ);
261 gem_set_domain(fd, scratch, /* no write hazard lies! */
262 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
263 gem_close(fd, scratch);
264
265 igt_assert_eq_u32(ptr[0], 2);
266 munmap(ptr, 4096);
267}
268
269static void reorder(int fd, unsigned ring, unsigned flags)
270#define EQUAL 1
271{
272 struct cork cork;
273 uint32_t scratch;
274 uint32_t *busy;
275 uint32_t *ptr;
276 uint32_t ctx[2];
277
278 ctx[LO] = gem_context_create(fd);
279 ctx_set_priority(fd, ctx[LO], -MAX_PRIO);
280
281 ctx[HI] = gem_context_create(fd);
282 ctx_set_priority(fd, ctx[HI], flags & EQUAL ? -MAX_PRIO : 0);
283
284 scratch = gem_create(fd, 4096);
285
286 busy = make_busy(fd, scratch, ring);
287 plug(fd, &cork);
288
289 /* We expect the high priority context to be executed first, and
290 * so the final result will be value from the low priority context.
291 */
292 store_dword(fd, ctx[LO], ring, scratch, 0, ctx[LO], cork.handle, 0);
293 store_dword(fd, ctx[HI], ring, scratch, 0, ctx[HI], cork.handle, 0);
294
295 unplug(&cork); /* only now submit our batches */
296 igt_debugfs_dump(fd, "i915_engine_info");
297 finish_busy(busy);
298
299 gem_context_destroy(fd, ctx[LO]);
300 gem_context_destroy(fd, ctx[HI]);
301
302 ptr = gem_mmap__gtt(fd, scratch, 4096, PROT_READ);
303 gem_set_domain(fd, scratch, /* no write hazard lies! */
304 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
305 gem_close(fd, scratch);
306
307 if (flags & EQUAL) /* equal priority, result will be fifo */
308 igt_assert_eq_u32(ptr[0], ctx[HI]);
309 else
310 igt_assert_eq_u32(ptr[0], ctx[LO]);
311 munmap(ptr, 4096);
312}
313
314static void promotion(int fd, unsigned ring)
315{
316 struct cork cork;
317 uint32_t result, dep;
318 uint32_t *busy;
319 uint32_t *ptr;
320 uint32_t ctx[3];
321
322 ctx[LO] = gem_context_create(fd);
323 ctx_set_priority(fd, ctx[LO], -MAX_PRIO);
324
325 ctx[HI] = gem_context_create(fd);
326 ctx_set_priority(fd, ctx[HI], 0);
327
328 ctx[NOISE] = gem_context_create(fd);
329 ctx_set_priority(fd, ctx[NOISE], -MAX_PRIO/2);
330
331 result = gem_create(fd, 4096);
332 dep = gem_create(fd, 4096);
333
334 busy = make_busy(fd, result, ring);
335 plug(fd, &cork);
336
337 /* Expect that HI promotes LO, so the order will be LO, HI, NOISE.
338 *
339 * fifo would be NOISE, LO, HI.
340 * strict priority would be HI, NOISE, LO
341 */
342 store_dword(fd, ctx[NOISE], ring, result, 0, ctx[NOISE], cork.handle, 0);
343 store_dword(fd, ctx[LO], ring, result, 0, ctx[LO], cork.handle, 0);
344
345 /* link LO <-> HI via a dependency on another buffer */
346 store_dword(fd, ctx[LO], ring, dep, 0, ctx[LO], 0, I915_GEM_DOMAIN_INSTRUCTION);
347 store_dword(fd, ctx[HI], ring, dep, 0, ctx[HI], 0, 0);
348
349 store_dword(fd, ctx[HI], ring, result, 0, ctx[HI], 0, 0);
350
351 unplug(&cork); /* only now submit our batches */
352 igt_debugfs_dump(fd, "i915_engine_info");
353 finish_busy(busy);
354
355 gem_context_destroy(fd, ctx[NOISE]);
356 gem_context_destroy(fd, ctx[LO]);
357 gem_context_destroy(fd, ctx[HI]);
358
359 ptr = gem_mmap__gtt(fd, dep, 4096, PROT_READ);
360 gem_set_domain(fd, dep, /* no write hazard lies! */
361 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
362 gem_close(fd, dep);
363
364 igt_assert_eq_u32(ptr[0], ctx[HI]);
365 munmap(ptr, 4096);
366
367 ptr = gem_mmap__gtt(fd, result, 4096, PROT_READ);
368 gem_set_domain(fd, result, /* no write hazard lies! */
369 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
370 gem_close(fd, result);
371
372 igt_assert_eq_u32(ptr[0], ctx[NOISE]);
373 munmap(ptr, 4096);
374}
375
376static void deep(int fd, unsigned ring)
377{
378#define XS 8
379 struct cork cork;
380 uint32_t result, dep[XS];
381 uint32_t *busy;
382 uint32_t *ptr;
383 uint32_t *ctx;
384
385 ctx = malloc(sizeof(*ctx)*(MAX_PRIO + 1));
386 for (int n = 0; n <= MAX_PRIO; n++) {
387 ctx[n] = gem_context_create(fd);
388 ctx_set_priority(fd, ctx[n], n);
389 }
390
391 result = gem_create(fd, 4096);
392 for (int m = 0; m < XS; m ++)
393 dep[m] = gem_create(fd, 4096);
394
395 busy = make_busy(fd, result, ring);
396 plug(fd, &cork);
397
398 /* Create a deep dependency chain, with a few branches */
399 for (int n = 0; n <= MAX_PRIO; n++)
400 for (int m = 0; m < XS; m++)
401 store_dword(fd, ctx[n], ring, dep[m], 4*n, ctx[n], cork.handle, I915_GEM_DOMAIN_INSTRUCTION);
402
403 for (int n = 0; n <= MAX_PRIO; n++) {
404 for (int m = 0; m < XS; m++) {
405 store_dword(fd, ctx[n], ring, result, 4*n, ctx[n], dep[m], 0);
406 store_dword(fd, ctx[n], ring, result, 4*m, ctx[n], 0, I915_GEM_DOMAIN_INSTRUCTION);
407 }
408 }
409
410 igt_assert(gem_bo_busy(fd, result));
411 unplug(&cork); /* only now submit our batches */
412 igt_debugfs_dump(fd, "i915_engine_info");
413 finish_busy(busy);
414
415 for (int n = 0; n <= MAX_PRIO; n++)
416 gem_context_destroy(fd, ctx[n]);
417
418 for (int m = 0; m < XS; m++) {
419 ptr = gem_mmap__gtt(fd, dep[m], 4096, PROT_READ);
420 gem_set_domain(fd, dep[m], /* no write hazard lies! */
421 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
422 gem_close(fd, dep[m]);
423
424 for (int n = 0; n <= MAX_PRIO; n++)
425 igt_assert_eq_u32(ptr[n], ctx[n]);
426 munmap(ptr, 4096);
427 }
428
429 ptr = gem_mmap__gtt(fd, result, 4096, PROT_READ);
430 gem_set_domain(fd, result, /* no write hazard lies! */
431 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
432 gem_close(fd, result);
433
434 for (int m = 0; m < XS; m++)
435 igt_assert_eq_u32(ptr[m], ctx[MAX_PRIO]);
436 munmap(ptr, 4096);
437
438 free(ctx);
Chris Wilsonf6920752017-04-24 13:20:04 +0100439#undef XS
440}
441
Chris Wilsona19ef052017-07-31 14:15:59 +0100442static void alarm_handler(int sig)
443{
444}
445
446static int __execbuf(int fd, struct drm_i915_gem_execbuffer2 *execbuf)
447{
448 return ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
449}
450
451static unsigned int measure_ring_size(int fd, unsigned int ring)
452{
453 struct sigaction sa = { .sa_handler = alarm_handler };
454 struct drm_i915_gem_exec_object2 obj[2];
455 struct drm_i915_gem_execbuffer2 execbuf;
456 const uint32_t bbe = MI_BATCH_BUFFER_END;
457 unsigned int count, last;
458 struct itimerval itv;
459 struct cork c;
460
461 memset(obj, 0, sizeof(obj));
462 obj[1].handle = gem_create(fd, 4096);
463 gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe));
464
465 memset(&execbuf, 0, sizeof(execbuf));
466 execbuf.buffers_ptr = to_user_pointer(obj + 1);
467 execbuf.buffer_count = 1;
468 execbuf.flags = ring;
469 gem_execbuf(fd, &execbuf);
470 gem_sync(fd, obj[1].handle);
471
472 plug(fd, &c);
473 obj[0].handle = c.handle;
474
475 execbuf.buffers_ptr = to_user_pointer(obj);
476 execbuf.buffer_count = 2;
477
478 sigaction(SIGALRM, &sa, NULL);
479 itv.it_interval.tv_sec = 0;
480 itv.it_interval.tv_usec = 100;
481 itv.it_value.tv_sec = 0;
482 itv.it_value.tv_usec = 1000;
483 setitimer(ITIMER_REAL, &itv, NULL);
484
485 last = -1;
486 count = 0;
487 do {
488 if (__execbuf(fd, &execbuf) == 0) {
489 count++;
490 continue;
491 }
492
493 if (last == count)
494 break;
495
496 last = count;
497 } while (1);
498
499 memset(&itv, 0, sizeof(itv));
500 setitimer(ITIMER_REAL, &itv, NULL);
501
502 unplug(&c);
503 gem_close(fd, obj[1].handle);
504
505 return count;
506}
507
Chris Wilsonf6920752017-04-24 13:20:04 +0100508static void wide(int fd, unsigned ring)
509{
Chris Wilsonf6920752017-04-24 13:20:04 +0100510#define NCTX 4096
Chris Wilsona19ef052017-07-31 14:15:59 +0100511 struct timespec tv = {};
512 unsigned int ring_size = measure_ring_size(fd, ring);
Chris Wilsonf6920752017-04-24 13:20:04 +0100513
514 struct cork cork;
515 uint32_t result;
516 uint32_t *busy;
517 uint32_t *ptr;
518 uint32_t *ctx;
Chris Wilsona19ef052017-07-31 14:15:59 +0100519 unsigned int count;
Chris Wilsonf6920752017-04-24 13:20:04 +0100520
521 ctx = malloc(sizeof(*ctx)*NCTX);
522 for (int n = 0; n < NCTX; n++)
523 ctx[n] = gem_context_create(fd);
524
Chris Wilsonf6920752017-04-24 13:20:04 +0100525 result = gem_create(fd, 4*NCTX);
526
527 busy = make_busy(fd, result, ring);
528 plug(fd, &cork);
529
530 /* Lots of in-order requests, plugged and submitted simultaneously */
Chris Wilsona19ef052017-07-31 14:15:59 +0100531 for (count = 0;
532 igt_seconds_elapsed(&tv) < 5 && count < ring_size;
533 count++) {
534 for (int n = 0; n < NCTX; n++) {
535 store_dword(fd, ctx[n], ring, result, 4*n, ctx[n], cork.handle, I915_GEM_DOMAIN_INSTRUCTION);
536 }
Chris Wilsonf6920752017-04-24 13:20:04 +0100537 }
Chris Wilsona19ef052017-07-31 14:15:59 +0100538 igt_info("Submitted %d requests over %d contexts in %.1fms\n",
539 count, NCTX, igt_nsec_elapsed(&tv) * 1e-6);
Chris Wilsonf6920752017-04-24 13:20:04 +0100540
541 igt_assert(gem_bo_busy(fd, result));
542 unplug(&cork); /* only now submit our batches */
543 igt_debugfs_dump(fd, "i915_engine_info");
544 finish_busy(busy);
545
546 for (int n = 0; n < NCTX; n++)
547 gem_context_destroy(fd, ctx[n]);
548
549 ptr = gem_mmap__gtt(fd, result, 4*NCTX, PROT_READ);
550 gem_set_domain(fd, result, /* no write hazard lies! */
551 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
552 for (int n = 0; n < NCTX; n++)
553 igt_assert_eq_u32(ptr[n], ctx[n]);
Chris Wilson61f8de72017-07-20 10:08:28 +0100554 munmap(ptr, 4*NCTX);
Chris Wilsonf6920752017-04-24 13:20:04 +0100555
Chris Wilsonf6920752017-04-24 13:20:04 +0100556 gem_close(fd, result);
557 free(ctx);
Chris Wilson61f8de72017-07-20 10:08:28 +0100558#undef NCTX
559}
560
561static void reorder_wide(int fd, unsigned ring)
562{
563 const int gen = intel_gen(intel_get_drm_devid(fd));
564 struct drm_i915_gem_relocation_entry reloc;
565 struct drm_i915_gem_exec_object2 obj[3];
566 struct drm_i915_gem_execbuffer2 execbuf;
567 struct cork cork;
568 uint32_t result, target;
569 uint32_t *busy;
570 uint32_t *r, *t;
571
572 result = gem_create(fd, 4096);
573 target = gem_create(fd, 4096);
574
575 busy = make_busy(fd, result, ring);
576 plug(fd, &cork);
577
578 t = gem_mmap__cpu(fd, target, 0, 4096, PROT_WRITE);
579 gem_set_domain(fd, target, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
580
581 memset(obj, 0, sizeof(obj));
582 obj[0].handle = cork.handle;
583 obj[1].handle = result;
584 obj[2].relocs_ptr = to_user_pointer(&reloc);
585 obj[2].relocation_count = 1;
586
587 memset(&reloc, 0, sizeof(reloc));
588 reloc.target_handle = result;
589 reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
590 reloc.write_domain = 0; /* lies */
591
592 memset(&execbuf, 0, sizeof(execbuf));
593 execbuf.buffers_ptr = to_user_pointer(obj);
594 execbuf.buffer_count = 3;
595 execbuf.flags = ring;
596 if (gen < 6)
597 execbuf.flags |= I915_EXEC_SECURE;
598
599 for (int n = -MAX_PRIO, x = 1; n <= MAX_PRIO; n++, x++) {
600 uint32_t *batch;
601
602 execbuf.rsvd1 = gem_context_create(fd);
603 ctx_set_priority(fd, execbuf.rsvd1, n);
604
605 obj[2].handle = gem_create(fd, 128 * 64);
606 batch = gem_mmap__gtt(fd, obj[2].handle, 128 * 64, PROT_WRITE);
607 gem_set_domain(fd, obj[2].handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
608
609 for (int m = 0; m < 128; m++) {
610 uint64_t addr;
611 int idx = hars_petruska_f54_1_random_unsafe_max( 1024);
612 int i;
613
614 execbuf.batch_start_offset = m * 64;
615 reloc.offset = execbuf.batch_start_offset + sizeof(uint32_t);
616 reloc.delta = idx * sizeof(uint32_t);
617 addr = reloc.presumed_offset + reloc.delta;
618
619 i = execbuf.batch_start_offset / sizeof(uint32_t);
620 batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
621 if (gen >= 8) {
622 batch[++i] = addr;
623 batch[++i] = addr >> 32;
624 } else if (gen >= 4) {
625 batch[++i] = 0;
626 batch[++i] = addr;
627 reloc.offset += sizeof(uint32_t);
628 } else {
629 batch[i]--;
630 batch[++i] = addr;
631 }
632 batch[++i] = x;
633 batch[++i] = MI_BATCH_BUFFER_END;
634
635 if (!t[idx])
636 t[idx] = x;
637
638 gem_execbuf(fd, &execbuf);
639 }
640
641 munmap(batch, 128 * 64);
642 gem_close(fd, obj[2].handle);
643 gem_context_destroy(fd, execbuf.rsvd1);
644 }
645
646 igt_assert(gem_bo_busy(fd, result));
647 unplug(&cork); /* only now submit our batches */
648 igt_debugfs_dump(fd, "i915_engine_info");
649 finish_busy(busy);
650
651 r = gem_mmap__gtt(fd, result, 4096, PROT_READ);
652 gem_set_domain(fd, result, /* no write hazard lies! */
653 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
654 for (int n = 0; n < 1024; n++)
655 igt_assert_eq_u32(r[n], t[n]);
656 munmap(r, 4096);
657 munmap(t, 4096);
658
659 gem_close(fd, result);
660 gem_close(fd, target);
Chris Wilson721d8742016-10-27 11:32:47 +0100661}
662
663static bool has_scheduler(int fd)
664{
665 drm_i915_getparam_t gp;
666 int has = -1;
667
668 gp.param = LOCAL_PARAM_HAS_SCHEDULER;
669 gp.value = &has;
670 drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
671
672 return has > 0;
673}
674
675igt_main
676{
677 const struct intel_execution_engine *e;
678 int fd = -1;
679
680 igt_skip_on_simulation();
681
682 igt_fixture {
683 fd = drm_open_driver_master(DRIVER_INTEL);
Chris Wilson9518cb52017-02-22 15:24:54 +0000684 igt_require_gem(fd);
Chris Wilson721d8742016-10-27 11:32:47 +0100685 gem_require_mmap_wc(fd);
686 igt_fork_hang_detector(fd);
687 }
688
689 igt_subtest_group {
690 for (e = intel_execution_engines; e->name; e++) {
691 /* default exec-id is purely symbolic */
692 if (e->exec_id == 0)
693 continue;
694
695 igt_subtest_f("fifo-%s", e->name) {
696 gem_require_ring(fd, e->exec_id | e->flags);
Chris Wilsonbc787762017-05-18 12:11:59 +0100697 igt_require(gem_can_store_dword(fd, e->exec_id) | e->flags);
Chris Wilson721d8742016-10-27 11:32:47 +0100698 fifo(fd, e->exec_id | e->flags);
699 }
700 }
701 }
702
703 igt_subtest_group {
704 igt_fixture {
705 igt_require(has_scheduler(fd));
Chris Wilsonaf0e1c52017-02-21 18:25:58 +0000706 ctx_has_priority(fd);
Chris Wilson721d8742016-10-27 11:32:47 +0100707 }
708
709 for (e = intel_execution_engines; e->name; e++) {
710 /* default exec-id is purely symbolic */
711 if (e->exec_id == 0)
712 continue;
713
714 igt_subtest_group {
Chris Wilson073cfd72017-03-17 11:52:51 +0000715 igt_fixture {
Chris Wilson721d8742016-10-27 11:32:47 +0100716 gem_require_ring(fd, e->exec_id | e->flags);
Chris Wilsonbc787762017-05-18 12:11:59 +0100717 igt_require(gem_can_store_dword(fd, e->exec_id) | e->flags);
Chris Wilson073cfd72017-03-17 11:52:51 +0000718 }
Chris Wilson721d8742016-10-27 11:32:47 +0100719
720 igt_subtest_f("in-order-%s", e->name)
721 reorder(fd, e->exec_id | e->flags, EQUAL);
722
723 igt_subtest_f("out-order-%s", e->name)
724 reorder(fd, e->exec_id | e->flags, 0);
725
726 igt_subtest_f("promotion-%s", e->name)
727 promotion(fd, e->exec_id | e->flags);
728
729 igt_subtest_f("deep-%s", e->name)
730 deep(fd, e->exec_id | e->flags);
Chris Wilsonf6920752017-04-24 13:20:04 +0100731
732 igt_subtest_f("wide-%s", e->name)
733 wide(fd, e->exec_id | e->flags);
Chris Wilson61f8de72017-07-20 10:08:28 +0100734
735 igt_subtest_f("reorder-wide-%s", e->name)
736 reorder_wide(fd, e->exec_id | e->flags);
Chris Wilson721d8742016-10-27 11:32:47 +0100737 }
738 }
739 }
740
741 igt_fixture {
742 igt_stop_hang_detector();
743 close(fd);
744 }
745}