xref: /aosp_15_r20/external/igt-gpu-tools/tests/i915/i915_query.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 "igt.h"
25*d83cc019SAndroid Build Coastguard Worker 
26*d83cc019SAndroid Build Coastguard Worker #include <limits.h>
27*d83cc019SAndroid Build Coastguard Worker 
28*d83cc019SAndroid Build Coastguard Worker IGT_TEST_DESCRIPTION("Testing the i915 query uAPI.");
29*d83cc019SAndroid Build Coastguard Worker 
30*d83cc019SAndroid Build Coastguard Worker /*
31*d83cc019SAndroid Build Coastguard Worker  * We should at least get 3 bytes for data for each slices, subslices & EUs
32*d83cc019SAndroid Build Coastguard Worker  * masks.
33*d83cc019SAndroid Build Coastguard Worker  */
34*d83cc019SAndroid Build Coastguard Worker #define MIN_TOPOLOGY_ITEM_SIZE (sizeof(struct drm_i915_query_topology_info) + 3)
35*d83cc019SAndroid Build Coastguard Worker 
36*d83cc019SAndroid Build Coastguard Worker static int
__i915_query(int fd,struct drm_i915_query * q)37*d83cc019SAndroid Build Coastguard Worker __i915_query(int fd, struct drm_i915_query *q)
38*d83cc019SAndroid Build Coastguard Worker {
39*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, DRM_IOCTL_I915_QUERY, q))
40*d83cc019SAndroid Build Coastguard Worker 		return -errno;
41*d83cc019SAndroid Build Coastguard Worker 	return 0;
42*d83cc019SAndroid Build Coastguard Worker }
43*d83cc019SAndroid Build Coastguard Worker 
44*d83cc019SAndroid Build Coastguard Worker static int
__i915_query_items(int fd,struct drm_i915_query_item * items,uint32_t n_items)45*d83cc019SAndroid Build Coastguard Worker __i915_query_items(int fd, struct drm_i915_query_item *items, uint32_t n_items)
46*d83cc019SAndroid Build Coastguard Worker {
47*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query q = {
48*d83cc019SAndroid Build Coastguard Worker 		.num_items = n_items,
49*d83cc019SAndroid Build Coastguard Worker 		.items_ptr = to_user_pointer(items),
50*d83cc019SAndroid Build Coastguard Worker 	};
51*d83cc019SAndroid Build Coastguard Worker 	return __i915_query(fd, &q);
52*d83cc019SAndroid Build Coastguard Worker }
53*d83cc019SAndroid Build Coastguard Worker 
54*d83cc019SAndroid Build Coastguard Worker #define i915_query_items(fd, items, n_items) do { \
55*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(__i915_query_items(fd, items, n_items), 0); \
56*d83cc019SAndroid Build Coastguard Worker 		errno = 0; \
57*d83cc019SAndroid Build Coastguard Worker 	} while (0)
58*d83cc019SAndroid Build Coastguard Worker #define i915_query_items_err(fd, items, n_items, err) do { \
59*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(__i915_query_items(fd, items, n_items), -err); \
60*d83cc019SAndroid Build Coastguard Worker 	} while (0)
61*d83cc019SAndroid Build Coastguard Worker 
has_query_supports(int fd)62*d83cc019SAndroid Build Coastguard Worker static bool has_query_supports(int fd)
63*d83cc019SAndroid Build Coastguard Worker {
64*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query query = {};
65*d83cc019SAndroid Build Coastguard Worker 
66*d83cc019SAndroid Build Coastguard Worker 	return __i915_query(fd, &query) == 0;
67*d83cc019SAndroid Build Coastguard Worker }
68*d83cc019SAndroid Build Coastguard Worker 
test_query_garbage(int fd)69*d83cc019SAndroid Build Coastguard Worker static void test_query_garbage(int fd)
70*d83cc019SAndroid Build Coastguard Worker {
71*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query query;
72*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item;
73*d83cc019SAndroid Build Coastguard Worker 
74*d83cc019SAndroid Build Coastguard Worker 	/* Verify that invalid query pointers are rejected. */
75*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__i915_query(fd, NULL), -EFAULT);
76*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__i915_query(fd, (void *) -1), -EFAULT);
77*d83cc019SAndroid Build Coastguard Worker 
78*d83cc019SAndroid Build Coastguard Worker 	/*
79*d83cc019SAndroid Build Coastguard Worker 	 * Query flags field is currently valid only if equals to 0. This might
80*d83cc019SAndroid Build Coastguard Worker 	 * change in the future.
81*d83cc019SAndroid Build Coastguard Worker 	 */
82*d83cc019SAndroid Build Coastguard Worker 	memset(&query, 0, sizeof(query));
83*d83cc019SAndroid Build Coastguard Worker 	query.flags = 42;
84*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__i915_query(fd, &query), -EINVAL);
85*d83cc019SAndroid Build Coastguard Worker 
86*d83cc019SAndroid Build Coastguard Worker 	/* Test a couple of invalid pointers. */
87*d83cc019SAndroid Build Coastguard Worker 	i915_query_items_err(fd, (void *) ULONG_MAX, 1, EFAULT);
88*d83cc019SAndroid Build Coastguard Worker 	i915_query_items_err(fd, (void *) 0, 1, EFAULT);
89*d83cc019SAndroid Build Coastguard Worker 
90*d83cc019SAndroid Build Coastguard Worker 	/* Test the invalid query id = 0. */
91*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
92*d83cc019SAndroid Build Coastguard Worker 	i915_query_items_err(fd, &item, 1, EINVAL);
93*d83cc019SAndroid Build Coastguard Worker }
94*d83cc019SAndroid Build Coastguard Worker 
test_query_garbage_items(int fd)95*d83cc019SAndroid Build Coastguard Worker static void test_query_garbage_items(int fd)
96*d83cc019SAndroid Build Coastguard Worker {
97*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item items[2];
98*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item *items_ptr;
99*d83cc019SAndroid Build Coastguard Worker 	int i, n_items;
100*d83cc019SAndroid Build Coastguard Worker 
101*d83cc019SAndroid Build Coastguard Worker 	/*
102*d83cc019SAndroid Build Coastguard Worker 	 * Query item flags field is currently valid only if equals to 0.
103*d83cc019SAndroid Build Coastguard Worker 	 * Subject to change in the future.
104*d83cc019SAndroid Build Coastguard Worker 	 */
105*d83cc019SAndroid Build Coastguard Worker 	memset(items, 0, sizeof(items));
106*d83cc019SAndroid Build Coastguard Worker 	items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
107*d83cc019SAndroid Build Coastguard Worker 	items[0].flags = 42;
108*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, items, 1);
109*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(items[0].length, -EINVAL);
110*d83cc019SAndroid Build Coastguard Worker 
111*d83cc019SAndroid Build Coastguard Worker 	/*
112*d83cc019SAndroid Build Coastguard Worker 	 * Test an invalid query id in the second item and verify that the first
113*d83cc019SAndroid Build Coastguard Worker 	 * one is properly processed.
114*d83cc019SAndroid Build Coastguard Worker 	 */
115*d83cc019SAndroid Build Coastguard Worker 	memset(items, 0, sizeof(items));
116*d83cc019SAndroid Build Coastguard Worker 	items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
117*d83cc019SAndroid Build Coastguard Worker 	items[1].query_id = ULONG_MAX;
118*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, items, 2);
119*d83cc019SAndroid Build Coastguard Worker 	igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[0].length);
120*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(items[1].length, -EINVAL);
121*d83cc019SAndroid Build Coastguard Worker 
122*d83cc019SAndroid Build Coastguard Worker 	/*
123*d83cc019SAndroid Build Coastguard Worker 	 * Test a invalid query id in the first item and verify that the second
124*d83cc019SAndroid Build Coastguard Worker 	 * one is properly processed (the driver is expected to go through them
125*d83cc019SAndroid Build Coastguard Worker 	 * all and place error codes in the failed items).
126*d83cc019SAndroid Build Coastguard Worker 	 */
127*d83cc019SAndroid Build Coastguard Worker 	memset(items, 0, sizeof(items));
128*d83cc019SAndroid Build Coastguard Worker 	items[0].query_id = ULONG_MAX;
129*d83cc019SAndroid Build Coastguard Worker 	items[1].query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
130*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, items, 2);
131*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(items[0].length, -EINVAL);
132*d83cc019SAndroid Build Coastguard Worker 	igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[1].length);
133*d83cc019SAndroid Build Coastguard Worker 
134*d83cc019SAndroid Build Coastguard Worker 	/* Test a couple of invalid data pointer in query item. */
135*d83cc019SAndroid Build Coastguard Worker 	memset(items, 0, sizeof(items));
136*d83cc019SAndroid Build Coastguard Worker 	items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
137*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, items, 1);
138*d83cc019SAndroid Build Coastguard Worker 	igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[0].length);
139*d83cc019SAndroid Build Coastguard Worker 
140*d83cc019SAndroid Build Coastguard Worker 	items[0].data_ptr = 0;
141*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, items, 1);
142*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(items[0].length, -EFAULT);
143*d83cc019SAndroid Build Coastguard Worker 
144*d83cc019SAndroid Build Coastguard Worker 	items[0].data_ptr = ULONG_MAX;
145*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, items, 1);
146*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(items[0].length, -EFAULT);
147*d83cc019SAndroid Build Coastguard Worker 
148*d83cc019SAndroid Build Coastguard Worker 
149*d83cc019SAndroid Build Coastguard Worker 	/* Test an invalid query item length. */
150*d83cc019SAndroid Build Coastguard Worker 	memset(items, 0, sizeof(items));
151*d83cc019SAndroid Build Coastguard Worker 	items[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
152*d83cc019SAndroid Build Coastguard Worker 	items[1].query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
153*d83cc019SAndroid Build Coastguard Worker 	items[1].length = sizeof(struct drm_i915_query_topology_info) - 1;
154*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, items, 2);
155*d83cc019SAndroid Build Coastguard Worker 	igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items[0].length);
156*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(items[1].length, -EINVAL);
157*d83cc019SAndroid Build Coastguard Worker 
158*d83cc019SAndroid Build Coastguard Worker 	/*
159*d83cc019SAndroid Build Coastguard Worker 	 * Map memory for a query item in which the kernel is going to write the
160*d83cc019SAndroid Build Coastguard Worker 	 * length of the item in the first ioctl(). Then unmap that memory and
161*d83cc019SAndroid Build Coastguard Worker 	 * verify that the kernel correctly returns EFAULT as memory of the item
162*d83cc019SAndroid Build Coastguard Worker 	 * has been removed from our address space.
163*d83cc019SAndroid Build Coastguard Worker 	 */
164*d83cc019SAndroid Build Coastguard Worker 	items_ptr = mmap(0, 4096, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
165*d83cc019SAndroid Build Coastguard Worker 	items_ptr[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
166*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, items_ptr, 1);
167*d83cc019SAndroid Build Coastguard Worker 	igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, items_ptr[0].length);
168*d83cc019SAndroid Build Coastguard Worker 	munmap(items_ptr, 4096);
169*d83cc019SAndroid Build Coastguard Worker 	i915_query_items_err(fd, items_ptr, 1, EFAULT);
170*d83cc019SAndroid Build Coastguard Worker 
171*d83cc019SAndroid Build Coastguard Worker 	/*
172*d83cc019SAndroid Build Coastguard Worker 	 * Map memory for a query item, then make it read only and verify that
173*d83cc019SAndroid Build Coastguard Worker 	 * the kernel errors out with EFAULT.
174*d83cc019SAndroid Build Coastguard Worker 	 */
175*d83cc019SAndroid Build Coastguard Worker 	items_ptr = mmap(0, 4096, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
176*d83cc019SAndroid Build Coastguard Worker 	items_ptr[0].query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
177*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(0, mprotect(items_ptr, 4096, PROT_READ));
178*d83cc019SAndroid Build Coastguard Worker 	i915_query_items_err(fd, items_ptr, 1, EFAULT);
179*d83cc019SAndroid Build Coastguard Worker 	munmap(items_ptr, 4096);
180*d83cc019SAndroid Build Coastguard Worker 
181*d83cc019SAndroid Build Coastguard Worker 	/*
182*d83cc019SAndroid Build Coastguard Worker 	 * Allocate 2 pages, prepare those 2 pages with valid query items, then
183*d83cc019SAndroid Build Coastguard Worker 	 * switch the second page to read only and expect an EFAULT error.
184*d83cc019SAndroid Build Coastguard Worker 	 */
185*d83cc019SAndroid Build Coastguard Worker 	items_ptr = mmap(0, 8192, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
186*d83cc019SAndroid Build Coastguard Worker 	memset(items_ptr, 0, 8192);
187*d83cc019SAndroid Build Coastguard Worker 	n_items = 8192 / sizeof(struct drm_i915_query_item);
188*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < n_items; i++)
189*d83cc019SAndroid Build Coastguard Worker 		items_ptr[i].query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
190*d83cc019SAndroid Build Coastguard Worker 	mprotect(((uint8_t *)items_ptr) + 4096, 4096, PROT_READ);
191*d83cc019SAndroid Build Coastguard Worker 	i915_query_items_err(fd, items_ptr, n_items, EFAULT);
192*d83cc019SAndroid Build Coastguard Worker 	munmap(items_ptr, 8192);
193*d83cc019SAndroid Build Coastguard Worker }
194*d83cc019SAndroid Build Coastguard Worker 
195*d83cc019SAndroid Build Coastguard Worker /*
196*d83cc019SAndroid Build Coastguard Worker  * Allocate more on both sides of where the kernel is going to write and verify
197*d83cc019SAndroid Build Coastguard Worker  * that it writes only where it's supposed to.
198*d83cc019SAndroid Build Coastguard Worker  */
test_query_topology_kernel_writes(int fd)199*d83cc019SAndroid Build Coastguard Worker static void test_query_topology_kernel_writes(int fd)
200*d83cc019SAndroid Build Coastguard Worker {
201*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item;
202*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_topology_info *topo_info;
203*d83cc019SAndroid Build Coastguard Worker 	uint8_t *_topo_info;
204*d83cc019SAndroid Build Coastguard Worker 	int b, total_size;
205*d83cc019SAndroid Build Coastguard Worker 
206*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
207*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
208*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
209*d83cc019SAndroid Build Coastguard Worker 	igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, item.length);
210*d83cc019SAndroid Build Coastguard Worker 
211*d83cc019SAndroid Build Coastguard Worker 	total_size = item.length + 2 * sizeof(*_topo_info);
212*d83cc019SAndroid Build Coastguard Worker 	_topo_info = malloc(total_size);
213*d83cc019SAndroid Build Coastguard Worker 	memset(_topo_info, 0xff, total_size);
214*d83cc019SAndroid Build Coastguard Worker 	topo_info = (struct drm_i915_query_topology_info *) (_topo_info + sizeof(*_topo_info));
215*d83cc019SAndroid Build Coastguard Worker 	memset(topo_info, 0, item.length);
216*d83cc019SAndroid Build Coastguard Worker 
217*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(topo_info);
218*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
219*d83cc019SAndroid Build Coastguard Worker 
220*d83cc019SAndroid Build Coastguard Worker 	for (b = 0; b < sizeof(*_topo_info); b++) {
221*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(_topo_info[b], 0xff);
222*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(_topo_info[sizeof(*_topo_info) + item.length + b], 0xff);
223*d83cc019SAndroid Build Coastguard Worker 	}
224*d83cc019SAndroid Build Coastguard Worker }
225*d83cc019SAndroid Build Coastguard Worker 
query_topology_supported(int fd)226*d83cc019SAndroid Build Coastguard Worker static bool query_topology_supported(int fd)
227*d83cc019SAndroid Build Coastguard Worker {
228*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item = {
229*d83cc019SAndroid Build Coastguard Worker 		.query_id = DRM_I915_QUERY_TOPOLOGY_INFO,
230*d83cc019SAndroid Build Coastguard Worker 	};
231*d83cc019SAndroid Build Coastguard Worker 
232*d83cc019SAndroid Build Coastguard Worker 	return __i915_query_items(fd, &item, 1) == 0 && item.length > 0;
233*d83cc019SAndroid Build Coastguard Worker }
234*d83cc019SAndroid Build Coastguard Worker 
test_query_topology_unsupported(int fd)235*d83cc019SAndroid Build Coastguard Worker static void test_query_topology_unsupported(int fd)
236*d83cc019SAndroid Build Coastguard Worker {
237*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item = {
238*d83cc019SAndroid Build Coastguard Worker 		.query_id = DRM_I915_QUERY_TOPOLOGY_INFO,
239*d83cc019SAndroid Build Coastguard Worker 	};
240*d83cc019SAndroid Build Coastguard Worker 
241*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
242*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -ENODEV);
243*d83cc019SAndroid Build Coastguard Worker }
244*d83cc019SAndroid Build Coastguard Worker 
245*d83cc019SAndroid Build Coastguard Worker static bool
slice_available(const struct drm_i915_query_topology_info * topo_info,int s)246*d83cc019SAndroid Build Coastguard Worker slice_available(const struct drm_i915_query_topology_info *topo_info,
247*d83cc019SAndroid Build Coastguard Worker 		int s)
248*d83cc019SAndroid Build Coastguard Worker {
249*d83cc019SAndroid Build Coastguard Worker 	return (topo_info->data[s / 8] >> (s % 8)) & 1;
250*d83cc019SAndroid Build Coastguard Worker }
251*d83cc019SAndroid Build Coastguard Worker 
252*d83cc019SAndroid Build Coastguard Worker static bool
subslice_available(const struct drm_i915_query_topology_info * topo_info,int s,int ss)253*d83cc019SAndroid Build Coastguard Worker subslice_available(const struct drm_i915_query_topology_info *topo_info,
254*d83cc019SAndroid Build Coastguard Worker 		   int s, int ss)
255*d83cc019SAndroid Build Coastguard Worker {
256*d83cc019SAndroid Build Coastguard Worker 	return (topo_info->data[topo_info->subslice_offset +
257*d83cc019SAndroid Build Coastguard Worker 				s * topo_info->subslice_stride +
258*d83cc019SAndroid Build Coastguard Worker 				ss / 8] >> (ss % 8)) & 1;
259*d83cc019SAndroid Build Coastguard Worker }
260*d83cc019SAndroid Build Coastguard Worker 
261*d83cc019SAndroid Build Coastguard Worker static bool
eu_available(const struct drm_i915_query_topology_info * topo_info,int s,int ss,int eu)262*d83cc019SAndroid Build Coastguard Worker eu_available(const struct drm_i915_query_topology_info *topo_info,
263*d83cc019SAndroid Build Coastguard Worker 	     int s, int ss, int eu)
264*d83cc019SAndroid Build Coastguard Worker {
265*d83cc019SAndroid Build Coastguard Worker 	return (topo_info->data[topo_info->eu_offset +
266*d83cc019SAndroid Build Coastguard Worker 				(s * topo_info->max_subslices + ss) * topo_info->eu_stride +
267*d83cc019SAndroid Build Coastguard Worker 				eu / 8] >> (eu % 8)) & 1;
268*d83cc019SAndroid Build Coastguard Worker }
269*d83cc019SAndroid Build Coastguard Worker 
270*d83cc019SAndroid Build Coastguard Worker /*
271*d83cc019SAndroid Build Coastguard Worker  * Verify that we get coherent values between the legacy getparam slice/subslice
272*d83cc019SAndroid Build Coastguard Worker  * masks and the new topology query.
273*d83cc019SAndroid Build Coastguard Worker  */
274*d83cc019SAndroid Build Coastguard Worker static void
test_query_topology_coherent_slice_mask(int fd)275*d83cc019SAndroid Build Coastguard Worker test_query_topology_coherent_slice_mask(int fd)
276*d83cc019SAndroid Build Coastguard Worker {
277*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item;
278*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_topology_info *topo_info;
279*d83cc019SAndroid Build Coastguard Worker 	drm_i915_getparam_t gp;
280*d83cc019SAndroid Build Coastguard Worker 	int slice_mask, subslice_mask;
281*d83cc019SAndroid Build Coastguard Worker 	int s, topology_slices, topology_subslices_slice0;
282*d83cc019SAndroid Build Coastguard Worker 	int32_t first_query_length;
283*d83cc019SAndroid Build Coastguard Worker 
284*d83cc019SAndroid Build Coastguard Worker 	gp.param = I915_PARAM_SLICE_MASK;
285*d83cc019SAndroid Build Coastguard Worker 	gp.value = &slice_mask;
286*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on(igt_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) != 0);
287*d83cc019SAndroid Build Coastguard Worker 
288*d83cc019SAndroid Build Coastguard Worker 	gp.param = I915_PARAM_SUBSLICE_MASK;
289*d83cc019SAndroid Build Coastguard Worker 	gp.value = &subslice_mask;
290*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on(igt_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) != 0);
291*d83cc019SAndroid Build Coastguard Worker 
292*d83cc019SAndroid Build Coastguard Worker 	/* Slices */
293*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
294*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
295*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
296*d83cc019SAndroid Build Coastguard Worker 	/* We expect at least one byte for each slices, subslices & EUs masks. */
297*d83cc019SAndroid Build Coastguard Worker 	igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, item.length);
298*d83cc019SAndroid Build Coastguard Worker 	first_query_length = item.length;
299*d83cc019SAndroid Build Coastguard Worker 
300*d83cc019SAndroid Build Coastguard Worker 	topo_info = calloc(1, item.length);
301*d83cc019SAndroid Build Coastguard Worker 
302*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(topo_info);
303*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
304*d83cc019SAndroid Build Coastguard Worker 	/* We should get the same size once the data has been written. */
305*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(first_query_length, item.length);
306*d83cc019SAndroid Build Coastguard Worker 	/* We expect at least one byte for each slices, subslices & EUs masks. */
307*d83cc019SAndroid Build Coastguard Worker 	igt_assert_lte(MIN_TOPOLOGY_ITEM_SIZE, item.length);
308*d83cc019SAndroid Build Coastguard Worker 
309*d83cc019SAndroid Build Coastguard Worker 	topology_slices = 0;
310*d83cc019SAndroid Build Coastguard Worker 	for (s = 0; s < topo_info->max_slices; s++) {
311*d83cc019SAndroid Build Coastguard Worker 		if (slice_available(topo_info, s))
312*d83cc019SAndroid Build Coastguard Worker 			topology_slices |= 1UL << s;
313*d83cc019SAndroid Build Coastguard Worker 	}
314*d83cc019SAndroid Build Coastguard Worker 
315*d83cc019SAndroid Build Coastguard Worker 	igt_debug("slice mask getparam=0x%x / query=0x%x\n",
316*d83cc019SAndroid Build Coastguard Worker 		  slice_mask, topology_slices);
317*d83cc019SAndroid Build Coastguard Worker 
318*d83cc019SAndroid Build Coastguard Worker 	/* These 2 should always match. */
319*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(slice_mask, topology_slices);
320*d83cc019SAndroid Build Coastguard Worker 
321*d83cc019SAndroid Build Coastguard Worker 	topology_subslices_slice0 = 0;
322*d83cc019SAndroid Build Coastguard Worker 	for (s = 0; s < topo_info->max_subslices; s++) {
323*d83cc019SAndroid Build Coastguard Worker 		if (subslice_available(topo_info, 0, s))
324*d83cc019SAndroid Build Coastguard Worker 			topology_subslices_slice0 |= 1UL << s;
325*d83cc019SAndroid Build Coastguard Worker 	}
326*d83cc019SAndroid Build Coastguard Worker 
327*d83cc019SAndroid Build Coastguard Worker 	igt_debug("subslice mask getparam=0x%x / query=0x%x\n",
328*d83cc019SAndroid Build Coastguard Worker 		  subslice_mask, topology_subslices_slice0);
329*d83cc019SAndroid Build Coastguard Worker 
330*d83cc019SAndroid Build Coastguard Worker 	/*
331*d83cc019SAndroid Build Coastguard Worker 	 * I915_PARAM_SUBSLICE_MASK returns the value for slice0, we should
332*d83cc019SAndroid Build Coastguard Worker 	 * match the values for the first slice of the topology.
333*d83cc019SAndroid Build Coastguard Worker 	 */
334*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(subslice_mask, topology_subslices_slice0);
335*d83cc019SAndroid Build Coastguard Worker 
336*d83cc019SAndroid Build Coastguard Worker 	free(topo_info);
337*d83cc019SAndroid Build Coastguard Worker }
338*d83cc019SAndroid Build Coastguard Worker 
339*d83cc019SAndroid Build Coastguard Worker /*
340*d83cc019SAndroid Build Coastguard Worker  * Verify that we get same total number of EUs from getparam and topology query.
341*d83cc019SAndroid Build Coastguard Worker  */
342*d83cc019SAndroid Build Coastguard Worker static void
test_query_topology_matches_eu_total(int fd)343*d83cc019SAndroid Build Coastguard Worker test_query_topology_matches_eu_total(int fd)
344*d83cc019SAndroid Build Coastguard Worker {
345*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item;
346*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_topology_info *topo_info;
347*d83cc019SAndroid Build Coastguard Worker 	drm_i915_getparam_t gp;
348*d83cc019SAndroid Build Coastguard Worker 	int n_eus, n_eus_topology, s;
349*d83cc019SAndroid Build Coastguard Worker 
350*d83cc019SAndroid Build Coastguard Worker 	gp.param = I915_PARAM_EU_TOTAL;
351*d83cc019SAndroid Build Coastguard Worker 	gp.value = &n_eus;
352*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
353*d83cc019SAndroid Build Coastguard Worker 	igt_debug("n_eus=%i\n", n_eus);
354*d83cc019SAndroid Build Coastguard Worker 
355*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
356*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
357*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
358*d83cc019SAndroid Build Coastguard Worker 
359*d83cc019SAndroid Build Coastguard Worker 	topo_info = calloc(1, item.length);
360*d83cc019SAndroid Build Coastguard Worker 
361*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(topo_info);
362*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
363*d83cc019SAndroid Build Coastguard Worker 
364*d83cc019SAndroid Build Coastguard Worker 	igt_debug("max_slices=%hu max_subslices=%hu max_eus_per_subslice=%hu\n",
365*d83cc019SAndroid Build Coastguard Worker 		  topo_info->max_slices, topo_info->max_subslices,
366*d83cc019SAndroid Build Coastguard Worker 		  topo_info->max_eus_per_subslice);
367*d83cc019SAndroid Build Coastguard Worker 	igt_debug(" subslice_offset=%hu subslice_stride=%hu\n",
368*d83cc019SAndroid Build Coastguard Worker 		  topo_info->subslice_offset, topo_info->subslice_stride);
369*d83cc019SAndroid Build Coastguard Worker 	igt_debug(" eu_offset=%hu eu_stride=%hu\n",
370*d83cc019SAndroid Build Coastguard Worker 		  topo_info->eu_offset, topo_info->eu_stride);
371*d83cc019SAndroid Build Coastguard Worker 
372*d83cc019SAndroid Build Coastguard Worker 	n_eus_topology = 0;
373*d83cc019SAndroid Build Coastguard Worker 	for (s = 0; s < topo_info->max_slices; s++) {
374*d83cc019SAndroid Build Coastguard Worker 		int ss;
375*d83cc019SAndroid Build Coastguard Worker 
376*d83cc019SAndroid Build Coastguard Worker 		igt_debug("slice%i: (%s)\n", s,
377*d83cc019SAndroid Build Coastguard Worker 			  slice_available(topo_info, s) ? "available" : "fused");
378*d83cc019SAndroid Build Coastguard Worker 
379*d83cc019SAndroid Build Coastguard Worker 		if (!slice_available(topo_info, s))
380*d83cc019SAndroid Build Coastguard Worker 			continue;
381*d83cc019SAndroid Build Coastguard Worker 
382*d83cc019SAndroid Build Coastguard Worker 		for (ss = 0; ss < topo_info->max_subslices; ss++) {
383*d83cc019SAndroid Build Coastguard Worker 			int eu, n_subslice_eus = 0;
384*d83cc019SAndroid Build Coastguard Worker 
385*d83cc019SAndroid Build Coastguard Worker 			igt_debug("\tsubslice%i: (%s)\n", ss,
386*d83cc019SAndroid Build Coastguard Worker 				  subslice_available(topo_info, s, ss) ? "available" : "fused");
387*d83cc019SAndroid Build Coastguard Worker 
388*d83cc019SAndroid Build Coastguard Worker 			if (!subslice_available(topo_info, s, ss))
389*d83cc019SAndroid Build Coastguard Worker 				continue;
390*d83cc019SAndroid Build Coastguard Worker 
391*d83cc019SAndroid Build Coastguard Worker 			igt_debug("\t\teu_mask: 0b");
392*d83cc019SAndroid Build Coastguard Worker 			for (eu = 0; eu < topo_info->max_eus_per_subslice; eu++) {
393*d83cc019SAndroid Build Coastguard Worker 				uint8_t val = eu_available(topo_info, s, ss,
394*d83cc019SAndroid Build Coastguard Worker 							   topo_info->max_eus_per_subslice - 1 - eu);
395*d83cc019SAndroid Build Coastguard Worker 				igt_debug("%hhi", val);
396*d83cc019SAndroid Build Coastguard Worker 				n_subslice_eus += __builtin_popcount(val);
397*d83cc019SAndroid Build Coastguard Worker 				n_eus_topology += __builtin_popcount(val);
398*d83cc019SAndroid Build Coastguard Worker 			}
399*d83cc019SAndroid Build Coastguard Worker 
400*d83cc019SAndroid Build Coastguard Worker 			igt_debug(" (%i)\n", n_subslice_eus);
401*d83cc019SAndroid Build Coastguard Worker 
402*d83cc019SAndroid Build Coastguard Worker 			/* Sanity checks. */
403*d83cc019SAndroid Build Coastguard Worker 			if (n_subslice_eus > 0) {
404*d83cc019SAndroid Build Coastguard Worker 				igt_assert(slice_available(topo_info, s));
405*d83cc019SAndroid Build Coastguard Worker 				igt_assert(subslice_available(topo_info, s, ss));
406*d83cc019SAndroid Build Coastguard Worker 			}
407*d83cc019SAndroid Build Coastguard Worker 			if (subslice_available(topo_info, s, ss)) {
408*d83cc019SAndroid Build Coastguard Worker 				igt_assert(slice_available(topo_info, s));
409*d83cc019SAndroid Build Coastguard Worker 			}
410*d83cc019SAndroid Build Coastguard Worker 		}
411*d83cc019SAndroid Build Coastguard Worker 	}
412*d83cc019SAndroid Build Coastguard Worker 
413*d83cc019SAndroid Build Coastguard Worker 	free(topo_info);
414*d83cc019SAndroid Build Coastguard Worker 
415*d83cc019SAndroid Build Coastguard Worker 	igt_assert(n_eus_topology == n_eus);
416*d83cc019SAndroid Build Coastguard Worker }
417*d83cc019SAndroid Build Coastguard Worker 
418*d83cc019SAndroid Build Coastguard Worker /*
419*d83cc019SAndroid Build Coastguard Worker  * Verify some numbers on Gens that we know for sure the characteristics from
420*d83cc019SAndroid Build Coastguard Worker  * the PCI ids.
421*d83cc019SAndroid Build Coastguard Worker  */
422*d83cc019SAndroid Build Coastguard Worker static void
test_query_topology_known_pci_ids(int fd,int devid)423*d83cc019SAndroid Build Coastguard Worker test_query_topology_known_pci_ids(int fd, int devid)
424*d83cc019SAndroid Build Coastguard Worker {
425*d83cc019SAndroid Build Coastguard Worker 	const struct intel_device_info *dev_info = intel_get_device_info(devid);
426*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item;
427*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_topology_info *topo_info;
428*d83cc019SAndroid Build Coastguard Worker 	int n_slices = 0, n_subslices = 0;
429*d83cc019SAndroid Build Coastguard Worker 	int s, ss;
430*d83cc019SAndroid Build Coastguard Worker 
431*d83cc019SAndroid Build Coastguard Worker 	/* The GT size on some Broadwell skus is not defined, skip those. */
432*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on(dev_info->gt == 0);
433*d83cc019SAndroid Build Coastguard Worker 
434*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
435*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_TOPOLOGY_INFO;
436*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
437*d83cc019SAndroid Build Coastguard Worker 
438*d83cc019SAndroid Build Coastguard Worker 	topo_info = (struct drm_i915_query_topology_info *) calloc(1, item.length);
439*d83cc019SAndroid Build Coastguard Worker 
440*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(topo_info);
441*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
442*d83cc019SAndroid Build Coastguard Worker 
443*d83cc019SAndroid Build Coastguard Worker 	for (s = 0; s < topo_info->max_slices; s++) {
444*d83cc019SAndroid Build Coastguard Worker 		if (slice_available(topo_info, s))
445*d83cc019SAndroid Build Coastguard Worker 			n_slices++;
446*d83cc019SAndroid Build Coastguard Worker 
447*d83cc019SAndroid Build Coastguard Worker 		for (ss = 0; ss < topo_info->max_subslices; ss++) {
448*d83cc019SAndroid Build Coastguard Worker 			if (subslice_available(topo_info, s, ss))
449*d83cc019SAndroid Build Coastguard Worker 				n_subslices++;
450*d83cc019SAndroid Build Coastguard Worker 		}
451*d83cc019SAndroid Build Coastguard Worker 	}
452*d83cc019SAndroid Build Coastguard Worker 
453*d83cc019SAndroid Build Coastguard Worker 	igt_debug("Platform=%s GT=%u slices=%u subslices=%u\n",
454*d83cc019SAndroid Build Coastguard Worker 		  dev_info->codename, dev_info->gt, n_slices, n_subslices);
455*d83cc019SAndroid Build Coastguard Worker 
456*d83cc019SAndroid Build Coastguard Worker 	switch (dev_info->gt) {
457*d83cc019SAndroid Build Coastguard Worker 	case 1:
458*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(n_slices, 1);
459*d83cc019SAndroid Build Coastguard Worker 		igt_assert(n_subslices == 1 || n_subslices == 2 || n_subslices == 3);
460*d83cc019SAndroid Build Coastguard Worker 		break;
461*d83cc019SAndroid Build Coastguard Worker 	case 2:
462*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(n_slices, 1);
463*d83cc019SAndroid Build Coastguard Worker 		if (dev_info->is_haswell)
464*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(n_subslices, 2);
465*d83cc019SAndroid Build Coastguard Worker 		else
466*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(n_subslices, 3);
467*d83cc019SAndroid Build Coastguard Worker 		break;
468*d83cc019SAndroid Build Coastguard Worker 	case 3:
469*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(n_slices, 2);
470*d83cc019SAndroid Build Coastguard Worker 		if (dev_info->is_haswell)
471*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(n_subslices, 2 * 2);
472*d83cc019SAndroid Build Coastguard Worker 		else
473*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(n_subslices, 2 * 3);
474*d83cc019SAndroid Build Coastguard Worker 		break;
475*d83cc019SAndroid Build Coastguard Worker 	case 4:
476*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(n_slices, 3);
477*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(n_subslices, 3 * 3);
478*d83cc019SAndroid Build Coastguard Worker 		break;
479*d83cc019SAndroid Build Coastguard Worker 	default:
480*d83cc019SAndroid Build Coastguard Worker 		igt_assert(false);
481*d83cc019SAndroid Build Coastguard Worker 	}
482*d83cc019SAndroid Build Coastguard Worker 
483*d83cc019SAndroid Build Coastguard Worker 	free(topo_info);
484*d83cc019SAndroid Build Coastguard Worker }
485*d83cc019SAndroid Build Coastguard Worker 
query_engine_info_supported(int fd)486*d83cc019SAndroid Build Coastguard Worker static bool query_engine_info_supported(int fd)
487*d83cc019SAndroid Build Coastguard Worker {
488*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item = {
489*d83cc019SAndroid Build Coastguard Worker 		.query_id = DRM_I915_QUERY_ENGINE_INFO,
490*d83cc019SAndroid Build Coastguard Worker 	};
491*d83cc019SAndroid Build Coastguard Worker 
492*d83cc019SAndroid Build Coastguard Worker 	return __i915_query_items(fd, &item, 1) == 0 && item.length > 0;
493*d83cc019SAndroid Build Coastguard Worker }
494*d83cc019SAndroid Build Coastguard Worker 
engines_invalid(int fd)495*d83cc019SAndroid Build Coastguard Worker static void engines_invalid(int fd)
496*d83cc019SAndroid Build Coastguard Worker {
497*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_engine_info *engines;
498*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item;
499*d83cc019SAndroid Build Coastguard Worker 	unsigned int len;
500*d83cc019SAndroid Build Coastguard Worker 
501*d83cc019SAndroid Build Coastguard Worker 	/* Flags is MBZ. */
502*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
503*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
504*d83cc019SAndroid Build Coastguard Worker 	item.flags = 1;
505*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
506*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -EINVAL);
507*d83cc019SAndroid Build Coastguard Worker 
508*d83cc019SAndroid Build Coastguard Worker 	/* Length not zero and not greater or equal required size. */
509*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
510*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
511*d83cc019SAndroid Build Coastguard Worker 	item.length = 1;
512*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
513*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -EINVAL);
514*d83cc019SAndroid Build Coastguard Worker 
515*d83cc019SAndroid Build Coastguard Worker 	/* Query correct length. */
516*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
517*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
518*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
519*d83cc019SAndroid Build Coastguard Worker 	igt_assert(item.length >= 0);
520*d83cc019SAndroid Build Coastguard Worker 	len = item.length;
521*d83cc019SAndroid Build Coastguard Worker 
522*d83cc019SAndroid Build Coastguard Worker 	engines = malloc(len);
523*d83cc019SAndroid Build Coastguard Worker 	igt_assert(engines);
524*d83cc019SAndroid Build Coastguard Worker 
525*d83cc019SAndroid Build Coastguard Worker 	/* Ivalid pointer. */
526*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
527*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
528*d83cc019SAndroid Build Coastguard Worker 	item.length = len;
529*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
530*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -EFAULT);
531*d83cc019SAndroid Build Coastguard Worker 
532*d83cc019SAndroid Build Coastguard Worker 	/* All fields in engines query are MBZ and only filled by the kernel. */
533*d83cc019SAndroid Build Coastguard Worker 
534*d83cc019SAndroid Build Coastguard Worker 	memset(engines, 0, len);
535*d83cc019SAndroid Build Coastguard Worker 	engines->num_engines = 1;
536*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
537*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
538*d83cc019SAndroid Build Coastguard Worker 	item.length = len;
539*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(engines);
540*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
541*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -EINVAL);
542*d83cc019SAndroid Build Coastguard Worker 
543*d83cc019SAndroid Build Coastguard Worker 	memset(engines, 0, len);
544*d83cc019SAndroid Build Coastguard Worker 	engines->rsvd[0] = 1;
545*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
546*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
547*d83cc019SAndroid Build Coastguard Worker 	item.length = len;
548*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(engines);
549*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
550*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -EINVAL);
551*d83cc019SAndroid Build Coastguard Worker 
552*d83cc019SAndroid Build Coastguard Worker 	memset(engines, 0, len);
553*d83cc019SAndroid Build Coastguard Worker 	engines->rsvd[1] = 1;
554*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
555*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
556*d83cc019SAndroid Build Coastguard Worker 	item.length = len;
557*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(engines);
558*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
559*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -EINVAL);
560*d83cc019SAndroid Build Coastguard Worker 
561*d83cc019SAndroid Build Coastguard Worker 	memset(engines, 0, len);
562*d83cc019SAndroid Build Coastguard Worker 	engines->rsvd[2] = 1;
563*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
564*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
565*d83cc019SAndroid Build Coastguard Worker 	item.length = len;
566*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(engines);
567*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
568*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -EINVAL);
569*d83cc019SAndroid Build Coastguard Worker 
570*d83cc019SAndroid Build Coastguard Worker 	free(engines);
571*d83cc019SAndroid Build Coastguard Worker 
572*d83cc019SAndroid Build Coastguard Worker 	igt_assert(len <= 4096);
573*d83cc019SAndroid Build Coastguard Worker 	engines = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
574*d83cc019SAndroid Build Coastguard Worker 		       -1, 0);
575*d83cc019SAndroid Build Coastguard Worker 	igt_assert(engines != MAP_FAILED);
576*d83cc019SAndroid Build Coastguard Worker 
577*d83cc019SAndroid Build Coastguard Worker 	/* PROT_NONE is similar to unmapped area. */
578*d83cc019SAndroid Build Coastguard Worker 	memset(engines, 0, len);
579*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mprotect(engines, len, PROT_NONE), 0);
580*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
581*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
582*d83cc019SAndroid Build Coastguard Worker 	item.length = len;
583*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(engines);
584*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
585*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -EFAULT);
586*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mprotect(engines, len, PROT_WRITE), 0);
587*d83cc019SAndroid Build Coastguard Worker 
588*d83cc019SAndroid Build Coastguard Worker 	/* Read-only so kernel cannot fill the data back. */
589*d83cc019SAndroid Build Coastguard Worker 	memset(engines, 0, len);
590*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mprotect(engines, len, PROT_READ), 0);
591*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
592*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
593*d83cc019SAndroid Build Coastguard Worker 	item.length = len;
594*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(engines);
595*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
596*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, -EFAULT);
597*d83cc019SAndroid Build Coastguard Worker 
598*d83cc019SAndroid Build Coastguard Worker 	munmap(engines, 4096);
599*d83cc019SAndroid Build Coastguard Worker }
600*d83cc019SAndroid Build Coastguard Worker 
601*d83cc019SAndroid Build Coastguard Worker static bool
has_engine(struct drm_i915_query_engine_info * engines,unsigned class,unsigned instance)602*d83cc019SAndroid Build Coastguard Worker has_engine(struct drm_i915_query_engine_info *engines,
603*d83cc019SAndroid Build Coastguard Worker 	   unsigned class, unsigned instance)
604*d83cc019SAndroid Build Coastguard Worker {
605*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
606*d83cc019SAndroid Build Coastguard Worker 
607*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < engines->num_engines; i++) {
608*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_engine_info *engine =
609*d83cc019SAndroid Build Coastguard Worker 			(struct drm_i915_engine_info *)&engines->engines[i];
610*d83cc019SAndroid Build Coastguard Worker 
611*d83cc019SAndroid Build Coastguard Worker 		if (engine->engine.engine_class == class &&
612*d83cc019SAndroid Build Coastguard Worker 		    engine->engine.engine_instance == instance)
613*d83cc019SAndroid Build Coastguard Worker 			return true;
614*d83cc019SAndroid Build Coastguard Worker 	}
615*d83cc019SAndroid Build Coastguard Worker 
616*d83cc019SAndroid Build Coastguard Worker 	return false;
617*d83cc019SAndroid Build Coastguard Worker }
618*d83cc019SAndroid Build Coastguard Worker 
engines(int fd)619*d83cc019SAndroid Build Coastguard Worker static void engines(int fd)
620*d83cc019SAndroid Build Coastguard Worker {
621*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_engine_info *engines;
622*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item;
623*d83cc019SAndroid Build Coastguard Worker 	unsigned int len, i;
624*d83cc019SAndroid Build Coastguard Worker 
625*d83cc019SAndroid Build Coastguard Worker 	engines = malloc(4096);
626*d83cc019SAndroid Build Coastguard Worker 	igt_assert(engines);
627*d83cc019SAndroid Build Coastguard Worker 
628*d83cc019SAndroid Build Coastguard Worker 	/* Query required buffer length. */
629*d83cc019SAndroid Build Coastguard Worker 	memset(engines, 0, 4096);
630*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
631*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
632*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(engines);
633*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
634*d83cc019SAndroid Build Coastguard Worker 	igt_assert(item.length >= 0);
635*d83cc019SAndroid Build Coastguard Worker 	igt_assert(item.length <= 4096);
636*d83cc019SAndroid Build Coastguard Worker 	len = item.length;
637*d83cc019SAndroid Build Coastguard Worker 
638*d83cc019SAndroid Build Coastguard Worker 	/* Check length larger than required works and reports same length. */
639*d83cc019SAndroid Build Coastguard Worker 	memset(engines, 0, 4096);
640*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
641*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
642*d83cc019SAndroid Build Coastguard Worker 	item.length = 4096;
643*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(engines);
644*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
645*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, len);
646*d83cc019SAndroid Build Coastguard Worker 
647*d83cc019SAndroid Build Coastguard Worker 	/* Actual query. */
648*d83cc019SAndroid Build Coastguard Worker 	memset(engines, 0, 4096);
649*d83cc019SAndroid Build Coastguard Worker 	memset(&item, 0, sizeof(item));
650*d83cc019SAndroid Build Coastguard Worker 	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
651*d83cc019SAndroid Build Coastguard Worker 	item.length = len;
652*d83cc019SAndroid Build Coastguard Worker 	item.data_ptr = to_user_pointer(engines);
653*d83cc019SAndroid Build Coastguard Worker 	i915_query_items(fd, &item, 1);
654*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(item.length, len);
655*d83cc019SAndroid Build Coastguard Worker 
656*d83cc019SAndroid Build Coastguard Worker 	/* Every GPU has at least one engine. */
657*d83cc019SAndroid Build Coastguard Worker 	igt_assert(engines->num_engines > 0);
658*d83cc019SAndroid Build Coastguard Worker 
659*d83cc019SAndroid Build Coastguard Worker 	/* MBZ fields. */
660*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(engines->rsvd[0], 0);
661*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(engines->rsvd[1], 0);
662*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(engines->rsvd[2], 0);
663*d83cc019SAndroid Build Coastguard Worker 
664*d83cc019SAndroid Build Coastguard Worker 	/* Check results match the legacy GET_PARAM (where we can). */
665*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < engines->num_engines; i++) {
666*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_engine_info *engine =
667*d83cc019SAndroid Build Coastguard Worker 			(struct drm_i915_engine_info *)&engines->engines[i];
668*d83cc019SAndroid Build Coastguard Worker 
669*d83cc019SAndroid Build Coastguard Worker 		igt_debug("%u: class=%u instance=%u flags=%llx capabilities=%llx\n",
670*d83cc019SAndroid Build Coastguard Worker 			  i,
671*d83cc019SAndroid Build Coastguard Worker 			  engine->engine.engine_class,
672*d83cc019SAndroid Build Coastguard Worker 			  engine->engine.engine_instance,
673*d83cc019SAndroid Build Coastguard Worker 			  engine->flags,
674*d83cc019SAndroid Build Coastguard Worker 			  engine->capabilities);
675*d83cc019SAndroid Build Coastguard Worker 
676*d83cc019SAndroid Build Coastguard Worker 		/* MBZ fields. */
677*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(engine->rsvd0, 0);
678*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(engine->rsvd1[0], 0);
679*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(engine->rsvd1[1], 0);
680*d83cc019SAndroid Build Coastguard Worker 
681*d83cc019SAndroid Build Coastguard Worker 		switch (engine->engine.engine_class) {
682*d83cc019SAndroid Build Coastguard Worker 		case I915_ENGINE_CLASS_RENDER:
683*d83cc019SAndroid Build Coastguard Worker 			/* Will be tested later. */
684*d83cc019SAndroid Build Coastguard Worker 			break;
685*d83cc019SAndroid Build Coastguard Worker 		case I915_ENGINE_CLASS_COPY:
686*d83cc019SAndroid Build Coastguard Worker 			igt_assert(gem_has_blt(fd));
687*d83cc019SAndroid Build Coastguard Worker 			break;
688*d83cc019SAndroid Build Coastguard Worker 		case I915_ENGINE_CLASS_VIDEO:
689*d83cc019SAndroid Build Coastguard Worker 			switch (engine->engine.engine_instance) {
690*d83cc019SAndroid Build Coastguard Worker 			case 0:
691*d83cc019SAndroid Build Coastguard Worker 				igt_assert(gem_has_bsd(fd));
692*d83cc019SAndroid Build Coastguard Worker 				break;
693*d83cc019SAndroid Build Coastguard Worker 			case 1:
694*d83cc019SAndroid Build Coastguard Worker 				igt_assert(gem_has_bsd2(fd));
695*d83cc019SAndroid Build Coastguard Worker 				break;
696*d83cc019SAndroid Build Coastguard Worker 			}
697*d83cc019SAndroid Build Coastguard Worker 			break;
698*d83cc019SAndroid Build Coastguard Worker 		case I915_ENGINE_CLASS_VIDEO_ENHANCE:
699*d83cc019SAndroid Build Coastguard Worker 			igt_assert(gem_has_vebox(fd));
700*d83cc019SAndroid Build Coastguard Worker 			break;
701*d83cc019SAndroid Build Coastguard Worker 		default:
702*d83cc019SAndroid Build Coastguard Worker 			igt_assert(0);
703*d83cc019SAndroid Build Coastguard Worker 		}
704*d83cc019SAndroid Build Coastguard Worker 	}
705*d83cc019SAndroid Build Coastguard Worker 
706*d83cc019SAndroid Build Coastguard Worker 	/* Reverse check to the above - all GET_PARAM engines are present. */
707*d83cc019SAndroid Build Coastguard Worker 	igt_assert(has_engine(engines, I915_ENGINE_CLASS_RENDER, 0));
708*d83cc019SAndroid Build Coastguard Worker 	if (gem_has_blt(fd))
709*d83cc019SAndroid Build Coastguard Worker 		igt_assert(has_engine(engines, I915_ENGINE_CLASS_COPY, 0));
710*d83cc019SAndroid Build Coastguard Worker 	if (gem_has_bsd(fd))
711*d83cc019SAndroid Build Coastguard Worker 		igt_assert(has_engine(engines, I915_ENGINE_CLASS_VIDEO, 0));
712*d83cc019SAndroid Build Coastguard Worker 	if (gem_has_bsd2(fd))
713*d83cc019SAndroid Build Coastguard Worker 		igt_assert(has_engine(engines, I915_ENGINE_CLASS_VIDEO, 1));
714*d83cc019SAndroid Build Coastguard Worker 	if (gem_has_vebox(fd))
715*d83cc019SAndroid Build Coastguard Worker 		igt_assert(has_engine(engines, I915_ENGINE_CLASS_VIDEO_ENHANCE,
716*d83cc019SAndroid Build Coastguard Worker 				       0));
717*d83cc019SAndroid Build Coastguard Worker 
718*d83cc019SAndroid Build Coastguard Worker 	free(engines);
719*d83cc019SAndroid Build Coastguard Worker }
720*d83cc019SAndroid Build Coastguard Worker 
721*d83cc019SAndroid Build Coastguard Worker igt_main
722*d83cc019SAndroid Build Coastguard Worker {
723*d83cc019SAndroid Build Coastguard Worker 	int fd = -1;
724*d83cc019SAndroid Build Coastguard Worker 	int devid;
725*d83cc019SAndroid Build Coastguard Worker 
726*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
727*d83cc019SAndroid Build Coastguard Worker 		fd = drm_open_driver(DRIVER_INTEL);
728*d83cc019SAndroid Build Coastguard Worker 		igt_require(has_query_supports(fd));
729*d83cc019SAndroid Build Coastguard Worker 		devid = intel_get_drm_devid(fd);
730*d83cc019SAndroid Build Coastguard Worker 	}
731*d83cc019SAndroid Build Coastguard Worker 
732*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("query-garbage")
733*d83cc019SAndroid Build Coastguard Worker 		test_query_garbage(fd);
734*d83cc019SAndroid Build Coastguard Worker 
735*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("query-garbage-items") {
736*d83cc019SAndroid Build Coastguard Worker 		igt_require(query_topology_supported(fd));
737*d83cc019SAndroid Build Coastguard Worker 		test_query_garbage_items(fd);
738*d83cc019SAndroid Build Coastguard Worker 	}
739*d83cc019SAndroid Build Coastguard Worker 
740*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("query-topology-kernel-writes") {
741*d83cc019SAndroid Build Coastguard Worker 		igt_require(query_topology_supported(fd));
742*d83cc019SAndroid Build Coastguard Worker 		test_query_topology_kernel_writes(fd);
743*d83cc019SAndroid Build Coastguard Worker 	}
744*d83cc019SAndroid Build Coastguard Worker 
745*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("query-topology-unsupported") {
746*d83cc019SAndroid Build Coastguard Worker 		igt_require(!query_topology_supported(fd));
747*d83cc019SAndroid Build Coastguard Worker 		test_query_topology_unsupported(fd);
748*d83cc019SAndroid Build Coastguard Worker 	}
749*d83cc019SAndroid Build Coastguard Worker 
750*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("query-topology-coherent-slice-mask") {
751*d83cc019SAndroid Build Coastguard Worker 		igt_require(query_topology_supported(fd));
752*d83cc019SAndroid Build Coastguard Worker 		test_query_topology_coherent_slice_mask(fd);
753*d83cc019SAndroid Build Coastguard Worker 	}
754*d83cc019SAndroid Build Coastguard Worker 
755*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("query-topology-matches-eu-total") {
756*d83cc019SAndroid Build Coastguard Worker 		igt_require(query_topology_supported(fd));
757*d83cc019SAndroid Build Coastguard Worker 		test_query_topology_matches_eu_total(fd);
758*d83cc019SAndroid Build Coastguard Worker 	}
759*d83cc019SAndroid Build Coastguard Worker 
760*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("query-topology-known-pci-ids") {
761*d83cc019SAndroid Build Coastguard Worker 		igt_require(query_topology_supported(fd));
762*d83cc019SAndroid Build Coastguard Worker 		igt_require(IS_HASWELL(devid) || IS_BROADWELL(devid) ||
763*d83cc019SAndroid Build Coastguard Worker 			    IS_SKYLAKE(devid) || IS_KABYLAKE(devid) ||
764*d83cc019SAndroid Build Coastguard Worker 			    IS_COFFEELAKE(devid));
765*d83cc019SAndroid Build Coastguard Worker 		test_query_topology_known_pci_ids(fd, devid);
766*d83cc019SAndroid Build Coastguard Worker 	}
767*d83cc019SAndroid Build Coastguard Worker 
768*d83cc019SAndroid Build Coastguard Worker 	igt_subtest_group {
769*d83cc019SAndroid Build Coastguard Worker 		igt_fixture {
770*d83cc019SAndroid Build Coastguard Worker 			igt_require(query_engine_info_supported(fd));
771*d83cc019SAndroid Build Coastguard Worker 		}
772*d83cc019SAndroid Build Coastguard Worker 
773*d83cc019SAndroid Build Coastguard Worker 		igt_subtest("engine-info-invalid")
774*d83cc019SAndroid Build Coastguard Worker 			engines_invalid(fd);
775*d83cc019SAndroid Build Coastguard Worker 
776*d83cc019SAndroid Build Coastguard Worker 		igt_subtest("engine-info")
777*d83cc019SAndroid Build Coastguard Worker 			engines(fd);
778*d83cc019SAndroid Build Coastguard Worker 	}
779*d83cc019SAndroid Build Coastguard Worker 
780*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
781*d83cc019SAndroid Build Coastguard Worker 		close(fd);
782*d83cc019SAndroid Build Coastguard Worker 	}
783*d83cc019SAndroid Build Coastguard Worker }
784