xref: /aosp_15_r20/external/igt-gpu-tools/lib/i915/gem_context.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2017 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 <errno.h>
25*d83cc019SAndroid Build Coastguard Worker #include <string.h>
26*d83cc019SAndroid Build Coastguard Worker 
27*d83cc019SAndroid Build Coastguard Worker #include "ioctl_wrappers.h"
28*d83cc019SAndroid Build Coastguard Worker #include "drmtest.h"
29*d83cc019SAndroid Build Coastguard Worker 
30*d83cc019SAndroid Build Coastguard Worker #include "i915/gem_context.h"
31*d83cc019SAndroid Build Coastguard Worker 
32*d83cc019SAndroid Build Coastguard Worker /**
33*d83cc019SAndroid Build Coastguard Worker  * SECTION:gem_context
34*d83cc019SAndroid Build Coastguard Worker  * @short_description: Helpers for dealing with contexts
35*d83cc019SAndroid Build Coastguard Worker  * @title: GEM Context
36*d83cc019SAndroid Build Coastguard Worker  *
37*d83cc019SAndroid Build Coastguard Worker  * This helper library contains functions used for handling gem contexts.
38*d83cc019SAndroid Build Coastguard Worker  * Conceptually, gem contexts are similar to their CPU counterparts, in that
39*d83cc019SAndroid Build Coastguard Worker  * they are a mix of software and hardware features allowing to isolate some
40*d83cc019SAndroid Build Coastguard Worker  * aspects of task execution. Initially it was just a matter of maintaining
41*d83cc019SAndroid Build Coastguard Worker  * separate state for each context, but more features were added, some
42*d83cc019SAndroid Build Coastguard Worker  * improving contexts isolation (per-context address space), some are just
43*d83cc019SAndroid Build Coastguard Worker  * software features improving submission model (context priority).
44*d83cc019SAndroid Build Coastguard Worker  */
45*d83cc019SAndroid Build Coastguard Worker 
46*d83cc019SAndroid Build Coastguard Worker /**
47*d83cc019SAndroid Build Coastguard Worker  * gem_has_contexts:
48*d83cc019SAndroid Build Coastguard Worker  * @fd: open i915 drm file descriptor
49*d83cc019SAndroid Build Coastguard Worker  *
50*d83cc019SAndroid Build Coastguard Worker  * Queries whether context creation is supported or not.
51*d83cc019SAndroid Build Coastguard Worker  *
52*d83cc019SAndroid Build Coastguard Worker  * Returns: Context creation availability.
53*d83cc019SAndroid Build Coastguard Worker  */
gem_has_contexts(int fd)54*d83cc019SAndroid Build Coastguard Worker bool gem_has_contexts(int fd)
55*d83cc019SAndroid Build Coastguard Worker {
56*d83cc019SAndroid Build Coastguard Worker 	uint32_t ctx_id = 0;
57*d83cc019SAndroid Build Coastguard Worker 
58*d83cc019SAndroid Build Coastguard Worker 	__gem_context_create(fd, &ctx_id);
59*d83cc019SAndroid Build Coastguard Worker 	if (ctx_id)
60*d83cc019SAndroid Build Coastguard Worker 		gem_context_destroy(fd, ctx_id);
61*d83cc019SAndroid Build Coastguard Worker 
62*d83cc019SAndroid Build Coastguard Worker 	return ctx_id;
63*d83cc019SAndroid Build Coastguard Worker }
64*d83cc019SAndroid Build Coastguard Worker 
65*d83cc019SAndroid Build Coastguard Worker /**
66*d83cc019SAndroid Build Coastguard Worker  * gem_require_contexts:
67*d83cc019SAndroid Build Coastguard Worker  * @fd: open i915 drm file descriptor
68*d83cc019SAndroid Build Coastguard Worker  *
69*d83cc019SAndroid Build Coastguard Worker  * This helper will automatically skip the test on platforms where context
70*d83cc019SAndroid Build Coastguard Worker  * support is not available.
71*d83cc019SAndroid Build Coastguard Worker  */
gem_require_contexts(int fd)72*d83cc019SAndroid Build Coastguard Worker void gem_require_contexts(int fd)
73*d83cc019SAndroid Build Coastguard Worker {
74*d83cc019SAndroid Build Coastguard Worker 	igt_require(gem_has_contexts(fd));
75*d83cc019SAndroid Build Coastguard Worker }
76*d83cc019SAndroid Build Coastguard Worker 
__gem_context_create(int fd,uint32_t * ctx_id)77*d83cc019SAndroid Build Coastguard Worker int __gem_context_create(int fd, uint32_t *ctx_id)
78*d83cc019SAndroid Build Coastguard Worker {
79*d83cc019SAndroid Build Coastguard Worker        struct drm_i915_gem_context_create create;
80*d83cc019SAndroid Build Coastguard Worker        int err = 0;
81*d83cc019SAndroid Build Coastguard Worker 
82*d83cc019SAndroid Build Coastguard Worker        memset(&create, 0, sizeof(create));
83*d83cc019SAndroid Build Coastguard Worker        if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create) == 0) {
84*d83cc019SAndroid Build Coastguard Worker                *ctx_id = create.ctx_id;
85*d83cc019SAndroid Build Coastguard Worker        } else {
86*d83cc019SAndroid Build Coastguard Worker 	       err = -errno;
87*d83cc019SAndroid Build Coastguard Worker 	       igt_assume(err != 0);
88*d83cc019SAndroid Build Coastguard Worker        }
89*d83cc019SAndroid Build Coastguard Worker 
90*d83cc019SAndroid Build Coastguard Worker        errno = 0;
91*d83cc019SAndroid Build Coastguard Worker        return err;
92*d83cc019SAndroid Build Coastguard Worker }
93*d83cc019SAndroid Build Coastguard Worker 
94*d83cc019SAndroid Build Coastguard Worker /**
95*d83cc019SAndroid Build Coastguard Worker  * gem_context_create:
96*d83cc019SAndroid Build Coastguard Worker  * @fd: open i915 drm file descriptor
97*d83cc019SAndroid Build Coastguard Worker  *
98*d83cc019SAndroid Build Coastguard Worker  * This wraps the CONTEXT_CREATE ioctl, which is used to allocate a new
99*d83cc019SAndroid Build Coastguard Worker  * context. Note that similarly to gem_set_caching() this wrapper skips on
100*d83cc019SAndroid Build Coastguard Worker  * kernels and platforms where context support is not available.
101*d83cc019SAndroid Build Coastguard Worker  *
102*d83cc019SAndroid Build Coastguard Worker  * Returns: The id of the allocated context.
103*d83cc019SAndroid Build Coastguard Worker  */
gem_context_create(int fd)104*d83cc019SAndroid Build Coastguard Worker uint32_t gem_context_create(int fd)
105*d83cc019SAndroid Build Coastguard Worker {
106*d83cc019SAndroid Build Coastguard Worker 	uint32_t ctx_id;
107*d83cc019SAndroid Build Coastguard Worker 
108*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_context_create(fd, &ctx_id), 0);
109*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ctx_id != 0);
110*d83cc019SAndroid Build Coastguard Worker 
111*d83cc019SAndroid Build Coastguard Worker 	return ctx_id;
112*d83cc019SAndroid Build Coastguard Worker }
113*d83cc019SAndroid Build Coastguard Worker 
__gem_context_destroy(int fd,uint32_t ctx_id)114*d83cc019SAndroid Build Coastguard Worker int __gem_context_destroy(int fd, uint32_t ctx_id)
115*d83cc019SAndroid Build Coastguard Worker {
116*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_context_destroy destroy = { ctx_id };
117*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
118*d83cc019SAndroid Build Coastguard Worker 
119*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy)) {
120*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
121*d83cc019SAndroid Build Coastguard Worker 		igt_assume(err);
122*d83cc019SAndroid Build Coastguard Worker 	}
123*d83cc019SAndroid Build Coastguard Worker 
124*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
125*d83cc019SAndroid Build Coastguard Worker 	return err;
126*d83cc019SAndroid Build Coastguard Worker }
127*d83cc019SAndroid Build Coastguard Worker 
128*d83cc019SAndroid Build Coastguard Worker /**
129*d83cc019SAndroid Build Coastguard Worker  * gem_context_destroy:
130*d83cc019SAndroid Build Coastguard Worker  * @fd: open i915 drm file descriptor
131*d83cc019SAndroid Build Coastguard Worker  * @ctx_id: i915 context id
132*d83cc019SAndroid Build Coastguard Worker  *
133*d83cc019SAndroid Build Coastguard Worker  * This wraps the CONTEXT_DESTROY ioctl, which is used to free a context.
134*d83cc019SAndroid Build Coastguard Worker  */
gem_context_destroy(int fd,uint32_t ctx_id)135*d83cc019SAndroid Build Coastguard Worker void gem_context_destroy(int fd, uint32_t ctx_id)
136*d83cc019SAndroid Build Coastguard Worker {
137*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_context_destroy(fd, ctx_id), 0);
138*d83cc019SAndroid Build Coastguard Worker }
139*d83cc019SAndroid Build Coastguard Worker 
__gem_context_get_param(int fd,struct drm_i915_gem_context_param * p)140*d83cc019SAndroid Build Coastguard Worker int __gem_context_get_param(int fd, struct drm_i915_gem_context_param *p)
141*d83cc019SAndroid Build Coastguard Worker {
142*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
143*d83cc019SAndroid Build Coastguard Worker 
144*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, p)) {
145*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
146*d83cc019SAndroid Build Coastguard Worker 		igt_assume(err);
147*d83cc019SAndroid Build Coastguard Worker 	}
148*d83cc019SAndroid Build Coastguard Worker 
149*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
150*d83cc019SAndroid Build Coastguard Worker 	return err;
151*d83cc019SAndroid Build Coastguard Worker }
152*d83cc019SAndroid Build Coastguard Worker 
153*d83cc019SAndroid Build Coastguard Worker /**
154*d83cc019SAndroid Build Coastguard Worker  * gem_context_get_param:
155*d83cc019SAndroid Build Coastguard Worker  * @fd: open i915 drm file descriptor
156*d83cc019SAndroid Build Coastguard Worker  * @p: i915 context parameter
157*d83cc019SAndroid Build Coastguard Worker  *
158*d83cc019SAndroid Build Coastguard Worker  * This wraps the CONTEXT_GET_PARAM ioctl, which is used to get a context
159*d83cc019SAndroid Build Coastguard Worker  * parameter.
160*d83cc019SAndroid Build Coastguard Worker  */
gem_context_get_param(int fd,struct drm_i915_gem_context_param * p)161*d83cc019SAndroid Build Coastguard Worker void gem_context_get_param(int fd, struct drm_i915_gem_context_param *p)
162*d83cc019SAndroid Build Coastguard Worker {
163*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_context_get_param(fd, p), 0);
164*d83cc019SAndroid Build Coastguard Worker }
165*d83cc019SAndroid Build Coastguard Worker 
__gem_context_set_param(int fd,struct drm_i915_gem_context_param * p)166*d83cc019SAndroid Build Coastguard Worker int __gem_context_set_param(int fd, struct drm_i915_gem_context_param *p)
167*d83cc019SAndroid Build Coastguard Worker {
168*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
169*d83cc019SAndroid Build Coastguard Worker 
170*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, p)) {
171*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
172*d83cc019SAndroid Build Coastguard Worker 		igt_assume(err);
173*d83cc019SAndroid Build Coastguard Worker 	}
174*d83cc019SAndroid Build Coastguard Worker 
175*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
176*d83cc019SAndroid Build Coastguard Worker 	return err;
177*d83cc019SAndroid Build Coastguard Worker }
178*d83cc019SAndroid Build Coastguard Worker 
179*d83cc019SAndroid Build Coastguard Worker /**
180*d83cc019SAndroid Build Coastguard Worker  * gem_context_set_param:
181*d83cc019SAndroid Build Coastguard Worker  * @fd: open i915 drm file descriptor
182*d83cc019SAndroid Build Coastguard Worker  * @p: i915 context parameter
183*d83cc019SAndroid Build Coastguard Worker  *
184*d83cc019SAndroid Build Coastguard Worker  * This wraps the CONTEXT_SET_PARAM ioctl, which is used to set a context
185*d83cc019SAndroid Build Coastguard Worker  * parameter.
186*d83cc019SAndroid Build Coastguard Worker  */
gem_context_set_param(int fd,struct drm_i915_gem_context_param * p)187*d83cc019SAndroid Build Coastguard Worker void gem_context_set_param(int fd, struct drm_i915_gem_context_param *p)
188*d83cc019SAndroid Build Coastguard Worker {
189*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_context_set_param(fd, p), 0);
190*d83cc019SAndroid Build Coastguard Worker }
191*d83cc019SAndroid Build Coastguard Worker 
192*d83cc019SAndroid Build Coastguard Worker /**
193*d83cc019SAndroid Build Coastguard Worker  * gem_context_require_param:
194*d83cc019SAndroid Build Coastguard Worker  * @fd: open i915 drm file descriptor
195*d83cc019SAndroid Build Coastguard Worker  * @param: i915 context parameter
196*d83cc019SAndroid Build Coastguard Worker  *
197*d83cc019SAndroid Build Coastguard Worker  * Feature test macro to query whether context parameter support for @param
198*d83cc019SAndroid Build Coastguard Worker  * is available. Automatically skips through igt_require() if not.
199*d83cc019SAndroid Build Coastguard Worker  */
gem_context_require_param(int fd,uint64_t param)200*d83cc019SAndroid Build Coastguard Worker void gem_context_require_param(int fd, uint64_t param)
201*d83cc019SAndroid Build Coastguard Worker {
202*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_context_param p = { .param = param };
203*d83cc019SAndroid Build Coastguard Worker 
204*d83cc019SAndroid Build Coastguard Worker 	igt_require(__gem_context_get_param(fd, &p) == 0);
205*d83cc019SAndroid Build Coastguard Worker }
206*d83cc019SAndroid Build Coastguard Worker 
gem_context_require_bannable(int fd)207*d83cc019SAndroid Build Coastguard Worker void gem_context_require_bannable(int fd)
208*d83cc019SAndroid Build Coastguard Worker {
209*d83cc019SAndroid Build Coastguard Worker 	static int has_ban_period = -1;
210*d83cc019SAndroid Build Coastguard Worker 	static int has_bannable = -1;
211*d83cc019SAndroid Build Coastguard Worker 
212*d83cc019SAndroid Build Coastguard Worker 	if (has_bannable < 0) {
213*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_context_param p;
214*d83cc019SAndroid Build Coastguard Worker 
215*d83cc019SAndroid Build Coastguard Worker 		p.ctx_id = 0;
216*d83cc019SAndroid Build Coastguard Worker 		p.param = I915_CONTEXT_PARAM_BANNABLE;
217*d83cc019SAndroid Build Coastguard Worker 		p.value = 0;
218*d83cc019SAndroid Build Coastguard Worker 		p.size = 0;
219*d83cc019SAndroid Build Coastguard Worker 
220*d83cc019SAndroid Build Coastguard Worker 		has_bannable = igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &p) == 0;
221*d83cc019SAndroid Build Coastguard Worker 	}
222*d83cc019SAndroid Build Coastguard Worker 
223*d83cc019SAndroid Build Coastguard Worker 	if (has_ban_period < 0) {
224*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_context_param p;
225*d83cc019SAndroid Build Coastguard Worker 
226*d83cc019SAndroid Build Coastguard Worker 		p.ctx_id = 0;
227*d83cc019SAndroid Build Coastguard Worker 		p.param = I915_CONTEXT_PARAM_BAN_PERIOD;
228*d83cc019SAndroid Build Coastguard Worker 		p.value = 0;
229*d83cc019SAndroid Build Coastguard Worker 		p.size = 0;
230*d83cc019SAndroid Build Coastguard Worker 
231*d83cc019SAndroid Build Coastguard Worker 		has_ban_period = igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &p) == 0;
232*d83cc019SAndroid Build Coastguard Worker 	}
233*d83cc019SAndroid Build Coastguard Worker 
234*d83cc019SAndroid Build Coastguard Worker 	igt_require(has_ban_period || has_bannable);
235*d83cc019SAndroid Build Coastguard Worker }
236*d83cc019SAndroid Build Coastguard Worker 
237*d83cc019SAndroid Build Coastguard Worker #define DRM_I915_CONTEXT_PARAM_PRIORITY 0x6
238*d83cc019SAndroid Build Coastguard Worker 
239*d83cc019SAndroid Build Coastguard Worker /**
240*d83cc019SAndroid Build Coastguard Worker  * __gem_context_set_priority:
241*d83cc019SAndroid Build Coastguard Worker  * @fd: open i915 drm file descriptor
242*d83cc019SAndroid Build Coastguard Worker  * @ctx_id: i915 context id
243*d83cc019SAndroid Build Coastguard Worker  * @prio: desired context priority
244*d83cc019SAndroid Build Coastguard Worker  *
245*d83cc019SAndroid Build Coastguard Worker  * This function modifies priority property of the context.
246*d83cc019SAndroid Build Coastguard Worker  * It is used by the scheduler to decide on the ordering of requests submitted
247*d83cc019SAndroid Build Coastguard Worker  * to the hardware.
248*d83cc019SAndroid Build Coastguard Worker  *
249*d83cc019SAndroid Build Coastguard Worker  * Returns: An integer equal to zero for success and negative for failure
250*d83cc019SAndroid Build Coastguard Worker  */
__gem_context_set_priority(int fd,uint32_t ctx_id,int prio)251*d83cc019SAndroid Build Coastguard Worker int __gem_context_set_priority(int fd, uint32_t ctx_id, int prio)
252*d83cc019SAndroid Build Coastguard Worker {
253*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_context_param p = {
254*d83cc019SAndroid Build Coastguard Worker 		.ctx_id = ctx_id,
255*d83cc019SAndroid Build Coastguard Worker 		.param = DRM_I915_CONTEXT_PARAM_PRIORITY,
256*d83cc019SAndroid Build Coastguard Worker 		.value = prio,
257*d83cc019SAndroid Build Coastguard Worker 	};
258*d83cc019SAndroid Build Coastguard Worker 
259*d83cc019SAndroid Build Coastguard Worker 	return __gem_context_set_param(fd, &p);
260*d83cc019SAndroid Build Coastguard Worker }
261*d83cc019SAndroid Build Coastguard Worker 
262*d83cc019SAndroid Build Coastguard Worker /**
263*d83cc019SAndroid Build Coastguard Worker  * gem_context_set_priority:
264*d83cc019SAndroid Build Coastguard Worker  * @fd: open i915 drm file descriptor
265*d83cc019SAndroid Build Coastguard Worker  * @ctx_id: i915 context id
266*d83cc019SAndroid Build Coastguard Worker  * @prio: desired context priority
267*d83cc019SAndroid Build Coastguard Worker  *
268*d83cc019SAndroid Build Coastguard Worker  * Like __gem_context_set_priority(), except we assert on failure.
269*d83cc019SAndroid Build Coastguard Worker  */
gem_context_set_priority(int fd,uint32_t ctx_id,int prio)270*d83cc019SAndroid Build Coastguard Worker void gem_context_set_priority(int fd, uint32_t ctx_id, int prio)
271*d83cc019SAndroid Build Coastguard Worker {
272*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_context_set_priority(fd, ctx_id, prio), 0);
273*d83cc019SAndroid Build Coastguard Worker }
274*d83cc019SAndroid Build Coastguard Worker 
275*d83cc019SAndroid Build Coastguard Worker int
__gem_context_clone(int i915,uint32_t src,unsigned int share,unsigned int flags,uint32_t * out)276*d83cc019SAndroid Build Coastguard Worker __gem_context_clone(int i915,
277*d83cc019SAndroid Build Coastguard Worker 		    uint32_t src, unsigned int share,
278*d83cc019SAndroid Build Coastguard Worker 		    unsigned int flags,
279*d83cc019SAndroid Build Coastguard Worker 		    uint32_t *out)
280*d83cc019SAndroid Build Coastguard Worker {
281*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_context_create_ext_clone clone = {
282*d83cc019SAndroid Build Coastguard Worker 		{ .name = I915_CONTEXT_CREATE_EXT_CLONE },
283*d83cc019SAndroid Build Coastguard Worker 		.clone_id = src,
284*d83cc019SAndroid Build Coastguard Worker 		.flags = share,
285*d83cc019SAndroid Build Coastguard Worker 	};
286*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_context_create_ext arg = {
287*d83cc019SAndroid Build Coastguard Worker 		.flags = flags | I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
288*d83cc019SAndroid Build Coastguard Worker 		.extensions = to_user_pointer(&clone),
289*d83cc019SAndroid Build Coastguard Worker 	};
290*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
291*d83cc019SAndroid Build Coastguard Worker 
292*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, &arg)) {
293*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
294*d83cc019SAndroid Build Coastguard Worker 		igt_assume(err);
295*d83cc019SAndroid Build Coastguard Worker 	}
296*d83cc019SAndroid Build Coastguard Worker 
297*d83cc019SAndroid Build Coastguard Worker 	*out = arg.ctx_id;
298*d83cc019SAndroid Build Coastguard Worker 
299*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
300*d83cc019SAndroid Build Coastguard Worker 	return err;
301*d83cc019SAndroid Build Coastguard Worker }
302*d83cc019SAndroid Build Coastguard Worker 
__gem_context_has(int i915,uint32_t share,unsigned int flags)303*d83cc019SAndroid Build Coastguard Worker static bool __gem_context_has(int i915, uint32_t share, unsigned int flags)
304*d83cc019SAndroid Build Coastguard Worker {
305*d83cc019SAndroid Build Coastguard Worker 	uint32_t ctx;
306*d83cc019SAndroid Build Coastguard Worker 
307*d83cc019SAndroid Build Coastguard Worker 	__gem_context_clone(i915, 0, share, flags, &ctx);
308*d83cc019SAndroid Build Coastguard Worker 	if (ctx)
309*d83cc019SAndroid Build Coastguard Worker 		gem_context_destroy(i915, ctx);
310*d83cc019SAndroid Build Coastguard Worker 
311*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
312*d83cc019SAndroid Build Coastguard Worker 	return ctx;
313*d83cc019SAndroid Build Coastguard Worker }
314*d83cc019SAndroid Build Coastguard Worker 
gem_contexts_has_shared_gtt(int i915)315*d83cc019SAndroid Build Coastguard Worker bool gem_contexts_has_shared_gtt(int i915)
316*d83cc019SAndroid Build Coastguard Worker {
317*d83cc019SAndroid Build Coastguard Worker 	return __gem_context_has(i915, I915_CONTEXT_CLONE_VM, 0);
318*d83cc019SAndroid Build Coastguard Worker }
319*d83cc019SAndroid Build Coastguard Worker 
gem_has_queues(int i915)320*d83cc019SAndroid Build Coastguard Worker bool gem_has_queues(int i915)
321*d83cc019SAndroid Build Coastguard Worker {
322*d83cc019SAndroid Build Coastguard Worker 	return __gem_context_has(i915,
323*d83cc019SAndroid Build Coastguard Worker 				 I915_CONTEXT_CLONE_VM,
324*d83cc019SAndroid Build Coastguard Worker 				 I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE);
325*d83cc019SAndroid Build Coastguard Worker }
326*d83cc019SAndroid Build Coastguard Worker 
gem_context_clone(int i915,uint32_t src,unsigned int share,unsigned int flags)327*d83cc019SAndroid Build Coastguard Worker uint32_t gem_context_clone(int i915,
328*d83cc019SAndroid Build Coastguard Worker 			   uint32_t src, unsigned int share,
329*d83cc019SAndroid Build Coastguard Worker 			   unsigned int flags)
330*d83cc019SAndroid Build Coastguard Worker {
331*d83cc019SAndroid Build Coastguard Worker 	uint32_t ctx;
332*d83cc019SAndroid Build Coastguard Worker 
333*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_context_clone(i915, src, share, flags, &ctx), 0);
334*d83cc019SAndroid Build Coastguard Worker 
335*d83cc019SAndroid Build Coastguard Worker 	return ctx;
336*d83cc019SAndroid Build Coastguard Worker }
337*d83cc019SAndroid Build Coastguard Worker 
gem_queue_create(int i915)338*d83cc019SAndroid Build Coastguard Worker uint32_t gem_queue_create(int i915)
339*d83cc019SAndroid Build Coastguard Worker {
340*d83cc019SAndroid Build Coastguard Worker 	return gem_context_clone(i915, 0,
341*d83cc019SAndroid Build Coastguard Worker 				 I915_CONTEXT_CLONE_VM,
342*d83cc019SAndroid Build Coastguard Worker 				 I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE);
343*d83cc019SAndroid Build Coastguard Worker }
344*d83cc019SAndroid Build Coastguard Worker 
gem_context_has_engine(int fd,uint32_t ctx,uint64_t engine)345*d83cc019SAndroid Build Coastguard Worker bool gem_context_has_engine(int fd, uint32_t ctx, uint64_t engine)
346*d83cc019SAndroid Build Coastguard Worker {
347*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 exec = {};
348*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf = {
349*d83cc019SAndroid Build Coastguard Worker 		.buffers_ptr = to_user_pointer(&exec),
350*d83cc019SAndroid Build Coastguard Worker 		.buffer_count = 1,
351*d83cc019SAndroid Build Coastguard Worker 		.flags = engine,
352*d83cc019SAndroid Build Coastguard Worker 		.rsvd1 = ctx,
353*d83cc019SAndroid Build Coastguard Worker 	};
354*d83cc019SAndroid Build Coastguard Worker 
355*d83cc019SAndroid Build Coastguard Worker 	/*
356*d83cc019SAndroid Build Coastguard Worker 	 * 'engine' value can either store an execbuf engine selector
357*d83cc019SAndroid Build Coastguard Worker 	 * or a context map index; for the latter case we do not expect
358*d83cc019SAndroid Build Coastguard Worker 	 * to have any value at bit 13 and 14 (BSD1/2 selector),
359*d83cc019SAndroid Build Coastguard Worker 	 * therefore, we assume that the following check is safe and it
360*d83cc019SAndroid Build Coastguard Worker 	 * wouldn't produce any result.
361*d83cc019SAndroid Build Coastguard Worker 	 */
362*d83cc019SAndroid Build Coastguard Worker 	if ((engine & ~(3<<13)) == I915_EXEC_BSD) {
363*d83cc019SAndroid Build Coastguard Worker 		if (engine & (2 << 13) && !gem_has_bsd2(fd))
364*d83cc019SAndroid Build Coastguard Worker 			return false;
365*d83cc019SAndroid Build Coastguard Worker 	}
366*d83cc019SAndroid Build Coastguard Worker 
367*d83cc019SAndroid Build Coastguard Worker 	return __gem_execbuf(fd, &execbuf) == -ENOENT;
368*d83cc019SAndroid Build Coastguard Worker }
369