blob: f6cc20b05dfcb1d1971f4f95b4664086c29ca7e6 [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{
129 struct local_i915_gem_context_param param;
130
131 param.param = LOCAL_CONTEXT_PARAM_BANNABLE;
132 param.value = 0;
133 param.size = 0;
134
135 if (__gem_context_get_param(fd, &param) == -EINVAL) {
136 igt_assert(param.value == 0);
137 param.param = LOCAL_CONTEXT_PARAM_BAN_PERIOD;
138 gem_context_get_param(fd, &param);
139 }
140
141 return param.value;
142}
143
144static void context_set_ban(int fd, unsigned ctx, unsigned ban)
145{
146 struct local_i915_gem_context_param param;
147
Chris Wilsoncc8c9602017-02-04 19:29:57 +0000148 memset(&param, 0, sizeof(param));
149 param.context = ctx;
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200150 param.value = ban;
151 param.size = 0;
152 param.param = LOCAL_CONTEXT_PARAM_BANNABLE;
153
154 if(__gem_context_set_param(fd, &param) == -EINVAL) {
155 igt_assert(param.value == ban);
156 param.param = LOCAL_CONTEXT_PARAM_BAN_PERIOD;
157 gem_context_set_param(fd, &param);
158 }
159}
160
Chris Wilson0a1fc452016-09-13 11:13:14 +0100161igt_hang_t igt_allow_hang(int fd, unsigned ctx, unsigned flags)
162{
163 struct local_i915_gem_context_param param;
164 unsigned ban;
165
Chris Wilson310eaeb2017-06-05 11:55:57 +0100166 igt_assert(igt_sysfs_set_parameter
167 (fd, "reset", "%d", INT_MAX /* any reset method */));
168
Chris Wilson0a1fc452016-09-13 11:13:14 +0100169 if (!igt_check_boolean_env_var("IGT_HANG", true))
170 igt_skip("hang injection disabled by user");
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200171 gem_context_require_bannable(fd);
Chris Wilson0a1fc452016-09-13 11:13:14 +0100172 if (!igt_check_boolean_env_var("IGT_HANG_WITHOUT_RESET", false))
173 igt_require(has_gpu_reset(fd));
174
175 param.context = ctx;
176 param.size = 0;
177
178 if ((flags & HANG_ALLOW_CAPTURE) == 0) {
179 param.param = LOCAL_CONTEXT_PARAM_NO_ERROR_CAPTURE;
180 param.value = 1;
181 /* Older kernels may not have NO_ERROR_CAPTURE, in which case
182 * we just eat the error state in post-hang (and hope we eat
183 * the right one).
184 */
185 __gem_context_set_param(fd, &param);
186 }
187
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200188 ban = context_get_ban(fd, ctx);
189 if ((flags & HANG_ALLOW_BAN) == 0)
190 context_set_ban(fd, ctx, 0);
Chris Wilson0a1fc452016-09-13 11:13:14 +0100191
192 return (struct igt_hang){ 0, ctx, ban, flags };
193}
194
195void igt_disallow_hang(int fd, igt_hang_t arg)
196{
197 struct local_i915_gem_context_param param;
198
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200199 context_set_ban(fd, arg.ctx, arg.ban);
Chris Wilson0a1fc452016-09-13 11:13:14 +0100200
201 if ((arg.flags & HANG_ALLOW_CAPTURE) == 0) {
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200202 param.context = arg.ctx;
203 param.size = 0;
Chris Wilson0a1fc452016-09-13 11:13:14 +0100204 param.param = LOCAL_CONTEXT_PARAM_NO_ERROR_CAPTURE;
205 param.value = 0;
206 if (__gem_context_set_param(fd, &param))
Chris Wilsone4424812016-10-13 11:04:40 +0100207 eat_error_state(fd);
Chris Wilson0a1fc452016-09-13 11:13:14 +0100208 }
209}
210
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100211/**
Vinay Belgaumkar7bf3bd72017-10-13 10:22:20 -0700212 * has_ctx_exec:
213 * @fd: open i915 drm file descriptor
214 * @ring: execbuf ring flag
215 * @ctx: Context to be checked
216 *
217 * This helper function checks if non default context submission is allowed
218 * on a ring.
219 *
220 * Returns:
221 * True if allowed
222 *
223 */
224static bool has_ctx_exec(int fd, unsigned ring, uint32_t ctx)
225{
226 struct drm_i915_gem_execbuffer2 execbuf;
227 struct drm_i915_gem_exec_object2 exec;
228
229 /* silly ABI, the kernel thinks everyone who has BSD also has BSD2 */
230 if ((ring & ~(3<<13)) == I915_EXEC_BSD) {
231 if (ring & (3 << 13) && !gem_has_bsd2(fd))
232 return false;
233 }
234
235 memset(&exec, 0, sizeof(exec));
236 memset(&execbuf, 0, sizeof(execbuf));
237 execbuf.buffers_ptr = to_user_pointer(&exec);
238 execbuf.buffer_count = 1;
239 execbuf.flags = ring;
240 execbuf.rsvd1 = ctx;
241 /*
242 * If context submission is not allowed, this will return EINVAL
243 * Otherwise, this will return ENOENT on account of no gem obj
244 * being submitted
245 */
246 return __gem_execbuf(fd, &execbuf) == -ENOENT;
247}
248
249/**
Chris Wilson19642c62015-12-11 13:27:49 +0000250 * igt_hang_ring_ctx:
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100251 * @fd: open i915 drm file descriptor
Chris Wilson19642c62015-12-11 13:27:49 +0000252 * @ctx: the contxt specifier
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100253 * @ring: execbuf ring flag
Chris Wilson19642c62015-12-11 13:27:49 +0000254 * @flags: set of flags to control execution
Vinay Belgaumkar7bf3bd72017-10-13 10:22:20 -0700255 * @offset: The resultant gtt offset of the exec obj
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100256 *
Chris Wilson19642c62015-12-11 13:27:49 +0000257 * This helper function injects a hanging batch associated with @ctx into @ring.
Chris Wilson0a1fc452016-09-13 11:13:14 +0100258 * It returns a #igt_hang_t structure which must be passed to
Chris Wilson19642c62015-12-11 13:27:49 +0000259 * igt_post_hang_ring() for hang post-processing (after the gpu hang
260 * interaction has been tested.
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100261 *
262 * Returns:
263 * Structure with helper internal state for igt_post_hang_ring().
264 */
Chris Wilson0a1fc452016-09-13 11:13:14 +0100265igt_hang_t igt_hang_ctx(int fd,
266 uint32_t ctx,
267 int ring,
268 unsigned flags,
269 uint64_t *offset)
Chris Wilson16bafdf2014-09-04 09:26:24 +0100270{
271 struct drm_i915_gem_relocation_entry reloc;
272 struct drm_i915_gem_execbuffer2 execbuf;
273 struct drm_i915_gem_exec_object2 exec;
274 struct local_i915_gem_context_param param;
Chris Wilson415398a2016-05-20 22:06:09 +0100275 uint32_t b[16];
Chris Wilson16bafdf2014-09-04 09:26:24 +0100276 unsigned ban;
277 unsigned len;
278
Chris Wilsona2eb6372015-12-11 21:24:21 +0000279 igt_require_hang_ring(fd, ring);
280
Vinay Belgaumkar7bf3bd72017-10-13 10:22:20 -0700281 /* check if non-default ctx submission is allowed */
282 igt_require(ctx == 0 || has_ctx_exec(fd, ring, ctx));
Chris Wilson19642c62015-12-11 13:27:49 +0000283
284 param.context = ctx;
Chris Wilson16bafdf2014-09-04 09:26:24 +0100285 param.size = 0;
Chris Wilson19642c62015-12-11 13:27:49 +0000286
287 if ((flags & HANG_ALLOW_CAPTURE) == 0) {
Chris Wilson19642c62015-12-11 13:27:49 +0000288 param.param = LOCAL_CONTEXT_PARAM_NO_ERROR_CAPTURE;
289 param.value = 1;
290 /* Older kernels may not have NO_ERROR_CAPTURE, in which case
291 * we just eat the error state in post-hang (and hope we eat
292 * the right one).
293 */
294 __gem_context_set_param(fd, &param);
Chris Wilson19642c62015-12-11 13:27:49 +0000295 }
296
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200297 ban = context_get_ban(fd, ctx);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100298
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200299 if ((flags & HANG_ALLOW_BAN) == 0)
300 context_set_ban(fd, ctx, 0);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100301
302 memset(&reloc, 0, sizeof(reloc));
303 memset(&exec, 0, sizeof(exec));
304 memset(&execbuf, 0, sizeof(execbuf));
305
306 exec.handle = gem_create(fd, 4096);
307 exec.relocation_count = 1;
Chris Wilson39858a12017-01-02 11:05:21 +0000308 exec.relocs_ptr = to_user_pointer(&reloc);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100309
Chris Wilson19642c62015-12-11 13:27:49 +0000310 memset(b, 0xc5, sizeof(b));
Mika Kuoppalab5ef40e2016-06-08 15:50:50 +0300311
Chris Wilson16bafdf2014-09-04 09:26:24 +0100312 len = 2;
Chris Wilson27ff12f2017-08-07 13:36:36 +0100313 if (intel_gen(intel_get_drm_devid(fd)) >= 8)
Chris Wilson16bafdf2014-09-04 09:26:24 +0100314 len++;
Chris Wilson27ff12f2017-08-07 13:36:36 +0100315 b[0] = MI_BATCH_BUFFER_START | (len - 2);
316 b[len] = MI_BATCH_BUFFER_END;
317 b[len+1] = MI_NOOP;
Chris Wilson16bafdf2014-09-04 09:26:24 +0100318 gem_write(fd, exec.handle, 0, b, sizeof(b));
319
Chris Wilson27ff12f2017-08-07 13:36:36 +0100320 reloc.offset = sizeof(uint32_t);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100321 reloc.target_handle = exec.handle;
322 reloc.read_domains = I915_GEM_DOMAIN_COMMAND;
323
Chris Wilson39858a12017-01-02 11:05:21 +0000324 execbuf.buffers_ptr = to_user_pointer(&exec);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100325 execbuf.buffer_count = 1;
Chris Wilson16bafdf2014-09-04 09:26:24 +0100326 execbuf.flags = ring;
Chris Wilson19642c62015-12-11 13:27:49 +0000327 i915_execbuffer2_set_context_id(execbuf, ctx);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100328 gem_execbuf(fd, &execbuf);
329
Chris Wilson19642c62015-12-11 13:27:49 +0000330 if (offset)
331 *offset = exec.offset;
332
Chris Wilson0a1fc452016-09-13 11:13:14 +0100333 return (igt_hang_t){ exec.handle, ctx, ban, flags };
Chris Wilson19642c62015-12-11 13:27:49 +0000334}
335
336/**
337 * igt_hang_ring:
338 * @fd: open i915 drm file descriptor
339 * @ring: execbuf ring flag
340 *
341 * This helper function injects a hanging batch into @ring. It returns a
Chris Wilson0a1fc452016-09-13 11:13:14 +0100342 * #igt_hang_t structure which must be passed to igt_post_hang_ring() for
Chris Wilson19642c62015-12-11 13:27:49 +0000343 * hang post-processing (after the gpu hang interaction has been tested.
344 *
345 * Returns:
346 * Structure with helper internal state for igt_post_hang_ring().
347 */
Chris Wilson0a1fc452016-09-13 11:13:14 +0100348igt_hang_t igt_hang_ring(int fd, int ring)
Chris Wilson19642c62015-12-11 13:27:49 +0000349{
350 return igt_hang_ctx(fd, 0, ring, 0, NULL);
351}
352
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100353/**
Thomas Wood26f40812015-02-20 11:31:01 +0000354 * igt_post_hang_ring:
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100355 * @fd: open i915 drm file descriptor
356 * @arg: hang state from igt_hang_ring()
357 *
358 * This function does the necessary post-processing after a gpu hang injected
359 * with igt_hang_ring().
360 */
Chris Wilson0a1fc452016-09-13 11:13:14 +0100361void igt_post_hang_ring(int fd, igt_hang_t arg)
Chris Wilson16bafdf2014-09-04 09:26:24 +0100362{
363 struct local_i915_gem_context_param param;
364
365 if (arg.handle == 0)
366 return;
367
368 gem_set_domain(fd, arg.handle,
369 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
370 gem_close(fd, arg.handle);
371
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200372 context_set_ban(fd, arg.ctx, arg.ban);
Chris Wilson19642c62015-12-11 13:27:49 +0000373
374 if ((arg.flags & HANG_ALLOW_CAPTURE) == 0) {
Mika Kuoppala773ac7c2016-11-08 12:31:06 +0200375 param.context = arg.ctx;
376 param.size = 0;
Chris Wilson19642c62015-12-11 13:27:49 +0000377 param.param = LOCAL_CONTEXT_PARAM_NO_ERROR_CAPTURE;
378 param.value = 0;
379 if (__gem_context_set_param(fd, &param))
Chris Wilsone4424812016-10-13 11:04:40 +0100380 eat_error_state(fd);
Chris Wilson19642c62015-12-11 13:27:49 +0000381 }
Chris Wilson16bafdf2014-09-04 09:26:24 +0100382}
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100383
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000384/**
385 * igt_force_gpu_reset:
386 *
387 * forces a gpu reset using the i915_wedged debugfs interface. To be used to
388 * recover from situations where the hangcheck didn't trigger and/or the gpu is
389 * stuck, either because the test manually disabled gpu resets or because the
390 * test hit an hangcheck bug
391 */
Chris Wilson83884e92017-03-21 17:16:03 +0000392void igt_force_gpu_reset(int drm_fd)
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000393{
Chris Wilson58de7852017-03-24 18:11:08 +0000394 int dir, wedged;
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000395
396 igt_debug("Triggering GPU reset\n");
397
Chris Wilson58de7852017-03-24 18:11:08 +0000398 dir = igt_debugfs_dir(drm_fd);
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000399
Chris Wilson58de7852017-03-24 18:11:08 +0000400 igt_sysfs_set(dir, "i915_wedged", "-1");
401 igt_sysfs_scanf(dir, "i915_wedged", "%d", &wedged);
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000402
Chris Wilson58de7852017-03-24 18:11:08 +0000403 close(dir);
Chris Wilson28a2f142017-03-08 12:22:13 +0000404
405 igt_assert(!wedged);
Daniele Ceraolo Spurio03c7f842016-03-01 11:01:32 +0000406}
407
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100408/* GPU abusers */
409static struct igt_helper_process hang_helper;
410static void __attribute__((noreturn))
411hang_helper_process(pid_t pid, int fd)
412{
413 while (1) {
414 if (kill(pid, 0)) /* Parent has died, so must we. */
415 exit(0);
416
417 igt_post_hang_ring(fd,
418 igt_hang_ring(fd, I915_EXEC_DEFAULT));
419
420 sleep(1);
421 }
422}
423
424/**
425 * igt_fork_hang_helper:
426 *
427 * Fork a child process using #igt_fork_helper to hang the default engine
428 * of the GPU at regular intervals.
429 *
430 * This is useful to exercise slow running code (such as aperture placement)
431 * which needs to be robust against a GPU reset.
432 *
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100433 * This function automatically skips when test requirements aren't met using
434 * igt_skip().
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100435 */
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100436void igt_fork_hang_helper(void)
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100437{
438 int fd, gen;
439
Micah Fedkec81d2932015-07-22 21:54:02 +0000440 fd = drm_open_driver(DRIVER_INTEL);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100441
442 gen = intel_gen(intel_get_drm_devid(fd));
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100443 igt_skip_on(gen < 5);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100444
445 igt_fork_helper(&hang_helper)
446 hang_helper_process(getppid(), fd);
447
448 close(fd);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100449}
450
451/**
452 * igt_stop_hang_helper:
453 *
454 * Stops the child process spawned with igt_fork_hang_helper().
455 *
456 * In tests with subtests this function can be called outside of failure
457 * catching code blocks like #igt_fixture or #igt_subtest.
458 */
459void igt_stop_hang_helper(void)
460{
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100461 if (hang_helper.running)
462 igt_stop_helper(&hang_helper);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100463}
464
465/**
466 * igt_open_forcewake_handle:
467 *
468 * This functions opens the debugfs forcewake file and so prevents the GT from
469 * suspending. The reference is automatically dropped when the is closed.
470 *
471 * Returns:
472 * The file descriptor of the forcewake handle or -1 if that didn't work out.
473 */
Chris Wilson83884e92017-03-21 17:16:03 +0000474int igt_open_forcewake_handle(int fd)
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100475{
476 if (getenv("IGT_NO_FORCEWAKE"))
477 return -1;
Chris Wilson83884e92017-03-21 17:16:03 +0000478 return igt_debugfs_open(fd, "i915_forcewake_user", O_WRONLY);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100479}
Chris Wilsona6090c72016-01-08 16:32:29 +0000480
Chris Wilson7d089132016-05-01 16:39:14 +0100481#if defined(__x86_64__) || defined(__i386__)
Robert Foss8875bb12016-06-27 06:58:24 -0400482static unsigned int clflush_size;
483
Chris Wilsona6090c72016-01-08 16:32:29 +0000484int igt_setup_clflush(void)
485{
486 FILE *file;
487 char *line = NULL;
488 size_t size = 0;
489 int first_stanza = 1;
490 int has_clflush = 0;
491
492 if (clflush_size)
493 return 1;
494
495 file = fopen("/proc/cpuinfo", "r");
496 if (file == NULL)
497 return 0;
498
499 while (getline(&line, &size, file) != -1) {
500 if (strncmp(line, "processor", 9) == 0) {
501 if (!first_stanza)
502 break;
503 first_stanza = 0;
504 }
505
506 if (strncmp(line, "flags", 5) == 0) {
507 if (strstr(line, "clflush"))
508 has_clflush = 1;
509 }
510
511 if (strncmp(line, "clflush size", 12) == 0) {
512 char *colon = strchr(line, ':');
513 if (colon)
514 clflush_size = atoi(colon + 1);
515 }
516 }
517 free(line);
518 fclose(file);
519
520 return has_clflush && clflush_size;
521}
522
Chris Wilson7d089132016-05-01 16:39:14 +0100523__attribute__((target("sse2")))
Chris Wilsona6090c72016-01-08 16:32:29 +0000524void igt_clflush_range(void *addr, int size)
525{
526 char *p, *end;
527
528 end = (char *)addr + size;
529 p = (char *)((uintptr_t)addr & ~((uintptr_t)clflush_size - 1));
530
Chris Wilson7499b912016-03-03 11:51:18 +0000531 __builtin_ia32_mfence();
Chris Wilsona6090c72016-01-08 16:32:29 +0000532 for (; p < end; p += clflush_size)
Chris Wilson7499b912016-03-03 11:51:18 +0000533 __builtin_ia32_clflush(p);
Chris Wilsonb4817052016-05-01 09:07:29 +0100534 __builtin_ia32_clflush(end - 1); /* magic serialisation for byt+ */
Chris Wilson7499b912016-03-03 11:51:18 +0000535 __builtin_ia32_mfence();
Chris Wilsona6090c72016-01-08 16:32:29 +0000536}
Chris Wilson7d089132016-05-01 16:39:14 +0100537#else
538int igt_setup_clflush(void)
539{
540 /* requires mfence + clflush, both SSE2 instructions */
541 return 0;
542}
543
544void igt_clflush_range(void *addr, int size)
545{
546 fprintf(stderr, "igt_clflush_range() unsupported\n");
547}
548#endif
Chris Wilson5b675f72016-01-22 17:33:40 +0000549
550/**
551 * intel_detect_and_clear_missed_irq:
552 * @fd: open i915 drm file descriptor, used to quiesce the gpu
553 *
554 * This functions idles the GPU and then queries whether there has
555 * been a missed interrupt reported by the driver. Afterwards it
556 * clears the missed interrupt flag, in order to disable the timer
557 * fallback for the next test.
558 */
559unsigned intel_detect_and_clear_missed_interrupts(int fd)
560{
Chris Wilson58de7852017-03-24 18:11:08 +0000561 unsigned missed;
562 int dir;
Chris Wilson5b675f72016-01-22 17:33:40 +0000563
564 gem_quiescent_gpu(fd);
565
Chris Wilson58de7852017-03-24 18:11:08 +0000566 dir = igt_debugfs_dir(fd);
567
568 missed = 0;
569 igt_assert(igt_sysfs_scanf(dir, "i915_ring_missed_irq", "%x", &missed) == 1);
570 if (missed)
571 igt_sysfs_set(dir, "i915_ring_missed_irq", "0");
572
573 close(dir);
Chris Wilson5b675f72016-01-22 17:33:40 +0000574
Chris Wilsonf22e19b2017-03-23 10:51:28 +0000575 errno = 0;
Chris Wilson5b675f72016-01-22 17:33:40 +0000576 return missed;
577}
Chris Wilson04f52152016-01-27 14:07:27 +0000578
579const struct intel_execution_engine intel_execution_engines[] = {
Chris Wilsonec91c562017-07-06 14:01:56 +0100580 { "default", NULL, 0, 0 },
Chris Wilson82fdfc62017-04-11 20:20:28 +0100581 { "render", "rcs0", I915_EXEC_RENDER, 0 },
582 { "bsd", "vcs0", I915_EXEC_BSD, 0 },
583 { "bsd1", "vcs0", I915_EXEC_BSD, 1<<13 /*I915_EXEC_BSD_RING1*/ },
584 { "bsd2", "vcs1", I915_EXEC_BSD, 2<<13 /*I915_EXEC_BSD_RING2*/ },
585 { "blt", "bcs0", I915_EXEC_BLT, 0 },
586 { "vebox", "vecs0", I915_EXEC_VEBOX, 0 },
Chris Wilson04f52152016-01-27 14:07:27 +0000587 { NULL, 0, 0 }
588};
Chris Wilsonbc787762017-05-18 12:11:59 +0100589
590bool gem_can_store_dword(int fd, unsigned int engine)
591{
592 uint16_t devid = intel_get_drm_devid(fd);
593 const struct intel_device_info *info = intel_get_device_info(devid);
594 const int gen = ffs(info->gen);
595
596 if (gen <= 2) /* requires physical addresses */
597 return false;
598
Chris Wilsondddbc2e2017-09-06 15:34:13 +0100599 if (gen == 3 && (info->is_grantsdale || info->is_alviso))
600 return false; /* only supports physical addresses */
601
Chris Wilsonbc787762017-05-18 12:11:59 +0100602 if (gen == 6 && (engine & ~(3<<13)) == I915_EXEC_BSD)
603 return false; /* kills the machine! */
604
605 if (info->is_broadwater)
606 return false; /* Not sure yet... */
607
608 return true;
609}