xref: /aosp_15_r20/external/igt-gpu-tools/tests/i915/gem_spin_batch.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1 /*
2  * Copyright © 2017 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24 
25 #include "igt.h"
26 
27 #define MAX_ERROR 5 /* % */
28 
29 #define assert_within_epsilon(x, ref, tolerance) \
30 	igt_assert_f(100 * x <= (100 + tolerance) * ref && \
31 		     100 * x >= (100 - tolerance) * ref, \
32 		     "'%s' != '%s' (%lld not within %d%% tolerance of %lld)\n",\
33 		     #x, #ref, (long long)x, tolerance, (long long)ref)
34 
spin(int fd,const struct intel_execution_engine2 * e2,unsigned int timeout_sec)35 static void spin(int fd, const struct intel_execution_engine2 *e2,
36 		 unsigned int timeout_sec)
37 {
38 	const uint64_t timeout_100ms = 100000000LL;
39 	unsigned long loops = 0;
40 	igt_spin_t *spin;
41 	struct timespec tv = { };
42 	struct timespec itv = { };
43 	uint64_t elapsed;
44 
45 	spin = __igt_spin_new(fd, .engine = e2->flags);
46 	while ((elapsed = igt_nsec_elapsed(&tv)) >> 30 < timeout_sec) {
47 		igt_spin_t *next = __igt_spin_new(fd, .engine = e2->flags);
48 
49 		igt_spin_set_timeout(spin,
50 				     timeout_100ms - igt_nsec_elapsed(&itv));
51 		gem_sync(fd, spin->handle);
52 		igt_debug("loop %lu: interval=%fms (target 100ms), elapsed %fms\n",
53 			  loops,
54 			  igt_nsec_elapsed(&itv) * 1e-6,
55 			  igt_nsec_elapsed(&tv) * 1e-6);
56 		memset(&itv, 0, sizeof(itv));
57 
58 		igt_spin_free(fd, spin);
59 		spin = next;
60 		loops++;
61 	}
62 	igt_spin_free(fd, spin);
63 
64 	igt_info("Completed %ld loops in %lld ns, target %ld\n",
65 		 loops, (long long)elapsed, (long)(elapsed / timeout_100ms));
66 
67 	assert_within_epsilon(timeout_100ms * loops, elapsed, MAX_ERROR);
68 }
69 
70 #define RESUBMIT_NEW_CTX     (1 << 0)
71 #define RESUBMIT_ALL_ENGINES (1 << 1)
72 
spin_resubmit(int fd,const struct intel_execution_engine2 * e2,unsigned int flags)73 static void spin_resubmit(int fd, const struct intel_execution_engine2 *e2,
74 			  unsigned int flags)
75 {
76 	const uint32_t ctx0 = gem_context_create(fd);
77 	const uint32_t ctx1 = (flags & RESUBMIT_NEW_CTX) ?
78 		gem_context_create(fd) : ctx0;
79 	igt_spin_t *spin = __igt_spin_new(fd, .ctx = ctx0, .engine = e2->flags);
80 	const struct intel_execution_engine2 *other;
81 
82 	struct drm_i915_gem_execbuffer2 eb = {
83 		.buffer_count = 1,
84 		.buffers_ptr = to_user_pointer(&spin->obj[IGT_SPIN_BATCH]),
85 		.rsvd1 = ctx1,
86 	};
87 
88 	igt_assert(gem_context_has_engine_map(fd, 0) ||
89 		   !(flags & RESUBMIT_ALL_ENGINES));
90 
91 	if (flags & RESUBMIT_ALL_ENGINES) {
92 		gem_context_set_all_engines(fd, ctx0);
93 		if (ctx0 != ctx1)
94 			gem_context_set_all_engines(fd, ctx1);
95 
96 		for_each_context_engine(fd, ctx1, other) {
97 			if (gem_engine_is_equal(other, e2))
98 				continue;
99 
100 			eb.flags = other->flags;
101 			gem_execbuf(fd, &eb);
102 		}
103 	} else {
104 		eb.flags = e2->flags;
105 		gem_execbuf(fd, &eb);
106 	}
107 
108 	igt_spin_end(spin);
109 
110 	gem_sync(fd, spin->handle);
111 
112 	igt_spin_free(fd, spin);
113 
114 	if (ctx1 != ctx0)
115 		gem_context_destroy(fd, ctx1);
116 
117 	gem_context_destroy(fd, ctx0);
118 }
119 
spin_exit_handler(int sig)120 static void spin_exit_handler(int sig)
121 {
122 	igt_terminate_spins();
123 }
124 
spin_on_all_engines(int fd,unsigned int timeout_sec)125 static void spin_on_all_engines(int fd, unsigned int timeout_sec)
126 {
127 	const struct intel_execution_engine2 *e2;
128 
129 	__for_each_physical_engine(fd, e2) {
130 		igt_fork(child, 1) {
131 			igt_install_exit_handler(spin_exit_handler);
132 			spin(fd, e2, timeout_sec);
133 		}
134 	}
135 
136 	igt_waitchildren();
137 }
138 
139 igt_main
140 {
141 	const struct intel_execution_engine2 *e2;
142 	const struct intel_execution_engine *e;
143 	struct intel_execution_engine2 e2__;
144 	int fd = -1;
145 
146 	igt_skip_on_simulation();
147 
148 	igt_fixture {
149 		fd = drm_open_driver(DRIVER_INTEL);
150 		igt_require_gem(fd);
151 		igt_fork_hang_detector(fd);
152 	}
153 
154 	for (e = intel_execution_engines; e->name; e++) {
155 		e2__ = gem_eb_flags_to_engine(e->exec_id | e->flags);
156 		if (e2__.flags == -1)
157 			continue;
158 		e2 = &e2__;
159 
160 		igt_subtest_f("legacy-%s", e->name)
161 			spin(fd, e2, 3);
162 
163 		igt_subtest_f("legacy-resubmit-%s", e->name)
164 			spin_resubmit(fd, e2, 0);
165 
166 		igt_subtest_f("legacy-resubmit-new-%s", e->name)
167 			spin_resubmit(fd, e2, RESUBMIT_NEW_CTX);
168 	}
169 
__for_each_physical_engine(fd,e2)170 	__for_each_physical_engine(fd, e2) {
171 		igt_subtest_f("%s", e2->name)
172 			spin(fd, e2, 3);
173 
174 		igt_subtest_f("resubmit-%s", e2->name)
175 			spin_resubmit(fd, e2, 0);
176 
177 		igt_subtest_f("resubmit-new-%s", e2->name)
178 			spin_resubmit(fd, e2, RESUBMIT_NEW_CTX);
179 
180 		igt_subtest_f("resubmit-all-%s", e2->name)
181 			spin_resubmit(fd, e2, RESUBMIT_ALL_ENGINES);
182 
183 		igt_subtest_f("resubmit-new-all-%s", e2->name)
184 			spin_resubmit(fd, e2,
185 				      RESUBMIT_NEW_CTX |
186 				      RESUBMIT_ALL_ENGINES);
187 	}
188 
189 	igt_subtest("spin-each")
190 		spin_on_all_engines(fd, 3);
191 
192 	igt_fixture {
193 		igt_stop_hang_detector();
194 		close(fd);
195 	}
196 }
197