blob: f79728fd60f59394d299cd31368db96a5f782ab0 [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
24#include <string.h>
Daniel Vetter3cd45de2015-02-10 17:46:43 +010025#include <signal.h>
Chris Wilson16bafdf2014-09-04 09:26:24 +010026#include <errno.h>
Daniel Vetter3cd45de2015-02-10 17:46:43 +010027#include <sys/types.h>
28#include <sys/stat.h>
Chris Wilsonc83299d2015-06-15 14:51:54 +010029#include <sys/ioctl.h>
Daniel Vetter3cd45de2015-02-10 17:46:43 +010030#include <fcntl.h>
Chris Wilson16bafdf2014-09-04 09:26:24 +010031
Daniel Vetter3cd45de2015-02-10 17:46:43 +010032#include "drmtest.h"
Chris Wilson16bafdf2014-09-04 09:26:24 +010033#include "igt_core.h"
34#include "igt_gt.h"
35#include "igt_debugfs.h"
36#include "ioctl_wrappers.h"
37#include "intel_reg.h"
Daniel Vetterc66b2422015-02-06 10:49:20 +010038#include "intel_chipset.h"
Chris Wilson16bafdf2014-09-04 09:26:24 +010039
Daniel Vetter3cd45de2015-02-10 17:46:43 +010040/**
41 * SECTION:igt_gt
42 * @short_description: GT support library
Damien Lespiau6ebd8c22015-06-26 14:28:41 +010043 * @title: GT
Thomas Woodf0381d12015-09-07 09:26:01 +010044 * @include: igt.h
Daniel Vetter3cd45de2015-02-10 17:46:43 +010045 *
46 * This library provides various auxiliary helper functions to handle general
47 * interactions with the GT like forcewake handling, injecting hangs or stopping
48 * engines.
49 */
50
Chris Wilsonc83299d2015-06-15 14:51:54 +010051static bool has_gpu_reset(int fd)
52{
53 struct drm_i915_getparam gp;
54 int val = 0;
55
56 memset(&gp, 0, sizeof(gp));
57 gp.param = 35; /* HAS_GPU_RESET */
58 gp.value = &val;
59
60 if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
61 return intel_gen(intel_get_drm_devid(fd)) >= 5;
62
63 return val > 0;
64}
Daniel Vetter3cd45de2015-02-10 17:46:43 +010065
66/**
67 * igt_require_hang_ring:
68 * @fd: open i915 drm file descriptor
69 * @ring: execbuf ring flag
70 *
71 * Convenience helper to check whether advanced hang injection is supported by
72 * the kernel. Uses igt_skip to automatically skip the test/subtest if this
73 * isn't the case.
74 */
Daniel Vetterc66b2422015-02-06 10:49:20 +010075void igt_require_hang_ring(int fd, int ring)
Chris Wilson16bafdf2014-09-04 09:26:24 +010076{
Chris Wilsonfb950bc2015-04-13 19:04:13 +010077 gem_context_require_ban_period(fd);
Chris Wilsonc83299d2015-06-15 14:51:54 +010078 igt_require(has_gpu_reset(fd));
Chris Wilson16bafdf2014-09-04 09:26:24 +010079}
80
Daniel Vetter3cd45de2015-02-10 17:46:43 +010081/**
82 * igt_hang_ring:
83 * @fd: open i915 drm file descriptor
84 * @ring: execbuf ring flag
85 *
86 * This helper function injects a hanging batch into @ring. It returns a
87 * #igt_hang_ring_t structure which must be passed to igt_post_hang_ring() for
88 * hang post-processing (after the gpu hang interaction has been tested.
89 *
90 * Returns:
91 * Structure with helper internal state for igt_post_hang_ring().
92 */
93igt_hang_ring_t igt_hang_ring(int fd, int ring)
Chris Wilson16bafdf2014-09-04 09:26:24 +010094{
95 struct drm_i915_gem_relocation_entry reloc;
96 struct drm_i915_gem_execbuffer2 execbuf;
97 struct drm_i915_gem_exec_object2 exec;
98 struct local_i915_gem_context_param param;
99 uint32_t b[8];
100 unsigned ban;
101 unsigned len;
102
103 param.context = 0;
104 param.size = 0;
105 param.param = LOCAL_CONTEXT_PARAM_BAN_PERIOD;
106 param.value = 0;
107 gem_context_get_param(fd, &param);
108 ban = param.value;
109
110 param.value = 0;
Daniel Vetter8d21b392015-02-06 11:10:25 +0100111 gem_context_set_param(fd, &param);
Chris Wilson16bafdf2014-09-04 09:26:24 +0100112
113 memset(&reloc, 0, sizeof(reloc));
114 memset(&exec, 0, sizeof(exec));
115 memset(&execbuf, 0, sizeof(execbuf));
116
117 exec.handle = gem_create(fd, 4096);
118 exec.relocation_count = 1;
119 exec.relocs_ptr = (uintptr_t)&reloc;
120
121 len = 2;
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100122 if (intel_gen(intel_get_drm_devid(fd)) >= 8)
Chris Wilson16bafdf2014-09-04 09:26:24 +0100123 len++;
124 b[0] = MI_BATCH_BUFFER_START | (len - 2);
125 b[len] = MI_BATCH_BUFFER_END;
126 b[len+1] = MI_NOOP;
127 gem_write(fd, exec.handle, 0, b, sizeof(b));
128
129 reloc.offset = 4;
130 reloc.target_handle = exec.handle;
131 reloc.read_domains = I915_GEM_DOMAIN_COMMAND;
132
133 execbuf.buffers_ptr = (uintptr_t)&exec;
134 execbuf.buffer_count = 1;
135 execbuf.batch_len = sizeof(b);
136 execbuf.flags = ring;
137 gem_execbuf(fd, &execbuf);
138
139 return (struct igt_hang_ring){ exec.handle, ban };
140}
141
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100142/**
Thomas Wood26f40812015-02-20 11:31:01 +0000143 * igt_post_hang_ring:
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100144 * @fd: open i915 drm file descriptor
145 * @arg: hang state from igt_hang_ring()
146 *
147 * This function does the necessary post-processing after a gpu hang injected
148 * with igt_hang_ring().
149 */
Chris Wilson16bafdf2014-09-04 09:26:24 +0100150void igt_post_hang_ring(int fd, struct igt_hang_ring arg)
151{
152 struct local_i915_gem_context_param param;
153
154 if (arg.handle == 0)
155 return;
156
157 gem_set_domain(fd, arg.handle,
158 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
159 gem_close(fd, arg.handle);
160
161 param.context = 0;
162 param.size = 0;
163 param.param = LOCAL_CONTEXT_PARAM_BAN_PERIOD;
164 param.value = arg.ban;
165 gem_context_set_param(fd, &param);
166}
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100167
168/* GPU abusers */
169static struct igt_helper_process hang_helper;
170static void __attribute__((noreturn))
171hang_helper_process(pid_t pid, int fd)
172{
173 while (1) {
174 if (kill(pid, 0)) /* Parent has died, so must we. */
175 exit(0);
176
177 igt_post_hang_ring(fd,
178 igt_hang_ring(fd, I915_EXEC_DEFAULT));
179
180 sleep(1);
181 }
182}
183
184/**
185 * igt_fork_hang_helper:
186 *
187 * Fork a child process using #igt_fork_helper to hang the default engine
188 * of the GPU at regular intervals.
189 *
190 * This is useful to exercise slow running code (such as aperture placement)
191 * which needs to be robust against a GPU reset.
192 *
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100193 * This function automatically skips when test requirements aren't met using
194 * igt_skip().
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100195 */
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100196void igt_fork_hang_helper(void)
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100197{
198 int fd, gen;
199
Micah Fedkec81d2932015-07-22 21:54:02 +0000200 fd = drm_open_driver(DRIVER_INTEL);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100201
202 gen = intel_gen(intel_get_drm_devid(fd));
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100203 igt_skip_on(gen < 5);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100204
205 igt_fork_helper(&hang_helper)
206 hang_helper_process(getppid(), fd);
207
208 close(fd);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100209}
210
211/**
212 * igt_stop_hang_helper:
213 *
214 * Stops the child process spawned with igt_fork_hang_helper().
215 *
216 * In tests with subtests this function can be called outside of failure
217 * catching code blocks like #igt_fixture or #igt_subtest.
218 */
219void igt_stop_hang_helper(void)
220{
Daniel Vetterd8d1eab2015-12-03 07:45:34 +0100221 if (hang_helper.running)
222 igt_stop_helper(&hang_helper);
Daniel Vetter3cd45de2015-02-10 17:46:43 +0100223}
224
225/**
226 * igt_open_forcewake_handle:
227 *
228 * This functions opens the debugfs forcewake file and so prevents the GT from
229 * suspending. The reference is automatically dropped when the is closed.
230 *
231 * Returns:
232 * The file descriptor of the forcewake handle or -1 if that didn't work out.
233 */
234int igt_open_forcewake_handle(void)
235{
236 if (getenv("IGT_NO_FORCEWAKE"))
237 return -1;
238 return igt_debugfs_open("i915_forcewake_user", O_WRONLY);
239}
240
241/**
242 * igt_to_stop_ring_flag:
243 * @ring: the specified ring flag from execbuf ioctl (I915_EXEC_*)
244 *
245 * This converts the specified ring to a ring flag to be used
246 * with igt_get_stop_rings() and igt_set_stop_rings().
247 *
248 * Returns:
249 * Ring flag for the given ring.
250 */
251enum stop_ring_flags igt_to_stop_ring_flag(int ring) {
252 if (ring == I915_EXEC_DEFAULT)
253 return STOP_RING_RENDER;
254
255 igt_assert(ring && ((ring & ~I915_EXEC_RING_MASK) == 0));
256 return 1 << (ring - 1);
257}
258
259static void stop_rings_write(uint32_t mask)
260{
261 int fd;
262 char buf[80];
263
264 igt_assert(snprintf(buf, sizeof(buf), "0x%08x", mask) == 10);
265 fd = igt_debugfs_open("i915_ring_stop", O_WRONLY);
266 igt_assert(fd >= 0);
267
268 igt_assert(write(fd, buf, strlen(buf)) == strlen(buf));
269 close(fd);
270}
271
272/**
273 * igt_get_stop_rings:
274 *
275 * Read current ring flags from 'i915_ring_stop' debugfs entry.
276 *
277 * Returns:
278 * Current ring flags.
279 */
280enum stop_ring_flags igt_get_stop_rings(void)
281{
282 int fd;
283 char buf[80];
284 int l;
285 unsigned long long ring_mask;
286
287 fd = igt_debugfs_open("i915_ring_stop", O_RDONLY);
288 igt_assert(fd >= 0);
289 l = read(fd, buf, sizeof(buf)-1);
290 igt_assert(l > 0);
291 igt_assert(l < sizeof(buf));
292
293 buf[l] = '\0';
294
295 close(fd);
296
297 errno = 0;
298 ring_mask = strtoull(buf, NULL, 0);
299 igt_assert(errno == 0);
300 return ring_mask;
301}
302
303/**
304 * igt_set_stop_rings:
305 * @flags: Ring flags to write
306 *
307 * This writes @flags to 'i915_ring_stop' debugfs entry. Driver will
308 * prevent the CPU from writing tail pointer for the ring that @flags
309 * specify. Note that the ring is not stopped right away. Instead any
310 * further command emissions won't be executed after the flag is set.
311 *
312 * This is the least invasive way to make the GPU stuck. Hence you must
313 * set this after a batch submission with it's own invalid or endless
314 * looping instructions. In this case it is merely for giving notification
315 * for the driver that this was simulated hang, as the batch would have
316 * caused hang in any case. On the other hand if you use a valid or noop
317 * batch and want to hang the ring (GPU), you must set corresponding flag
318 * before submitting the batch.
319 *
320 * Driver checks periodically if a ring is making any progress, and if
321 * it is not, it will declare the ring to be hung and will reset the GPU.
322 * After reset, the driver will clear flags in 'i915_ring_stop'
323 *
324 * Note: Always when hanging the GPU, use igt_set_stop_rings() to
325 * notify the driver. Driver controls hang log messaging based on
326 * these flags and thus prevents false positives on logs.
327 */
328void igt_set_stop_rings(enum stop_ring_flags flags)
329{
330 enum stop_ring_flags current;
331
332 igt_assert((flags & ~(STOP_RING_ALL |
333 STOP_RING_ALLOW_BAN |
334 STOP_RING_ALLOW_ERRORS)) == 0);
335
336 current = igt_get_stop_rings();
337 igt_assert_f(flags == 0 || current == 0,
338 "previous i915_ring_stop is still 0x%x\n", current);
339
340 stop_rings_write(flags);
341 current = igt_get_stop_rings();
342 igt_warn_on_f(current != flags,
343 "i915_ring_stop readback mismatch 0x%x vs 0x%x\n",
344 flags, current);
345}
Chris Wilsona6090c72016-01-08 16:32:29 +0000346
347static unsigned int clflush_size;
348
349int igt_setup_clflush(void)
350{
351 FILE *file;
352 char *line = NULL;
353 size_t size = 0;
354 int first_stanza = 1;
355 int has_clflush = 0;
356
357 if (clflush_size)
358 return 1;
359
360 file = fopen("/proc/cpuinfo", "r");
361 if (file == NULL)
362 return 0;
363
364 while (getline(&line, &size, file) != -1) {
365 if (strncmp(line, "processor", 9) == 0) {
366 if (!first_stanza)
367 break;
368 first_stanza = 0;
369 }
370
371 if (strncmp(line, "flags", 5) == 0) {
372 if (strstr(line, "clflush"))
373 has_clflush = 1;
374 }
375
376 if (strncmp(line, "clflush size", 12) == 0) {
377 char *colon = strchr(line, ':');
378 if (colon)
379 clflush_size = atoi(colon + 1);
380 }
381 }
382 free(line);
383 fclose(file);
384
385 return has_clflush && clflush_size;
386}
387
388void igt_clflush_range(void *addr, int size)
389{
390 char *p, *end;
391
392 end = (char *)addr + size;
393 p = (char *)((uintptr_t)addr & ~((uintptr_t)clflush_size - 1));
394
395 asm volatile("mfence" ::: "memory");
396 for (; p < end; p += clflush_size)
397 asm volatile("clflush %0" : "+m" (*(volatile char *)p));
398 asm volatile("mfence" ::: "memory");
399}