lib: make rendercopy.h an internal header
[platform/upstream/intel-gpu-tools.git] / tests / gem_reset_stats.c
1 /*
2  * Copyright (c) 2013 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  * Authors:
24  *  Mika Kuoppala <mika.kuoppala@intel.com>
25  *
26  */
27
28 #define _GNU_SOURCE
29 #include <stdbool.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <inttypes.h>
36 #include <errno.h>
37 #include <sys/stat.h>
38 #include <sys/ioctl.h>
39 #include <sys/mman.h>
40 #include <time.h>
41 #include <signal.h>
42
43 #include "i915_drm.h"
44 #include "drmtest.h"
45 #include "igt_debugfs.h"
46 #include "intel_bufmgr.h"
47 #include "intel_batchbuffer.h"
48 #include "intel_gpu_tools.h"
49
50 #define RS_NO_ERROR      0
51 #define RS_BATCH_ACTIVE  (1 << 0)
52 #define RS_BATCH_PENDING (1 << 1)
53 #define RS_UNKNOWN       (1 << 2)
54
55 struct local_drm_i915_reset_stats {
56         __u32 ctx_id;
57         __u32 flags;
58         __u32 reset_count;
59         __u32 batch_active;
60         __u32 batch_pending;
61         __u32 pad;
62 };
63
64 struct local_drm_i915_gem_context_create {
65         __u32 ctx_id;
66         __u32 pad;
67 };
68
69 struct local_drm_i915_gem_context_destroy {
70         __u32 ctx_id;
71         __u32 pad;
72 };
73
74 #define MAX_FD 32
75
76 #define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_gem_context_create)
77 #define CONTEXT_DESTROY_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2e, struct local_drm_i915_gem_context_destroy)
78 #define GET_RESET_STATS_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x32, struct local_drm_i915_reset_stats)
79
80 #define LOCAL_I915_EXEC_VEBOX   (4 << 0)
81
82 struct target_ring;
83
84 static bool gem_has_render(int fd)
85 {
86         return true;
87 }
88
89 static bool has_context(const struct target_ring *ring);
90
91 static const struct target_ring {
92         uint32_t exec;
93         bool (*present)(int fd);
94         bool (*contexts)(const struct target_ring *ring);
95         const char *name;
96 } rings[] = {
97         { I915_EXEC_RENDER, gem_has_render, has_context, "render" },
98         { I915_EXEC_BLT, gem_has_blt, has_context, "blt" },
99         { I915_EXEC_BSD, gem_has_bsd, has_context, "bsd" },
100         { LOCAL_I915_EXEC_VEBOX, gem_has_vebox, has_context, "vebox" },
101 };
102
103 static bool has_context(const struct target_ring *ring)
104 {
105         if(ring->exec == I915_EXEC_RENDER)
106                 return true;
107
108         return false;
109 }
110
111 #define NUM_RINGS (sizeof(rings)/sizeof(struct target_ring))
112
113 static const struct target_ring *current_ring;
114
115 static uint32_t context_create(int fd)
116 {
117         struct local_drm_i915_gem_context_create create;
118         int ret;
119
120         create.ctx_id = rand();
121         create.pad = rand();
122
123         ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create);
124         igt_assert(ret == 0);
125
126         return create.ctx_id;
127 }
128
129 static int context_destroy(int fd, uint32_t ctx_id)
130 {
131         int ret;
132         struct local_drm_i915_gem_context_destroy destroy;
133
134         destroy.ctx_id = ctx_id;
135         destroy.pad = rand();
136
137         ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy);
138         if (ret != 0)
139                 return -errno;
140
141         return 0;
142 }
143
144 static int gem_reset_stats(int fd, int ctx_id,
145                            struct local_drm_i915_reset_stats *rs)
146 {
147         int ret;
148
149         rs->ctx_id = ctx_id;
150         rs->flags = 0;
151         rs->reset_count = rand();
152         rs->batch_active = rand();
153         rs->batch_pending = rand();
154         rs->pad = 0;
155
156         do {
157                 ret = ioctl(fd, GET_RESET_STATS_IOCTL, rs);
158         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
159
160         if (ret < 0)
161                 return -errno;
162
163         return 0;
164 }
165
166 static int gem_reset_status(int fd, int ctx_id)
167 {
168         int ret;
169         struct local_drm_i915_reset_stats rs;
170
171         ret = gem_reset_stats(fd, ctx_id, &rs);
172         if (ret)
173                 return ret;
174
175         if (rs.batch_active)
176                 return RS_BATCH_ACTIVE;
177         if (rs.batch_pending)
178                 return RS_BATCH_PENDING;
179
180         return RS_NO_ERROR;
181 }
182
183 static int gem_exec(int fd, struct drm_i915_gem_execbuffer2 *execbuf)
184 {
185         int ret;
186
187         ret = ioctl(fd,
188                     DRM_IOCTL_I915_GEM_EXECBUFFER2,
189                     execbuf);
190
191         if (ret < 0)
192                 return -errno;
193
194         return 0;
195 }
196
197 static int exec_valid_ring(int fd, int ctx, int ring)
198 {
199         struct drm_i915_gem_execbuffer2 execbuf;
200         struct drm_i915_gem_exec_object2 exec;
201         int ret;
202
203         uint32_t buf[2] = { MI_BATCH_BUFFER_END, 0 };
204
205         exec.handle = gem_create(fd, 4096);
206         gem_write(fd, exec.handle, 0, buf, sizeof(buf));
207         exec.relocation_count = 0;
208         exec.relocs_ptr = 0;
209         exec.alignment = 0;
210         exec.offset = 0;
211         exec.flags = 0;
212         exec.rsvd1 = 0;
213         exec.rsvd2 = 0;
214
215         execbuf.buffers_ptr = (uintptr_t)&exec;
216         execbuf.buffer_count = 1;
217         execbuf.batch_start_offset = 0;
218         execbuf.batch_len = sizeof(buf);
219         execbuf.cliprects_ptr = 0;
220         execbuf.num_cliprects = 0;
221         execbuf.DR1 = 0;
222         execbuf.DR4 = 0;
223         execbuf.flags = ring;
224         i915_execbuffer2_set_context_id(execbuf, ctx);
225         execbuf.rsvd2 = 0;
226
227         ret = gem_exec(fd, &execbuf);
228         if (ret < 0)
229                 return ret;
230
231         return exec.handle;
232 }
233
234 static int exec_valid(int fd, int ctx)
235 {
236         return exec_valid_ring(fd, ctx, current_ring->exec);
237 }
238
239 static void stop_rings(const int mask)
240 {
241         int fd;
242         char buf[80];
243
244         igt_assert((mask & ~((1 << NUM_RINGS) - 1)) == 0);
245         igt_assert(snprintf(buf, sizeof(buf), "0x%02x", mask) == 4);
246         fd = igt_debugfs_open("i915_ring_stop", O_WRONLY);
247         igt_assert(fd >= 0);
248
249         igt_assert(write(fd, buf, 4) == 4);
250         close(fd);
251 }
252
253 #define BUFSIZE (4 * 1024)
254 #define ITEMS   (BUFSIZE >> 2)
255
256 static int ring_to_mask(int ring)
257 {
258         for (unsigned i = 0; i < NUM_RINGS; i++) {
259                 const struct target_ring *r = &rings[i];
260
261                 if (r->exec == ring)
262                         return (1 << i);
263         }
264
265         igt_assert(0);
266
267         return -1;
268 }
269
270 static int inject_hang_ring(int fd, int ctx, int ring)
271 {
272         struct drm_i915_gem_execbuffer2 execbuf;
273         struct drm_i915_gem_exec_object2 exec;
274         uint64_t gtt_off;
275         uint32_t *buf;
276         int roff, i;
277         unsigned cmd_len = 2;
278
279         srandom(time(NULL));
280
281         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
282                 cmd_len = 3;
283
284         buf = malloc(BUFSIZE);
285         igt_assert(buf != NULL);
286
287         buf[0] = MI_BATCH_BUFFER_END;
288         buf[1] = MI_NOOP;
289
290         exec.handle = gem_create(fd, BUFSIZE);
291         gem_write(fd, exec.handle, 0, buf, BUFSIZE);
292         exec.relocation_count = 0;
293         exec.relocs_ptr = 0;
294         exec.alignment = 0;
295         exec.offset = 0;
296         exec.flags = 0;
297         exec.rsvd1 = 0;
298         exec.rsvd2 = 0;
299
300         execbuf.buffers_ptr = (uintptr_t)&exec;
301         execbuf.buffer_count = 1;
302         execbuf.batch_start_offset = 0;
303         execbuf.batch_len = BUFSIZE;
304         execbuf.cliprects_ptr = 0;
305         execbuf.num_cliprects = 0;
306         execbuf.DR1 = 0;
307         execbuf.DR4 = 0;
308         execbuf.flags = ring;
309         i915_execbuffer2_set_context_id(execbuf, ctx);
310         execbuf.rsvd2 = 0;
311
312         igt_assert(gem_exec(fd, &execbuf) == 0);
313
314         gtt_off = exec.offset;
315
316         for (i = 0; i < ITEMS; i++)
317                 buf[i] = MI_NOOP;
318
319         roff = random() % (ITEMS - cmd_len);
320         buf[roff] = MI_BATCH_BUFFER_START | (cmd_len - 2);
321         buf[roff + 1] = (gtt_off & 0xfffffffc) + (roff << 2);
322         if (cmd_len == 3)
323                 buf[roff + 2] = gtt_off & 0xffffffff00000000ull;
324
325 #ifdef VERBOSE
326         printf("loop injected at 0x%lx (off 0x%x, bo_start 0x%lx, bo_end 0x%lx)\n",
327                (long unsigned int)((roff << 2) + gtt_off),
328                roff << 2, (long unsigned int)gtt_off,
329                (long unsigned int)(gtt_off + BUFSIZE - 1));
330 #endif
331         gem_write(fd, exec.handle, 0, buf, BUFSIZE);
332
333         exec.relocation_count = 0;
334         exec.relocs_ptr = 0;
335         exec.alignment = 0;
336         exec.offset = 0;
337         exec.flags = 0;
338         exec.rsvd1 = 0;
339         exec.rsvd2 = 0;
340
341         execbuf.buffers_ptr = (uintptr_t)&exec;
342         execbuf.buffer_count = 1;
343         execbuf.batch_start_offset = 0;
344         execbuf.batch_len = BUFSIZE;
345         execbuf.cliprects_ptr = 0;
346         execbuf.num_cliprects = 0;
347         execbuf.DR1 = 0;
348         execbuf.DR4 = 0;
349         execbuf.flags = ring;
350         i915_execbuffer2_set_context_id(execbuf, ctx);
351         execbuf.rsvd2 = 0;
352
353         igt_assert(gem_exec(fd, &execbuf) == 0);
354
355         igt_assert(gtt_off == exec.offset);
356
357         free(buf);
358
359         stop_rings(ring_to_mask(ring));
360
361         return exec.handle;
362 }
363
364 static int inject_hang(int fd, int ctx)
365 {
366         return inject_hang_ring(fd, ctx, current_ring->exec);
367 }
368
369 static int _assert_reset_status(int fd, int ctx, int status)
370 {
371         int rs;
372
373         rs = gem_reset_status(fd, ctx);
374         if (rs < 0) {
375                 printf("reset status for %d ctx %d returned %d\n",
376                        fd, ctx, rs);
377                 return rs;
378         }
379
380         if (rs != status) {
381                 printf("%d:%d reset status %d differs from assumed %d\n",
382                        fd, ctx, rs, status);
383
384                 return 1;
385         }
386
387         return 0;
388 }
389
390 #define assert_reset_status(fd, ctx, status) \
391         igt_assert(_assert_reset_status(fd, ctx, status) == 0)
392
393 static void test_rs(int num_fds, int hang_index, int rs_assumed_no_hang)
394 {
395         int i;
396         int fd[MAX_FD];
397         int h[MAX_FD];
398
399         igt_assert (num_fds <= MAX_FD);
400         igt_assert (hang_index < MAX_FD);
401
402         for (i = 0; i < num_fds; i++) {
403                 fd[i] = drm_open_any();
404                 igt_assert(fd[i]);
405         }
406
407         for (i = 0; i < num_fds; i++)
408                 assert_reset_status(fd[i], 0, RS_NO_ERROR);
409
410         for (i = 0; i < num_fds; i++) {
411                 if (i == hang_index)
412                         h[i] = inject_hang(fd[i], 0);
413                 else
414                         h[i] = exec_valid(fd[i], 0);
415         }
416
417         gem_sync(fd[num_fds - 1], h[num_fds - 1]);
418
419         for (i = 0; i < num_fds; i++) {
420                 if (hang_index < 0) {
421                         assert_reset_status(fd[i], 0, rs_assumed_no_hang);
422                         continue;
423                 }
424
425                 if (i < hang_index)
426                         assert_reset_status(fd[i], 0, RS_NO_ERROR);
427                 if (i == hang_index)
428                         assert_reset_status(fd[i], 0, RS_BATCH_ACTIVE);
429                 if (i > hang_index)
430                         assert_reset_status(fd[i], 0, RS_BATCH_PENDING);
431         }
432
433         for (i = 0; i < num_fds; i++) {
434                 gem_close(fd[i], h[i]);
435                 close(fd[i]);
436         }
437 }
438
439 #define MAX_CTX 100
440 static void test_rs_ctx(int num_fds, int num_ctx, int hang_index,
441                         int hang_context)
442 {
443         int i, j;
444         int fd[MAX_FD];
445         int h[MAX_FD][MAX_CTX];
446         int ctx[MAX_FD][MAX_CTX];
447
448         igt_assert (num_fds <= MAX_FD);
449         igt_assert (hang_index < MAX_FD);
450
451         igt_assert (num_ctx <= MAX_CTX);
452         igt_assert (hang_context < MAX_CTX);
453
454         test_rs(num_fds, -1, RS_NO_ERROR);
455
456         for (i = 0; i < num_fds; i++) {
457                 fd[i] = drm_open_any();
458                 igt_assert(fd[i]);
459                 assert_reset_status(fd[i], 0, RS_NO_ERROR);
460
461                 for (j = 0; j < num_ctx; j++) {
462                         ctx[i][j] = context_create(fd[i]);
463
464                 }
465
466                 assert_reset_status(fd[i], 0, RS_NO_ERROR);
467         }
468
469         for (i = 0; i < num_fds; i++) {
470
471                 assert_reset_status(fd[i], 0, RS_NO_ERROR);
472
473                 for (j = 0; j < num_ctx; j++)
474                         assert_reset_status(fd[i], ctx[i][j], RS_NO_ERROR);
475
476                 assert_reset_status(fd[i], 0, RS_NO_ERROR);
477         }
478
479         for (i = 0; i < num_fds; i++) {
480                 for (j = 0; j < num_ctx; j++) {
481                         if (i == hang_index && j == hang_context)
482                                 h[i][j] = inject_hang(fd[i], ctx[i][j]);
483                         else
484                                 h[i][j] = exec_valid(fd[i], ctx[i][j]);
485                 }
486         }
487
488         gem_sync(fd[num_fds - 1], ctx[num_fds - 1][num_ctx - 1]);
489
490         for (i = 0; i < num_fds; i++)
491                 assert_reset_status(fd[i], 0, RS_NO_ERROR);
492
493         for (i = 0; i < num_fds; i++) {
494                 for (j = 0; j < num_ctx; j++) {
495                         if (i < hang_index)
496                                 assert_reset_status(fd[i], ctx[i][j], RS_NO_ERROR);
497                         if (i == hang_index && j < hang_context)
498                                 assert_reset_status(fd[i], ctx[i][j], RS_NO_ERROR);
499                         if (i == hang_index && j == hang_context)
500                                 assert_reset_status(fd[i], ctx[i][j],
501                                                     RS_BATCH_ACTIVE);
502                         if (i == hang_index && j > hang_context)
503                                 assert_reset_status(fd[i], ctx[i][j],
504                                                     RS_BATCH_PENDING);
505                         if (i > hang_index)
506                                 assert_reset_status(fd[i], ctx[i][j],
507                                                     RS_BATCH_PENDING);
508                 }
509         }
510
511         for (i = 0; i < num_fds; i++) {
512                 for (j = 0; j < num_ctx; j++) {
513                         gem_close(fd[i], h[i][j]);
514                         igt_assert(context_destroy(fd[i], ctx[i][j]) == 0);
515                 }
516
517                 assert_reset_status(fd[i], 0, RS_NO_ERROR);
518
519                 close(fd[i]);
520         }
521 }
522
523 static void test_ban(void)
524 {
525         int h1,h2,h3,h4,h5,h6,h7;
526         int fd_bad, fd_good;
527         int retry = 10;
528         int active_count = 0, pending_count = 0;
529         struct local_drm_i915_reset_stats rs_bad, rs_good;
530
531         fd_bad = drm_open_any();
532         igt_assert(fd_bad >= 0);
533
534         fd_good = drm_open_any();
535         igt_assert(fd_good >= 0);
536
537         assert_reset_status(fd_bad, 0, RS_NO_ERROR);
538         assert_reset_status(fd_good, 0, RS_NO_ERROR);
539
540         h1 = exec_valid(fd_bad, 0);
541         igt_assert(h1 >= 0);
542         h5 = exec_valid(fd_good, 0);
543         igt_assert(h5 >= 0);
544
545         assert_reset_status(fd_bad, 0, RS_NO_ERROR);
546         assert_reset_status(fd_good, 0, RS_NO_ERROR);
547
548         h2 = inject_hang(fd_bad, 0);
549         igt_assert(h2 >= 0);
550         active_count++;
551         /* Second hang will be pending for this */
552         pending_count++;
553
554         h6 = exec_valid(fd_good, 0);
555         h7 = exec_valid(fd_good, 0);
556
557         while (retry--) {
558                 h3 = inject_hang(fd_bad, 0);
559                 igt_assert(h3 >= 0);
560                 gem_sync(fd_bad, h3);
561                 active_count++;
562                 /* This second hand will count as pending */
563                 assert_reset_status(fd_bad, 0, RS_BATCH_ACTIVE);
564
565                 h4 = exec_valid(fd_bad, 0);
566                 if (h4 == -EIO) {
567                         gem_close(fd_bad, h3);
568                         break;
569                 }
570
571                 /* Should not happen often but sometimes hang is declared too slow
572                  * due to our way of faking hang using loop */
573
574                 igt_assert(h4 >= 0);
575                 gem_close(fd_bad, h3);
576                 gem_close(fd_bad, h4);
577
578                 printf("retrying for ban (%d)\n", retry);
579         }
580
581         igt_assert(h4 == -EIO);
582         assert_reset_status(fd_bad, 0, RS_BATCH_ACTIVE);
583
584         gem_sync(fd_good, h7);
585         assert_reset_status(fd_good, 0, RS_BATCH_PENDING);
586
587         igt_assert(gem_reset_stats(fd_good, 0, &rs_good) == 0);
588         igt_assert(gem_reset_stats(fd_bad, 0, &rs_bad) == 0);
589
590         igt_assert(rs_bad.batch_active == active_count);
591         igt_assert(rs_bad.batch_pending == pending_count);
592         igt_assert(rs_good.batch_active == 0);
593         igt_assert(rs_good.batch_pending == 2);
594
595         gem_close(fd_bad, h1);
596         gem_close(fd_bad, h2);
597         gem_close(fd_good, h6);
598         gem_close(fd_good, h7);
599
600         h1 = exec_valid(fd_good, 0);
601         igt_assert(h1 >= 0);
602         gem_close(fd_good, h1);
603
604         close(fd_bad);
605         close(fd_good);
606
607         igt_assert(gem_reset_status(fd_bad, 0) < 0);
608         igt_assert(gem_reset_status(fd_good, 0) < 0);
609 }
610
611 static void test_ban_ctx(void)
612 {
613         int h1,h2,h3,h4,h5,h6,h7;
614         int ctx_good, ctx_bad;
615         int fd;
616         int retry = 10;
617         int active_count = 0, pending_count = 0;
618         struct local_drm_i915_reset_stats rs_bad, rs_good;
619
620         fd = drm_open_any();
621         igt_assert(fd >= 0);
622
623         assert_reset_status(fd, 0, RS_NO_ERROR);
624
625         ctx_good = context_create(fd);
626         ctx_bad = context_create(fd);
627
628         assert_reset_status(fd, 0, RS_NO_ERROR);
629         assert_reset_status(fd, ctx_good, RS_NO_ERROR);
630         assert_reset_status(fd, ctx_bad, RS_NO_ERROR);
631
632         h1 = exec_valid(fd, ctx_bad);
633         igt_assert(h1 >= 0);
634         h5 = exec_valid(fd, ctx_good);
635         igt_assert(h5 >= 0);
636
637         assert_reset_status(fd, ctx_good, RS_NO_ERROR);
638         assert_reset_status(fd, ctx_bad, RS_NO_ERROR);
639
640         h2 = inject_hang(fd, ctx_bad);
641         igt_assert(h2 >= 0);
642         active_count++;
643         /* Second hang will be pending for this */
644         pending_count++;
645
646         h6 = exec_valid(fd, ctx_good);
647         h7 = exec_valid(fd, ctx_good);
648
649         while (retry--) {
650                 h3 = inject_hang(fd, ctx_bad);
651                 igt_assert(h3 >= 0);
652                 gem_sync(fd, h3);
653                 active_count++;
654                 /* This second hand will count as pending */
655                 assert_reset_status(fd, ctx_bad, RS_BATCH_ACTIVE);
656
657                 h4 = exec_valid(fd, ctx_bad);
658                 if (h4 == -EIO) {
659                         gem_close(fd, h3);
660                         break;
661                 }
662
663                 /* Should not happen often but sometimes hang is declared too slow
664                  * due to our way of faking hang using loop */
665
666                 igt_assert(h4 >= 0);
667                 gem_close(fd, h3);
668                 gem_close(fd, h4);
669
670                 printf("retrying for ban (%d)\n", retry);
671         }
672
673         igt_assert(h4 == -EIO);
674         assert_reset_status(fd, ctx_bad, RS_BATCH_ACTIVE);
675
676         gem_sync(fd, h7);
677         assert_reset_status(fd, ctx_good, RS_BATCH_PENDING);
678
679         igt_assert(gem_reset_stats(fd, ctx_good, &rs_good) == 0);
680         igt_assert(gem_reset_stats(fd, ctx_bad, &rs_bad) == 0);
681
682         igt_assert(rs_bad.batch_active == active_count);
683         igt_assert(rs_bad.batch_pending == pending_count);
684         igt_assert(rs_good.batch_active == 0);
685         igt_assert(rs_good.batch_pending == 2);
686
687         gem_close(fd, h1);
688         gem_close(fd, h2);
689         gem_close(fd, h6);
690         gem_close(fd, h7);
691
692         h1 = exec_valid(fd, ctx_good);
693         igt_assert(h1 >= 0);
694         gem_close(fd, h1);
695
696         igt_assert(context_destroy(fd, ctx_good) == 0);
697         igt_assert(context_destroy(fd, ctx_bad) == 0);
698         igt_assert(gem_reset_status(fd, ctx_good) < 0);
699         igt_assert(gem_reset_status(fd, ctx_bad) < 0);
700         igt_assert(exec_valid(fd, ctx_good) < 0);
701         igt_assert(exec_valid(fd, ctx_bad) < 0);
702
703         close(fd);
704 }
705
706 static void test_unrelated_ctx(void)
707 {
708         int h1,h2;
709         int fd1,fd2;
710         int ctx_guilty, ctx_unrelated;
711
712         fd1 = drm_open_any();
713         fd2 = drm_open_any();
714         assert_reset_status(fd1, 0, RS_NO_ERROR);
715         assert_reset_status(fd2, 0, RS_NO_ERROR);
716         ctx_guilty = context_create(fd1);
717         ctx_unrelated = context_create(fd2);
718
719         assert_reset_status(fd1, ctx_guilty, RS_NO_ERROR);
720         assert_reset_status(fd2, ctx_unrelated, RS_NO_ERROR);
721
722         h1 = inject_hang(fd1, ctx_guilty);
723         igt_assert(h1 >= 0);
724         gem_sync(fd1, h1);
725         assert_reset_status(fd1, ctx_guilty, RS_BATCH_ACTIVE);
726         assert_reset_status(fd2, ctx_unrelated, RS_NO_ERROR);
727
728         h2 = exec_valid(fd2, ctx_unrelated);
729         igt_assert(h2 >= 0);
730         gem_sync(fd2, h2);
731         assert_reset_status(fd1, ctx_guilty, RS_BATCH_ACTIVE);
732         assert_reset_status(fd2, ctx_unrelated, RS_NO_ERROR);
733         gem_close(fd1, h1);
734         gem_close(fd2, h2);
735
736         igt_assert(context_destroy(fd1, ctx_guilty) == 0);
737         igt_assert(context_destroy(fd2, ctx_unrelated) == 0);
738
739         close(fd1);
740         close(fd2);
741 }
742
743 static int get_reset_count(int fd, int ctx)
744 {
745         int ret;
746         struct local_drm_i915_reset_stats rs;
747
748         ret = gem_reset_stats(fd, ctx, &rs);
749         if (ret)
750                 return ret;
751
752         return rs.reset_count;
753 }
754
755 static void test_close_pending_ctx(void)
756 {
757         int fd, h;
758         uint32_t ctx;
759
760         fd = drm_open_any();
761         igt_assert(fd >= 0);
762         ctx = context_create(fd);
763
764         assert_reset_status(fd, ctx, RS_NO_ERROR);
765
766         h = inject_hang(fd, ctx);
767         igt_assert(h >= 0);
768         igt_assert(context_destroy(fd, ctx) == 0);
769         igt_assert(context_destroy(fd, ctx) == -ENOENT);
770
771         gem_close(fd, h);
772         close(fd);
773 }
774
775 static void test_close_pending(void)
776 {
777         int fd, h;
778
779         fd = drm_open_any();
780         igt_assert(fd >= 0);
781
782         assert_reset_status(fd, 0, RS_NO_ERROR);
783
784         h = inject_hang(fd, 0);
785         igt_assert(h >= 0);
786
787         gem_close(fd, h);
788         close(fd);
789 }
790
791 static void exec_noop_on_each_ring(int fd, const bool reverse)
792 {
793         uint32_t batch[2] = {MI_BATCH_BUFFER_END, 0};
794         uint32_t handle;
795         struct drm_i915_gem_execbuffer2 execbuf;
796         struct drm_i915_gem_exec_object2 exec[1];
797
798         handle = gem_create(fd, 4096);
799         gem_write(fd, handle, 0, batch, sizeof(batch));
800
801         exec[0].handle = handle;
802         exec[0].relocation_count = 0;
803         exec[0].relocs_ptr = 0;
804         exec[0].alignment = 0;
805         exec[0].offset = 0;
806         exec[0].flags = 0;
807         exec[0].rsvd1 = 0;
808         exec[0].rsvd2 = 0;
809
810         execbuf.buffers_ptr = (uintptr_t)exec;
811         execbuf.buffer_count = 1;
812         execbuf.batch_start_offset = 0;
813         execbuf.batch_len = 8;
814         execbuf.cliprects_ptr = 0;
815         execbuf.num_cliprects = 0;
816         execbuf.DR1 = 0;
817         execbuf.DR4 = 0;
818         execbuf.flags = 0;
819         i915_execbuffer2_set_context_id(execbuf, 0);
820         execbuf.rsvd2 = 0;
821
822         for (unsigned i = 0; i < NUM_RINGS; i++) {
823                 const struct target_ring *ring;
824
825                 ring = reverse ? &rings[NUM_RINGS - 1 - i] : &rings[i];
826
827                 if (ring->present(fd)) {
828                         execbuf.flags = ring->exec;
829                         do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
830                 }
831         }
832
833         gem_sync(fd, handle);
834         gem_close(fd, handle);
835 }
836
837 static void test_close_pending_fork(const bool reverse)
838 {
839         int pid;
840         int fd, h;
841
842         fd = drm_open_any();
843         igt_assert(fd >= 0);
844
845         assert_reset_status(fd, 0, RS_NO_ERROR);
846
847         h = inject_hang(fd, 0);
848         igt_assert(h >= 0);
849
850         sleep(1);
851
852         /* Avoid helpers as we need to kill the child
853          * without any extra signal handling on behalf of
854          * lib/drmtest.c
855          */
856         pid = fork();
857         if (pid == 0) {
858                 const int fd2 = drm_open_any();
859                 igt_assert(fd2 >= 0);
860
861                 /* The crucial component is that we schedule the same noop batch
862                  * on each ring. This exercises batch_obj reference counting,
863                  * when gpu is reset and ring lists are cleared.
864                  */
865                 exec_noop_on_each_ring(fd2, reverse);
866
867                 close(fd2);
868                 return;
869         } else {
870                 igt_assert(pid > 0);
871                 sleep(1);
872
873                 /* Kill the child to reduce refcounts on
874                    batch_objs */
875                 kill(pid, SIGKILL);
876         }
877
878         gem_close(fd, h);
879         close(fd);
880
881         /* Then we just wait on hang to happen */
882         fd = drm_open_any();
883         igt_assert(fd >= 0);
884
885         h = exec_valid(fd, 0);
886         igt_assert(h >= 0);
887
888         gem_sync(fd, h);
889         gem_close(fd, h);
890         close(fd);
891 }
892
893 static void test_reset_count(const bool create_ctx)
894 {
895         int fd, h, ctx;
896         long c1, c2;
897
898         fd = drm_open_any();
899         igt_assert(fd >= 0);
900         if (create_ctx)
901                 ctx = context_create(fd);
902         else
903                 ctx = 0;
904
905         assert_reset_status(fd, ctx, RS_NO_ERROR);
906
907         c1 = get_reset_count(fd, ctx);
908         igt_assert(c1 >= 0);
909
910         h = inject_hang(fd, ctx);
911         igt_assert (h >= 0);
912         gem_sync(fd, h);
913
914         assert_reset_status(fd, ctx, RS_BATCH_ACTIVE);
915         c2 = get_reset_count(fd, ctx);
916         igt_assert(c2 >= 0);
917         igt_assert(c2 == (c1 + 1));
918
919         igt_fork(child, 1) {
920                 igt_drop_root();
921
922                 c2 = get_reset_count(fd, ctx);
923
924                 if (ctx == 0)
925                         igt_assert(c2 == -EPERM);
926                 else
927                         igt_assert(c2 == 0);
928         }
929
930         igt_waitchildren();
931
932         gem_close(fd, h);
933
934         if (create_ctx)
935                 context_destroy(fd, ctx);
936
937         close(fd);
938 }
939
940 static int _test_params(int fd, int ctx, uint32_t flags, uint32_t pad)
941 {
942         struct local_drm_i915_reset_stats rs;
943         int ret;
944
945         rs.ctx_id = ctx;
946         rs.flags = flags;
947         rs.reset_count = rand();
948         rs.batch_active = rand();
949         rs.batch_pending = rand();
950         rs.pad = pad;
951
952         do {
953                 ret = ioctl(fd, GET_RESET_STATS_IOCTL, &rs);
954         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
955
956         if (ret < 0)
957                 return -errno;
958
959         return 0;
960 }
961
962 typedef enum { root = 0, user } cap_t;
963
964 static void test_param_ctx(const int fd, const int ctx, const cap_t cap)
965 {
966         const uint32_t bad = rand() + 1;
967
968         if (ctx == 0) {
969                 if (cap == root)
970                         igt_assert(_test_params(fd, ctx, 0, 0) == 0);
971                 else
972                         igt_assert(_test_params(fd, ctx, 0, 0) == -EPERM);
973         }
974
975         igt_assert(_test_params(fd, ctx, 0, bad) == -EINVAL);
976         igt_assert(_test_params(fd, ctx, bad, 0) == -EINVAL);
977         igt_assert(_test_params(fd, ctx, bad, bad) == -EINVAL);
978 }
979
980 static void check_params(const int fd, const int ctx, cap_t cap)
981 {
982         igt_assert(ioctl(fd, GET_RESET_STATS_IOCTL, 0) == -1);
983         igt_assert(_test_params(fd, 0xbadbad, 0, 0) == -ENOENT);
984
985         test_param_ctx(fd, 0, cap);
986         test_param_ctx(fd, ctx, cap);
987 }
988
989 static void _test_param(const int fd, const int ctx)
990 {
991         check_params(fd, ctx, root);
992
993         igt_fork(child, 1) {
994                 check_params(fd, ctx, root);
995
996                 igt_drop_root();
997
998                 check_params(fd, ctx, user);
999         }
1000
1001         check_params(fd, ctx, root);
1002
1003         igt_waitchildren();
1004 }
1005
1006 static void test_params(void)
1007 {
1008         int fd, ctx;
1009
1010         fd = drm_open_any();
1011         igt_assert(fd >= 0);
1012         ctx = context_create(fd);
1013
1014         _test_param(fd, ctx);
1015
1016         close(fd);
1017 }
1018
1019 #define RING_HAS_CONTEXTS current_ring->contexts(current_ring)
1020 #define RUN_CTX_TEST(...) do { igt_skip_on(RING_HAS_CONTEXTS == false); __VA_ARGS__; } while (0)
1021
1022 int fd;
1023
1024 igt_main
1025 {
1026         struct local_drm_i915_gem_context_create create;
1027         uint32_t devid;
1028         int ret;
1029
1030         igt_skip_on_simulation();
1031
1032         igt_fixture {
1033                 fd = drm_open_any();
1034                 devid = intel_get_drm_devid(fd);
1035                 igt_require_f(intel_gen(devid) >= 4,
1036                               "Architecture %d too old\n", intel_gen(devid));
1037
1038                 ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create);
1039                 igt_skip_on_f(ret != 0 && (errno == ENODEV || errno == EINVAL),
1040                               "Kernel is too old, or contexts not supported: %s\n",
1041                               strerror(errno));
1042         }
1043
1044         igt_subtest("params")
1045                 test_params();
1046
1047         for (int i = 0; i < NUM_RINGS; i++) {
1048                 const char *name;
1049
1050                 current_ring = &rings[i];
1051                 name = current_ring->name;
1052
1053                 igt_fixture
1054                         gem_require_ring(fd, current_ring->exec);
1055
1056                 igt_subtest_f("reset-stats-%s", name)
1057                         test_rs(4, 1, 0);
1058
1059                 igt_subtest_f("reset-stats-ctx-%s", name)
1060                         RUN_CTX_TEST(test_rs_ctx(4, 4, 1, 2));
1061
1062                 igt_subtest_f("ban-%s", name)
1063                         test_ban();
1064
1065                 igt_subtest_f("ban-ctx-%s", name)
1066                         RUN_CTX_TEST(test_ban_ctx());
1067
1068                 igt_subtest_f("reset-count-%s", name)
1069                         test_reset_count(false);
1070
1071                 igt_subtest_f("reset-count-ctx-%s", name)
1072                         RUN_CTX_TEST(test_reset_count(true));
1073
1074                 igt_subtest_f("unrelated-ctx-%s", name)
1075                         RUN_CTX_TEST(test_unrelated_ctx());
1076
1077                 igt_subtest_f("close-pending-%s", name) {
1078                         test_close_pending();
1079                         gem_quiescent_gpu(fd);
1080                 }
1081
1082                 igt_subtest_f("close-pending-ctx-%s", name) {
1083                         RUN_CTX_TEST(test_close_pending_ctx());
1084                         gem_quiescent_gpu(fd);
1085                 }
1086
1087                 igt_subtest_f("close-pending-fork-%s", name) {
1088                         test_close_pending_fork(true);
1089                         test_close_pending_fork(false);
1090                 }
1091         }
1092
1093         igt_fixture
1094                 close(fd);
1095 }