1 /*
2 * Copyright © 2007, 2011, 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 * Eric Anholt <eric@anholt.net>
25 * Daniel Vetter <daniel.vetter@ffwll.ch>
26 *
27 */
28
29 #ifdef HAVE_LIBGEN_H
30 #include <libgen.h>
31 #endif
32 #include <stdio.h>
33 #include <fcntl.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <string.h>
37 #include <sys/mman.h>
38 #include <signal.h>
39 #include <pciaccess.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <sys/wait.h>
43 #include <sys/types.h>
44 #include <sys/syscall.h>
45 #include <sys/utsname.h>
46 #include <termios.h>
47 #include <pthread.h>
48
49 #include "drmtest.h"
50 #include "i915_drm.h"
51 #include "intel_chipset.h"
52 #include "intel_io.h"
53 #include "igt_debugfs.h"
54 #include "igt_device.h"
55 #include "igt_gt.h"
56 #include "igt_kmod.h"
57 #include "igt_sysfs.h"
58 #include "version.h"
59 #include "config.h"
60 #include "intel_reg.h"
61 #include "ioctl_wrappers.h"
62 #include "igt_dummyload.h"
63
64 /**
65 * SECTION:drmtest
66 * @short_description: Base library for drm tests and tools
67 * @title: drmtest
68 * @include: igt.h
69 *
70 * This library contains the basic support for writing tests, with the most
71 * important part being the helper function to open drm device nodes.
72 *
73 * But there's also a bit of other assorted stuff here.
74 *
75 * Note that this library's header pulls in the [i-g-t core](igt-gpu-tools-i-g-t-core.html)
76 * and [batchbuffer](igt-gpu-tools-intel-batchbuffer.html) libraries as dependencies.
77 */
78
__get_drm_device_name(int fd,char * name,int name_size)79 static int __get_drm_device_name(int fd, char *name, int name_size)
80 {
81 drm_version_t version;
82
83 memset(&version, 0, sizeof(version));
84 version.name_len = name_size;
85 version.name = name;
86
87 if (!drmIoctl(fd, DRM_IOCTL_VERSION, &version)){
88 return 0;
89 }
90
91 return -1;
92 }
93
__is_device(int fd,const char * expect)94 static bool __is_device(int fd, const char *expect)
95 {
96 char name[12] = "";
97
98 if (__get_drm_device_name(fd, name, sizeof(name) - 1))
99 return false;
100
101 return strcmp(expect, name) == 0;
102 }
103
is_amdgpu_device(int fd)104 bool is_amdgpu_device(int fd)
105 {
106 return __is_device(fd, "amdgpu");
107 }
108
is_i915_device(int fd)109 bool is_i915_device(int fd)
110 {
111 return __is_device(fd, "i915");
112 }
113
is_vc4_device(int fd)114 bool is_vc4_device(int fd)
115 {
116 return __is_device(fd, "vc4");
117 }
118
has_known_intel_chipset(int fd)119 static bool has_known_intel_chipset(int fd)
120 {
121 struct drm_i915_getparam gp;
122 int devid = 0;
123
124 memset(&gp, 0, sizeof(gp));
125 gp.param = I915_PARAM_CHIPSET_ID;
126 gp.value = &devid;
127
128 if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp)))
129 return false;
130
131 if (!intel_gen(devid))
132 return false;
133
134 return true;
135 }
136
137 static char _forced_driver[16] = "";
138
139 /**
140 * __set_forced_driver:
141 * @name: name of driver to forcibly use
142 *
143 * Set the name of a driver to use when calling #drm_open_driver with
144 * the #DRIVER_ANY flag.
145 */
__set_forced_driver(const char * name)146 void __set_forced_driver(const char *name)
147 {
148 if (!name) {
149 igt_warn("No driver specified, keep default behaviour\n");
150 return;
151 }
152
153 strncpy(_forced_driver, name, sizeof(_forced_driver) - 1);
154 }
155
forced_driver(void)156 static const char *forced_driver(void)
157 {
158 if (_forced_driver[0])
159 return _forced_driver;
160
161 return NULL;
162 }
163
164 #define LOCAL_I915_EXEC_VEBOX (4 << 0)
165 /**
166 * gem_quiescent_gpu:
167 * @fd: open i915 drm file descriptor
168 *
169 * Ensure the gpu is idle by launching a nop execbuf and stalling for it. This
170 * is automatically run when opening a drm device node and is also installed as
171 * an exit handler to have the best assurance that the test is run in a pristine
172 * and controlled environment.
173 *
174 * This function simply allows tests to make additional calls in-between, if so
175 * desired.
176 */
gem_quiescent_gpu(int fd)177 void gem_quiescent_gpu(int fd)
178 {
179 igt_terminate_spins();
180
181 igt_drop_caches_set(fd,
182 DROP_ACTIVE | DROP_RETIRE | DROP_IDLE | DROP_FREED);
183 }
184
modprobe(const char * driver)185 static int modprobe(const char *driver)
186 {
187 return igt_kmod_load(driver, "");
188 }
189
modprobe_i915(const char * name)190 static void modprobe_i915(const char *name)
191 {
192 /* When loading i915, we also want to load snd-hda et al */
193 igt_i915_driver_load(NULL);
194 }
195
196 static const struct module {
197 unsigned int bit;
198 const char *module;
199 void (*modprobe)(const char *name);
200 } modules[] = {
201 { DRIVER_AMDGPU, "amdgpu" },
202 { DRIVER_INTEL, "i915", modprobe_i915 },
203 { DRIVER_PANFROST, "panfrost" },
204 { DRIVER_V3D, "v3d" },
205 { DRIVER_VC4, "vc4" },
206 { DRIVER_VGEM, "vgem" },
207 {}
208 };
209
open_device(const char * name,unsigned int chipset)210 static int open_device(const char *name, unsigned int chipset)
211 {
212 const char *forced;
213 char dev_name[16] = "";
214 int chip = DRIVER_ANY;
215 int fd;
216
217 fd = open(name, O_RDWR);
218 if (fd == -1)
219 return -1;
220
221 if (__get_drm_device_name(fd, dev_name, sizeof(dev_name) - 1) == -1)
222 goto err;
223
224 forced = forced_driver();
225 if (forced && chipset == DRIVER_ANY && strcmp(forced, dev_name))
226 goto err;
227
228 for (int start = 0, end = ARRAY_SIZE(modules) - 1; start < end; ){
229 int mid = start + (end - start) / 2;
230 int ret = strcmp(modules[mid].module, dev_name);
231 if (ret < 0) {
232 start = mid + 1;
233 } else if (ret > 0) {
234 end = mid;
235 } else {
236 chip = modules[mid].bit;
237 break;
238 }
239 }
240 if ((chipset & chip) == chip)
241 return fd;
242
243 err:
244 close(fd);
245 return -1;
246 }
247
__search_and_open(const char * base,int offset,unsigned int chipset)248 static int __search_and_open(const char *base, int offset, unsigned int chipset)
249 {
250 const char *forced;
251
252 forced = forced_driver();
253 if (forced)
254 igt_info("Force option used: Using driver %s\n", forced);
255
256 for (int i = 0; i < 16; i++) {
257 char name[80];
258 int fd;
259
260 sprintf(name, "%s%u", base, i + offset);
261 fd = open_device(name, chipset);
262 if (fd != -1)
263 return fd;
264 }
265
266 return -1;
267 }
268
__open_driver(const char * base,int offset,unsigned int chipset)269 static int __open_driver(const char *base, int offset, unsigned int chipset)
270 {
271 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
272 int fd;
273
274 fd = __search_and_open(base, offset, chipset);
275 if (fd != -1)
276 return fd;
277
278 pthread_mutex_lock(&mutex);
279 for (const struct module *m = modules; m->module; m++) {
280 if (chipset & m->bit) {
281 if (m->modprobe)
282 m->modprobe(m->module);
283 else
284 modprobe(m->module);
285 }
286 }
287 pthread_mutex_unlock(&mutex);
288
289 return __search_and_open(base, offset, chipset);
290 }
291
292 /**
293 * __drm_open_driver:
294 * @chipset: OR'd flags for each chipset to search, eg. #DRIVER_INTEL
295 *
296 * Open the first DRM device we can find, searching up to 16 device nodes
297 *
298 * Returns:
299 * An open DRM fd or -1 on error
300 */
__drm_open_driver(int chipset)301 int __drm_open_driver(int chipset)
302 {
303 return __open_driver("/dev/dri/card", 0, chipset);
304 }
305
__drm_open_driver_render(int chipset)306 static int __drm_open_driver_render(int chipset)
307 {
308 return __open_driver("/dev/dri/renderD", 128, chipset);
309 }
310
311 static int at_exit_drm_fd = -1;
312 static int at_exit_drm_render_fd = -1;
313
__cancel_work_at_exit(int fd)314 static void __cancel_work_at_exit(int fd)
315 {
316 igt_terminate_spins(); /* for older kernels */
317
318 igt_sysfs_set_parameter(fd, "reset", "%x", -1u /* any method */);
319 igt_drop_caches_set(fd,
320 /* cancel everything */
321 DROP_RESET_ACTIVE | DROP_RESET_SEQNO |
322 /* cleanup */
323 DROP_ACTIVE | DROP_RETIRE | DROP_IDLE | DROP_FREED);
324 }
325
cancel_work_at_exit(int sig)326 static void cancel_work_at_exit(int sig)
327 {
328 if (at_exit_drm_fd < 0)
329 return;
330
331 __cancel_work_at_exit(at_exit_drm_fd);
332
333 close(at_exit_drm_fd);
334 at_exit_drm_fd = -1;
335 }
336
cancel_work_at_exit_render(int sig)337 static void cancel_work_at_exit_render(int sig)
338 {
339 if (at_exit_drm_render_fd < 0)
340 return;
341
342 __cancel_work_at_exit(at_exit_drm_render_fd);
343
344 close(at_exit_drm_render_fd);
345 at_exit_drm_render_fd = -1;
346 }
347
chipset_to_str(int chipset)348 static const char *chipset_to_str(int chipset)
349 {
350 switch (chipset) {
351 case DRIVER_INTEL:
352 return "intel";
353 case DRIVER_V3D:
354 return "v3d";
355 case DRIVER_VC4:
356 return "vc4";
357 case DRIVER_VGEM:
358 return "vgem";
359 case DRIVER_AMDGPU:
360 return "amdgpu";
361 case DRIVER_PANFROST:
362 return "panfrost";
363 case DRIVER_ANY:
364 return "any";
365 default:
366 return "other";
367 }
368 }
369
370 /**
371 * drm_open_driver:
372 * @chipset: OR'd flags for each chipset to search, eg. #DRIVER_INTEL
373 *
374 * Open a drm legacy device node. This function always returns a valid
375 * file descriptor.
376 *
377 * Returns: a drm file descriptor
378 */
drm_open_driver(int chipset)379 int drm_open_driver(int chipset)
380 {
381 static int open_count;
382 int fd;
383
384 fd = __drm_open_driver(chipset);
385 igt_skip_on_f(fd<0, "No known gpu found for chipset flags 0x%u (%s)\n",
386 chipset, chipset_to_str(chipset));
387
388 /* For i915, at least, we ensure that the driver is idle before
389 * starting a test and we install an exit handler to wait until
390 * idle before quitting.
391 */
392 if (is_i915_device(fd)) {
393 if (__sync_fetch_and_add(&open_count, 1) == 0) {
394 gem_quiescent_gpu(fd);
395
396 at_exit_drm_fd = __drm_open_driver(chipset);
397 igt_install_exit_handler(cancel_work_at_exit);
398 }
399 }
400
401 return fd;
402 }
403
404 /**
405 * drm_open_driver_master:
406 * @chipset: OR'd flags for each chipset to search, eg. #DRIVER_INTEL
407 *
408 * Open a drm legacy device node and ensure that it is drm master.
409 *
410 * Returns:
411 * The drm file descriptor or -1 on error
412 */
drm_open_driver_master(int chipset)413 int drm_open_driver_master(int chipset)
414 {
415 int fd = drm_open_driver(chipset);
416
417 igt_device_set_master(fd);
418
419 return fd;
420 }
421
422 /**
423 * drm_open_driver_render:
424 * @chipset: OR'd flags for each chipset to search, eg. #DRIVER_INTEL
425 *
426 * Open a drm render device node.
427 *
428 * Returns:
429 * The drm file descriptor or -1 on error
430 */
drm_open_driver_render(int chipset)431 int drm_open_driver_render(int chipset)
432 {
433 static int open_count;
434 int fd = __drm_open_driver_render(chipset);
435
436 /* no render nodes, fallback to drm_open_driver() */
437 if (fd == -1)
438 return drm_open_driver(chipset);
439
440 if (__sync_fetch_and_add(&open_count, 1))
441 return fd;
442
443 at_exit_drm_render_fd = __drm_open_driver(chipset);
444 if(chipset & DRIVER_INTEL){
445 gem_quiescent_gpu(fd);
446 igt_install_exit_handler(cancel_work_at_exit_render);
447 }
448
449 return fd;
450 }
451
igt_require_amdgpu(int fd)452 void igt_require_amdgpu(int fd)
453 {
454 igt_require(is_amdgpu_device(fd));
455 }
456
igt_require_intel(int fd)457 void igt_require_intel(int fd)
458 {
459 igt_require(is_i915_device(fd) && has_known_intel_chipset(fd));
460 }
461
igt_require_vc4(int fd)462 void igt_require_vc4(int fd)
463 {
464 igt_require(is_vc4_device(fd));
465 }
466