xref: /aosp_15_r20/external/igt-gpu-tools/tests/i915/gem_sync.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2016 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  */
23*d83cc019SAndroid Build Coastguard Worker 
24*d83cc019SAndroid Build Coastguard Worker #include <time.h>
25*d83cc019SAndroid Build Coastguard Worker #include <pthread.h>
26*d83cc019SAndroid Build Coastguard Worker 
27*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
28*d83cc019SAndroid Build Coastguard Worker #include "igt_sysfs.h"
29*d83cc019SAndroid Build Coastguard Worker 
30*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_NO_RELOC (1<<11)
31*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_HANDLE_LUT (1<<12)
32*d83cc019SAndroid Build Coastguard Worker 
33*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_BSD_SHIFT      (13)
34*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_BSD_MASK       (3 << LOCAL_I915_EXEC_BSD_SHIFT)
35*d83cc019SAndroid Build Coastguard Worker 
36*d83cc019SAndroid Build Coastguard Worker #define MAX_PRIO LOCAL_I915_CONTEXT_MAX_USER_PRIORITY
37*d83cc019SAndroid Build Coastguard Worker #define MIN_PRIO LOCAL_I915_CONTEXT_MIN_USER_PRIORITY
38*d83cc019SAndroid Build Coastguard Worker 
39*d83cc019SAndroid Build Coastguard Worker #define ENGINE_MASK  (I915_EXEC_RING_MASK | LOCAL_I915_EXEC_BSD_MASK)
40*d83cc019SAndroid Build Coastguard Worker 
41*d83cc019SAndroid Build Coastguard Worker IGT_TEST_DESCRIPTION("Basic check of ring<->ring write synchronisation.");
42*d83cc019SAndroid Build Coastguard Worker 
43*d83cc019SAndroid Build Coastguard Worker /*
44*d83cc019SAndroid Build Coastguard Worker  * Testcase: Basic check of sync
45*d83cc019SAndroid Build Coastguard Worker  *
46*d83cc019SAndroid Build Coastguard Worker  * Extremely efficient at catching missed irqs
47*d83cc019SAndroid Build Coastguard Worker  */
48*d83cc019SAndroid Build Coastguard Worker 
gettime(void)49*d83cc019SAndroid Build Coastguard Worker static double gettime(void)
50*d83cc019SAndroid Build Coastguard Worker {
51*d83cc019SAndroid Build Coastguard Worker 	static clockid_t clock = -1;
52*d83cc019SAndroid Build Coastguard Worker 	struct timespec ts;
53*d83cc019SAndroid Build Coastguard Worker 
54*d83cc019SAndroid Build Coastguard Worker 	/* Stay on the same clock for consistency. */
55*d83cc019SAndroid Build Coastguard Worker 	if (clock != (clockid_t)-1) {
56*d83cc019SAndroid Build Coastguard Worker 		if (clock_gettime(clock, &ts))
57*d83cc019SAndroid Build Coastguard Worker 			goto error;
58*d83cc019SAndroid Build Coastguard Worker 		goto out;
59*d83cc019SAndroid Build Coastguard Worker 	}
60*d83cc019SAndroid Build Coastguard Worker 
61*d83cc019SAndroid Build Coastguard Worker #ifdef CLOCK_MONOTONIC_RAW
62*d83cc019SAndroid Build Coastguard Worker 	if (!clock_gettime(clock = CLOCK_MONOTONIC_RAW, &ts))
63*d83cc019SAndroid Build Coastguard Worker 		goto out;
64*d83cc019SAndroid Build Coastguard Worker #endif
65*d83cc019SAndroid Build Coastguard Worker #ifdef CLOCK_MONOTONIC_COARSE
66*d83cc019SAndroid Build Coastguard Worker 	if (!clock_gettime(clock = CLOCK_MONOTONIC_COARSE, &ts))
67*d83cc019SAndroid Build Coastguard Worker 		goto out;
68*d83cc019SAndroid Build Coastguard Worker #endif
69*d83cc019SAndroid Build Coastguard Worker 	if (!clock_gettime(clock = CLOCK_MONOTONIC, &ts))
70*d83cc019SAndroid Build Coastguard Worker 		goto out;
71*d83cc019SAndroid Build Coastguard Worker error:
72*d83cc019SAndroid Build Coastguard Worker 	igt_warn("Could not read monotonic time: %s\n",
73*d83cc019SAndroid Build Coastguard Worker 			strerror(errno));
74*d83cc019SAndroid Build Coastguard Worker 	igt_assert(0);
75*d83cc019SAndroid Build Coastguard Worker 	return 0;
76*d83cc019SAndroid Build Coastguard Worker 
77*d83cc019SAndroid Build Coastguard Worker out:
78*d83cc019SAndroid Build Coastguard Worker 	return ts.tv_sec + 1e-9*ts.tv_nsec;
79*d83cc019SAndroid Build Coastguard Worker }
80*d83cc019SAndroid Build Coastguard Worker 
81*d83cc019SAndroid Build Coastguard Worker static void
sync_ring(int fd,unsigned ring,int num_children,int timeout)82*d83cc019SAndroid Build Coastguard Worker sync_ring(int fd, unsigned ring, int num_children, int timeout)
83*d83cc019SAndroid Build Coastguard Worker {
84*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16];
85*d83cc019SAndroid Build Coastguard Worker 	const char *names[16];
86*d83cc019SAndroid Build Coastguard Worker 	int num_engines = 0;
87*d83cc019SAndroid Build Coastguard Worker 
88*d83cc019SAndroid Build Coastguard Worker 	if (ring == ALL_ENGINES) {
89*d83cc019SAndroid Build Coastguard Worker 		for_each_physical_engine(fd, ring) {
90*d83cc019SAndroid Build Coastguard Worker 			names[num_engines] = e__->name;
91*d83cc019SAndroid Build Coastguard Worker 			engines[num_engines++] = ring;
92*d83cc019SAndroid Build Coastguard Worker 			if (num_engines == ARRAY_SIZE(engines))
93*d83cc019SAndroid Build Coastguard Worker 				break;
94*d83cc019SAndroid Build Coastguard Worker 		}
95*d83cc019SAndroid Build Coastguard Worker 
96*d83cc019SAndroid Build Coastguard Worker 		num_children *= num_engines;
97*d83cc019SAndroid Build Coastguard Worker 	} else {
98*d83cc019SAndroid Build Coastguard Worker 		gem_require_ring(fd, ring);
99*d83cc019SAndroid Build Coastguard Worker 		names[num_engines] = NULL;
100*d83cc019SAndroid Build Coastguard Worker 		engines[num_engines++] = ring;
101*d83cc019SAndroid Build Coastguard Worker 	}
102*d83cc019SAndroid Build Coastguard Worker 
103*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
104*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_children) {
105*d83cc019SAndroid Build Coastguard Worker 		const uint32_t bbe = MI_BATCH_BUFFER_END;
106*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_exec_object2 object;
107*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_execbuffer2 execbuf;
108*d83cc019SAndroid Build Coastguard Worker 		double start, elapsed;
109*d83cc019SAndroid Build Coastguard Worker 		unsigned long cycles;
110*d83cc019SAndroid Build Coastguard Worker 
111*d83cc019SAndroid Build Coastguard Worker 		memset(&object, 0, sizeof(object));
112*d83cc019SAndroid Build Coastguard Worker 		object.handle = gem_create(fd, 4096);
113*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
114*d83cc019SAndroid Build Coastguard Worker 
115*d83cc019SAndroid Build Coastguard Worker 		memset(&execbuf, 0, sizeof(execbuf));
116*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffers_ptr = to_user_pointer(&object);
117*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 1;
118*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags = engines[child % num_engines];
119*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
120*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, object.handle);
121*d83cc019SAndroid Build Coastguard Worker 
122*d83cc019SAndroid Build Coastguard Worker 		start = gettime();
123*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
124*d83cc019SAndroid Build Coastguard Worker 		do {
125*d83cc019SAndroid Build Coastguard Worker 			do {
126*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &execbuf);
127*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, object.handle);
128*d83cc019SAndroid Build Coastguard Worker 			} while (++cycles & 1023);
129*d83cc019SAndroid Build Coastguard Worker 		} while ((elapsed = gettime() - start) < timeout);
130*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%sompleted %ld cycles: %.3f us\n",
131*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ?: "",
132*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ? " c" : "C",
133*d83cc019SAndroid Build Coastguard Worker 			 cycles, elapsed*1e6/cycles);
134*d83cc019SAndroid Build Coastguard Worker 
135*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object.handle);
136*d83cc019SAndroid Build Coastguard Worker 	}
137*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(timeout+10, NULL);
138*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
139*d83cc019SAndroid Build Coastguard Worker }
140*d83cc019SAndroid Build Coastguard Worker 
141*d83cc019SAndroid Build Coastguard Worker static void
idle_ring(int fd,unsigned ring,int timeout)142*d83cc019SAndroid Build Coastguard Worker idle_ring(int fd, unsigned ring, int timeout)
143*d83cc019SAndroid Build Coastguard Worker {
144*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
145*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object;
146*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
147*d83cc019SAndroid Build Coastguard Worker 	double start, elapsed;
148*d83cc019SAndroid Build Coastguard Worker 	unsigned long cycles;
149*d83cc019SAndroid Build Coastguard Worker 
150*d83cc019SAndroid Build Coastguard Worker 	gem_require_ring(fd, ring);
151*d83cc019SAndroid Build Coastguard Worker 
152*d83cc019SAndroid Build Coastguard Worker 	memset(&object, 0, sizeof(object));
153*d83cc019SAndroid Build Coastguard Worker 	object.handle = gem_create(fd, 4096);
154*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
155*d83cc019SAndroid Build Coastguard Worker 
156*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
157*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&object);
158*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
159*d83cc019SAndroid Build Coastguard Worker 	execbuf.flags = ring;
160*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
161*d83cc019SAndroid Build Coastguard Worker 	gem_sync(fd, object.handle);
162*d83cc019SAndroid Build Coastguard Worker 
163*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
164*d83cc019SAndroid Build Coastguard Worker 	start = gettime();
165*d83cc019SAndroid Build Coastguard Worker 	cycles = 0;
166*d83cc019SAndroid Build Coastguard Worker 	do {
167*d83cc019SAndroid Build Coastguard Worker 		do {
168*d83cc019SAndroid Build Coastguard Worker 			gem_execbuf(fd, &execbuf);
169*d83cc019SAndroid Build Coastguard Worker 			gem_quiescent_gpu(fd);
170*d83cc019SAndroid Build Coastguard Worker 		} while (++cycles & 1023);
171*d83cc019SAndroid Build Coastguard Worker 	} while ((elapsed = gettime() - start) < timeout);
172*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
173*d83cc019SAndroid Build Coastguard Worker 
174*d83cc019SAndroid Build Coastguard Worker 	igt_info("Completed %ld cycles: %.3f us\n",
175*d83cc019SAndroid Build Coastguard Worker 		 cycles, elapsed*1e6/cycles);
176*d83cc019SAndroid Build Coastguard Worker 
177*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object.handle);
178*d83cc019SAndroid Build Coastguard Worker }
179*d83cc019SAndroid Build Coastguard Worker 
180*d83cc019SAndroid Build Coastguard Worker static void
wakeup_ring(int fd,unsigned ring,int timeout,int wlen)181*d83cc019SAndroid Build Coastguard Worker wakeup_ring(int fd, unsigned ring, int timeout, int wlen)
182*d83cc019SAndroid Build Coastguard Worker {
183*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16];
184*d83cc019SAndroid Build Coastguard Worker 	const char *names[16];
185*d83cc019SAndroid Build Coastguard Worker 	int num_engines = 0;
186*d83cc019SAndroid Build Coastguard Worker 
187*d83cc019SAndroid Build Coastguard Worker 	if (ring == ALL_ENGINES) {
188*d83cc019SAndroid Build Coastguard Worker 		for_each_physical_engine(fd, ring) {
189*d83cc019SAndroid Build Coastguard Worker 			if (!gem_can_store_dword(fd, ring))
190*d83cc019SAndroid Build Coastguard Worker 				continue;
191*d83cc019SAndroid Build Coastguard Worker 
192*d83cc019SAndroid Build Coastguard Worker 			names[num_engines] = e__->name;
193*d83cc019SAndroid Build Coastguard Worker 			engines[num_engines++] = ring;
194*d83cc019SAndroid Build Coastguard Worker 			if (num_engines == ARRAY_SIZE(engines))
195*d83cc019SAndroid Build Coastguard Worker 				break;
196*d83cc019SAndroid Build Coastguard Worker 		}
197*d83cc019SAndroid Build Coastguard Worker 		igt_require(num_engines);
198*d83cc019SAndroid Build Coastguard Worker 	} else {
199*d83cc019SAndroid Build Coastguard Worker 		gem_require_ring(fd, ring);
200*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_can_store_dword(fd, ring));
201*d83cc019SAndroid Build Coastguard Worker 		names[num_engines] = NULL;
202*d83cc019SAndroid Build Coastguard Worker 		engines[num_engines++] = ring;
203*d83cc019SAndroid Build Coastguard Worker 	}
204*d83cc019SAndroid Build Coastguard Worker 
205*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
206*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_engines) {
207*d83cc019SAndroid Build Coastguard Worker 		const uint32_t bbe = MI_BATCH_BUFFER_END;
208*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_exec_object2 object;
209*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_execbuffer2 execbuf;
210*d83cc019SAndroid Build Coastguard Worker 		double end, this, elapsed, now, baseline;
211*d83cc019SAndroid Build Coastguard Worker 		unsigned long cycles;
212*d83cc019SAndroid Build Coastguard Worker 		igt_spin_t *spin;
213*d83cc019SAndroid Build Coastguard Worker 
214*d83cc019SAndroid Build Coastguard Worker 		memset(&object, 0, sizeof(object));
215*d83cc019SAndroid Build Coastguard Worker 		object.handle = gem_create(fd, 4096);
216*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
217*d83cc019SAndroid Build Coastguard Worker 
218*d83cc019SAndroid Build Coastguard Worker 		memset(&execbuf, 0, sizeof(execbuf));
219*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffers_ptr = to_user_pointer(&object);
220*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 1;
221*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags = engines[child % num_engines];
222*d83cc019SAndroid Build Coastguard Worker 
223*d83cc019SAndroid Build Coastguard Worker 		spin = __igt_spin_new(fd,
224*d83cc019SAndroid Build Coastguard Worker 				      .engine = execbuf.flags,
225*d83cc019SAndroid Build Coastguard Worker 				      .flags = (IGT_SPIN_POLL_RUN |
226*d83cc019SAndroid Build Coastguard Worker 						IGT_SPIN_FAST));
227*d83cc019SAndroid Build Coastguard Worker 		igt_assert(igt_spin_has_poll(spin));
228*d83cc019SAndroid Build Coastguard Worker 
229*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
230*d83cc019SAndroid Build Coastguard Worker 
231*d83cc019SAndroid Build Coastguard Worker 		igt_spin_end(spin);
232*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, object.handle);
233*d83cc019SAndroid Build Coastguard Worker 
234*d83cc019SAndroid Build Coastguard Worker 		for (int warmup = 0; warmup <= 1; warmup++) {
235*d83cc019SAndroid Build Coastguard Worker 			end = gettime() + timeout/10.;
236*d83cc019SAndroid Build Coastguard Worker 			elapsed = 0;
237*d83cc019SAndroid Build Coastguard Worker 			cycles = 0;
238*d83cc019SAndroid Build Coastguard Worker 			do {
239*d83cc019SAndroid Build Coastguard Worker 				igt_spin_reset(spin);
240*d83cc019SAndroid Build Coastguard Worker 
241*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &spin->execbuf);
242*d83cc019SAndroid Build Coastguard Worker 				igt_spin_busywait_until_started(spin);
243*d83cc019SAndroid Build Coastguard Worker 
244*d83cc019SAndroid Build Coastguard Worker 				this = gettime();
245*d83cc019SAndroid Build Coastguard Worker 				igt_spin_end(spin);
246*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, spin->handle);
247*d83cc019SAndroid Build Coastguard Worker 				now = gettime();
248*d83cc019SAndroid Build Coastguard Worker 
249*d83cc019SAndroid Build Coastguard Worker 				elapsed += now - this;
250*d83cc019SAndroid Build Coastguard Worker 				cycles++;
251*d83cc019SAndroid Build Coastguard Worker 			} while (now < end);
252*d83cc019SAndroid Build Coastguard Worker 			baseline = elapsed / cycles;
253*d83cc019SAndroid Build Coastguard Worker 		}
254*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%saseline %ld cycles: %.3f us\n",
255*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ?: "",
256*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ? " b" : "B",
257*d83cc019SAndroid Build Coastguard Worker 			 cycles, elapsed*1e6/cycles);
258*d83cc019SAndroid Build Coastguard Worker 
259*d83cc019SAndroid Build Coastguard Worker 		end = gettime() + timeout;
260*d83cc019SAndroid Build Coastguard Worker 		elapsed = 0;
261*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
262*d83cc019SAndroid Build Coastguard Worker 		do {
263*d83cc019SAndroid Build Coastguard Worker 			igt_spin_reset(spin);
264*d83cc019SAndroid Build Coastguard Worker 
265*d83cc019SAndroid Build Coastguard Worker 			gem_execbuf(fd, &spin->execbuf);
266*d83cc019SAndroid Build Coastguard Worker 			igt_spin_busywait_until_started(spin);
267*d83cc019SAndroid Build Coastguard Worker 
268*d83cc019SAndroid Build Coastguard Worker 			for (int n = 0; n < wlen; n++)
269*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &execbuf);
270*d83cc019SAndroid Build Coastguard Worker 
271*d83cc019SAndroid Build Coastguard Worker 			this = gettime();
272*d83cc019SAndroid Build Coastguard Worker 			igt_spin_end(spin);
273*d83cc019SAndroid Build Coastguard Worker 			gem_sync(fd, object.handle);
274*d83cc019SAndroid Build Coastguard Worker 			now = gettime();
275*d83cc019SAndroid Build Coastguard Worker 
276*d83cc019SAndroid Build Coastguard Worker 			elapsed += now - this;
277*d83cc019SAndroid Build Coastguard Worker 			cycles++;
278*d83cc019SAndroid Build Coastguard Worker 		} while (now < end);
279*d83cc019SAndroid Build Coastguard Worker 		elapsed -= cycles * baseline;
280*d83cc019SAndroid Build Coastguard Worker 
281*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%sompleted %ld cycles: %.3f + %.3f us\n",
282*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ?: "",
283*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ? " c" : "C",
284*d83cc019SAndroid Build Coastguard Worker 			 cycles, 1e6*baseline, elapsed*1e6/cycles);
285*d83cc019SAndroid Build Coastguard Worker 
286*d83cc019SAndroid Build Coastguard Worker 		igt_spin_free(fd, spin);
287*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object.handle);
288*d83cc019SAndroid Build Coastguard Worker 	}
289*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(2*timeout, NULL);
290*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
291*d83cc019SAndroid Build Coastguard Worker }
292*d83cc019SAndroid Build Coastguard Worker 
active_ring(int fd,unsigned ring,int timeout)293*d83cc019SAndroid Build Coastguard Worker static void active_ring(int fd, unsigned ring, int timeout)
294*d83cc019SAndroid Build Coastguard Worker {
295*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16];
296*d83cc019SAndroid Build Coastguard Worker 	const char *names[16];
297*d83cc019SAndroid Build Coastguard Worker 	int num_engines = 0;
298*d83cc019SAndroid Build Coastguard Worker 
299*d83cc019SAndroid Build Coastguard Worker 	if (ring == ALL_ENGINES) {
300*d83cc019SAndroid Build Coastguard Worker 		for_each_physical_engine(fd, ring) {
301*d83cc019SAndroid Build Coastguard Worker 			if (!gem_can_store_dword(fd, ring))
302*d83cc019SAndroid Build Coastguard Worker 				continue;
303*d83cc019SAndroid Build Coastguard Worker 
304*d83cc019SAndroid Build Coastguard Worker 			names[num_engines] = e__->name;
305*d83cc019SAndroid Build Coastguard Worker 			engines[num_engines++] = ring;
306*d83cc019SAndroid Build Coastguard Worker 			if (num_engines == ARRAY_SIZE(engines))
307*d83cc019SAndroid Build Coastguard Worker 				break;
308*d83cc019SAndroid Build Coastguard Worker 		}
309*d83cc019SAndroid Build Coastguard Worker 		igt_require(num_engines);
310*d83cc019SAndroid Build Coastguard Worker 	} else {
311*d83cc019SAndroid Build Coastguard Worker 		gem_require_ring(fd, ring);
312*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_can_store_dword(fd, ring));
313*d83cc019SAndroid Build Coastguard Worker 		names[num_engines] = NULL;
314*d83cc019SAndroid Build Coastguard Worker 		engines[num_engines++] = ring;
315*d83cc019SAndroid Build Coastguard Worker 	}
316*d83cc019SAndroid Build Coastguard Worker 
317*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
318*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_engines) {
319*d83cc019SAndroid Build Coastguard Worker 		double start, end, elapsed;
320*d83cc019SAndroid Build Coastguard Worker 		unsigned long cycles;
321*d83cc019SAndroid Build Coastguard Worker 		igt_spin_t *spin[2];
322*d83cc019SAndroid Build Coastguard Worker 
323*d83cc019SAndroid Build Coastguard Worker 		spin[0] = __igt_spin_new(fd,
324*d83cc019SAndroid Build Coastguard Worker 					 .engine = ring,
325*d83cc019SAndroid Build Coastguard Worker 					 .flags = IGT_SPIN_FAST);
326*d83cc019SAndroid Build Coastguard Worker 
327*d83cc019SAndroid Build Coastguard Worker 		spin[1] = __igt_spin_new(fd,
328*d83cc019SAndroid Build Coastguard Worker 					 .engine = ring,
329*d83cc019SAndroid Build Coastguard Worker 					 .flags = IGT_SPIN_FAST);
330*d83cc019SAndroid Build Coastguard Worker 
331*d83cc019SAndroid Build Coastguard Worker 		start = gettime();
332*d83cc019SAndroid Build Coastguard Worker 		end = start + timeout;
333*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
334*d83cc019SAndroid Build Coastguard Worker 		do {
335*d83cc019SAndroid Build Coastguard Worker 			for (int loop = 0; loop < 1024; loop++) {
336*d83cc019SAndroid Build Coastguard Worker 				igt_spin_t *s = spin[loop & 1];
337*d83cc019SAndroid Build Coastguard Worker 
338*d83cc019SAndroid Build Coastguard Worker 				igt_spin_end(s);
339*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, s->handle);
340*d83cc019SAndroid Build Coastguard Worker 
341*d83cc019SAndroid Build Coastguard Worker 				igt_spin_reset(s);
342*d83cc019SAndroid Build Coastguard Worker 
343*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &s->execbuf);
344*d83cc019SAndroid Build Coastguard Worker 			}
345*d83cc019SAndroid Build Coastguard Worker 			cycles += 1024;
346*d83cc019SAndroid Build Coastguard Worker 		} while ((elapsed = gettime()) < end);
347*d83cc019SAndroid Build Coastguard Worker 		igt_spin_free(fd, spin[1]);
348*d83cc019SAndroid Build Coastguard Worker 		igt_spin_free(fd, spin[0]);
349*d83cc019SAndroid Build Coastguard Worker 
350*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%sompleted %ld cycles: %.3f us\n",
351*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ?: "",
352*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ? " c" : "C",
353*d83cc019SAndroid Build Coastguard Worker 			 cycles, (elapsed - start)*1e6/cycles);
354*d83cc019SAndroid Build Coastguard Worker 	}
355*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(2*timeout, NULL);
356*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
357*d83cc019SAndroid Build Coastguard Worker }
358*d83cc019SAndroid Build Coastguard Worker 
359*d83cc019SAndroid Build Coastguard Worker static void
active_wakeup_ring(int fd,unsigned ring,int timeout,int wlen)360*d83cc019SAndroid Build Coastguard Worker active_wakeup_ring(int fd, unsigned ring, int timeout, int wlen)
361*d83cc019SAndroid Build Coastguard Worker {
362*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16];
363*d83cc019SAndroid Build Coastguard Worker 	const char *names[16];
364*d83cc019SAndroid Build Coastguard Worker 	int num_engines = 0;
365*d83cc019SAndroid Build Coastguard Worker 
366*d83cc019SAndroid Build Coastguard Worker 	if (ring == ALL_ENGINES) {
367*d83cc019SAndroid Build Coastguard Worker 		for_each_physical_engine(fd, ring) {
368*d83cc019SAndroid Build Coastguard Worker 			if (!gem_can_store_dword(fd, ring))
369*d83cc019SAndroid Build Coastguard Worker 				continue;
370*d83cc019SAndroid Build Coastguard Worker 
371*d83cc019SAndroid Build Coastguard Worker 			names[num_engines] = e__->name;
372*d83cc019SAndroid Build Coastguard Worker 			engines[num_engines++] = ring;
373*d83cc019SAndroid Build Coastguard Worker 			if (num_engines == ARRAY_SIZE(engines))
374*d83cc019SAndroid Build Coastguard Worker 				break;
375*d83cc019SAndroid Build Coastguard Worker 		}
376*d83cc019SAndroid Build Coastguard Worker 		igt_require(num_engines);
377*d83cc019SAndroid Build Coastguard Worker 	} else {
378*d83cc019SAndroid Build Coastguard Worker 		gem_require_ring(fd, ring);
379*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_can_store_dword(fd, ring));
380*d83cc019SAndroid Build Coastguard Worker 		names[num_engines] = NULL;
381*d83cc019SAndroid Build Coastguard Worker 		engines[num_engines++] = ring;
382*d83cc019SAndroid Build Coastguard Worker 	}
383*d83cc019SAndroid Build Coastguard Worker 
384*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
385*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_engines) {
386*d83cc019SAndroid Build Coastguard Worker 		const uint32_t bbe = MI_BATCH_BUFFER_END;
387*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_exec_object2 object;
388*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_execbuffer2 execbuf;
389*d83cc019SAndroid Build Coastguard Worker 		double end, this, elapsed, now, baseline;
390*d83cc019SAndroid Build Coastguard Worker 		unsigned long cycles;
391*d83cc019SAndroid Build Coastguard Worker 		igt_spin_t *spin[2];
392*d83cc019SAndroid Build Coastguard Worker 
393*d83cc019SAndroid Build Coastguard Worker 		memset(&object, 0, sizeof(object));
394*d83cc019SAndroid Build Coastguard Worker 		object.handle = gem_create(fd, 4096);
395*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
396*d83cc019SAndroid Build Coastguard Worker 
397*d83cc019SAndroid Build Coastguard Worker 		memset(&execbuf, 0, sizeof(execbuf));
398*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffers_ptr = to_user_pointer(&object);
399*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 1;
400*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags = engines[child % num_engines];
401*d83cc019SAndroid Build Coastguard Worker 
402*d83cc019SAndroid Build Coastguard Worker 		spin[0] = __igt_spin_new(fd,
403*d83cc019SAndroid Build Coastguard Worker 					 .engine = execbuf.flags,
404*d83cc019SAndroid Build Coastguard Worker 					 .flags = (IGT_SPIN_POLL_RUN |
405*d83cc019SAndroid Build Coastguard Worker 						   IGT_SPIN_FAST));
406*d83cc019SAndroid Build Coastguard Worker 		igt_assert(igt_spin_has_poll(spin[0]));
407*d83cc019SAndroid Build Coastguard Worker 
408*d83cc019SAndroid Build Coastguard Worker 		spin[1] = __igt_spin_new(fd,
409*d83cc019SAndroid Build Coastguard Worker 					 .engine = execbuf.flags,
410*d83cc019SAndroid Build Coastguard Worker 					 .flags = (IGT_SPIN_POLL_RUN |
411*d83cc019SAndroid Build Coastguard Worker 						   IGT_SPIN_FAST));
412*d83cc019SAndroid Build Coastguard Worker 
413*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
414*d83cc019SAndroid Build Coastguard Worker 
415*d83cc019SAndroid Build Coastguard Worker 		igt_spin_end(spin[1]);
416*d83cc019SAndroid Build Coastguard Worker 		igt_spin_end(spin[0]);
417*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, object.handle);
418*d83cc019SAndroid Build Coastguard Worker 
419*d83cc019SAndroid Build Coastguard Worker 		for (int warmup = 0; warmup <= 1; warmup++) {
420*d83cc019SAndroid Build Coastguard Worker 			igt_spin_reset(spin[0]);
421*d83cc019SAndroid Build Coastguard Worker 
422*d83cc019SAndroid Build Coastguard Worker 			gem_execbuf(fd, &spin[0]->execbuf);
423*d83cc019SAndroid Build Coastguard Worker 
424*d83cc019SAndroid Build Coastguard Worker 			end = gettime() + timeout/10.;
425*d83cc019SAndroid Build Coastguard Worker 			elapsed = 0;
426*d83cc019SAndroid Build Coastguard Worker 			cycles = 0;
427*d83cc019SAndroid Build Coastguard Worker 			do {
428*d83cc019SAndroid Build Coastguard Worker 				igt_spin_busywait_until_started(spin[0]);
429*d83cc019SAndroid Build Coastguard Worker 
430*d83cc019SAndroid Build Coastguard Worker 				igt_spin_reset(spin[1]);
431*d83cc019SAndroid Build Coastguard Worker 
432*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &spin[1]->execbuf);
433*d83cc019SAndroid Build Coastguard Worker 
434*d83cc019SAndroid Build Coastguard Worker 				this = gettime();
435*d83cc019SAndroid Build Coastguard Worker 				igt_spin_end(spin[0]);
436*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, spin[0]->handle);
437*d83cc019SAndroid Build Coastguard Worker 				now = gettime();
438*d83cc019SAndroid Build Coastguard Worker 
439*d83cc019SAndroid Build Coastguard Worker 				elapsed += now - this;
440*d83cc019SAndroid Build Coastguard Worker 				cycles++;
441*d83cc019SAndroid Build Coastguard Worker 				igt_swap(spin[0], spin[1]);
442*d83cc019SAndroid Build Coastguard Worker 			} while (now < end);
443*d83cc019SAndroid Build Coastguard Worker 			igt_spin_end(spin[0]);
444*d83cc019SAndroid Build Coastguard Worker 			baseline = elapsed / cycles;
445*d83cc019SAndroid Build Coastguard Worker 		}
446*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%saseline %ld cycles: %.3f us\n",
447*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ?: "",
448*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ? " b" : "B",
449*d83cc019SAndroid Build Coastguard Worker 			 cycles, elapsed*1e6/cycles);
450*d83cc019SAndroid Build Coastguard Worker 
451*d83cc019SAndroid Build Coastguard Worker 		igt_spin_reset(spin[0]);
452*d83cc019SAndroid Build Coastguard Worker 
453*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &spin[0]->execbuf);
454*d83cc019SAndroid Build Coastguard Worker 
455*d83cc019SAndroid Build Coastguard Worker 		end = gettime() + timeout;
456*d83cc019SAndroid Build Coastguard Worker 		elapsed = 0;
457*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
458*d83cc019SAndroid Build Coastguard Worker 		do {
459*d83cc019SAndroid Build Coastguard Worker 			igt_spin_busywait_until_started(spin[0]);
460*d83cc019SAndroid Build Coastguard Worker 
461*d83cc019SAndroid Build Coastguard Worker 			for (int n = 0; n < wlen; n++)
462*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &execbuf);
463*d83cc019SAndroid Build Coastguard Worker 
464*d83cc019SAndroid Build Coastguard Worker 			igt_spin_reset(spin[1]);
465*d83cc019SAndroid Build Coastguard Worker 
466*d83cc019SAndroid Build Coastguard Worker 			gem_execbuf(fd, &spin[1]->execbuf);
467*d83cc019SAndroid Build Coastguard Worker 
468*d83cc019SAndroid Build Coastguard Worker 			this = gettime();
469*d83cc019SAndroid Build Coastguard Worker 			igt_spin_end(spin[0]);
470*d83cc019SAndroid Build Coastguard Worker 			gem_sync(fd, object.handle);
471*d83cc019SAndroid Build Coastguard Worker 			now = gettime();
472*d83cc019SAndroid Build Coastguard Worker 
473*d83cc019SAndroid Build Coastguard Worker 			elapsed += now - this;
474*d83cc019SAndroid Build Coastguard Worker 			cycles++;
475*d83cc019SAndroid Build Coastguard Worker 			igt_swap(spin[0], spin[1]);
476*d83cc019SAndroid Build Coastguard Worker 		} while (now < end);
477*d83cc019SAndroid Build Coastguard Worker 		igt_spin_end(spin[0]);
478*d83cc019SAndroid Build Coastguard Worker 		elapsed -= cycles * baseline;
479*d83cc019SAndroid Build Coastguard Worker 
480*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%sompleted %ld cycles: %.3f + %.3f us\n",
481*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ?: "",
482*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ? " c" : "C",
483*d83cc019SAndroid Build Coastguard Worker 			 cycles, 1e6*baseline, elapsed*1e6/cycles);
484*d83cc019SAndroid Build Coastguard Worker 
485*d83cc019SAndroid Build Coastguard Worker 		igt_spin_free(fd, spin[1]);
486*d83cc019SAndroid Build Coastguard Worker 		igt_spin_free(fd, spin[0]);
487*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object.handle);
488*d83cc019SAndroid Build Coastguard Worker 	}
489*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(2*timeout, NULL);
490*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
491*d83cc019SAndroid Build Coastguard Worker }
492*d83cc019SAndroid Build Coastguard Worker 
493*d83cc019SAndroid Build Coastguard Worker static void
store_ring(int fd,unsigned ring,int num_children,int timeout)494*d83cc019SAndroid Build Coastguard Worker store_ring(int fd, unsigned ring, int num_children, int timeout)
495*d83cc019SAndroid Build Coastguard Worker {
496*d83cc019SAndroid Build Coastguard Worker 	const int gen = intel_gen(intel_get_drm_devid(fd));
497*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16];
498*d83cc019SAndroid Build Coastguard Worker 	const char *names[16];
499*d83cc019SAndroid Build Coastguard Worker 	int num_engines = 0;
500*d83cc019SAndroid Build Coastguard Worker 
501*d83cc019SAndroid Build Coastguard Worker 	if (ring == ALL_ENGINES) {
502*d83cc019SAndroid Build Coastguard Worker 		for_each_physical_engine(fd, ring) {
503*d83cc019SAndroid Build Coastguard Worker 			if (!gem_can_store_dword(fd, ring))
504*d83cc019SAndroid Build Coastguard Worker 				continue;
505*d83cc019SAndroid Build Coastguard Worker 
506*d83cc019SAndroid Build Coastguard Worker 			names[num_engines] = e__->name;
507*d83cc019SAndroid Build Coastguard Worker 			engines[num_engines++] = ring;
508*d83cc019SAndroid Build Coastguard Worker 			if (num_engines == ARRAY_SIZE(engines))
509*d83cc019SAndroid Build Coastguard Worker 				break;
510*d83cc019SAndroid Build Coastguard Worker 		}
511*d83cc019SAndroid Build Coastguard Worker 
512*d83cc019SAndroid Build Coastguard Worker 		num_children *= num_engines;
513*d83cc019SAndroid Build Coastguard Worker 	} else {
514*d83cc019SAndroid Build Coastguard Worker 		gem_require_ring(fd, ring);
515*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_can_store_dword(fd, ring));
516*d83cc019SAndroid Build Coastguard Worker 		names[num_engines] = NULL;
517*d83cc019SAndroid Build Coastguard Worker 		engines[num_engines++] = ring;
518*d83cc019SAndroid Build Coastguard Worker 	}
519*d83cc019SAndroid Build Coastguard Worker 
520*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
521*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_children) {
522*d83cc019SAndroid Build Coastguard Worker 		const uint32_t bbe = MI_BATCH_BUFFER_END;
523*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_exec_object2 object[2];
524*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_relocation_entry reloc[1024];
525*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_execbuffer2 execbuf;
526*d83cc019SAndroid Build Coastguard Worker 		double start, elapsed;
527*d83cc019SAndroid Build Coastguard Worker 		unsigned long cycles;
528*d83cc019SAndroid Build Coastguard Worker 		uint32_t *batch, *b;
529*d83cc019SAndroid Build Coastguard Worker 
530*d83cc019SAndroid Build Coastguard Worker 		memset(&execbuf, 0, sizeof(execbuf));
531*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffers_ptr = to_user_pointer(object);
532*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags = engines[child % num_engines];
533*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
534*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT;
535*d83cc019SAndroid Build Coastguard Worker 		if (gen < 6)
536*d83cc019SAndroid Build Coastguard Worker 			execbuf.flags |= I915_EXEC_SECURE;
537*d83cc019SAndroid Build Coastguard Worker 
538*d83cc019SAndroid Build Coastguard Worker 		memset(object, 0, sizeof(object));
539*d83cc019SAndroid Build Coastguard Worker 		object[0].handle = gem_create(fd, 4096);
540*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, object[0].handle, 0, &bbe, sizeof(bbe));
541*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 1;
542*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
543*d83cc019SAndroid Build Coastguard Worker 
544*d83cc019SAndroid Build Coastguard Worker 		object[0].flags |= EXEC_OBJECT_WRITE;
545*d83cc019SAndroid Build Coastguard Worker 		object[1].handle = gem_create(fd, 20*1024);
546*d83cc019SAndroid Build Coastguard Worker 
547*d83cc019SAndroid Build Coastguard Worker 		object[1].relocs_ptr = to_user_pointer(reloc);
548*d83cc019SAndroid Build Coastguard Worker 		object[1].relocation_count = 1024;
549*d83cc019SAndroid Build Coastguard Worker 
550*d83cc019SAndroid Build Coastguard Worker 		batch = gem_mmap__cpu(fd, object[1].handle, 0, 20*1024,
551*d83cc019SAndroid Build Coastguard Worker 				PROT_WRITE | PROT_READ);
552*d83cc019SAndroid Build Coastguard Worker 		gem_set_domain(fd, object[1].handle,
553*d83cc019SAndroid Build Coastguard Worker 				I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
554*d83cc019SAndroid Build Coastguard Worker 
555*d83cc019SAndroid Build Coastguard Worker 		memset(reloc, 0, sizeof(reloc));
556*d83cc019SAndroid Build Coastguard Worker 		b = batch;
557*d83cc019SAndroid Build Coastguard Worker 		for (int i = 0; i < 1024; i++) {
558*d83cc019SAndroid Build Coastguard Worker 			uint64_t offset;
559*d83cc019SAndroid Build Coastguard Worker 
560*d83cc019SAndroid Build Coastguard Worker 			reloc[i].presumed_offset = object[0].offset;
561*d83cc019SAndroid Build Coastguard Worker 			reloc[i].offset = (b - batch + 1) * sizeof(*batch);
562*d83cc019SAndroid Build Coastguard Worker 			reloc[i].delta = i * sizeof(uint32_t);
563*d83cc019SAndroid Build Coastguard Worker 			reloc[i].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
564*d83cc019SAndroid Build Coastguard Worker 			reloc[i].write_domain = I915_GEM_DOMAIN_INSTRUCTION;
565*d83cc019SAndroid Build Coastguard Worker 
566*d83cc019SAndroid Build Coastguard Worker 			offset = object[0].offset + reloc[i].delta;
567*d83cc019SAndroid Build Coastguard Worker 			*b++ = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
568*d83cc019SAndroid Build Coastguard Worker 			if (gen >= 8) {
569*d83cc019SAndroid Build Coastguard Worker 				*b++ = offset;
570*d83cc019SAndroid Build Coastguard Worker 				*b++ = offset >> 32;
571*d83cc019SAndroid Build Coastguard Worker 			} else if (gen >= 4) {
572*d83cc019SAndroid Build Coastguard Worker 				*b++ = 0;
573*d83cc019SAndroid Build Coastguard Worker 				*b++ = offset;
574*d83cc019SAndroid Build Coastguard Worker 				reloc[i].offset += sizeof(*batch);
575*d83cc019SAndroid Build Coastguard Worker 			} else {
576*d83cc019SAndroid Build Coastguard Worker 				b[-1] -= 1;
577*d83cc019SAndroid Build Coastguard Worker 				*b++ = offset;
578*d83cc019SAndroid Build Coastguard Worker 			}
579*d83cc019SAndroid Build Coastguard Worker 			*b++ = i;
580*d83cc019SAndroid Build Coastguard Worker 		}
581*d83cc019SAndroid Build Coastguard Worker 		*b++ = MI_BATCH_BUFFER_END;
582*d83cc019SAndroid Build Coastguard Worker 		igt_assert((b - batch)*sizeof(uint32_t) < 20*1024);
583*d83cc019SAndroid Build Coastguard Worker 		munmap(batch, 20*1024);
584*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 2;
585*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
586*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, object[1].handle);
587*d83cc019SAndroid Build Coastguard Worker 
588*d83cc019SAndroid Build Coastguard Worker 		start = gettime();
589*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
590*d83cc019SAndroid Build Coastguard Worker 		do {
591*d83cc019SAndroid Build Coastguard Worker 			do {
592*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &execbuf);
593*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, object[1].handle);
594*d83cc019SAndroid Build Coastguard Worker 			} while (++cycles & 1023);
595*d83cc019SAndroid Build Coastguard Worker 		} while ((elapsed = gettime() - start) < timeout);
596*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%sompleted %ld cycles: %.3f us\n",
597*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ?: "",
598*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ? " c" : "C",
599*d83cc019SAndroid Build Coastguard Worker 			 cycles, elapsed*1e6/cycles);
600*d83cc019SAndroid Build Coastguard Worker 
601*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object[1].handle);
602*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object[0].handle);
603*d83cc019SAndroid Build Coastguard Worker 	}
604*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(timeout+10, NULL);
605*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
606*d83cc019SAndroid Build Coastguard Worker }
607*d83cc019SAndroid Build Coastguard Worker 
608*d83cc019SAndroid Build Coastguard Worker static void
switch_ring(int fd,unsigned ring,int num_children,int timeout)609*d83cc019SAndroid Build Coastguard Worker switch_ring(int fd, unsigned ring, int num_children, int timeout)
610*d83cc019SAndroid Build Coastguard Worker {
611*d83cc019SAndroid Build Coastguard Worker 	const int gen = intel_gen(intel_get_drm_devid(fd));
612*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16];
613*d83cc019SAndroid Build Coastguard Worker 	const char *names[16];
614*d83cc019SAndroid Build Coastguard Worker 	int num_engines = 0;
615*d83cc019SAndroid Build Coastguard Worker 
616*d83cc019SAndroid Build Coastguard Worker 	gem_require_contexts(fd);
617*d83cc019SAndroid Build Coastguard Worker 
618*d83cc019SAndroid Build Coastguard Worker 	if (ring == ALL_ENGINES) {
619*d83cc019SAndroid Build Coastguard Worker 		for_each_physical_engine(fd, ring) {
620*d83cc019SAndroid Build Coastguard Worker 			if (!gem_can_store_dword(fd, ring))
621*d83cc019SAndroid Build Coastguard Worker 				continue;
622*d83cc019SAndroid Build Coastguard Worker 
623*d83cc019SAndroid Build Coastguard Worker 			names[num_engines] = e__->name;
624*d83cc019SAndroid Build Coastguard Worker 			engines[num_engines++] = ring;
625*d83cc019SAndroid Build Coastguard Worker 			if (num_engines == ARRAY_SIZE(engines))
626*d83cc019SAndroid Build Coastguard Worker 				break;
627*d83cc019SAndroid Build Coastguard Worker 		}
628*d83cc019SAndroid Build Coastguard Worker 
629*d83cc019SAndroid Build Coastguard Worker 		num_children *= num_engines;
630*d83cc019SAndroid Build Coastguard Worker 	} else {
631*d83cc019SAndroid Build Coastguard Worker 		gem_require_ring(fd, ring);
632*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_can_store_dword(fd, ring));
633*d83cc019SAndroid Build Coastguard Worker 		names[num_engines] = NULL;
634*d83cc019SAndroid Build Coastguard Worker 		engines[num_engines++] = ring;
635*d83cc019SAndroid Build Coastguard Worker 	}
636*d83cc019SAndroid Build Coastguard Worker 
637*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
638*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_children) {
639*d83cc019SAndroid Build Coastguard Worker 		struct context {
640*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_exec_object2 object[2];
641*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_relocation_entry reloc[1024];
642*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_execbuffer2 execbuf;
643*d83cc019SAndroid Build Coastguard Worker 		} contexts[2];
644*d83cc019SAndroid Build Coastguard Worker 		double elapsed, baseline;
645*d83cc019SAndroid Build Coastguard Worker 		unsigned long cycles;
646*d83cc019SAndroid Build Coastguard Worker 
647*d83cc019SAndroid Build Coastguard Worker 		for (int i = 0; i < ARRAY_SIZE(contexts); i++) {
648*d83cc019SAndroid Build Coastguard Worker 			const uint32_t bbe = MI_BATCH_BUFFER_END;
649*d83cc019SAndroid Build Coastguard Worker 			const uint32_t sz = 32 << 10;
650*d83cc019SAndroid Build Coastguard Worker 			struct context *c = &contexts[i];
651*d83cc019SAndroid Build Coastguard Worker 			uint32_t *batch, *b;
652*d83cc019SAndroid Build Coastguard Worker 
653*d83cc019SAndroid Build Coastguard Worker 			memset(&c->execbuf, 0, sizeof(c->execbuf));
654*d83cc019SAndroid Build Coastguard Worker 			c->execbuf.buffers_ptr = to_user_pointer(c->object);
655*d83cc019SAndroid Build Coastguard Worker 			c->execbuf.flags = engines[child % num_engines];
656*d83cc019SAndroid Build Coastguard Worker 			c->execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
657*d83cc019SAndroid Build Coastguard Worker 			c->execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT;
658*d83cc019SAndroid Build Coastguard Worker 			if (gen < 6)
659*d83cc019SAndroid Build Coastguard Worker 				c->execbuf.flags |= I915_EXEC_SECURE;
660*d83cc019SAndroid Build Coastguard Worker 			c->execbuf.rsvd1 = gem_context_create(fd);
661*d83cc019SAndroid Build Coastguard Worker 
662*d83cc019SAndroid Build Coastguard Worker 			memset(c->object, 0, sizeof(c->object));
663*d83cc019SAndroid Build Coastguard Worker 			c->object[0].handle = gem_create(fd, 4096);
664*d83cc019SAndroid Build Coastguard Worker 			gem_write(fd, c->object[0].handle, 0, &bbe, sizeof(bbe));
665*d83cc019SAndroid Build Coastguard Worker 			c->execbuf.buffer_count = 1;
666*d83cc019SAndroid Build Coastguard Worker 			gem_execbuf(fd, &c->execbuf);
667*d83cc019SAndroid Build Coastguard Worker 
668*d83cc019SAndroid Build Coastguard Worker 			c->object[0].flags |= EXEC_OBJECT_WRITE;
669*d83cc019SAndroid Build Coastguard Worker 			c->object[1].handle = gem_create(fd, sz);
670*d83cc019SAndroid Build Coastguard Worker 
671*d83cc019SAndroid Build Coastguard Worker 			c->object[1].relocs_ptr = to_user_pointer(c->reloc);
672*d83cc019SAndroid Build Coastguard Worker 			c->object[1].relocation_count = 1024 * i;
673*d83cc019SAndroid Build Coastguard Worker 
674*d83cc019SAndroid Build Coastguard Worker 			batch = gem_mmap__cpu(fd, c->object[1].handle, 0, sz,
675*d83cc019SAndroid Build Coastguard Worker 					PROT_WRITE | PROT_READ);
676*d83cc019SAndroid Build Coastguard Worker 			gem_set_domain(fd, c->object[1].handle,
677*d83cc019SAndroid Build Coastguard Worker 					I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
678*d83cc019SAndroid Build Coastguard Worker 
679*d83cc019SAndroid Build Coastguard Worker 			memset(c->reloc, 0, sizeof(c->reloc));
680*d83cc019SAndroid Build Coastguard Worker 			b = batch;
681*d83cc019SAndroid Build Coastguard Worker 			for (int r = 0; r < c->object[1].relocation_count; r++) {
682*d83cc019SAndroid Build Coastguard Worker 				uint64_t offset;
683*d83cc019SAndroid Build Coastguard Worker 
684*d83cc019SAndroid Build Coastguard Worker 				c->reloc[r].presumed_offset = c->object[0].offset;
685*d83cc019SAndroid Build Coastguard Worker 				c->reloc[r].offset = (b - batch + 1) * sizeof(*batch);
686*d83cc019SAndroid Build Coastguard Worker 				c->reloc[r].delta = r * sizeof(uint32_t);
687*d83cc019SAndroid Build Coastguard Worker 				c->reloc[r].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
688*d83cc019SAndroid Build Coastguard Worker 				c->reloc[r].write_domain = I915_GEM_DOMAIN_INSTRUCTION;
689*d83cc019SAndroid Build Coastguard Worker 
690*d83cc019SAndroid Build Coastguard Worker 				offset = c->object[0].offset + c->reloc[r].delta;
691*d83cc019SAndroid Build Coastguard Worker 				*b++ = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
692*d83cc019SAndroid Build Coastguard Worker 				if (gen >= 8) {
693*d83cc019SAndroid Build Coastguard Worker 					*b++ = offset;
694*d83cc019SAndroid Build Coastguard Worker 					*b++ = offset >> 32;
695*d83cc019SAndroid Build Coastguard Worker 				} else if (gen >= 4) {
696*d83cc019SAndroid Build Coastguard Worker 					*b++ = 0;
697*d83cc019SAndroid Build Coastguard Worker 					*b++ = offset;
698*d83cc019SAndroid Build Coastguard Worker 					c->reloc[r].offset += sizeof(*batch);
699*d83cc019SAndroid Build Coastguard Worker 				} else {
700*d83cc019SAndroid Build Coastguard Worker 					b[-1] -= 1;
701*d83cc019SAndroid Build Coastguard Worker 					*b++ = offset;
702*d83cc019SAndroid Build Coastguard Worker 				}
703*d83cc019SAndroid Build Coastguard Worker 				*b++ = r;
704*d83cc019SAndroid Build Coastguard Worker 				*b++ = 0x5 << 23;
705*d83cc019SAndroid Build Coastguard Worker 			}
706*d83cc019SAndroid Build Coastguard Worker 			*b++ = MI_BATCH_BUFFER_END;
707*d83cc019SAndroid Build Coastguard Worker 			igt_assert((b - batch)*sizeof(uint32_t) < sz);
708*d83cc019SAndroid Build Coastguard Worker 			munmap(batch, sz);
709*d83cc019SAndroid Build Coastguard Worker 			c->execbuf.buffer_count = 2;
710*d83cc019SAndroid Build Coastguard Worker 			gem_execbuf(fd, &c->execbuf);
711*d83cc019SAndroid Build Coastguard Worker 			gem_sync(fd, c->object[1].handle);
712*d83cc019SAndroid Build Coastguard Worker 		}
713*d83cc019SAndroid Build Coastguard Worker 
714*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
715*d83cc019SAndroid Build Coastguard Worker 		baseline = 0;
716*d83cc019SAndroid Build Coastguard Worker 		igt_until_timeout(timeout) {
717*d83cc019SAndroid Build Coastguard Worker 			do {
718*d83cc019SAndroid Build Coastguard Worker 				double this;
719*d83cc019SAndroid Build Coastguard Worker 
720*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &contexts[1].execbuf);
721*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &contexts[0].execbuf);
722*d83cc019SAndroid Build Coastguard Worker 
723*d83cc019SAndroid Build Coastguard Worker 				this = gettime();
724*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, contexts[1].object[1].handle);
725*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, contexts[0].object[1].handle);
726*d83cc019SAndroid Build Coastguard Worker 				baseline += gettime() - this;
727*d83cc019SAndroid Build Coastguard Worker 			} while (++cycles & 1023);
728*d83cc019SAndroid Build Coastguard Worker 		}
729*d83cc019SAndroid Build Coastguard Worker 		baseline /= cycles;
730*d83cc019SAndroid Build Coastguard Worker 
731*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
732*d83cc019SAndroid Build Coastguard Worker 		elapsed = 0;
733*d83cc019SAndroid Build Coastguard Worker 		igt_until_timeout(timeout) {
734*d83cc019SAndroid Build Coastguard Worker 			do {
735*d83cc019SAndroid Build Coastguard Worker 				double this;
736*d83cc019SAndroid Build Coastguard Worker 
737*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &contexts[1].execbuf);
738*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &contexts[0].execbuf);
739*d83cc019SAndroid Build Coastguard Worker 
740*d83cc019SAndroid Build Coastguard Worker 				this = gettime();
741*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, contexts[0].object[1].handle);
742*d83cc019SAndroid Build Coastguard Worker 				elapsed += gettime() - this;
743*d83cc019SAndroid Build Coastguard Worker 
744*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, contexts[1].object[1].handle);
745*d83cc019SAndroid Build Coastguard Worker 			} while (++cycles & 1023);
746*d83cc019SAndroid Build Coastguard Worker 		}
747*d83cc019SAndroid Build Coastguard Worker 		elapsed /= cycles;
748*d83cc019SAndroid Build Coastguard Worker 
749*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%sompleted %ld cycles: %.3f us, baseline %.3f us\n",
750*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ?: "",
751*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ? " c" : "C",
752*d83cc019SAndroid Build Coastguard Worker 			 cycles, elapsed*1e6, baseline*1e6);
753*d83cc019SAndroid Build Coastguard Worker 
754*d83cc019SAndroid Build Coastguard Worker 		for (int i = 0; i < ARRAY_SIZE(contexts); i++) {
755*d83cc019SAndroid Build Coastguard Worker 			gem_close(fd, contexts[i].object[1].handle);
756*d83cc019SAndroid Build Coastguard Worker 			gem_close(fd, contexts[i].object[0].handle);
757*d83cc019SAndroid Build Coastguard Worker 			gem_context_destroy(fd, contexts[i].execbuf.rsvd1);
758*d83cc019SAndroid Build Coastguard Worker 		}
759*d83cc019SAndroid Build Coastguard Worker 	}
760*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(timeout+10, NULL);
761*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
762*d83cc019SAndroid Build Coastguard Worker }
763*d83cc019SAndroid Build Coastguard Worker 
xchg(void * array,unsigned i,unsigned j)764*d83cc019SAndroid Build Coastguard Worker static void xchg(void *array, unsigned i, unsigned j)
765*d83cc019SAndroid Build Coastguard Worker {
766*d83cc019SAndroid Build Coastguard Worker 	uint32_t *u32 = array;
767*d83cc019SAndroid Build Coastguard Worker 	uint32_t tmp = u32[i];
768*d83cc019SAndroid Build Coastguard Worker 	u32[i] = u32[j];
769*d83cc019SAndroid Build Coastguard Worker 	u32[j] = tmp;
770*d83cc019SAndroid Build Coastguard Worker }
771*d83cc019SAndroid Build Coastguard Worker 
772*d83cc019SAndroid Build Coastguard Worker struct waiter {
773*d83cc019SAndroid Build Coastguard Worker 	pthread_t thread;
774*d83cc019SAndroid Build Coastguard Worker 	pthread_mutex_t mutex;
775*d83cc019SAndroid Build Coastguard Worker 	pthread_cond_t cond;
776*d83cc019SAndroid Build Coastguard Worker 
777*d83cc019SAndroid Build Coastguard Worker 	int ready;
778*d83cc019SAndroid Build Coastguard Worker 	volatile int *done;
779*d83cc019SAndroid Build Coastguard Worker 
780*d83cc019SAndroid Build Coastguard Worker 	int fd;
781*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object;
782*d83cc019SAndroid Build Coastguard Worker 	uint32_t handles[64];
783*d83cc019SAndroid Build Coastguard Worker };
784*d83cc019SAndroid Build Coastguard Worker 
waiter(void * arg)785*d83cc019SAndroid Build Coastguard Worker static void *waiter(void *arg)
786*d83cc019SAndroid Build Coastguard Worker {
787*d83cc019SAndroid Build Coastguard Worker 	struct waiter *w = arg;
788*d83cc019SAndroid Build Coastguard Worker 
789*d83cc019SAndroid Build Coastguard Worker 	do {
790*d83cc019SAndroid Build Coastguard Worker 		pthread_mutex_lock(&w->mutex);
791*d83cc019SAndroid Build Coastguard Worker 		w->ready = 0;
792*d83cc019SAndroid Build Coastguard Worker 		pthread_cond_signal(&w->cond);
793*d83cc019SAndroid Build Coastguard Worker 		while (!w->ready)
794*d83cc019SAndroid Build Coastguard Worker 			pthread_cond_wait(&w->cond, &w->mutex);
795*d83cc019SAndroid Build Coastguard Worker 		pthread_mutex_unlock(&w->mutex);
796*d83cc019SAndroid Build Coastguard Worker 		if (*w->done < 0)
797*d83cc019SAndroid Build Coastguard Worker 			return NULL;
798*d83cc019SAndroid Build Coastguard Worker 
799*d83cc019SAndroid Build Coastguard Worker 		gem_sync(w->fd, w->object.handle);
800*d83cc019SAndroid Build Coastguard Worker 		for (int n = 0;  n < ARRAY_SIZE(w->handles); n++)
801*d83cc019SAndroid Build Coastguard Worker 			gem_sync(w->fd, w->handles[n]);
802*d83cc019SAndroid Build Coastguard Worker 	} while (1);
803*d83cc019SAndroid Build Coastguard Worker }
804*d83cc019SAndroid Build Coastguard Worker 
805*d83cc019SAndroid Build Coastguard Worker static void
__store_many(int fd,unsigned ring,int timeout,unsigned long * cycles)806*d83cc019SAndroid Build Coastguard Worker __store_many(int fd, unsigned ring, int timeout, unsigned long *cycles)
807*d83cc019SAndroid Build Coastguard Worker {
808*d83cc019SAndroid Build Coastguard Worker 	const int gen = intel_gen(intel_get_drm_devid(fd));
809*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
810*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object[2];
811*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
812*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_relocation_entry reloc[1024];
813*d83cc019SAndroid Build Coastguard Worker 	struct waiter threads[64];
814*d83cc019SAndroid Build Coastguard Worker 	int order[64];
815*d83cc019SAndroid Build Coastguard Worker 	uint32_t *batch, *b;
816*d83cc019SAndroid Build Coastguard Worker 	int done;
817*d83cc019SAndroid Build Coastguard Worker 
818*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
819*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(object);
820*d83cc019SAndroid Build Coastguard Worker 	execbuf.flags = ring;
821*d83cc019SAndroid Build Coastguard Worker 	execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
822*d83cc019SAndroid Build Coastguard Worker 	execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT;
823*d83cc019SAndroid Build Coastguard Worker 	if (gen < 6)
824*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags |= I915_EXEC_SECURE;
825*d83cc019SAndroid Build Coastguard Worker 
826*d83cc019SAndroid Build Coastguard Worker 	memset(object, 0, sizeof(object));
827*d83cc019SAndroid Build Coastguard Worker 	object[0].handle = gem_create(fd, 4096);
828*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, object[0].handle, 0, &bbe, sizeof(bbe));
829*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
830*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
831*d83cc019SAndroid Build Coastguard Worker 	object[0].flags |= EXEC_OBJECT_WRITE;
832*d83cc019SAndroid Build Coastguard Worker 
833*d83cc019SAndroid Build Coastguard Worker 	object[1].relocs_ptr = to_user_pointer(reloc);
834*d83cc019SAndroid Build Coastguard Worker 	object[1].relocation_count = 1024;
835*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 2;
836*d83cc019SAndroid Build Coastguard Worker 
837*d83cc019SAndroid Build Coastguard Worker 	memset(reloc, 0, sizeof(reloc));
838*d83cc019SAndroid Build Coastguard Worker 	b = batch = malloc(20*1024);
839*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < 1024; i++) {
840*d83cc019SAndroid Build Coastguard Worker 		uint64_t offset;
841*d83cc019SAndroid Build Coastguard Worker 
842*d83cc019SAndroid Build Coastguard Worker 		reloc[i].presumed_offset = object[0].offset;
843*d83cc019SAndroid Build Coastguard Worker 		reloc[i].offset = (b - batch + 1) * sizeof(*batch);
844*d83cc019SAndroid Build Coastguard Worker 		reloc[i].delta = i * sizeof(uint32_t);
845*d83cc019SAndroid Build Coastguard Worker 		reloc[i].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
846*d83cc019SAndroid Build Coastguard Worker 		reloc[i].write_domain = I915_GEM_DOMAIN_INSTRUCTION;
847*d83cc019SAndroid Build Coastguard Worker 
848*d83cc019SAndroid Build Coastguard Worker 		offset = object[0].offset + reloc[i].delta;
849*d83cc019SAndroid Build Coastguard Worker 		*b++ = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
850*d83cc019SAndroid Build Coastguard Worker 		if (gen >= 8) {
851*d83cc019SAndroid Build Coastguard Worker 			*b++ = offset;
852*d83cc019SAndroid Build Coastguard Worker 			*b++ = offset >> 32;
853*d83cc019SAndroid Build Coastguard Worker 		} else if (gen >= 4) {
854*d83cc019SAndroid Build Coastguard Worker 			*b++ = 0;
855*d83cc019SAndroid Build Coastguard Worker 			*b++ = offset;
856*d83cc019SAndroid Build Coastguard Worker 			reloc[i].offset += sizeof(*batch);
857*d83cc019SAndroid Build Coastguard Worker 		} else {
858*d83cc019SAndroid Build Coastguard Worker 			b[-1] -= 1;
859*d83cc019SAndroid Build Coastguard Worker 			*b++ = offset;
860*d83cc019SAndroid Build Coastguard Worker 		}
861*d83cc019SAndroid Build Coastguard Worker 		*b++ = i;
862*d83cc019SAndroid Build Coastguard Worker 	}
863*d83cc019SAndroid Build Coastguard Worker 	*b++ = MI_BATCH_BUFFER_END;
864*d83cc019SAndroid Build Coastguard Worker 	igt_assert((b - batch)*sizeof(uint32_t) < 20*1024);
865*d83cc019SAndroid Build Coastguard Worker 
866*d83cc019SAndroid Build Coastguard Worker 	done = 0;
867*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < ARRAY_SIZE(threads); i++) {
868*d83cc019SAndroid Build Coastguard Worker 		threads[i].fd = fd;
869*d83cc019SAndroid Build Coastguard Worker 		threads[i].object = object[1];
870*d83cc019SAndroid Build Coastguard Worker 		threads[i].object.handle = gem_create(fd, 20*1024);
871*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, threads[i].object.handle, 0, batch, 20*1024);
872*d83cc019SAndroid Build Coastguard Worker 
873*d83cc019SAndroid Build Coastguard Worker 		pthread_cond_init(&threads[i].cond, NULL);
874*d83cc019SAndroid Build Coastguard Worker 		pthread_mutex_init(&threads[i].mutex, NULL);
875*d83cc019SAndroid Build Coastguard Worker 		threads[i].done = &done;
876*d83cc019SAndroid Build Coastguard Worker 		threads[i].ready = 0;
877*d83cc019SAndroid Build Coastguard Worker 
878*d83cc019SAndroid Build Coastguard Worker 		pthread_create(&threads[i].thread, NULL, waiter, &threads[i]);
879*d83cc019SAndroid Build Coastguard Worker 		order[i] = i;
880*d83cc019SAndroid Build Coastguard Worker 	}
881*d83cc019SAndroid Build Coastguard Worker 	free(batch);
882*d83cc019SAndroid Build Coastguard Worker 
883*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < ARRAY_SIZE(threads); i++) {
884*d83cc019SAndroid Build Coastguard Worker 		for (int j = 0; j < ARRAY_SIZE(threads); j++)
885*d83cc019SAndroid Build Coastguard Worker 			threads[i].handles[j] = threads[j].object.handle;
886*d83cc019SAndroid Build Coastguard Worker 	}
887*d83cc019SAndroid Build Coastguard Worker 
888*d83cc019SAndroid Build Coastguard Worker 	igt_until_timeout(timeout) {
889*d83cc019SAndroid Build Coastguard Worker 		for (int i = 0; i < ARRAY_SIZE(threads); i++) {
890*d83cc019SAndroid Build Coastguard Worker 			pthread_mutex_lock(&threads[i].mutex);
891*d83cc019SAndroid Build Coastguard Worker 			while (threads[i].ready)
892*d83cc019SAndroid Build Coastguard Worker 				pthread_cond_wait(&threads[i].cond,
893*d83cc019SAndroid Build Coastguard Worker 						  &threads[i].mutex);
894*d83cc019SAndroid Build Coastguard Worker 			pthread_mutex_unlock(&threads[i].mutex);
895*d83cc019SAndroid Build Coastguard Worker 			igt_permute_array(threads[i].handles,
896*d83cc019SAndroid Build Coastguard Worker 					  ARRAY_SIZE(threads[i].handles),
897*d83cc019SAndroid Build Coastguard Worker 					  xchg);
898*d83cc019SAndroid Build Coastguard Worker 		}
899*d83cc019SAndroid Build Coastguard Worker 
900*d83cc019SAndroid Build Coastguard Worker 		igt_permute_array(order, ARRAY_SIZE(threads), xchg);
901*d83cc019SAndroid Build Coastguard Worker 		for (int i = 0; i < ARRAY_SIZE(threads); i++) {
902*d83cc019SAndroid Build Coastguard Worker 			object[1] = threads[i].object;
903*d83cc019SAndroid Build Coastguard Worker 			gem_execbuf(fd, &execbuf);
904*d83cc019SAndroid Build Coastguard Worker 			threads[i].object = object[1];
905*d83cc019SAndroid Build Coastguard Worker 		}
906*d83cc019SAndroid Build Coastguard Worker 		++*cycles;
907*d83cc019SAndroid Build Coastguard Worker 
908*d83cc019SAndroid Build Coastguard Worker 		for (int i = 0; i < ARRAY_SIZE(threads); i++) {
909*d83cc019SAndroid Build Coastguard Worker 			struct waiter *w = &threads[order[i]];
910*d83cc019SAndroid Build Coastguard Worker 
911*d83cc019SAndroid Build Coastguard Worker 			w->ready = 1;
912*d83cc019SAndroid Build Coastguard Worker 			pthread_cond_signal(&w->cond);
913*d83cc019SAndroid Build Coastguard Worker 		}
914*d83cc019SAndroid Build Coastguard Worker 	}
915*d83cc019SAndroid Build Coastguard Worker 
916*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < ARRAY_SIZE(threads); i++) {
917*d83cc019SAndroid Build Coastguard Worker 		pthread_mutex_lock(&threads[i].mutex);
918*d83cc019SAndroid Build Coastguard Worker 		while (threads[i].ready)
919*d83cc019SAndroid Build Coastguard Worker 			pthread_cond_wait(&threads[i].cond, &threads[i].mutex);
920*d83cc019SAndroid Build Coastguard Worker 		pthread_mutex_unlock(&threads[i].mutex);
921*d83cc019SAndroid Build Coastguard Worker 	}
922*d83cc019SAndroid Build Coastguard Worker 	done = -1;
923*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < ARRAY_SIZE(threads); i++) {
924*d83cc019SAndroid Build Coastguard Worker 		threads[i].ready = 1;
925*d83cc019SAndroid Build Coastguard Worker 		pthread_cond_signal(&threads[i].cond);
926*d83cc019SAndroid Build Coastguard Worker 		pthread_join(threads[i].thread, NULL);
927*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, threads[i].object.handle);
928*d83cc019SAndroid Build Coastguard Worker 	}
929*d83cc019SAndroid Build Coastguard Worker 
930*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object[0].handle);
931*d83cc019SAndroid Build Coastguard Worker }
932*d83cc019SAndroid Build Coastguard Worker 
933*d83cc019SAndroid Build Coastguard Worker static void
store_many(int fd,unsigned ring,int timeout)934*d83cc019SAndroid Build Coastguard Worker store_many(int fd, unsigned ring, int timeout)
935*d83cc019SAndroid Build Coastguard Worker {
936*d83cc019SAndroid Build Coastguard Worker 	unsigned long *shared;
937*d83cc019SAndroid Build Coastguard Worker 	const char *names[16];
938*d83cc019SAndroid Build Coastguard Worker 	int n = 0;
939*d83cc019SAndroid Build Coastguard Worker 
940*d83cc019SAndroid Build Coastguard Worker 	shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
941*d83cc019SAndroid Build Coastguard Worker 	igt_assert(shared != MAP_FAILED);
942*d83cc019SAndroid Build Coastguard Worker 
943*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
944*d83cc019SAndroid Build Coastguard Worker 
945*d83cc019SAndroid Build Coastguard Worker 	if (ring == ALL_ENGINES) {
946*d83cc019SAndroid Build Coastguard Worker 		for_each_physical_engine(fd, ring) {
947*d83cc019SAndroid Build Coastguard Worker 			if (!gem_can_store_dword(fd, ring))
948*d83cc019SAndroid Build Coastguard Worker 				continue;
949*d83cc019SAndroid Build Coastguard Worker 
950*d83cc019SAndroid Build Coastguard Worker 			igt_fork(child, 1)
951*d83cc019SAndroid Build Coastguard Worker 				__store_many(fd,
952*d83cc019SAndroid Build Coastguard Worker 					     ring,
953*d83cc019SAndroid Build Coastguard Worker 					     timeout,
954*d83cc019SAndroid Build Coastguard Worker 					     &shared[n]);
955*d83cc019SAndroid Build Coastguard Worker 
956*d83cc019SAndroid Build Coastguard Worker 			names[n++] = e__->name;
957*d83cc019SAndroid Build Coastguard Worker 		}
958*d83cc019SAndroid Build Coastguard Worker 		igt_waitchildren();
959*d83cc019SAndroid Build Coastguard Worker 	} else {
960*d83cc019SAndroid Build Coastguard Worker 		gem_require_ring(fd, ring);
961*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_can_store_dword(fd, ring));
962*d83cc019SAndroid Build Coastguard Worker 		__store_many(fd, ring, timeout, &shared[n]);
963*d83cc019SAndroid Build Coastguard Worker 		names[n++] = NULL;
964*d83cc019SAndroid Build Coastguard Worker 	}
965*d83cc019SAndroid Build Coastguard Worker 
966*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < n; i++) {
967*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%sompleted %ld cycles\n",
968*d83cc019SAndroid Build Coastguard Worker 			 names[i] ?: "", names[i] ? " c" : "C", shared[i]);
969*d83cc019SAndroid Build Coastguard Worker 	}
970*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
971*d83cc019SAndroid Build Coastguard Worker 	munmap(shared, 4096);
972*d83cc019SAndroid Build Coastguard Worker }
973*d83cc019SAndroid Build Coastguard Worker 
974*d83cc019SAndroid Build Coastguard Worker static void
sync_all(int fd,int num_children,int timeout)975*d83cc019SAndroid Build Coastguard Worker sync_all(int fd, int num_children, int timeout)
976*d83cc019SAndroid Build Coastguard Worker {
977*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16], engine;
978*d83cc019SAndroid Build Coastguard Worker 	int num_engines = 0;
979*d83cc019SAndroid Build Coastguard Worker 
980*d83cc019SAndroid Build Coastguard Worker 	for_each_physical_engine(fd, engine) {
981*d83cc019SAndroid Build Coastguard Worker 		engines[num_engines++] = engine;
982*d83cc019SAndroid Build Coastguard Worker 		if (num_engines == ARRAY_SIZE(engines))
983*d83cc019SAndroid Build Coastguard Worker 			break;
984*d83cc019SAndroid Build Coastguard Worker 	}
985*d83cc019SAndroid Build Coastguard Worker 	igt_require(num_engines);
986*d83cc019SAndroid Build Coastguard Worker 
987*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
988*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_children) {
989*d83cc019SAndroid Build Coastguard Worker 		const uint32_t bbe = MI_BATCH_BUFFER_END;
990*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_exec_object2 object;
991*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_execbuffer2 execbuf;
992*d83cc019SAndroid Build Coastguard Worker 		double start, elapsed;
993*d83cc019SAndroid Build Coastguard Worker 		unsigned long cycles;
994*d83cc019SAndroid Build Coastguard Worker 
995*d83cc019SAndroid Build Coastguard Worker 		memset(&object, 0, sizeof(object));
996*d83cc019SAndroid Build Coastguard Worker 		object.handle = gem_create(fd, 4096);
997*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
998*d83cc019SAndroid Build Coastguard Worker 
999*d83cc019SAndroid Build Coastguard Worker 		memset(&execbuf, 0, sizeof(execbuf));
1000*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffers_ptr = to_user_pointer(&object);
1001*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 1;
1002*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
1003*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, object.handle);
1004*d83cc019SAndroid Build Coastguard Worker 
1005*d83cc019SAndroid Build Coastguard Worker 		start = gettime();
1006*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
1007*d83cc019SAndroid Build Coastguard Worker 		do {
1008*d83cc019SAndroid Build Coastguard Worker 			do {
1009*d83cc019SAndroid Build Coastguard Worker 				for (int n = 0; n < num_engines; n++) {
1010*d83cc019SAndroid Build Coastguard Worker 					execbuf.flags = engines[n];
1011*d83cc019SAndroid Build Coastguard Worker 					gem_execbuf(fd, &execbuf);
1012*d83cc019SAndroid Build Coastguard Worker 				}
1013*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, object.handle);
1014*d83cc019SAndroid Build Coastguard Worker 			} while (++cycles & 1023);
1015*d83cc019SAndroid Build Coastguard Worker 		} while ((elapsed = gettime() - start) < timeout);
1016*d83cc019SAndroid Build Coastguard Worker 		igt_info("Completed %ld cycles: %.3f us\n",
1017*d83cc019SAndroid Build Coastguard Worker 			 cycles, elapsed*1e6/cycles);
1018*d83cc019SAndroid Build Coastguard Worker 
1019*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object.handle);
1020*d83cc019SAndroid Build Coastguard Worker 	}
1021*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(timeout+10, NULL);
1022*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
1023*d83cc019SAndroid Build Coastguard Worker }
1024*d83cc019SAndroid Build Coastguard Worker 
1025*d83cc019SAndroid Build Coastguard Worker static void
store_all(int fd,int num_children,int timeout)1026*d83cc019SAndroid Build Coastguard Worker store_all(int fd, int num_children, int timeout)
1027*d83cc019SAndroid Build Coastguard Worker {
1028*d83cc019SAndroid Build Coastguard Worker 	const int gen = intel_gen(intel_get_drm_devid(fd));
1029*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16];
1030*d83cc019SAndroid Build Coastguard Worker 	int num_engines = 0;
1031*d83cc019SAndroid Build Coastguard Worker 	unsigned int ring;
1032*d83cc019SAndroid Build Coastguard Worker 
1033*d83cc019SAndroid Build Coastguard Worker 	for_each_physical_engine(fd, ring) {
1034*d83cc019SAndroid Build Coastguard Worker 		if (!gem_can_store_dword(fd, ring))
1035*d83cc019SAndroid Build Coastguard Worker 			continue;
1036*d83cc019SAndroid Build Coastguard Worker 
1037*d83cc019SAndroid Build Coastguard Worker 		engines[num_engines++] = ring;
1038*d83cc019SAndroid Build Coastguard Worker 		if (num_engines == ARRAY_SIZE(engines))
1039*d83cc019SAndroid Build Coastguard Worker 			break;
1040*d83cc019SAndroid Build Coastguard Worker 	}
1041*d83cc019SAndroid Build Coastguard Worker 	igt_require(num_engines);
1042*d83cc019SAndroid Build Coastguard Worker 
1043*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
1044*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_children) {
1045*d83cc019SAndroid Build Coastguard Worker 		const uint32_t bbe = MI_BATCH_BUFFER_END;
1046*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_exec_object2 object[2];
1047*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_relocation_entry reloc[1024];
1048*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_execbuffer2 execbuf;
1049*d83cc019SAndroid Build Coastguard Worker 		double start, elapsed;
1050*d83cc019SAndroid Build Coastguard Worker 		unsigned long cycles;
1051*d83cc019SAndroid Build Coastguard Worker 		uint32_t *batch, *b;
1052*d83cc019SAndroid Build Coastguard Worker 
1053*d83cc019SAndroid Build Coastguard Worker 		memset(&execbuf, 0, sizeof(execbuf));
1054*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffers_ptr = to_user_pointer(object);
1055*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
1056*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT;
1057*d83cc019SAndroid Build Coastguard Worker 		if (gen < 6)
1058*d83cc019SAndroid Build Coastguard Worker 			execbuf.flags |= I915_EXEC_SECURE;
1059*d83cc019SAndroid Build Coastguard Worker 
1060*d83cc019SAndroid Build Coastguard Worker 		memset(object, 0, sizeof(object));
1061*d83cc019SAndroid Build Coastguard Worker 		object[0].handle = gem_create(fd, 4096);
1062*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, object[0].handle, 0, &bbe, sizeof(bbe));
1063*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 1;
1064*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
1065*d83cc019SAndroid Build Coastguard Worker 
1066*d83cc019SAndroid Build Coastguard Worker 		object[0].flags |= EXEC_OBJECT_WRITE;
1067*d83cc019SAndroid Build Coastguard Worker 		object[1].handle = gem_create(fd, 1024*16 + 4096);
1068*d83cc019SAndroid Build Coastguard Worker 
1069*d83cc019SAndroid Build Coastguard Worker 		object[1].relocs_ptr = to_user_pointer(reloc);
1070*d83cc019SAndroid Build Coastguard Worker 		object[1].relocation_count = 1024;
1071*d83cc019SAndroid Build Coastguard Worker 
1072*d83cc019SAndroid Build Coastguard Worker 		batch = gem_mmap__cpu(fd, object[1].handle, 0, 16*1024 + 4096,
1073*d83cc019SAndroid Build Coastguard Worker 				PROT_WRITE | PROT_READ);
1074*d83cc019SAndroid Build Coastguard Worker 		gem_set_domain(fd, object[1].handle,
1075*d83cc019SAndroid Build Coastguard Worker 				I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
1076*d83cc019SAndroid Build Coastguard Worker 
1077*d83cc019SAndroid Build Coastguard Worker 		memset(reloc, 0, sizeof(reloc));
1078*d83cc019SAndroid Build Coastguard Worker 		b = batch;
1079*d83cc019SAndroid Build Coastguard Worker 		for (int i = 0; i < 1024; i++) {
1080*d83cc019SAndroid Build Coastguard Worker 			uint64_t offset;
1081*d83cc019SAndroid Build Coastguard Worker 
1082*d83cc019SAndroid Build Coastguard Worker 			reloc[i].presumed_offset = object[0].offset;
1083*d83cc019SAndroid Build Coastguard Worker 			reloc[i].offset = (b - batch + 1) * sizeof(*batch);
1084*d83cc019SAndroid Build Coastguard Worker 			reloc[i].delta = i * sizeof(uint32_t);
1085*d83cc019SAndroid Build Coastguard Worker 			reloc[i].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
1086*d83cc019SAndroid Build Coastguard Worker 			reloc[i].write_domain = I915_GEM_DOMAIN_INSTRUCTION;
1087*d83cc019SAndroid Build Coastguard Worker 
1088*d83cc019SAndroid Build Coastguard Worker 			offset = object[0].offset + reloc[i].delta;
1089*d83cc019SAndroid Build Coastguard Worker 			*b++ = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
1090*d83cc019SAndroid Build Coastguard Worker 			if (gen >= 8) {
1091*d83cc019SAndroid Build Coastguard Worker 				*b++ = offset;
1092*d83cc019SAndroid Build Coastguard Worker 				*b++ = offset >> 32;
1093*d83cc019SAndroid Build Coastguard Worker 			} else if (gen >= 4) {
1094*d83cc019SAndroid Build Coastguard Worker 				*b++ = 0;
1095*d83cc019SAndroid Build Coastguard Worker 				*b++ = offset;
1096*d83cc019SAndroid Build Coastguard Worker 				reloc[i].offset += sizeof(*batch);
1097*d83cc019SAndroid Build Coastguard Worker 			} else {
1098*d83cc019SAndroid Build Coastguard Worker 				b[-1] -= 1;
1099*d83cc019SAndroid Build Coastguard Worker 				*b++ = offset;
1100*d83cc019SAndroid Build Coastguard Worker 			}
1101*d83cc019SAndroid Build Coastguard Worker 			*b++ = i;
1102*d83cc019SAndroid Build Coastguard Worker 		}
1103*d83cc019SAndroid Build Coastguard Worker 		*b++ = MI_BATCH_BUFFER_END;
1104*d83cc019SAndroid Build Coastguard Worker 		igt_assert((b - batch)*sizeof(uint32_t) < 20*1024);
1105*d83cc019SAndroid Build Coastguard Worker 		munmap(batch, 16*1024+4096);
1106*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 2;
1107*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
1108*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, object[1].handle);
1109*d83cc019SAndroid Build Coastguard Worker 
1110*d83cc019SAndroid Build Coastguard Worker 		start = gettime();
1111*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
1112*d83cc019SAndroid Build Coastguard Worker 		do {
1113*d83cc019SAndroid Build Coastguard Worker 			do {
1114*d83cc019SAndroid Build Coastguard Worker 				igt_permute_array(engines, num_engines, xchg);
1115*d83cc019SAndroid Build Coastguard Worker 				for (int n = 0; n < num_engines; n++) {
1116*d83cc019SAndroid Build Coastguard Worker 					execbuf.flags &= ~ENGINE_MASK;
1117*d83cc019SAndroid Build Coastguard Worker 					execbuf.flags |= engines[n];
1118*d83cc019SAndroid Build Coastguard Worker 					gem_execbuf(fd, &execbuf);
1119*d83cc019SAndroid Build Coastguard Worker 				}
1120*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, object[1].handle);
1121*d83cc019SAndroid Build Coastguard Worker 			} while (++cycles & 1023);
1122*d83cc019SAndroid Build Coastguard Worker 		} while ((elapsed = gettime() - start) < timeout);
1123*d83cc019SAndroid Build Coastguard Worker 		igt_info("Completed %ld cycles: %.3f us\n",
1124*d83cc019SAndroid Build Coastguard Worker 			 cycles, elapsed*1e6/cycles);
1125*d83cc019SAndroid Build Coastguard Worker 
1126*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object[1].handle);
1127*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object[0].handle);
1128*d83cc019SAndroid Build Coastguard Worker 	}
1129*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(timeout+10, NULL);
1130*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
1131*d83cc019SAndroid Build Coastguard Worker }
1132*d83cc019SAndroid Build Coastguard Worker 
1133*d83cc019SAndroid Build Coastguard Worker static void
preempt(int fd,unsigned ring,int num_children,int timeout)1134*d83cc019SAndroid Build Coastguard Worker preempt(int fd, unsigned ring, int num_children, int timeout)
1135*d83cc019SAndroid Build Coastguard Worker {
1136*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16];
1137*d83cc019SAndroid Build Coastguard Worker 	const char *names[16];
1138*d83cc019SAndroid Build Coastguard Worker 	int num_engines = 0;
1139*d83cc019SAndroid Build Coastguard Worker 	uint32_t ctx[2];
1140*d83cc019SAndroid Build Coastguard Worker 
1141*d83cc019SAndroid Build Coastguard Worker 	if (ring == ALL_ENGINES) {
1142*d83cc019SAndroid Build Coastguard Worker 		for_each_physical_engine(fd, ring) {
1143*d83cc019SAndroid Build Coastguard Worker 			names[num_engines] = e__->name;
1144*d83cc019SAndroid Build Coastguard Worker 			engines[num_engines++] = ring;
1145*d83cc019SAndroid Build Coastguard Worker 			if (num_engines == ARRAY_SIZE(engines))
1146*d83cc019SAndroid Build Coastguard Worker 				break;
1147*d83cc019SAndroid Build Coastguard Worker 		}
1148*d83cc019SAndroid Build Coastguard Worker 
1149*d83cc019SAndroid Build Coastguard Worker 		num_children *= num_engines;
1150*d83cc019SAndroid Build Coastguard Worker 	} else {
1151*d83cc019SAndroid Build Coastguard Worker 		gem_require_ring(fd, ring);
1152*d83cc019SAndroid Build Coastguard Worker 		names[num_engines] = NULL;
1153*d83cc019SAndroid Build Coastguard Worker 		engines[num_engines++] = ring;
1154*d83cc019SAndroid Build Coastguard Worker 	}
1155*d83cc019SAndroid Build Coastguard Worker 
1156*d83cc019SAndroid Build Coastguard Worker 	ctx[0] = gem_context_create(fd);
1157*d83cc019SAndroid Build Coastguard Worker 	gem_context_set_priority(fd, ctx[0], MIN_PRIO);
1158*d83cc019SAndroid Build Coastguard Worker 
1159*d83cc019SAndroid Build Coastguard Worker 	ctx[1] = gem_context_create(fd);
1160*d83cc019SAndroid Build Coastguard Worker 	gem_context_set_priority(fd, ctx[1], MAX_PRIO);
1161*d83cc019SAndroid Build Coastguard Worker 
1162*d83cc019SAndroid Build Coastguard Worker 	intel_detect_and_clear_missed_interrupts(fd);
1163*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_children) {
1164*d83cc019SAndroid Build Coastguard Worker 		const uint32_t bbe = MI_BATCH_BUFFER_END;
1165*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_exec_object2 object;
1166*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_execbuffer2 execbuf;
1167*d83cc019SAndroid Build Coastguard Worker 		double start, elapsed;
1168*d83cc019SAndroid Build Coastguard Worker 		unsigned long cycles;
1169*d83cc019SAndroid Build Coastguard Worker 
1170*d83cc019SAndroid Build Coastguard Worker 		memset(&object, 0, sizeof(object));
1171*d83cc019SAndroid Build Coastguard Worker 		object.handle = gem_create(fd, 4096);
1172*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
1173*d83cc019SAndroid Build Coastguard Worker 
1174*d83cc019SAndroid Build Coastguard Worker 		memset(&execbuf, 0, sizeof(execbuf));
1175*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffers_ptr = to_user_pointer(&object);
1176*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 1;
1177*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags = engines[child % num_engines];
1178*d83cc019SAndroid Build Coastguard Worker 		execbuf.rsvd1 = ctx[1];
1179*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
1180*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, object.handle);
1181*d83cc019SAndroid Build Coastguard Worker 
1182*d83cc019SAndroid Build Coastguard Worker 		start = gettime();
1183*d83cc019SAndroid Build Coastguard Worker 		cycles = 0;
1184*d83cc019SAndroid Build Coastguard Worker 		do {
1185*d83cc019SAndroid Build Coastguard Worker 			igt_spin_t *spin =
1186*d83cc019SAndroid Build Coastguard Worker 				__igt_spin_new(fd,
1187*d83cc019SAndroid Build Coastguard Worker 					       .ctx = ctx[0],
1188*d83cc019SAndroid Build Coastguard Worker 					       .engine = execbuf.flags);
1189*d83cc019SAndroid Build Coastguard Worker 
1190*d83cc019SAndroid Build Coastguard Worker 			do {
1191*d83cc019SAndroid Build Coastguard Worker 				gem_execbuf(fd, &execbuf);
1192*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, object.handle);
1193*d83cc019SAndroid Build Coastguard Worker 			} while (++cycles & 1023);
1194*d83cc019SAndroid Build Coastguard Worker 
1195*d83cc019SAndroid Build Coastguard Worker 			igt_spin_free(fd, spin);
1196*d83cc019SAndroid Build Coastguard Worker 		} while ((elapsed = gettime() - start) < timeout);
1197*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s%sompleted %ld cycles: %.3f us\n",
1198*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ?: "",
1199*d83cc019SAndroid Build Coastguard Worker 			 names[child % num_engines] ? " c" : "C",
1200*d83cc019SAndroid Build Coastguard Worker 			 cycles, elapsed*1e6/cycles);
1201*d83cc019SAndroid Build Coastguard Worker 
1202*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object.handle);
1203*d83cc019SAndroid Build Coastguard Worker 	}
1204*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(timeout+10, NULL);
1205*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
1206*d83cc019SAndroid Build Coastguard Worker 
1207*d83cc019SAndroid Build Coastguard Worker 	gem_context_destroy(fd, ctx[1]);
1208*d83cc019SAndroid Build Coastguard Worker 	gem_context_destroy(fd, ctx[0]);
1209*d83cc019SAndroid Build Coastguard Worker }
1210*d83cc019SAndroid Build Coastguard Worker 
1211*d83cc019SAndroid Build Coastguard Worker igt_main
1212*d83cc019SAndroid Build Coastguard Worker {
1213*d83cc019SAndroid Build Coastguard Worker 	const struct intel_execution_engine *e;
1214*d83cc019SAndroid Build Coastguard Worker 	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
1215*d83cc019SAndroid Build Coastguard Worker 	int fd = -1;
1216*d83cc019SAndroid Build Coastguard Worker 
1217*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on_simulation();
1218*d83cc019SAndroid Build Coastguard Worker 
1219*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
1220*d83cc019SAndroid Build Coastguard Worker 		fd = drm_open_driver(DRIVER_INTEL);
1221*d83cc019SAndroid Build Coastguard Worker 		igt_require_gem(fd);
1222*d83cc019SAndroid Build Coastguard Worker 		gem_submission_print_method(fd);
1223*d83cc019SAndroid Build Coastguard Worker 		gem_scheduler_print_capability(fd);
1224*d83cc019SAndroid Build Coastguard Worker 
1225*d83cc019SAndroid Build Coastguard Worker 		igt_fork_hang_detector(fd);
1226*d83cc019SAndroid Build Coastguard Worker 	}
1227*d83cc019SAndroid Build Coastguard Worker 
1228*d83cc019SAndroid Build Coastguard Worker 	for (e = intel_execution_engines; e->name; e++) {
1229*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("%s", e->name)
1230*d83cc019SAndroid Build Coastguard Worker 			sync_ring(fd, e->exec_id | e->flags, 1, 150);
1231*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("idle-%s", e->name)
1232*d83cc019SAndroid Build Coastguard Worker 			idle_ring(fd, e->exec_id | e->flags, 150);
1233*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("active-%s", e->name)
1234*d83cc019SAndroid Build Coastguard Worker 			active_ring(fd, e->exec_id | e->flags, 150);
1235*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("wakeup-%s", e->name)
1236*d83cc019SAndroid Build Coastguard Worker 			wakeup_ring(fd, e->exec_id | e->flags, 150, 1);
1237*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("active-wakeup-%s", e->name)
1238*d83cc019SAndroid Build Coastguard Worker 			active_wakeup_ring(fd, e->exec_id | e->flags, 150, 1);
1239*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("double-wakeup-%s", e->name)
1240*d83cc019SAndroid Build Coastguard Worker 			wakeup_ring(fd, e->exec_id | e->flags, 150, 2);
1241*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("store-%s", e->name)
1242*d83cc019SAndroid Build Coastguard Worker 			store_ring(fd, e->exec_id | e->flags, 1, 150);
1243*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("switch-%s", e->name)
1244*d83cc019SAndroid Build Coastguard Worker 			switch_ring(fd, e->exec_id | e->flags, 1, 150);
1245*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("forked-switch-%s", e->name)
1246*d83cc019SAndroid Build Coastguard Worker 			switch_ring(fd, e->exec_id | e->flags, ncpus, 150);
1247*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("many-%s", e->name)
1248*d83cc019SAndroid Build Coastguard Worker 			store_many(fd, e->exec_id | e->flags, 150);
1249*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("forked-%s", e->name)
1250*d83cc019SAndroid Build Coastguard Worker 			sync_ring(fd, e->exec_id | e->flags, ncpus, 150);
1251*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("forked-store-%s", e->name)
1252*d83cc019SAndroid Build Coastguard Worker 			store_ring(fd, e->exec_id | e->flags, ncpus, 150);
1253*d83cc019SAndroid Build Coastguard Worker 	}
1254*d83cc019SAndroid Build Coastguard Worker 
1255*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-each")
1256*d83cc019SAndroid Build Coastguard Worker 		sync_ring(fd, ALL_ENGINES, 1, 5);
1257*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-store-each")
1258*d83cc019SAndroid Build Coastguard Worker 		store_ring(fd, ALL_ENGINES, 1, 5);
1259*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-many-each")
1260*d83cc019SAndroid Build Coastguard Worker 		store_many(fd, ALL_ENGINES, 5);
1261*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("switch-each")
1262*d83cc019SAndroid Build Coastguard Worker 		switch_ring(fd, ALL_ENGINES, 1, 150);
1263*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("forked-switch-each")
1264*d83cc019SAndroid Build Coastguard Worker 		switch_ring(fd, ALL_ENGINES, ncpus, 150);
1265*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("forked-each")
1266*d83cc019SAndroid Build Coastguard Worker 		sync_ring(fd, ALL_ENGINES, ncpus, 150);
1267*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("forked-store-each")
1268*d83cc019SAndroid Build Coastguard Worker 		store_ring(fd, ALL_ENGINES, ncpus, 150);
1269*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("active-each")
1270*d83cc019SAndroid Build Coastguard Worker 		active_ring(fd, ALL_ENGINES, 150);
1271*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("wakeup-each")
1272*d83cc019SAndroid Build Coastguard Worker 		wakeup_ring(fd, ALL_ENGINES, 150, 1);
1273*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("active-wakeup-each")
1274*d83cc019SAndroid Build Coastguard Worker 		active_wakeup_ring(fd, ALL_ENGINES, 150, 1);
1275*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("double-wakeup-each")
1276*d83cc019SAndroid Build Coastguard Worker 		wakeup_ring(fd, ALL_ENGINES, 150, 2);
1277*d83cc019SAndroid Build Coastguard Worker 
1278*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-all")
1279*d83cc019SAndroid Build Coastguard Worker 		sync_all(fd, 1, 5);
1280*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-store-all")
1281*d83cc019SAndroid Build Coastguard Worker 		store_all(fd, 1, 5);
1282*d83cc019SAndroid Build Coastguard Worker 
1283*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("all")
1284*d83cc019SAndroid Build Coastguard Worker 		sync_all(fd, 1, 150);
1285*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("store-all")
1286*d83cc019SAndroid Build Coastguard Worker 		store_all(fd, 1, 150);
1287*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("forked-all")
1288*d83cc019SAndroid Build Coastguard Worker 		sync_all(fd, ncpus, 150);
1289*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("forked-store-all")
1290*d83cc019SAndroid Build Coastguard Worker 		store_all(fd, ncpus, 150);
1291*d83cc019SAndroid Build Coastguard Worker 
1292*d83cc019SAndroid Build Coastguard Worker 	igt_subtest_group {
1293*d83cc019SAndroid Build Coastguard Worker 		igt_fixture {
1294*d83cc019SAndroid Build Coastguard Worker 			gem_require_contexts(fd);
1295*d83cc019SAndroid Build Coastguard Worker 			igt_require(gem_scheduler_has_ctx_priority(fd));
1296*d83cc019SAndroid Build Coastguard Worker 			igt_require(gem_scheduler_has_preemption(fd));
1297*d83cc019SAndroid Build Coastguard Worker 		}
1298*d83cc019SAndroid Build Coastguard Worker 
1299*d83cc019SAndroid Build Coastguard Worker 		igt_subtest("preempt-all")
1300*d83cc019SAndroid Build Coastguard Worker 			preempt(fd, ALL_ENGINES, 1, 20);
1301*d83cc019SAndroid Build Coastguard Worker 
1302*d83cc019SAndroid Build Coastguard Worker 		for (e = intel_execution_engines; e->name; e++) {
1303*d83cc019SAndroid Build Coastguard Worker 			igt_subtest_f("preempt-%s", e->name)
1304*d83cc019SAndroid Build Coastguard Worker 				preempt(fd, e->exec_id | e->flags, ncpus, 150);
1305*d83cc019SAndroid Build Coastguard Worker 		}
1306*d83cc019SAndroid Build Coastguard Worker 	}
1307*d83cc019SAndroid Build Coastguard Worker 
1308*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
1309*d83cc019SAndroid Build Coastguard Worker 		igt_stop_hang_detector();
1310*d83cc019SAndroid Build Coastguard Worker 		close(fd);
1311*d83cc019SAndroid Build Coastguard Worker 	}
1312*d83cc019SAndroid Build Coastguard Worker }
1313