• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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  * Authors:
24  *    Daniel Vetter
25  *
26  */
27 
28 #include "igt.h"
29 #include "igt_device.h"
30 
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <fcntl.h>
37 #include <inttypes.h>
38 #include <errno.h>
39 #include <sys/stat.h>
40 #include <sys/ioctl.h>
41 #include <sys/time.h>
42 #include "drm.h"
43 
44 
45 #define LOCAL_I915_EXEC_VEBOX (4<<0)
46 #define LOCAL_I915_EXEC_BSD_MASK (3<<13)
47 #define LOCAL_I915_EXEC_BSD_RING1 (1<<13)
48 #define LOCAL_I915_EXEC_BSD_RING2 (2<<13)
49 #define LOCAL_I915_EXEC_RESOURCE_STREAMER (1<<15)
50 #define LOCAL_I915_EXEC_FENCE_IN (1 << 16)
51 #define LOCAL_I915_EXEC_FENCE_OUT (1 << 17)
52 #define LOCAL_I915_EXEC_BATCH_FIRST (1 << 18)
53 #define LOCAL_I915_EXEC_FENCE_ARRAY (1 << 19)
54 
has_ring(int fd,unsigned ring_exec_flags)55 static bool has_ring(int fd, unsigned ring_exec_flags)
56 {
57 	switch (ring_exec_flags & I915_EXEC_RING_MASK) {
58 	case 0:
59 	case I915_EXEC_RENDER:
60 		return true;
61 
62 	case I915_EXEC_BSD:
63 		if (ring_exec_flags & LOCAL_I915_EXEC_BSD_MASK)
64 			return gem_has_bsd2(fd);
65 		else
66 			return gem_has_bsd(fd);
67 
68 	case I915_EXEC_BLT:
69 		return gem_has_blt(fd);
70 
71 	case I915_EXEC_VEBOX:
72 		return gem_has_vebox(fd);
73 	}
74 
75 	igt_assert_f(0, "invalid exec flag 0x%x\n", ring_exec_flags);
76 	return false;
77 }
78 
has_exec_batch_first(int fd)79 static bool has_exec_batch_first(int fd)
80 {
81 	int val = -1;
82 	struct drm_i915_getparam gp = {
83 		.param = 48,
84 		.value = &val,
85 	};
86 	ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
87 	return val > 0;
88 }
89 
has_resource_streamer(int fd)90 static bool has_resource_streamer(int fd)
91 {
92 	int val = -1;
93 	struct drm_i915_getparam gp = {
94 		.param = I915_PARAM_HAS_RESOURCE_STREAMER,
95 		.value = &val,
96 	};
97 	ioctl(fd, DRM_IOCTL_I915_GETPARAM , &gp);
98 	return val > 0;
99 }
100 
test_batch_first(int fd)101 static void test_batch_first(int fd)
102 {
103 	const int gen = intel_gen(intel_get_drm_devid(fd));
104 	struct drm_i915_gem_execbuffer2 execbuf;
105 	struct drm_i915_gem_exec_object2 obj[3];
106 	struct drm_i915_gem_relocation_entry reloc[2];
107 	uint32_t *map, value;
108 	int i;
109 
110 	igt_require(gem_can_store_dword(fd, 0));
111 	igt_require(has_exec_batch_first(fd));
112 
113 	memset(obj, 0, sizeof(obj));
114 	memset(reloc, 0, sizeof(reloc));
115 
116 	obj[0].handle = gem_create(fd, 4096);
117 	obj[1].handle = gem_create(fd, 4096);
118 	obj[2].handle = gem_create(fd, 4096);
119 
120 	reloc[0].target_handle = obj[1].handle;
121 	reloc[0].offset = sizeof(uint32_t);
122 	reloc[0].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
123 	reloc[0].write_domain = I915_GEM_DOMAIN_INSTRUCTION;
124 	obj[0].relocs_ptr = to_user_pointer(&reloc[0]);
125 	obj[0].relocation_count = 1;
126 
127 	i = 0;
128 	map = gem_mmap__cpu(fd, obj[0].handle, 0, 4096, PROT_WRITE);
129 	gem_set_domain(fd, obj[0].handle,
130 			I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
131 	map[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
132 	if (gen >= 8) {
133 		map[++i] = 0;
134 		map[++i] = 0;
135 	} else if (gen >= 4) {
136 		map[++i] = 0;
137 		map[++i] = 0;
138 		reloc[0].offset += sizeof(uint32_t);
139 	} else {
140 		map[i]--;
141 		map[++i] = 0;
142 	}
143 	map[++i] = 1;
144 	map[++i] = MI_BATCH_BUFFER_END;
145 	munmap(map, 4096);
146 
147 	reloc[1].target_handle = obj[1].handle;
148 	reloc[1].offset = sizeof(uint32_t);
149 	reloc[1].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
150 	reloc[1].write_domain = I915_GEM_DOMAIN_INSTRUCTION;
151 	obj[2].relocs_ptr = to_user_pointer(&reloc[1]);
152 	obj[2].relocation_count = 1;
153 
154 	i = 0;
155 	map = gem_mmap__cpu(fd, obj[2].handle, 0, 4096, PROT_WRITE);
156 	gem_set_domain(fd, obj[2].handle,
157 			I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
158 	map[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
159 	if (gen >= 8) {
160 		map[++i] = 0;
161 		map[++i] = 0;
162 	} else if (gen >= 4) {
163 		map[++i] = 0;
164 		map[++i] = 0;
165 		reloc[1].offset += sizeof(uint32_t);
166 	} else {
167 		map[i]--;
168 		map[++i] = 0;
169 	}
170 	map[++i] = 2;
171 	map[++i] = MI_BATCH_BUFFER_END;
172 	munmap(map, 4096);
173 
174 	memset(&execbuf, 0, sizeof(execbuf));
175 	execbuf.buffers_ptr = to_user_pointer(obj);
176 	execbuf.buffer_count = ARRAY_SIZE(obj);
177 	if (gen > 3 && gen < 6)
178 		execbuf.flags |= I915_EXEC_SECURE;
179 
180 	/* Normal mode */
181 	gem_execbuf(fd, &execbuf);
182 	gem_read(fd, obj[1].handle, 0, &value, sizeof(value));
183 	igt_assert_eq_u32(value, 2);
184 
185 	/* Batch first mode */
186 	execbuf.flags |= LOCAL_I915_EXEC_BATCH_FIRST;
187 	gem_execbuf(fd, &execbuf);
188 	gem_read(fd, obj[1].handle, 0, &value, sizeof(value));
189 	igt_assert_eq_u32(value, 1);
190 
191 	gem_close(fd, obj[2].handle);
192 	gem_close(fd, obj[1].handle);
193 	gem_close(fd, obj[0].handle);
194 }
195 
196 struct drm_i915_gem_execbuffer2 execbuf;
197 struct drm_i915_gem_exec_object2 gem_exec[1];
198 uint32_t batch[2] = {MI_BATCH_BUFFER_END};
199 uint32_t handle, devid;
200 int fd;
201 
202 igt_main
203 {
204 	const struct intel_execution_engine *e;
205 
206 	igt_fixture {
207 		fd = drm_open_driver(DRIVER_INTEL);
208 		igt_require_gem(fd);
209 
210 		devid = intel_get_drm_devid(fd);
211 
212 		handle = gem_create(fd, 4096);
213 		gem_write(fd, handle, 0, batch, sizeof(batch));
214 
215 		gem_exec[0].handle = handle;
216 		gem_exec[0].relocation_count = 0;
217 		gem_exec[0].relocs_ptr = 0;
218 		gem_exec[0].alignment = 0;
219 		gem_exec[0].offset = 0;
220 		gem_exec[0].flags = 0;
221 		gem_exec[0].rsvd1 = 0;
222 		gem_exec[0].rsvd2 = 0;
223 
224 		execbuf.buffers_ptr = to_user_pointer(gem_exec);
225 		execbuf.buffer_count = 1;
226 		execbuf.batch_start_offset = 0;
227 		execbuf.batch_len = 8;
228 		execbuf.cliprects_ptr = 0;
229 		execbuf.num_cliprects = 0;
230 		execbuf.DR1 = 0;
231 		execbuf.DR4 = 0;
232 		execbuf.flags = 0;
233 		i915_execbuffer2_set_context_id(execbuf, 0);
234 		execbuf.rsvd2 = 0;
235 	}
236 
237 	igt_subtest("control") {
238 		for (e = intel_execution_engines; e->name; e++) {
239 			if (has_ring(fd, e->exec_id | e->flags)) {
240 				execbuf.flags = e->exec_id | e->flags;
241 				gem_execbuf(fd, &execbuf);
242 			}
243 		}
244 	}
245 
246 #define RUN_FAIL(expected_errno) do { \
247 		igt_assert_eq(__gem_execbuf(fd, &execbuf), -expected_errno); \
248 	} while(0)
249 
250 	igt_subtest("no-bsd") {
251 		igt_require(!gem_has_bsd(fd));
252 		execbuf.flags = I915_EXEC_BSD;
253 		RUN_FAIL(EINVAL);
254 	}
255 	igt_subtest("no-blt") {
256 		igt_require(!gem_has_blt(fd));
257 		execbuf.flags = I915_EXEC_BLT;
258 		RUN_FAIL(EINVAL);
259 	}
260 	igt_subtest("no-vebox") {
261 		igt_require(!gem_has_vebox(fd));
262 		execbuf.flags = LOCAL_I915_EXEC_VEBOX;
263 		RUN_FAIL(EINVAL);
264 	}
265 	igt_subtest("invalid-ring") {
266 		execbuf.flags = I915_EXEC_RING_MASK;
267 		RUN_FAIL(EINVAL);
268 	}
269 
270 	igt_subtest("invalid-ring2") {
271 		execbuf.flags = LOCAL_I915_EXEC_VEBOX+1;
272 		RUN_FAIL(EINVAL);
273 	}
274 
275 	igt_subtest("invalid-bsd-ring") {
276 		igt_require(gem_has_bsd2(fd));
277 		execbuf.flags = I915_EXEC_BSD | LOCAL_I915_EXEC_BSD_MASK;
278 		RUN_FAIL(EINVAL);
279 	}
280 
281 	igt_subtest("invalid-bsd1-flag-on-render") {
282 		execbuf.flags = I915_EXEC_RENDER | LOCAL_I915_EXEC_BSD_RING1;
283 		RUN_FAIL(EINVAL);
284 	}
285 
286 	igt_subtest("invalid-bsd2-flag-on-render") {
287 		execbuf.flags = I915_EXEC_RENDER | LOCAL_I915_EXEC_BSD_RING2;
288 		RUN_FAIL(EINVAL);
289 	}
290 
291 	igt_subtest("invalid-bsd1-flag-on-blt") {
292 		execbuf.flags = I915_EXEC_BLT | LOCAL_I915_EXEC_BSD_RING1;
293 		RUN_FAIL(EINVAL);
294 	}
295 
296 	igt_subtest("invalid-bsd2-flag-on-blt") {
297 		execbuf.flags = I915_EXEC_BLT | LOCAL_I915_EXEC_BSD_RING2;
298 		RUN_FAIL(EINVAL);
299 	}
300 
301 	igt_subtest("invalid-bsd1-flag-on-vebox") {
302 		igt_require(gem_has_vebox(fd));
303 		execbuf.flags = LOCAL_I915_EXEC_VEBOX | LOCAL_I915_EXEC_BSD_RING1;
304 		RUN_FAIL(EINVAL);
305 	}
306 
307 	igt_subtest("invalid-bsd2-flag-on-vebox") {
308 		igt_require(gem_has_vebox(fd));
309 		execbuf.flags = LOCAL_I915_EXEC_VEBOX | LOCAL_I915_EXEC_BSD_RING2;
310 		RUN_FAIL(EINVAL);
311 	}
312 
313 	igt_subtest("rel-constants-invalid-ring") {
314 		igt_require(gem_has_bsd(fd));
315 		execbuf.flags = I915_EXEC_BSD | I915_EXEC_CONSTANTS_ABSOLUTE;
316 		RUN_FAIL(EINVAL);
317 	}
318 
319 	igt_subtest("rel-constants-invalid-rel-gen5") {
320 		igt_require(intel_gen(devid) > 5);
321 		execbuf.flags = I915_EXEC_RENDER | I915_EXEC_CONSTANTS_REL_SURFACE;
322 		RUN_FAIL(EINVAL);
323 	}
324 
325 	igt_subtest("rel-constants-invalid") {
326 		execbuf.flags = I915_EXEC_RENDER | (I915_EXEC_CONSTANTS_REL_SURFACE+(1<<6));
327 		RUN_FAIL(EINVAL);
328 	}
329 
330 	igt_subtest("sol-reset-invalid") {
331 		igt_require(gem_has_bsd(fd));
332 		execbuf.flags = I915_EXEC_BSD | I915_EXEC_GEN7_SOL_RESET;
333 		RUN_FAIL(EINVAL);
334 	}
335 
336 	igt_subtest("sol-reset-not-gen7") {
337 		igt_require(intel_gen(devid) != 7);
338 		execbuf.flags = I915_EXEC_RENDER | I915_EXEC_GEN7_SOL_RESET;
339 		RUN_FAIL(EINVAL);
340 	}
341 
342 	igt_subtest("secure-non-root") {
343 		igt_fork(child, 1) {
344 			igt_drop_root();
345 
346 			execbuf.flags = I915_EXEC_RENDER | I915_EXEC_SECURE;
347 			RUN_FAIL(EPERM);
348 		}
349 
350 		igt_waitchildren();
351 	}
352 
353 	igt_subtest("secure-non-master") {
354 		igt_require(__igt_device_set_master(fd) == 0); /* Requires root privilege */
355 
356 		igt_device_drop_master(fd);
357 		execbuf.flags = I915_EXEC_RENDER | I915_EXEC_SECURE;
358 		RUN_FAIL(EPERM);
359 
360 		igt_device_set_master(fd);
361 		gem_execbuf(fd, &execbuf);
362 
363 		igt_device_drop_master(fd); /* Only needs temporary master */
364 	}
365 
366 	/* HANDLE_LUT and NO_RELOC are already exercised by gem_exec_lut_handle,
367 	 * EXEC_FENCE_IN and EXEC_FENCE_OUT correct usage is tested by
368 	 * gem_exec_fence, invalid usage of EXEC_FENCE_IN is tested below. */
369 
370 	igt_subtest("invalid-flag") {
371 		/* NOTE: This test intentionally exercise the next available
372 		 * flag. Don't "fix" this testcase without adding the required
373 		 * tests for the new flag first. */
374 		execbuf.flags = I915_EXEC_RENDER | (LOCAL_I915_EXEC_FENCE_ARRAY << 1);
375 		RUN_FAIL(EINVAL);
376 	}
377 
378 	/* rsvd1 aka context id is already exercised  by gem_ctx_bad_exec */
379 
380 	igt_subtest("cliprects-invalid") {
381 		igt_require(intel_gen(devid) >= 5);
382 		execbuf.flags = 0;
383 		execbuf.num_cliprects = 1;
384 		RUN_FAIL(EINVAL);
385 		execbuf.num_cliprects = 0;
386 	}
387 
388 	igt_subtest("rs-invalid") {
389 		bool has_rs = has_resource_streamer(fd);
390 		unsigned int engine;
391 
for_each_engine(fd,engine)392 		for_each_engine(fd, engine) {
393 			int expect = -EINVAL;
394 			if (has_rs && (engine == 0 || engine == I915_EXEC_RENDER))
395 				expect = 0;
396 
397 			execbuf.flags = engine | LOCAL_I915_EXEC_RESOURCE_STREAMER;
398 			igt_assert_eq(__gem_execbuf(fd, &execbuf), expect);
399 		}
400 	}
401 
402 	igt_subtest("invalid-fence-in") {
403 		igt_require(gem_has_exec_fence(fd));
404 		execbuf.flags = LOCAL_I915_EXEC_FENCE_IN;
405 		execbuf.rsvd2 = -1;
406 		RUN_FAIL(EINVAL);
407 		execbuf.rsvd2 = fd;
408 		RUN_FAIL(EINVAL);
409 	}
410 
411 	igt_subtest("rsvd2-dirt") {
412 		igt_require(!gem_has_exec_fence(fd));
413 		execbuf.flags = 0;
414 		execbuf.rsvd2 = 1;
415 		RUN_FAIL(EINVAL);
416 		execbuf.rsvd2 = 0;
417 	}
418 
419 	igt_subtest("batch-first")
420 		test_batch_first(fd);
421 
422 #define DIRT(name) \
423 	igt_subtest(#name "-dirt") { \
424 		execbuf.flags = 0; \
425 		execbuf.name = 1; \
426 		RUN_FAIL(EINVAL); \
427 		execbuf.name = 0; \
428 	}
429 
430 	DIRT(cliprects_ptr);
431 	DIRT(DR1);
432 	DIRT(DR4);
433 #undef DIRT
434 
435 #undef RUN_FAIL
436 
437 	igt_fixture {
438 		gem_close(fd, handle);
439 
440 		close(fd);
441 	}
442 }
443