blob: 01aebc670862dc5ea0b56cceee0947756ead5345 [file] [log] [blame]
Chris Wilson16bafdf2014-09-04 09:26:24 +01001/*
2 * Copyright © 2014 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
Chris Wilson310eaeb2017-06-05 11:55:57 +010024#include <limits.h>
Chris Wilson16bafdf2014-09-04 09:26:24 +010025#include <string.h>
Arkadiusz Hileracfed732017-06-07 12:14:04 +020026#include <strings.h>
Daniel Vetter3cd45de2015-02-10 17:46:43 +010027#include <signal.h>
Chris Wilson16bafdf2014-09-04 09:26:24 +010028#include <errno.h>
Daniel Vetter3cd45de2015-02-10 17:46:43 +010029#include <sys/types.h>
30#include <sys/stat.h>
Chris Wilsonc83299d2015-06-15 14:51:54 +010031#include <sys/ioctl.h>
Daniel Vetter3cd45de2015-02-10 17:46:43 +010032#include <fcntl.h>
Chris Wilson16bafdf2014-09-04 09:26:24 +010033
Daniel Vetter3cd45de2015-02-10 17:46:43 +010034#include "drmtest.h"
Chris Wilsona2eb6372015-12-11 21:24:21 +000035#include "igt_aux.h"
Chris Wilson16bafdf2014-09-04 09:26:24 +010036#include "igt_core.h"
37#include "igt_gt.h"
Chris Wilsone4424812016-10-13 11:04:40 +010038#include "igt_sysfs.h"
Chris Wilson16bafdf2014-09-04 09:26:24 +010039#include "igt_debugfs.h"
40#include "ioctl_wrappers.h"
41#include "intel_reg.h"
Daniel Vetterc66b2422015-02-06 10:49:20 +010042#include "intel_chipset.h"
Chris Wilson16bafdf2014-09-04 09:26:24 +010043
Daniel Vetter3cd45de2015-02-10 17:46:43 +010044/**
45 * SECTION:igt_gt
46 * @short_description: GT support library
Damien Lespiau6ebd8c22015-06-26 14:28:41 +010047 * @title: GT
Thomas Woodf0381d12015-09-07 09:26:01 +010048 * @include: igt.h
Daniel Vetter3cd45de2015-02-10 17:46:43 +010049 *
50 * This library provides various auxiliary helper functions to handle general
51 * interactions with the GT like forcewake handling, injecting hangs or stopping
52 * engines.
53 */
54
Chris Wilsonc83299d2015-06-15 14:51:54 +010055static bool has_gpu_reset(int fd)
56{
Chris Wilsona2eb6372015-12-11 21:24:21 +000057 static int once = -1;
58 if (once < 0) {
59 struct drm_i915_getparam gp;
60 int val = 0;
Chris Wilsonc83299d2015-06-15 14:51:54 +010061
Chris Wilsona2eb6372015-12-11 21:24:21 +000062 memset(&gp, 0, sizeof(gp));
63 gp.param = 35; /* HAS_GPU_RESET */
64 gp.value = &val;
Chris Wilsonc83299d2015-06-15 14:51:54 +010065
Chris Wilsona2eb6372015-12-11 21:24:21 +000066 if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
67 once = intel_gen(intel_get_drm_devid(fd)) >= 5;
68 else
69 once = val > 0;
70 }
71 return once;
Chris Wilsonc83299d2015-06-15 14:51:54 +010072}
Daniel Vetter3cd45de2015-02-10 17:46:43 +010073
Chris Wilsone4424812016-10-13 11:04:40 +010074static void eat_error_state(int dev)
Chris Wilson0a1fc452016-09-13 11:13:14 +010075{
Chris Wilsone4424812016-10-13 11:04:40 +010076 int dir;
Chris Wilson0a1fc452016-09-13 11:13:14 +010077
Chris Wilsone4424812016-10-13 11:04:40 +010078 dir = igt_sysfs_open(dev, NULL);
79 if (dir < 0)
80 return;
81
82 /* Any write to the error state clears it */
83 igt_sysfs_set(dir, "error", "");
84 close(dir);
Chris Wilson0a1fc452016-09-13 11:13:14 +010085}
86
Daniel Vetter3cd45de2015-02-10 17:46:43 +010087/**
88 * igt_require_hang_ring:
89 * @fd: open i915 drm file descriptor
90 * @ring: execbuf ring flag
91 *
92 * Convenience helper to check whether advanced hang injection is supported by
93 * the kernel. Uses igt_skip to automatically skip the test/subtest if this
94 * isn't the case.
Chris Wilsona2eb6372015-12-11 21:24:21 +000095 *
96 * Note that we can't simply just call this from igt_hang_ring since some
97 * tests want to exercise gpu wedging behavior. For which we intentionally
98 * disable gpu reset support, but still want to inject a hang, see for example
99 * tests/gem_eio.c Instead, we expect that the first invocation of
100 * igt_require_hand_ring be from a vanilla context and use the has_gpu_reset()
101 * determined then for all later instances. This allows us the convenience
102 * of double checking when injecting hangs, whilst pushing the complexity
103 * to the tests that are deliberating trying to break the box.
104 *
105 * This function is also controlled by the environment variables:
106 *
107 * IGT_HANG (boolean) - if false, skip all tests that try to inject a hang.
108 * Default: true
109 *
110 * IGT_HANG_WITHOUT_RESET (boolean) - if true, allow the hang even if the
111 * kernel does not support GPU recovery. The machine will be wedged afterwards
112 * (and so require a reboot between testing), but it does allow limited testing
113 * to be done under hang injection.
114 * Default: false
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100115 */
Daniel Vetterc66b2422015-02-06 10:49:20 +0100116void igt_require_hang_ring(int fd, int ring)
Chris Wilson16bafdf2014-09-04 09:26:24 +0100117{
Chris Wilsona2eb6372015-12-11 21:24:21 +0000118 if (!igt_check_boolean_env_var("IGT_HANG", true))
119 igt_skip("hang injection disabled by user");
120
121 gem_require_ring(fd, ring);
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200122 gem_context_require_bannable(fd);
Chris Wilsona2eb6372015-12-11 21:24:21 +0000123 if (!igt_check_boolean_env_var("IGT_HANG_WITHOUT_RESET", false))
124 igt_require(has_gpu_reset(fd));
Chris Wilson16bafdf2014-09-04 09:26:24 +0100125}
126
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200127static unsigned context_get_ban(int fd, unsigned ctx)
128{
Chris Wilson4ead0252018-03-07 09:39:06 +0000129 struct drm_i915_gem_context_param param = {
130 .ctx_id = ctx,
131 .param = I915_CONTEXT_PARAM_BANNABLE,
132 };
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200133
134 if (__gem_context_get_param(fd, &param) == -EINVAL) {
135 igt_assert(param.value == 0);
Eric Anholtaa97faa2017-11-10 12:49:14 -0800136 param.param = I915_CONTEXT_PARAM_BAN_PERIOD;
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200137 gem_context_get_param(fd, &param);
138 }
139
140 return param.value;
141}
142
143static void context_set_ban(int fd, unsigned ctx, unsigned ban)
144{
Chris Wilson4ead0252018-03-07 09:39:06 +0000145 struct drm_i915_gem_context_param param = {
146 .ctx_id = ctx,
147 .param = I915_CONTEXT_PARAM_BANNABLE,
148 .value = ban,
149 };
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200150
151 if(__gem_context_set_param(fd, &param) == -EINVAL) {
152 igt_assert(param.value == ban);
Eric Anholtaa97faa2017-11-10 12:49:14 -0800153 param.param = I915_CONTEXT_PARAM_BAN_PERIOD;
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200154 gem_context_set_param(fd, &param);
155 }
156}
157
Chris Wilson0a1fc452016-09-13 11:13:14 +0100158igt_hang_t igt_allow_hang(int fd, unsigned ctx, unsigned flags)
159{
Chris Wilson4ead0252018-03-07 09:39:06 +0000160 struct drm_i915_gem_context_param param = {
161 .ctx_id = ctx,
162 };
Chris Wilson0a1fc452016-09-13 11:13:14 +0100163 unsigned ban;
164
Chris Wilson310eaeb2017-06-05 11:55:57 +0100165 igt_assert(igt_sysfs_set_parameter
166 (fd, "reset", "%d", INT_MAX /* any reset method */));
167
Chris Wilson0a1fc452016-09-13 11:13:14 +0100168 if (!igt_check_boolean_env_var("IGT_HANG", true))
169 igt_skip("hang injection disabled by user");
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200170 gem_context_require_bannable(fd);
Chris Wilson0a1fc452016-09-13 11:13:14 +0100171 if (!igt_check_boolean_env_var("IGT_HANG_WITHOUT_RESET", false))
172 igt_require(has_gpu_reset(fd));
173
Chris Wilson0a1fc452016-09-13 11:13:14 +0100174 if ((flags & HANG_ALLOW_CAPTURE) == 0) {
Eric Anholtaa97faa2017-11-10 12:49:14 -0800175 param.param = I915_CONTEXT_PARAM_NO_ERROR_CAPTURE;
Chris Wilson0a1fc452016-09-13 11:13:14 +0100176 param.value = 1;
177 /* Older kernels may not have NO_ERROR_CAPTURE, in which case
178 * we just eat the error state in post-hang (and hope we eat
179 * the right one).
180 */
181 __gem_context_set_param(fd, &param);
182 }
183
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200184 ban = context_get_ban(fd, ctx);
185 if ((flags & HANG_ALLOW_BAN) == 0)
186 context_set_ban(fd, ctx, 0);
Chris Wilson0a1fc452016-09-13 11:13:14 +0100187
188 return (struct igt_hang){ 0, ctx, ban, flags };
189}
190
191void igt_disallow_hang(int fd, igt_hang_t arg)
192{
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200193 context_set_ban(fd, arg.ctx, arg.ban);
Chris Wilson0a1fc452016-09-13 11:13:14 +0100194
195 if ((arg.flags & HANG_ALLOW_CAPTURE) == 0) {
Eric Anholtaa97faa2017-11-10 12:49:14 -0800196 struct drm_i915_gem_context_param param = {
197 .ctx_id = arg.ctx,
198 .param = I915_CONTEXT_PARAM_NO_ERROR_CAPTURE,
Chris Wilsone2598d42017-10-20 15:16:39 +0100199 .value = 0,
200 };
201 __gem_context_set_param(fd, &param);
202
203 eat_error_state(fd);
Chris Wilson0a1fc452016-09-13 11:13:14 +0100204 }
205}
206
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100207/**
Vinay Belgaumkar7bf3bd72017-10-13 10:22:20 -0700208 * has_ctx_exec:
209 * @fd: open i915 drm file descriptor
210 * @ring: execbuf ring flag
211 * @ctx: Context to be checked
212 *
213 * This helper function checks if non default context submission is allowed
214 * on a ring.
215 *
216 * Returns:
217 * True if allowed
218 *
219 */
220static bool has_ctx_exec(int fd, unsigned ring, uint32_t ctx)
221{
222 struct drm_i915_gem_execbuffer2 execbuf;
223 struct drm_i915_gem_exec_object2 exec;
224
225 /* silly ABI, the kernel thinks everyone who has BSD also has BSD2 */
226 if ((ring & ~(3<<13)) == I915_EXEC_BSD) {
227 if (ring & (3 << 13) && !gem_has_bsd2(fd))
228 return false;
229 }
230
231 memset(&exec, 0, sizeof(exec));
232 memset(&execbuf, 0, sizeof(execbuf));
233 execbuf.buffers_ptr = to_user_pointer(&exec);
234 execbuf.buffer_count = 1;
235 execbuf.flags = ring;
236 execbuf.rsvd1 = ctx;
237 /*
238 * If context submission is not allowed, this will return EINVAL
239 * Otherwise, this will return ENOENT on account of no gem obj
240 * being submitted
241 */
242 return __gem_execbuf(fd, &execbuf) == -ENOENT;
243}
244
245/**
Chris Wilson19642c62015-12-11 13:27:49 +0000246 * igt_hang_ring_ctx:
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100247 * @fd: open i915 drm file descriptor
Chris Wilson19642c62015-12-11 13:27:49 +0000248 * @ctx: the contxt specifier
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100249 * @ring: execbuf ring flag
Chris Wilson19642c62015-12-11 13:27:49 +0000250 * @flags: set of flags to control execution
Vinay Belgaumkar7bf3bd72017-10-13 10:22:20 -0700251 * @offset: The resultant gtt offset of the exec obj
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100252 *
Chris Wilson19642c62015-12-11 13:27:49 +0000253 * This helper function injects a hanging batch associated with @ctx into @ring.
Chris Wilson0a1fc452016-09-13 11:13:14 +0100254 * It returns a #igt_hang_t structure which must be passed to
Chris Wilson19642c62015-12-11 13:27:49 +0000255 * igt_post_hang_ring() for hang post-processing (after the gpu hang
256 * interaction has been tested.
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100257 *
258 * Returns:
259 * Structure with helper internal state for igt_post_hang_ring().
260 */
Chris Wilson0a1fc452016-09-13 11:13:14 +0100261igt_hang_t igt_hang_ctx(int fd,
262 uint32_t ctx,
263 int ring,
264 unsigned flags,
265 uint64_t *offset)
Chris Wilson16bafdf2014-09-04 09:26:24 +0100266{
267 struct drm_i915_gem_relocation_entry reloc;
268 struct drm_i915_gem_execbuffer2 execbuf;
269 struct drm_i915_gem_exec_object2 exec;
Eric Anholtaa97faa2017-11-10 12:49:14 -0800270 struct drm_i915_gem_context_param param;
Chris Wilson415398a2016-05-20 22:06:09 +0100271 uint32_t b[16];
Chris Wilson16bafdf2014-09-04 09:26:24 +0100272 unsigned ban;
273 unsigned len;
Chris Wilson8c408f92018-03-02 16:08:32 +0000274 int gen;
Chris Wilson16bafdf2014-09-04 09:26:24 +0100275
Chris Wilsona2eb6372015-12-11 21:24:21 +0000276 igt_require_hang_ring(fd, ring);
277
Vinay Belgaumkar7bf3bd72017-10-13 10:22:20 -0700278 /* check if non-default ctx submission is allowed */
279 igt_require(ctx == 0 || has_ctx_exec(fd, ring, ctx));
Chris Wilson19642c62015-12-11 13:27:49 +0000280
Eric Anholtaa97faa2017-11-10 12:49:14 -0800281 param.ctx_id = ctx;
Chris Wilson16bafdf2014-09-04 09:26:24 +0100282 param.size = 0;
Chris Wilson19642c62015-12-11 13:27:49 +0000283
284 if ((flags & HANG_ALLOW_CAPTURE) == 0) {
Eric Anholtaa97faa2017-11-10 12:49:14 -0800285 param.param = I915_CONTEXT_PARAM_NO_ERROR_CAPTURE;
Chris Wilson19642c62015-12-11 13:27:49 +0000286 param.value = 1;
287 /* Older kernels may not have NO_ERROR_CAPTURE, in which case
288 * we just eat the error state in post-hang (and hope we eat
289 * the right one).
290 */
291 __gem_context_set_param(fd, &param);
Chris Wilson19642c62015-12-11 13:27:49 +0000292 }
293
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200294 ban = context_get_ban(fd, ctx);
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200295 if ((flags & HANG_ALLOW_BAN) == 0)
296 context_set_ban(fd, ctx, 0);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100297
298 memset(&reloc, 0, sizeof(reloc));
299 memset(&exec, 0, sizeof(exec));
300 memset(&execbuf, 0, sizeof(execbuf));
301
302 exec.handle = gem_create(fd, 4096);
303 exec.relocation_count = 1;
Chris Wilson39858a12017-01-02 11:05:21 +0000304 exec.relocs_ptr = to_user_pointer(&reloc);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100305
Chris Wilson19642c62015-12-11 13:27:49 +0000306 memset(b, 0xc5, sizeof(b));
Mika Kuoppalab5ef40e2016-06-08 15:50:50 +0300307
Chris Wilson8c408f92018-03-02 16:08:32 +0000308 len = 0;
309 gen = intel_gen(intel_get_drm_devid(fd));
310 if (gen >= 8) {
311 b[len++] = MI_BATCH_BUFFER_START | 1 << 8 | 1;
312 b[len++] = 0;
313 b[len++] = 0;
314 } else if (gen >= 6) {
315 b[len++] = MI_BATCH_BUFFER_START | 1 << 8;
316 b[len++] = 0;
317 } else {
318 b[len++] = MI_BATCH_BUFFER_START | 2 << 6;
319 b[len] = 0;
320 if (gen < 4) {
321 b[len] |= 1;
322 reloc.delta = 1;
323 }
Chris Wilson16bafdf2014-09-04 09:26:24 +0100324 len++;
Chris Wilson8c408f92018-03-02 16:08:32 +0000325 }
326 b[len++] = MI_BATCH_BUFFER_END;
327 b[len] = MI_NOOP;
Chris Wilson16bafdf2014-09-04 09:26:24 +0100328 gem_write(fd, exec.handle, 0, b, sizeof(b));
329
Chris Wilson27ff12f2017-08-07 13:36:36 +0100330 reloc.offset = sizeof(uint32_t);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100331 reloc.target_handle = exec.handle;
332 reloc.read_domains = I915_GEM_DOMAIN_COMMAND;
333
Chris Wilson39858a12017-01-02 11:05:21 +0000334 execbuf.buffers_ptr = to_user_pointer(&exec);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100335 execbuf.buffer_count = 1;
Chris Wilson16bafdf2014-09-04 09:26:24 +0100336 execbuf.flags = ring;
Chris Wilson19642c62015-12-11 13:27:49 +0000337 i915_execbuffer2_set_context_id(execbuf, ctx);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100338 gem_execbuf(fd, &execbuf);
339
Chris Wilson19642c62015-12-11 13:27:49 +0000340 if (offset)
341 *offset = exec.offset;
342
Chris Wilson0a1fc452016-09-13 11:13:14 +0100343 return (igt_hang_t){ exec.handle, ctx, ban, flags };
Chris Wilson19642c62015-12-11 13:27:49 +0000344}
345
346/**
347 * igt_hang_ring:
348 * @fd: open i915 drm file descriptor
349 * @ring: execbuf ring flag
350 *
351 * This helper function injects a hanging batch into @ring. It returns a
Chris Wilson0a1fc452016-09-13 11:13:14 +0100352 * #igt_hang_t structure which must be passed to igt_post_hang_ring() for
Chris Wilson19642c62015-12-11 13:27:49 +0000353 * hang post-processing (after the gpu hang interaction has been tested.
354 *
355 * Returns:
356 * Structure with helper internal state for igt_post_hang_ring().
357 */
Chris Wilson0a1fc452016-09-13 11:13:14 +0100358igt_hang_t igt_hang_ring(int fd, int ring)
Chris Wilson19642c62015-12-11 13:27:49 +0000359{
360 return igt_hang_ctx(fd, 0, ring, 0, NULL);
361}
362
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100363/**
Thomas Wood26f40812015-02-20 11:31:01 +0000364 * igt_post_hang_ring:
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100365 * @fd: open i915 drm file descriptor
366 * @arg: hang state from igt_hang_ring()
367 *
368 * This function does the necessary post-processing after a gpu hang injected
369 * with igt_hang_ring().
370 */
Chris Wilson0a1fc452016-09-13 11:13:14 +0100371void igt_post_hang_ring(int fd, igt_hang_t arg)
Chris Wilson16bafdf2014-09-04 09:26:24 +0100372{
Chris Wilson16bafdf2014-09-04 09:26:24 +0100373 if (arg.handle == 0)
374 return;
375
Chris Wilson8c408f92018-03-02 16:08:32 +0000376 gem_sync(fd, arg.handle);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100377 gem_close(fd, arg.handle);
378
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200379 context_set_ban(fd, arg.ctx, arg.ban);
Chris Wilson19642c62015-12-11 13:27:49 +0000380
381 if ((arg.flags & HANG_ALLOW_CAPTURE) == 0) {
Eric Anholtaa97faa2017-11-10 12:49:14 -0800382 struct drm_i915_gem_context_param param = {
383 .ctx_id = arg.ctx,
384 .param = I915_CONTEXT_PARAM_NO_ERROR_CAPTURE,
Chris Wilsone2598d42017-10-20 15:16:39 +0100385 .value = 0,
386 };
387 __gem_context_set_param(fd, &param);
388
389 eat_error_state(fd);
Chris Wilson19642c62015-12-11 13:27:49 +0000390 }
Chris Wilson16bafdf2014-09-04 09:26:24 +0100391}
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100392
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000393/**
394 * igt_force_gpu_reset:
395 *
396 * forces a gpu reset using the i915_wedged debugfs interface. To be used to
397 * recover from situations where the hangcheck didn't trigger and/or the gpu is
398 * stuck, either because the test manually disabled gpu resets or because the
399 * test hit an hangcheck bug
400 */
Chris Wilson83884e92017-03-21 17:16:03 +0000401void igt_force_gpu_reset(int drm_fd)
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000402{
Chris Wilson58de7852017-03-24 18:11:08 +0000403 int dir, wedged;
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000404
405 igt_debug("Triggering GPU reset\n");
406
Chris Wilson58de7852017-03-24 18:11:08 +0000407 dir = igt_debugfs_dir(drm_fd);
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000408
Chris Wilson58de7852017-03-24 18:11:08 +0000409 igt_sysfs_set(dir, "i915_wedged", "-1");
410 igt_sysfs_scanf(dir, "i915_wedged", "%d", &wedged);
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000411
Chris Wilson58de7852017-03-24 18:11:08 +0000412 close(dir);
Chris Wilson9ba37172018-02-06 22:55:33 +0000413 errno = 0;
Chris Wilson28a2f142017-03-08 12:22:13 +0000414
415 igt_assert(!wedged);
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000416}
417
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100418/* GPU abusers */
419static struct igt_helper_process hang_helper;
420static void __attribute__((noreturn))
421hang_helper_process(pid_t pid, int fd)
422{
423 while (1) {
424 if (kill(pid, 0)) /* Parent has died, so must we. */
425 exit(0);
426
427 igt_post_hang_ring(fd,
428 igt_hang_ring(fd, I915_EXEC_DEFAULT));
429
430 sleep(1);
431 }
432}
433
434/**
435 * igt_fork_hang_helper:
436 *
437 * Fork a child process using #igt_fork_helper to hang the default engine
438 * of the GPU at regular intervals.
439 *
440 * This is useful to exercise slow running code (such as aperture placement)
441 * which needs to be robust against a GPU reset.
442 *
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100443 * This function automatically skips when test requirements aren't met using
444 * igt_skip().
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100445 */
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100446void igt_fork_hang_helper(void)
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100447{
448 int fd, gen;
449
Micah Fedkec81d2932015-07-22 21:54:02 +0000450 fd = drm_open_driver(DRIVER_INTEL);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100451
452 gen = intel_gen(intel_get_drm_devid(fd));
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100453 igt_skip_on(gen < 5);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100454
455 igt_fork_helper(&hang_helper)
456 hang_helper_process(getppid(), fd);
457
458 close(fd);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100459}
460
461/**
462 * igt_stop_hang_helper:
463 *
464 * Stops the child process spawned with igt_fork_hang_helper().
465 *
466 * In tests with subtests this function can be called outside of failure
467 * catching code blocks like #igt_fixture or #igt_subtest.
468 */
469void igt_stop_hang_helper(void)
470{
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100471 if (hang_helper.running)
472 igt_stop_helper(&hang_helper);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100473}
474
475/**
476 * igt_open_forcewake_handle:
477 *
478 * This functions opens the debugfs forcewake file and so prevents the GT from
479 * suspending. The reference is automatically dropped when the is closed.
480 *
481 * Returns:
482 * The file descriptor of the forcewake handle or -1 if that didn't work out.
483 */
Chris Wilson83884e92017-03-21 17:16:03 +0000484int igt_open_forcewake_handle(int fd)
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100485{
486 if (getenv("IGT_NO_FORCEWAKE"))
487 return -1;
Chris Wilson83884e92017-03-21 17:16:03 +0000488 return igt_debugfs_open(fd, "i915_forcewake_user", O_WRONLY);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100489}
Chris Wilsona6090c72016-01-08 16:32:29 +0000490
Chris Wilson7d089132016-05-01 16:39:14 +0100491#if defined(__x86_64__) || defined(__i386__)
Robert Foss8875bb12016-06-27 06:58:24 -0400492static unsigned int clflush_size;
493
Chris Wilsona6090c72016-01-08 16:32:29 +0000494int igt_setup_clflush(void)
495{
496 FILE *file;
497 char *line = NULL;
498 size_t size = 0;
499 int first_stanza = 1;
500 int has_clflush = 0;
501
502 if (clflush_size)
503 return 1;
504
505 file = fopen("/proc/cpuinfo", "r");
506 if (file == NULL)
507 return 0;
508
509 while (getline(&line, &size, file) != -1) {
510 if (strncmp(line, "processor", 9) == 0) {
511 if (!first_stanza)
512 break;
513 first_stanza = 0;
514 }
515
516 if (strncmp(line, "flags", 5) == 0) {
517 if (strstr(line, "clflush"))
518 has_clflush = 1;
519 }
520
521 if (strncmp(line, "clflush size", 12) == 0) {
522 char *colon = strchr(line, ':');
523 if (colon)
524 clflush_size = atoi(colon + 1);
525 }
526 }
527 free(line);
528 fclose(file);
529
530 return has_clflush && clflush_size;
531}
532
Chris Wilson7d089132016-05-01 16:39:14 +0100533__attribute__((target("sse2")))
Chris Wilsona6090c72016-01-08 16:32:29 +0000534void igt_clflush_range(void *addr, int size)
535{
536 char *p, *end;
537
538 end = (char *)addr + size;
539 p = (char *)((uintptr_t)addr & ~((uintptr_t)clflush_size - 1));
540
Chris Wilson7499b912016-03-03 11:51:18 +0000541 __builtin_ia32_mfence();
Chris Wilsona6090c72016-01-08 16:32:29 +0000542 for (; p < end; p += clflush_size)
Chris Wilson7499b912016-03-03 11:51:18 +0000543 __builtin_ia32_clflush(p);
Chris Wilsonb4817052016-05-01 09:07:29 +0100544 __builtin_ia32_clflush(end - 1); /* magic serialisation for byt+ */
Chris Wilson7499b912016-03-03 11:51:18 +0000545 __builtin_ia32_mfence();
Chris Wilsona6090c72016-01-08 16:32:29 +0000546}
Chris Wilson7d089132016-05-01 16:39:14 +0100547#else
548int igt_setup_clflush(void)
549{
550 /* requires mfence + clflush, both SSE2 instructions */
551 return 0;
552}
553
554void igt_clflush_range(void *addr, int size)
555{
556 fprintf(stderr, "igt_clflush_range() unsupported\n");
557}
558#endif
Chris Wilson5b675f72016-01-22 17:33:40 +0000559
560/**
561 * intel_detect_and_clear_missed_irq:
562 * @fd: open i915 drm file descriptor, used to quiesce the gpu
563 *
564 * This functions idles the GPU and then queries whether there has
565 * been a missed interrupt reported by the driver. Afterwards it
566 * clears the missed interrupt flag, in order to disable the timer
567 * fallback for the next test.
568 */
569unsigned intel_detect_and_clear_missed_interrupts(int fd)
570{
Chris Wilson58de7852017-03-24 18:11:08 +0000571 unsigned missed;
572 int dir;
Chris Wilson5b675f72016-01-22 17:33:40 +0000573
574 gem_quiescent_gpu(fd);
575
Chris Wilson58de7852017-03-24 18:11:08 +0000576 dir = igt_debugfs_dir(fd);
577
578 missed = 0;
579 igt_assert(igt_sysfs_scanf(dir, "i915_ring_missed_irq", "%x", &missed) == 1);
580 if (missed)
581 igt_sysfs_set(dir, "i915_ring_missed_irq", "0");
582
583 close(dir);
Chris Wilson5b675f72016-01-22 17:33:40 +0000584
Chris Wilsonf22e19b2017-03-23 10:51:28 +0000585 errno = 0;
Chris Wilson5b675f72016-01-22 17:33:40 +0000586 return missed;
587}
Chris Wilson04f52152016-01-27 14:07:27 +0000588
589const struct intel_execution_engine intel_execution_engines[] = {
Chris Wilsonec91c562017-07-06 14:01:56 +0100590 { "default", NULL, 0, 0 },
Chris Wilson82fdfc62017-04-11 20:20:28 +0100591 { "render", "rcs0", I915_EXEC_RENDER, 0 },
592 { "bsd", "vcs0", I915_EXEC_BSD, 0 },
593 { "bsd1", "vcs0", I915_EXEC_BSD, 1<<13 /*I915_EXEC_BSD_RING1*/ },
594 { "bsd2", "vcs1", I915_EXEC_BSD, 2<<13 /*I915_EXEC_BSD_RING2*/ },
595 { "blt", "bcs0", I915_EXEC_BLT, 0 },
596 { "vebox", "vecs0", I915_EXEC_VEBOX, 0 },
Chris Wilson04f52152016-01-27 14:07:27 +0000597 { NULL, 0, 0 }
598};
Chris Wilsonbc787762017-05-18 12:11:59 +0100599
600bool gem_can_store_dword(int fd, unsigned int engine)
601{
602 uint16_t devid = intel_get_drm_devid(fd);
603 const struct intel_device_info *info = intel_get_device_info(devid);
604 const int gen = ffs(info->gen);
605
606 if (gen <= 2) /* requires physical addresses */
607 return false;
608
Chris Wilsondddbc2e2017-09-06 15:34:13 +0100609 if (gen == 3 && (info->is_grantsdale || info->is_alviso))
610 return false; /* only supports physical addresses */
611
Chris Wilsonbc787762017-05-18 12:11:59 +0100612 if (gen == 6 && (engine & ~(3<<13)) == I915_EXEC_BSD)
613 return false; /* kills the machine! */
614
615 if (info->is_broadwater)
616 return false; /* Not sure yet... */
617
618 return true;
619}
Tvrtko Ursulin20d89b42017-09-18 09:06:19 +0100620
621const struct intel_execution_engine2 intel_execution_engines2[] = {
622 { "rcs0", I915_ENGINE_CLASS_RENDER, 0 },
623 { "bcs0", I915_ENGINE_CLASS_COPY, 0 },
624 { "vcs0", I915_ENGINE_CLASS_VIDEO, 0 },
625 { "vcs1", I915_ENGINE_CLASS_VIDEO, 1 },
626 { "vecs0", I915_ENGINE_CLASS_VIDEO_ENHANCE, 0 },
Petri Latvala261ab6b2017-12-05 12:16:30 +0200627 { }
Tvrtko Ursulin20d89b42017-09-18 09:06:19 +0100628};
629
630unsigned int
631gem_class_instance_to_eb_flags(int gem_fd,
632 enum drm_i915_gem_engine_class class,
633 unsigned int instance)
634{
635 if (class != I915_ENGINE_CLASS_VIDEO)
636 igt_assert(instance == 0);
637 else
638 igt_assert(instance >= 0 && instance <= 1);
639
640 switch (class) {
641 case I915_ENGINE_CLASS_RENDER:
642 return I915_EXEC_RENDER;
643 case I915_ENGINE_CLASS_COPY:
644 return I915_EXEC_BLT;
645 case I915_ENGINE_CLASS_VIDEO:
646 if (instance == 0) {
647 if (gem_has_bsd2(gem_fd))
648 return I915_EXEC_BSD | I915_EXEC_BSD_RING1;
649 else
650 return I915_EXEC_BSD;
651
652 } else {
653 return I915_EXEC_BSD | I915_EXEC_BSD_RING2;
654 }
655 case I915_ENGINE_CLASS_VIDEO_ENHANCE:
656 return I915_EXEC_VEBOX;
657 case I915_ENGINE_CLASS_INVALID:
658 default:
659 igt_assert(0);
660 };
661}
662
663bool gem_has_engine(int gem_fd,
664 enum drm_i915_gem_engine_class class,
665 unsigned int instance)
666{
667 return gem_has_ring(gem_fd,
668 gem_class_instance_to_eb_flags(gem_fd, class,
669 instance));
670}
Chris Wilson305ebce2018-02-21 14:13:16 +0000671
672bool gem_ring_is_physical_engine(int fd, unsigned ring)
673{
674 if (ring == I915_EXEC_DEFAULT)
675 return false;
676
677 /* BSD uses an extra flag to chose between aliasing modes */
678 if ((ring & 63) == I915_EXEC_BSD) {
679 bool explicit_bsd = ring & (3 << 13);
680 bool has_bsd2 = gem_has_bsd2(fd);
681 return explicit_bsd ? has_bsd2 : !has_bsd2;
682 }
683
684 return true;
685}
686
687bool gem_ring_has_physical_engine(int fd, unsigned ring)
688{
689 if (!gem_ring_is_physical_engine(fd, ring))
690 return false;
691
692 return gem_has_ring(fd, ring);
693}