xref: /aosp_15_r20/external/igt-gpu-tools/tests/i915/gem_softpin.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2015 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  * Authors:
24*d83cc019SAndroid Build Coastguard Worker  *    Vinay Belgaumkar <[email protected]>
25*d83cc019SAndroid Build Coastguard Worker  *    Thomas Daniel <[email protected]>
26*d83cc019SAndroid Build Coastguard Worker  *
27*d83cc019SAndroid Build Coastguard Worker  */
28*d83cc019SAndroid Build Coastguard Worker 
29*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
30*d83cc019SAndroid Build Coastguard Worker 
31*d83cc019SAndroid Build Coastguard Worker #define EXEC_OBJECT_PINNED	(1<<4)
32*d83cc019SAndroid Build Coastguard Worker #define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3)
33*d83cc019SAndroid Build Coastguard Worker 
34*d83cc019SAndroid Build Coastguard Worker /* gen8_canonical_addr
35*d83cc019SAndroid Build Coastguard Worker  * Used to convert any address into canonical form, i.e. [63:48] == [47].
36*d83cc019SAndroid Build Coastguard Worker  * Based on kernel's sign_extend64 implementation.
37*d83cc019SAndroid Build Coastguard Worker  * @address - a virtual address
38*d83cc019SAndroid Build Coastguard Worker */
39*d83cc019SAndroid Build Coastguard Worker #define GEN8_HIGH_ADDRESS_BIT 47
gen8_canonical_addr(uint64_t address)40*d83cc019SAndroid Build Coastguard Worker static uint64_t gen8_canonical_addr(uint64_t address)
41*d83cc019SAndroid Build Coastguard Worker {
42*d83cc019SAndroid Build Coastguard Worker 	__u8 shift = 63 - GEN8_HIGH_ADDRESS_BIT;
43*d83cc019SAndroid Build Coastguard Worker 	return (__s64)(address << shift) >> shift;
44*d83cc019SAndroid Build Coastguard Worker }
45*d83cc019SAndroid Build Coastguard Worker 
test_invalid(int fd)46*d83cc019SAndroid Build Coastguard Worker static void test_invalid(int fd)
47*d83cc019SAndroid Build Coastguard Worker {
48*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
49*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
50*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object;
51*d83cc019SAndroid Build Coastguard Worker 
52*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
53*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&object);
54*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
55*d83cc019SAndroid Build Coastguard Worker 
56*d83cc019SAndroid Build Coastguard Worker 	memset(&object, 0, sizeof(object));
57*d83cc019SAndroid Build Coastguard Worker 	object.handle = gem_create(fd, 2*4096);
58*d83cc019SAndroid Build Coastguard Worker 	object.flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS | EXEC_OBJECT_PINNED;
59*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
60*d83cc019SAndroid Build Coastguard Worker 
61*d83cc019SAndroid Build Coastguard Worker 	/* Check invalid alignment */
62*d83cc019SAndroid Build Coastguard Worker 	object.offset = 4096;
63*d83cc019SAndroid Build Coastguard Worker 	object.alignment = 64*1024;
64*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
65*d83cc019SAndroid Build Coastguard Worker 	object.alignment = 0;
66*d83cc019SAndroid Build Coastguard Worker 
67*d83cc019SAndroid Build Coastguard Worker 	/* Check wraparound */
68*d83cc019SAndroid Build Coastguard Worker 	object.offset = -4096ULL;
69*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
70*d83cc019SAndroid Build Coastguard Worker 
71*d83cc019SAndroid Build Coastguard Worker 	/* Check beyond bounds of aperture */
72*d83cc019SAndroid Build Coastguard Worker 	object.offset = gem_aperture_size(fd) - 4096;
73*d83cc019SAndroid Build Coastguard Worker 	object.offset = gen8_canonical_addr(object.offset);
74*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
75*d83cc019SAndroid Build Coastguard Worker 
76*d83cc019SAndroid Build Coastguard Worker 	/* Check gen8 canonical addressing */
77*d83cc019SAndroid Build Coastguard Worker 	if (gem_aperture_size(fd) > 1ull<<GEN8_HIGH_ADDRESS_BIT) {
78*d83cc019SAndroid Build Coastguard Worker 		object.offset = 1ull << GEN8_HIGH_ADDRESS_BIT;
79*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
80*d83cc019SAndroid Build Coastguard Worker 
81*d83cc019SAndroid Build Coastguard Worker 		object.offset = gen8_canonical_addr(object.offset);
82*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(__gem_execbuf(fd, &execbuf), 0);
83*d83cc019SAndroid Build Coastguard Worker 	}
84*d83cc019SAndroid Build Coastguard Worker 
85*d83cc019SAndroid Build Coastguard Worker 	/* Check extended range */
86*d83cc019SAndroid Build Coastguard Worker 	if (gem_aperture_size(fd) > 1ull<<32) {
87*d83cc019SAndroid Build Coastguard Worker 		object.flags = EXEC_OBJECT_PINNED;
88*d83cc019SAndroid Build Coastguard Worker 		object.offset = 1ull<<32;
89*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
90*d83cc019SAndroid Build Coastguard Worker 
91*d83cc019SAndroid Build Coastguard Worker 		object.offset = gen8_canonical_addr(object.offset);
92*d83cc019SAndroid Build Coastguard Worker 		object.flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
93*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(__gem_execbuf(fd, &execbuf), 0);
94*d83cc019SAndroid Build Coastguard Worker 	}
95*d83cc019SAndroid Build Coastguard Worker }
96*d83cc019SAndroid Build Coastguard Worker 
test_softpin(int fd)97*d83cc019SAndroid Build Coastguard Worker static void test_softpin(int fd)
98*d83cc019SAndroid Build Coastguard Worker {
99*d83cc019SAndroid Build Coastguard Worker 	const uint32_t size = 1024 * 1024;
100*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
101*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
102*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object;
103*d83cc019SAndroid Build Coastguard Worker 	uint64_t offset, end;
104*d83cc019SAndroid Build Coastguard Worker 	uint32_t last_handle;
105*d83cc019SAndroid Build Coastguard Worker 	int loop;
106*d83cc019SAndroid Build Coastguard Worker 
107*d83cc019SAndroid Build Coastguard Worker 	last_handle = gem_create(fd, size);
108*d83cc019SAndroid Build Coastguard Worker 
109*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
110*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&object);
111*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
112*d83cc019SAndroid Build Coastguard Worker 	for (loop = 0; loop < 1024; loop++) {
113*d83cc019SAndroid Build Coastguard Worker 		memset(&object, 0, sizeof(object));
114*d83cc019SAndroid Build Coastguard Worker 		object.handle = gem_create(fd, 2*size);
115*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
116*d83cc019SAndroid Build Coastguard Worker 
117*d83cc019SAndroid Build Coastguard Worker 		/* Find a hole */
118*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
119*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object.handle);
120*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, last_handle);
121*d83cc019SAndroid Build Coastguard Worker 
122*d83cc019SAndroid Build Coastguard Worker 		igt_debug("Made a 2 MiB hole: %08llx\n",
123*d83cc019SAndroid Build Coastguard Worker 			  object.offset);
124*d83cc019SAndroid Build Coastguard Worker 
125*d83cc019SAndroid Build Coastguard Worker 		object.handle = gem_create(fd, size);
126*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
127*d83cc019SAndroid Build Coastguard Worker 		object.flags |= EXEC_OBJECT_PINNED;
128*d83cc019SAndroid Build Coastguard Worker 
129*d83cc019SAndroid Build Coastguard Worker 		end = object.offset + size;
130*d83cc019SAndroid Build Coastguard Worker 		for (offset = object.offset; offset <= end; offset += 4096) {
131*d83cc019SAndroid Build Coastguard Worker 			object.offset = offset;
132*d83cc019SAndroid Build Coastguard Worker 			gem_execbuf(fd, &execbuf);
133*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq_u64(object.offset, offset);
134*d83cc019SAndroid Build Coastguard Worker 		}
135*d83cc019SAndroid Build Coastguard Worker 
136*d83cc019SAndroid Build Coastguard Worker 		last_handle = object.handle;
137*d83cc019SAndroid Build Coastguard Worker 	}
138*d83cc019SAndroid Build Coastguard Worker }
139*d83cc019SAndroid Build Coastguard Worker 
test_overlap(int fd)140*d83cc019SAndroid Build Coastguard Worker static void test_overlap(int fd)
141*d83cc019SAndroid Build Coastguard Worker {
142*d83cc019SAndroid Build Coastguard Worker 	const uint32_t size = 1024 * 1024;
143*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
144*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
145*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object[2];
146*d83cc019SAndroid Build Coastguard Worker 	uint64_t offset;
147*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
148*d83cc019SAndroid Build Coastguard Worker 
149*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, 3*size);
150*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, handle, 0, &bbe, sizeof(bbe));
151*d83cc019SAndroid Build Coastguard Worker 
152*d83cc019SAndroid Build Coastguard Worker 	memset(object, 0, sizeof(object));
153*d83cc019SAndroid Build Coastguard Worker 	object[0].handle = handle;
154*d83cc019SAndroid Build Coastguard Worker 
155*d83cc019SAndroid Build Coastguard Worker 	/* Find a hole */
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 	gem_execbuf(fd, &execbuf);
160*d83cc019SAndroid Build Coastguard Worker 
161*d83cc019SAndroid Build Coastguard Worker 	igt_debug("Made a 3x1 MiB hole: %08llx\n",
162*d83cc019SAndroid Build Coastguard Worker 		  object[0].offset);
163*d83cc019SAndroid Build Coastguard Worker 
164*d83cc019SAndroid Build Coastguard Worker 	object[0].handle = gem_create(fd, size);
165*d83cc019SAndroid Build Coastguard Worker 	object[0].offset += size;
166*d83cc019SAndroid Build Coastguard Worker 	object[0].flags |= EXEC_OBJECT_PINNED;
167*d83cc019SAndroid Build Coastguard Worker 	object[1].handle = gem_create(fd, size);
168*d83cc019SAndroid Build Coastguard Worker 	object[1].flags |= EXEC_OBJECT_PINNED;
169*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, object[1].handle, 0, &bbe, sizeof(bbe));
170*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 2;
171*d83cc019SAndroid Build Coastguard Worker 
172*d83cc019SAndroid Build Coastguard Worker 	/* Check that we fit into our hole */
173*d83cc019SAndroid Build Coastguard Worker 	object[1].offset = object[0].offset - size;
174*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
175*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq_u64(object[1].offset + size, object[0].offset);
176*d83cc019SAndroid Build Coastguard Worker 
177*d83cc019SAndroid Build Coastguard Worker 	object[1].offset = object[0].offset + size;
178*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
179*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq_u64(object[1].offset - size, object[0].offset);
180*d83cc019SAndroid Build Coastguard Worker 
181*d83cc019SAndroid Build Coastguard Worker 	/* Try all possible page-aligned overlaps */
182*d83cc019SAndroid Build Coastguard Worker 	for (offset = object[0].offset - size + 4096;
183*d83cc019SAndroid Build Coastguard Worker 	     offset < object[0].offset + size;
184*d83cc019SAndroid Build Coastguard Worker 	     offset += 4096) {
185*d83cc019SAndroid Build Coastguard Worker 		object[1].offset = offset;
186*d83cc019SAndroid Build Coastguard Worker 		igt_debug("[0]=[%08llx - %08llx] [1]=[%08llx - %08llx]\n",
187*d83cc019SAndroid Build Coastguard Worker 			  (long long)object[0].offset,
188*d83cc019SAndroid Build Coastguard Worker 			  (long long)object[0].offset + size,
189*d83cc019SAndroid Build Coastguard Worker 			  (long long)object[1].offset,
190*d83cc019SAndroid Build Coastguard Worker 			  (long long)object[1].offset + size);
191*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
192*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq_u64(object[1].offset, offset);
193*d83cc019SAndroid Build Coastguard Worker 	}
194*d83cc019SAndroid Build Coastguard Worker 
195*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object[1].handle);
196*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object[0].handle);
197*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
198*d83cc019SAndroid Build Coastguard Worker }
199*d83cc019SAndroid Build Coastguard Worker 
busy_batch(int fd)200*d83cc019SAndroid Build Coastguard Worker static uint64_t busy_batch(int fd)
201*d83cc019SAndroid Build Coastguard Worker {
202*d83cc019SAndroid Build Coastguard Worker 	const int gen = intel_gen(intel_get_drm_devid(fd));
203*d83cc019SAndroid Build Coastguard Worker 	const int has_64bit_reloc = gen >= 8;
204*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
205*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object[2];
206*d83cc019SAndroid Build Coastguard Worker 	uint32_t *map;
207*d83cc019SAndroid Build Coastguard Worker 	int factor = 10;
208*d83cc019SAndroid Build Coastguard Worker 	int i = 0;
209*d83cc019SAndroid Build Coastguard Worker 
210*d83cc019SAndroid Build Coastguard Worker 	memset(object, 0, sizeof(object));
211*d83cc019SAndroid Build Coastguard Worker 	object[0].handle = gem_create(fd, 1024*1024);
212*d83cc019SAndroid Build Coastguard Worker 	object[1].handle = gem_create(fd, 4096);
213*d83cc019SAndroid Build Coastguard Worker 	map = gem_mmap__cpu(fd, object[1].handle, 0, 4096, PROT_WRITE);
214*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, object[1].handle,
215*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
216*d83cc019SAndroid Build Coastguard Worker 
217*d83cc019SAndroid Build Coastguard Worker 	*map = MI_BATCH_BUFFER_END;
218*d83cc019SAndroid Build Coastguard Worker 
219*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
220*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(object);
221*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 2;
222*d83cc019SAndroid Build Coastguard Worker 	if (gen >= 6)
223*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags = I915_EXEC_BLT;
224*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
225*d83cc019SAndroid Build Coastguard Worker 
226*d83cc019SAndroid Build Coastguard Worker 	igt_debug("Active offsets = [%08llx, %08llx]\n",
227*d83cc019SAndroid Build Coastguard Worker 		  object[0].offset, object[1].offset);
228*d83cc019SAndroid Build Coastguard Worker 
229*d83cc019SAndroid Build Coastguard Worker #define COPY_BLT_CMD		(2<<29|0x53<<22|0x6)
230*d83cc019SAndroid Build Coastguard Worker #define BLT_WRITE_ALPHA		(1<<21)
231*d83cc019SAndroid Build Coastguard Worker #define BLT_WRITE_RGB		(1<<20)
232*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, object[1].handle,
233*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
234*d83cc019SAndroid Build Coastguard Worker 	while (factor--) {
235*d83cc019SAndroid Build Coastguard Worker 		/* XY_SRC_COPY */
236*d83cc019SAndroid Build Coastguard Worker 		map[i++] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB;
237*d83cc019SAndroid Build Coastguard Worker 		if (has_64bit_reloc)
238*d83cc019SAndroid Build Coastguard Worker 			map[i-1] += 2;
239*d83cc019SAndroid Build Coastguard Worker 		map[i++] = 0xcc << 16 | 1 << 25 | 1 << 24 | (4*1024);
240*d83cc019SAndroid Build Coastguard Worker 		map[i++] = 0;
241*d83cc019SAndroid Build Coastguard Worker 		map[i++] = 256 << 16 | 1024;
242*d83cc019SAndroid Build Coastguard Worker 		map[i++] = object[0].offset;
243*d83cc019SAndroid Build Coastguard Worker 		if (has_64bit_reloc)
244*d83cc019SAndroid Build Coastguard Worker 			map[i++] = object[0].offset >> 32;
245*d83cc019SAndroid Build Coastguard Worker 		map[i++] = 0;
246*d83cc019SAndroid Build Coastguard Worker 		map[i++] = 4096;
247*d83cc019SAndroid Build Coastguard Worker 		map[i++] = object[0].offset;
248*d83cc019SAndroid Build Coastguard Worker 		if (has_64bit_reloc)
249*d83cc019SAndroid Build Coastguard Worker 			map[i++] = object[0].offset >> 32;
250*d83cc019SAndroid Build Coastguard Worker 	}
251*d83cc019SAndroid Build Coastguard Worker 	map[i++] = MI_BATCH_BUFFER_END;
252*d83cc019SAndroid Build Coastguard Worker 	munmap(map, 4096);
253*d83cc019SAndroid Build Coastguard Worker 
254*d83cc019SAndroid Build Coastguard Worker 	object[0].flags = EXEC_OBJECT_PINNED | EXEC_OBJECT_WRITE;
255*d83cc019SAndroid Build Coastguard Worker 	object[1].flags = EXEC_OBJECT_PINNED;
256*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
257*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object[0].handle);
258*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object[1].handle);
259*d83cc019SAndroid Build Coastguard Worker 
260*d83cc019SAndroid Build Coastguard Worker 	return object[1].offset;
261*d83cc019SAndroid Build Coastguard Worker }
262*d83cc019SAndroid Build Coastguard Worker 
test_evict_active(int fd)263*d83cc019SAndroid Build Coastguard Worker static void test_evict_active(int fd)
264*d83cc019SAndroid Build Coastguard Worker {
265*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
266*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
267*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object;
268*d83cc019SAndroid Build Coastguard Worker 	uint64_t expected;
269*d83cc019SAndroid Build Coastguard Worker 
270*d83cc019SAndroid Build Coastguard Worker 	memset(&object, 0, sizeof(object));
271*d83cc019SAndroid Build Coastguard Worker 	object.handle = gem_create(fd, 4096);
272*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
273*d83cc019SAndroid Build Coastguard Worker 
274*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
275*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&object);
276*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
277*d83cc019SAndroid Build Coastguard Worker 
278*d83cc019SAndroid Build Coastguard Worker 	expected = busy_batch(fd);
279*d83cc019SAndroid Build Coastguard Worker 	object.offset = expected;
280*d83cc019SAndroid Build Coastguard Worker 	object.flags = EXEC_OBJECT_PINNED;
281*d83cc019SAndroid Build Coastguard Worker 
282*d83cc019SAndroid Build Coastguard Worker 	/* Replace the active batch with ourselves, forcing an eviction */
283*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
284*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq_u64(object.offset, expected);
285*d83cc019SAndroid Build Coastguard Worker 
286*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object.handle);
287*d83cc019SAndroid Build Coastguard Worker }
288*d83cc019SAndroid Build Coastguard Worker 
test_evict_snoop(int fd)289*d83cc019SAndroid Build Coastguard Worker static void test_evict_snoop(int fd)
290*d83cc019SAndroid Build Coastguard Worker {
291*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
292*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
293*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object[2];
294*d83cc019SAndroid Build Coastguard Worker 	uint64_t hole;
295*d83cc019SAndroid Build Coastguard Worker 
296*d83cc019SAndroid Build Coastguard Worker 	igt_require(!gem_has_llc(fd));
297*d83cc019SAndroid Build Coastguard Worker 	igt_require(!gem_uses_ppgtt(fd));
298*d83cc019SAndroid Build Coastguard Worker 
299*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
300*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(object);
301*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
302*d83cc019SAndroid Build Coastguard Worker 
303*d83cc019SAndroid Build Coastguard Worker 	/* Find a hole */
304*d83cc019SAndroid Build Coastguard Worker 	memset(object, 0, sizeof(object));
305*d83cc019SAndroid Build Coastguard Worker 	object[0].handle = gem_create(fd, 5*4096);
306*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, object[0].handle, 0, &bbe, sizeof(bbe));
307*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
308*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object[0].handle);
309*d83cc019SAndroid Build Coastguard Worker 	hole = object[0].offset + 4096;
310*d83cc019SAndroid Build Coastguard Worker 
311*d83cc019SAndroid Build Coastguard Worker 	/* Create a snoop + uncached pair */
312*d83cc019SAndroid Build Coastguard Worker 	object[0].handle = gem_create(fd, 4096);
313*d83cc019SAndroid Build Coastguard Worker 	object[0].flags = EXEC_OBJECT_PINNED;
314*d83cc019SAndroid Build Coastguard Worker 	gem_set_caching(fd, object[0].handle, 1);
315*d83cc019SAndroid Build Coastguard Worker 	object[1].handle = gem_create(fd, 4096);
316*d83cc019SAndroid Build Coastguard Worker 	object[1].flags = EXEC_OBJECT_PINNED;
317*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, object[1].handle, 4096-sizeof(bbe), &bbe, sizeof(bbe));
318*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 2;
319*d83cc019SAndroid Build Coastguard Worker 
320*d83cc019SAndroid Build Coastguard Worker 	/* snoop abutting before uncached -> error */
321*d83cc019SAndroid Build Coastguard Worker 	object[0].offset = hole;
322*d83cc019SAndroid Build Coastguard Worker 	object[1].offset = hole + 4096;
323*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
324*d83cc019SAndroid Build Coastguard Worker 
325*d83cc019SAndroid Build Coastguard Worker 	/* snoop abutting after uncached -> error */
326*d83cc019SAndroid Build Coastguard Worker 	object[0].offset = hole + 4096;
327*d83cc019SAndroid Build Coastguard Worker 	object[1].offset = hole;
328*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
329*d83cc019SAndroid Build Coastguard Worker 
330*d83cc019SAndroid Build Coastguard Worker 	/* with gap -> okay */
331*d83cc019SAndroid Build Coastguard Worker 	object[0].offset = hole + 2*4096;
332*d83cc019SAndroid Build Coastguard Worker 	object[1].offset = hole;
333*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_execbuf(fd, &execbuf), 0);
334*d83cc019SAndroid Build Coastguard Worker 
335*d83cc019SAndroid Build Coastguard Worker 	/* And we should force the snoop away (or the GPU may hang) */
336*d83cc019SAndroid Build Coastguard Worker 	object[0].flags = 0;
337*d83cc019SAndroid Build Coastguard Worker 	object[1].offset = hole + 4096;
338*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__gem_execbuf(fd, &execbuf), 0);
339*d83cc019SAndroid Build Coastguard Worker 	igt_assert(object[0].offset != hole);
340*d83cc019SAndroid Build Coastguard Worker 	igt_assert(object[0].offset != hole + 2*4096);
341*d83cc019SAndroid Build Coastguard Worker 
342*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object[0].handle);
343*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object[1].handle);
344*d83cc019SAndroid Build Coastguard Worker }
345*d83cc019SAndroid Build Coastguard Worker 
test_evict_hang(int fd)346*d83cc019SAndroid Build Coastguard Worker static void test_evict_hang(int fd)
347*d83cc019SAndroid Build Coastguard Worker {
348*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
349*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
350*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object;
351*d83cc019SAndroid Build Coastguard Worker 	igt_hang_t hang;
352*d83cc019SAndroid Build Coastguard Worker 	uint64_t expected;
353*d83cc019SAndroid Build Coastguard Worker 
354*d83cc019SAndroid Build Coastguard Worker 	memset(&object, 0, sizeof(object));
355*d83cc019SAndroid Build Coastguard Worker 	object.handle = gem_create(fd, 4096);
356*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
357*d83cc019SAndroid Build Coastguard Worker 
358*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
359*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&object);
360*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
361*d83cc019SAndroid Build Coastguard Worker 
362*d83cc019SAndroid Build Coastguard Worker 	hang = igt_hang_ctx(fd, 0, 0, 0);
363*d83cc019SAndroid Build Coastguard Worker 	expected = hang.spin->obj[IGT_SPIN_BATCH].offset;
364*d83cc019SAndroid Build Coastguard Worker 
365*d83cc019SAndroid Build Coastguard Worker 	/* Replace the hung batch with ourselves, forcing an eviction */
366*d83cc019SAndroid Build Coastguard Worker 	object.offset = expected;
367*d83cc019SAndroid Build Coastguard Worker 	object.flags = EXEC_OBJECT_PINNED;
368*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
369*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq_u64(object.offset, expected);
370*d83cc019SAndroid Build Coastguard Worker 
371*d83cc019SAndroid Build Coastguard Worker 	igt_post_hang_ring(fd, hang);
372*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object.handle);
373*d83cc019SAndroid Build Coastguard Worker }
374*d83cc019SAndroid Build Coastguard Worker 
xchg_offset(void * array,unsigned i,unsigned j)375*d83cc019SAndroid Build Coastguard Worker static void xchg_offset(void *array, unsigned i, unsigned j)
376*d83cc019SAndroid Build Coastguard Worker {
377*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 *object = array;
378*d83cc019SAndroid Build Coastguard Worker 	uint64_t tmp = object[i].offset;
379*d83cc019SAndroid Build Coastguard Worker 	object[i].offset = object[j].offset;
380*d83cc019SAndroid Build Coastguard Worker 	object[j].offset = tmp;
381*d83cc019SAndroid Build Coastguard Worker }
382*d83cc019SAndroid Build Coastguard Worker 
383*d83cc019SAndroid Build Coastguard Worker enum sleep { NOSLEEP, SUSPEND, HIBERNATE };
test_noreloc(int fd,enum sleep sleep)384*d83cc019SAndroid Build Coastguard Worker static void test_noreloc(int fd, enum sleep sleep)
385*d83cc019SAndroid Build Coastguard Worker {
386*d83cc019SAndroid Build Coastguard Worker 	const int gen = intel_gen(intel_get_drm_devid(fd));
387*d83cc019SAndroid Build Coastguard Worker 	const uint32_t size = 4096;
388*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
389*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
390*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 object[257];
391*d83cc019SAndroid Build Coastguard Worker 	uint64_t offset;
392*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
393*d83cc019SAndroid Build Coastguard Worker 	uint32_t *batch, *b;
394*d83cc019SAndroid Build Coastguard Worker 	int i, loop;
395*d83cc019SAndroid Build Coastguard Worker 
396*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, (ARRAY_SIZE(object)+1)*size);
397*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, handle, 0, &bbe, sizeof(bbe));
398*d83cc019SAndroid Build Coastguard Worker 
399*d83cc019SAndroid Build Coastguard Worker 	memset(object, 0, sizeof(object));
400*d83cc019SAndroid Build Coastguard Worker 	object[0].handle = handle;
401*d83cc019SAndroid Build Coastguard Worker 
402*d83cc019SAndroid Build Coastguard Worker 	/* Find a hole */
403*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
404*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(object);
405*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
406*d83cc019SAndroid Build Coastguard Worker 	if (gen < 6)
407*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags |= I915_EXEC_SECURE;
408*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
409*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, object[0].handle);
410*d83cc019SAndroid Build Coastguard Worker 
411*d83cc019SAndroid Build Coastguard Worker 	igt_debug("Made a %dx%d KiB hole: %08llx\n",
412*d83cc019SAndroid Build Coastguard Worker 		  (int)ARRAY_SIZE(object), size/1024, object[0].offset);
413*d83cc019SAndroid Build Coastguard Worker 
414*d83cc019SAndroid Build Coastguard Worker 	offset = object[0].offset;
415*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(object) - 1; i++) {
416*d83cc019SAndroid Build Coastguard Worker 		object[i].handle = gem_create(fd, size);
417*d83cc019SAndroid Build Coastguard Worker 		object[i].offset = offset + i*size;
418*d83cc019SAndroid Build Coastguard Worker 		object[i].flags = EXEC_OBJECT_PINNED | EXEC_OBJECT_WRITE;
419*d83cc019SAndroid Build Coastguard Worker 	}
420*d83cc019SAndroid Build Coastguard Worker 	object[i].handle = gem_create(fd, 2*size);
421*d83cc019SAndroid Build Coastguard Worker 	object[i].offset = offset + i*size;
422*d83cc019SAndroid Build Coastguard Worker 	object[i].flags = EXEC_OBJECT_PINNED;
423*d83cc019SAndroid Build Coastguard Worker 
424*d83cc019SAndroid Build Coastguard Worker 	b = batch = gem_mmap__cpu(fd, object[i].handle, 0, 2*size, PROT_WRITE);
425*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, object[i].handle,
426*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
427*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(object) - 1; i++) {
428*d83cc019SAndroid Build Coastguard Worker 		*b++ = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
429*d83cc019SAndroid Build Coastguard Worker 		if (gen >= 8) {
430*d83cc019SAndroid Build Coastguard Worker 			*b++ = object[i].offset;
431*d83cc019SAndroid Build Coastguard Worker 			*b++ = object[i].offset >> 32;
432*d83cc019SAndroid Build Coastguard Worker 		} else if (gen >= 4) {
433*d83cc019SAndroid Build Coastguard Worker 			*b++ = 0;
434*d83cc019SAndroid Build Coastguard Worker 			*b++ = object[i].offset;
435*d83cc019SAndroid Build Coastguard Worker 		} else {
436*d83cc019SAndroid Build Coastguard Worker 			b[-1]--;
437*d83cc019SAndroid Build Coastguard Worker 			*b++ = object[i].offset;
438*d83cc019SAndroid Build Coastguard Worker 		}
439*d83cc019SAndroid Build Coastguard Worker 		*b++ = i;
440*d83cc019SAndroid Build Coastguard Worker 	}
441*d83cc019SAndroid Build Coastguard Worker 	*b++ = MI_BATCH_BUFFER_END;
442*d83cc019SAndroid Build Coastguard Worker 	igt_assert(b - batch <= 2*size/sizeof(uint32_t));
443*d83cc019SAndroid Build Coastguard Worker 	munmap(batch, size);
444*d83cc019SAndroid Build Coastguard Worker 
445*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = ARRAY_SIZE(object);
446*d83cc019SAndroid Build Coastguard Worker 	for (loop = 0; loop < 1024; loop++) {
447*d83cc019SAndroid Build Coastguard Worker 		igt_permute_array(object, ARRAY_SIZE(object)-1, xchg_offset);
448*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
449*d83cc019SAndroid Build Coastguard Worker 
450*d83cc019SAndroid Build Coastguard Worker 		if ((loop & 127) == 0) {
451*d83cc019SAndroid Build Coastguard Worker 			switch (sleep) {
452*d83cc019SAndroid Build Coastguard Worker 			case NOSLEEP:
453*d83cc019SAndroid Build Coastguard Worker 				break;
454*d83cc019SAndroid Build Coastguard Worker 			case SUSPEND:
455*d83cc019SAndroid Build Coastguard Worker 				igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
456*d83cc019SAndroid Build Coastguard Worker 							      SUSPEND_TEST_NONE);
457*d83cc019SAndroid Build Coastguard Worker 				break;
458*d83cc019SAndroid Build Coastguard Worker 			case HIBERNATE:
459*d83cc019SAndroid Build Coastguard Worker 				igt_system_suspend_autoresume(SUSPEND_STATE_DISK,
460*d83cc019SAndroid Build Coastguard Worker 							      SUSPEND_TEST_NONE);
461*d83cc019SAndroid Build Coastguard Worker 				break;
462*d83cc019SAndroid Build Coastguard Worker 			}
463*d83cc019SAndroid Build Coastguard Worker 		}
464*d83cc019SAndroid Build Coastguard Worker 
465*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < ARRAY_SIZE(object) - 1; i++) {
466*d83cc019SAndroid Build Coastguard Worker 			uint32_t val;
467*d83cc019SAndroid Build Coastguard Worker 
468*d83cc019SAndroid Build Coastguard Worker 			gem_read(fd, object[i].handle, 0, &val, sizeof(val));
469*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(val, (object[i].offset - offset)/size);
470*d83cc019SAndroid Build Coastguard Worker 		}
471*d83cc019SAndroid Build Coastguard Worker 	}
472*d83cc019SAndroid Build Coastguard Worker 
473*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(object); i++)
474*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, object[i].handle);
475*d83cc019SAndroid Build Coastguard Worker }
476*d83cc019SAndroid Build Coastguard Worker 
477*d83cc019SAndroid Build Coastguard Worker igt_main
478*d83cc019SAndroid Build Coastguard Worker {
479*d83cc019SAndroid Build Coastguard Worker 	int fd = -1;
480*d83cc019SAndroid Build Coastguard Worker 
481*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on_simulation();
482*d83cc019SAndroid Build Coastguard Worker 
483*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
484*d83cc019SAndroid Build Coastguard Worker 		fd = drm_open_driver_master(DRIVER_INTEL);
485*d83cc019SAndroid Build Coastguard Worker 		igt_require_gem(fd);
486*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_has_softpin(fd));
487*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_can_store_dword(fd, 0));
488*d83cc019SAndroid Build Coastguard Worker 	}
489*d83cc019SAndroid Build Coastguard Worker 
490*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("invalid")
491*d83cc019SAndroid Build Coastguard Worker 		test_invalid(fd);
492*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("softpin")
493*d83cc019SAndroid Build Coastguard Worker 		test_softpin(fd);
494*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("overlap")
495*d83cc019SAndroid Build Coastguard Worker 		test_overlap(fd);
496*d83cc019SAndroid Build Coastguard Worker 
497*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("noreloc")
498*d83cc019SAndroid Build Coastguard Worker 		test_noreloc(fd, NOSLEEP);
499*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("noreloc-interruptible")
500*d83cc019SAndroid Build Coastguard Worker 		igt_while_interruptible(true) test_noreloc(fd, NOSLEEP);
501*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("noreloc-S3")
502*d83cc019SAndroid Build Coastguard Worker 		test_noreloc(fd, SUSPEND);
503*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("noreloc-S4")
504*d83cc019SAndroid Build Coastguard Worker 		test_noreloc(fd, HIBERNATE);
505*d83cc019SAndroid Build Coastguard Worker 
506*d83cc019SAndroid Build Coastguard Worker 	for (int signal = 0; signal <= 1; signal++) {
507*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("evict-active%s", signal ? "-interruptible" : "")
508*d83cc019SAndroid Build Coastguard Worker 			igt_while_interruptible(signal) test_evict_active(fd);
509*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("evict-snoop%s", signal ? "-interruptible" : "")
510*d83cc019SAndroid Build Coastguard Worker 			igt_while_interruptible(signal) test_evict_snoop(fd);
511*d83cc019SAndroid Build Coastguard Worker 	}
512*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("evict-hang")
513*d83cc019SAndroid Build Coastguard Worker 		test_evict_hang(fd);
514*d83cc019SAndroid Build Coastguard Worker 
515*d83cc019SAndroid Build Coastguard Worker 	igt_fixture
516*d83cc019SAndroid Build Coastguard Worker 		close(fd);
517*d83cc019SAndroid Build Coastguard Worker }
518