xref: /aosp_15_r20/external/igt-gpu-tools/tests/i915/gem_exec_reloc.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2016 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  */
23*d83cc019SAndroid Build Coastguard Worker 
24*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
25*d83cc019SAndroid Build Coastguard Worker #include "igt_dummyload.h"
26*d83cc019SAndroid Build Coastguard Worker 
27*d83cc019SAndroid Build Coastguard Worker IGT_TEST_DESCRIPTION("Basic sanity check of execbuf-ioctl relocations.");
28*d83cc019SAndroid Build Coastguard Worker 
29*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_BSD_SHIFT      (13)
30*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_BSD_MASK       (3 << LOCAL_I915_EXEC_BSD_SHIFT)
31*d83cc019SAndroid Build Coastguard Worker 
32*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_NO_RELOC (1<<11)
33*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_HANDLE_LUT (1<<12)
34*d83cc019SAndroid Build Coastguard Worker 
35*d83cc019SAndroid Build Coastguard Worker #define ENGINE_MASK  (I915_EXEC_RING_MASK | LOCAL_I915_EXEC_BSD_MASK)
36*d83cc019SAndroid Build Coastguard Worker 
find_last_set(uint64_t x)37*d83cc019SAndroid Build Coastguard Worker static uint32_t find_last_set(uint64_t x)
38*d83cc019SAndroid Build Coastguard Worker {
39*d83cc019SAndroid Build Coastguard Worker 	uint32_t i = 0;
40*d83cc019SAndroid Build Coastguard Worker 	while (x) {
41*d83cc019SAndroid Build Coastguard Worker 		x >>= 1;
42*d83cc019SAndroid Build Coastguard Worker 		i++;
43*d83cc019SAndroid Build Coastguard Worker 	}
44*d83cc019SAndroid Build Coastguard Worker 	return i;
45*d83cc019SAndroid Build Coastguard Worker }
46*d83cc019SAndroid Build Coastguard Worker 
write_dword(int fd,uint32_t target_handle,uint64_t target_offset,uint32_t value)47*d83cc019SAndroid Build Coastguard Worker static void write_dword(int fd,
48*d83cc019SAndroid Build Coastguard Worker 			uint32_t target_handle,
49*d83cc019SAndroid Build Coastguard Worker 			uint64_t target_offset,
50*d83cc019SAndroid Build Coastguard Worker 			uint32_t value)
51*d83cc019SAndroid Build Coastguard Worker {
52*d83cc019SAndroid Build Coastguard Worker 	int gen = intel_gen(intel_get_drm_devid(fd));
53*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
54*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 obj[2];
55*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_relocation_entry reloc;
56*d83cc019SAndroid Build Coastguard Worker 	uint32_t buf[16];
57*d83cc019SAndroid Build Coastguard Worker 	int i;
58*d83cc019SAndroid Build Coastguard Worker 
59*d83cc019SAndroid Build Coastguard Worker 	memset(obj, 0, sizeof(obj));
60*d83cc019SAndroid Build Coastguard Worker 	obj[0].handle = target_handle;
61*d83cc019SAndroid Build Coastguard Worker 	obj[1].handle = gem_create(fd, 4096);
62*d83cc019SAndroid Build Coastguard Worker 
63*d83cc019SAndroid Build Coastguard Worker 	i = 0;
64*d83cc019SAndroid Build Coastguard Worker 	buf[i++] = MI_STORE_DWORD_IMM | (gen < 6 ? 1<<22 : 0);
65*d83cc019SAndroid Build Coastguard Worker 	if (gen >= 8) {
66*d83cc019SAndroid Build Coastguard Worker 		buf[i++] = target_offset;
67*d83cc019SAndroid Build Coastguard Worker 		buf[i++] = target_offset >> 32;
68*d83cc019SAndroid Build Coastguard Worker 	} else if (gen >= 4) {
69*d83cc019SAndroid Build Coastguard Worker 		buf[i++] = 0;
70*d83cc019SAndroid Build Coastguard Worker 		buf[i++] = target_offset;
71*d83cc019SAndroid Build Coastguard Worker 	} else {
72*d83cc019SAndroid Build Coastguard Worker 		buf[i-1]--;
73*d83cc019SAndroid Build Coastguard Worker 		buf[i++] = target_offset;
74*d83cc019SAndroid Build Coastguard Worker 	}
75*d83cc019SAndroid Build Coastguard Worker 	buf[i++] = value;
76*d83cc019SAndroid Build Coastguard Worker 	buf[i++] = MI_BATCH_BUFFER_END;
77*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, obj[1].handle, 0, buf, sizeof(buf));
78*d83cc019SAndroid Build Coastguard Worker 
79*d83cc019SAndroid Build Coastguard Worker 	memset(&reloc, 0, sizeof(reloc));
80*d83cc019SAndroid Build Coastguard Worker 	if (gen >= 8 || gen < 4)
81*d83cc019SAndroid Build Coastguard Worker 		reloc.offset = sizeof(uint32_t);
82*d83cc019SAndroid Build Coastguard Worker 	else
83*d83cc019SAndroid Build Coastguard Worker 		reloc.offset = 2*sizeof(uint32_t);
84*d83cc019SAndroid Build Coastguard Worker 	reloc.target_handle = target_handle;
85*d83cc019SAndroid Build Coastguard Worker 	reloc.delta = target_offset;
86*d83cc019SAndroid Build Coastguard Worker 	reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
87*d83cc019SAndroid Build Coastguard Worker 	reloc.write_domain = I915_GEM_DOMAIN_INSTRUCTION;
88*d83cc019SAndroid Build Coastguard Worker 
89*d83cc019SAndroid Build Coastguard Worker 	obj[1].relocation_count = 1;
90*d83cc019SAndroid Build Coastguard Worker 	obj[1].relocs_ptr = to_user_pointer(&reloc);
91*d83cc019SAndroid Build Coastguard Worker 
92*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
93*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(obj);
94*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 2;
95*d83cc019SAndroid Build Coastguard Worker 	execbuf.flags = I915_EXEC_SECURE;
96*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
97*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, obj[1].handle);
98*d83cc019SAndroid Build Coastguard Worker }
99*d83cc019SAndroid Build Coastguard Worker 
100*d83cc019SAndroid Build Coastguard Worker enum mode { MEM, CPU, WC, GTT };
101*d83cc019SAndroid Build Coastguard Worker #define RO 0x100
from_mmap(int fd,uint64_t size,enum mode mode)102*d83cc019SAndroid Build Coastguard Worker static void from_mmap(int fd, uint64_t size, enum mode mode)
103*d83cc019SAndroid Build Coastguard Worker {
104*d83cc019SAndroid Build Coastguard Worker 	uint32_t bbe = MI_BATCH_BUFFER_END;
105*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
106*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 obj;
107*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_relocation_entry *relocs;
108*d83cc019SAndroid Build Coastguard Worker 	uint32_t reloc_handle;
109*d83cc019SAndroid Build Coastguard Worker 	uint64_t value;
110*d83cc019SAndroid Build Coastguard Worker 	uint64_t max, i;
111*d83cc019SAndroid Build Coastguard Worker 	int retry = 2;
112*d83cc019SAndroid Build Coastguard Worker 
113*d83cc019SAndroid Build Coastguard Worker 	/* Worst case is that the kernel has to copy the entire incoming
114*d83cc019SAndroid Build Coastguard Worker 	 * reloc[], so double the memory requirements.
115*d83cc019SAndroid Build Coastguard Worker 	 */
116*d83cc019SAndroid Build Coastguard Worker 	intel_require_memory(2, size, CHECK_RAM);
117*d83cc019SAndroid Build Coastguard Worker 
118*d83cc019SAndroid Build Coastguard Worker 	memset(&obj, 0, sizeof(obj));
119*d83cc019SAndroid Build Coastguard Worker 	obj.handle = gem_create(fd, 4096);
120*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
121*d83cc019SAndroid Build Coastguard Worker 
122*d83cc019SAndroid Build Coastguard Worker 	max = size / sizeof(*relocs);
123*d83cc019SAndroid Build Coastguard Worker 	switch (mode & ~RO) {
124*d83cc019SAndroid Build Coastguard Worker 	case MEM:
125*d83cc019SAndroid Build Coastguard Worker 		relocs = mmap(0, size,
126*d83cc019SAndroid Build Coastguard Worker 			      PROT_WRITE, MAP_PRIVATE | MAP_ANON,
127*d83cc019SAndroid Build Coastguard Worker 			      -1, 0);
128*d83cc019SAndroid Build Coastguard Worker 		igt_assert(relocs != (void *)-1);
129*d83cc019SAndroid Build Coastguard Worker 		break;
130*d83cc019SAndroid Build Coastguard Worker 	case GTT:
131*d83cc019SAndroid Build Coastguard Worker 		reloc_handle = gem_create(fd, size);
132*d83cc019SAndroid Build Coastguard Worker 		relocs = gem_mmap__gtt(fd, reloc_handle, size, PROT_WRITE);
133*d83cc019SAndroid Build Coastguard Worker 		gem_set_domain(fd, reloc_handle,
134*d83cc019SAndroid Build Coastguard Worker 				I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
135*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, reloc_handle);
136*d83cc019SAndroid Build Coastguard Worker 		break;
137*d83cc019SAndroid Build Coastguard Worker 	case CPU:
138*d83cc019SAndroid Build Coastguard Worker 		reloc_handle = gem_create(fd, size);
139*d83cc019SAndroid Build Coastguard Worker 		relocs = gem_mmap__cpu(fd, reloc_handle, 0, size, PROT_WRITE);
140*d83cc019SAndroid Build Coastguard Worker 		gem_set_domain(fd, reloc_handle,
141*d83cc019SAndroid Build Coastguard Worker 			       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
142*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, reloc_handle);
143*d83cc019SAndroid Build Coastguard Worker 		break;
144*d83cc019SAndroid Build Coastguard Worker 	case WC:
145*d83cc019SAndroid Build Coastguard Worker 		reloc_handle = gem_create(fd, size);
146*d83cc019SAndroid Build Coastguard Worker 		relocs = gem_mmap__wc(fd, reloc_handle, 0, size, PROT_WRITE);
147*d83cc019SAndroid Build Coastguard Worker 		gem_set_domain(fd, reloc_handle,
148*d83cc019SAndroid Build Coastguard Worker 			       I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
149*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, reloc_handle);
150*d83cc019SAndroid Build Coastguard Worker 		break;
151*d83cc019SAndroid Build Coastguard Worker 	}
152*d83cc019SAndroid Build Coastguard Worker 
153*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < max; i++) {
154*d83cc019SAndroid Build Coastguard Worker 		relocs[i].target_handle = obj.handle;
155*d83cc019SAndroid Build Coastguard Worker 		relocs[i].presumed_offset = ~0ull;
156*d83cc019SAndroid Build Coastguard Worker 		relocs[i].offset = 1024;
157*d83cc019SAndroid Build Coastguard Worker 		relocs[i].delta = i;
158*d83cc019SAndroid Build Coastguard Worker 		relocs[i].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
159*d83cc019SAndroid Build Coastguard Worker 		relocs[i].write_domain = 0;
160*d83cc019SAndroid Build Coastguard Worker 	}
161*d83cc019SAndroid Build Coastguard Worker 	obj.relocation_count = max;
162*d83cc019SAndroid Build Coastguard Worker 	obj.relocs_ptr = to_user_pointer(relocs);
163*d83cc019SAndroid Build Coastguard Worker 
164*d83cc019SAndroid Build Coastguard Worker 	if (mode & RO)
165*d83cc019SAndroid Build Coastguard Worker 		mprotect(relocs, size, PROT_READ);
166*d83cc019SAndroid Build Coastguard Worker 
167*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
168*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&obj);
169*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
170*d83cc019SAndroid Build Coastguard Worker 	while (relocs[0].presumed_offset == ~0ull && retry--)
171*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
172*d83cc019SAndroid Build Coastguard Worker 	gem_read(fd, obj.handle, 1024, &value, sizeof(value));
173*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, obj.handle);
174*d83cc019SAndroid Build Coastguard Worker 
175*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq_u64(value, obj.offset + max - 1);
176*d83cc019SAndroid Build Coastguard Worker 	if (relocs[0].presumed_offset != ~0ull) {
177*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < max; i++)
178*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq_u64(relocs[i].presumed_offset,
179*d83cc019SAndroid Build Coastguard Worker 					  obj.offset);
180*d83cc019SAndroid Build Coastguard Worker 	}
181*d83cc019SAndroid Build Coastguard Worker 	munmap(relocs, size);
182*d83cc019SAndroid Build Coastguard Worker }
183*d83cc019SAndroid Build Coastguard Worker 
from_gpu(int fd)184*d83cc019SAndroid Build Coastguard Worker static void from_gpu(int fd)
185*d83cc019SAndroid Build Coastguard Worker {
186*d83cc019SAndroid Build Coastguard Worker 	uint32_t bbe = MI_BATCH_BUFFER_END;
187*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
188*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 obj;
189*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_relocation_entry *relocs;
190*d83cc019SAndroid Build Coastguard Worker 	uint32_t reloc_handle;
191*d83cc019SAndroid Build Coastguard Worker 	uint64_t value;
192*d83cc019SAndroid Build Coastguard Worker 
193*d83cc019SAndroid Build Coastguard Worker 	igt_require(gem_can_store_dword(fd, 0));
194*d83cc019SAndroid Build Coastguard Worker 
195*d83cc019SAndroid Build Coastguard Worker 	memset(&obj, 0, sizeof(obj));
196*d83cc019SAndroid Build Coastguard Worker 	obj.handle = gem_create(fd, 4096);
197*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
198*d83cc019SAndroid Build Coastguard Worker 
199*d83cc019SAndroid Build Coastguard Worker 	reloc_handle = gem_create(fd, 4096);
200*d83cc019SAndroid Build Coastguard Worker 	write_dword(fd,
201*d83cc019SAndroid Build Coastguard Worker 		    reloc_handle,
202*d83cc019SAndroid Build Coastguard Worker 		    offsetof(struct drm_i915_gem_relocation_entry,
203*d83cc019SAndroid Build Coastguard Worker 			     target_handle),
204*d83cc019SAndroid Build Coastguard Worker 		    obj.handle);
205*d83cc019SAndroid Build Coastguard Worker 	write_dword(fd,
206*d83cc019SAndroid Build Coastguard Worker 		    reloc_handle,
207*d83cc019SAndroid Build Coastguard Worker 		    offsetof(struct drm_i915_gem_relocation_entry,
208*d83cc019SAndroid Build Coastguard Worker 			     offset),
209*d83cc019SAndroid Build Coastguard Worker 		    1024);
210*d83cc019SAndroid Build Coastguard Worker 	write_dword(fd,
211*d83cc019SAndroid Build Coastguard Worker 		    reloc_handle,
212*d83cc019SAndroid Build Coastguard Worker 		    offsetof(struct drm_i915_gem_relocation_entry,
213*d83cc019SAndroid Build Coastguard Worker 			     read_domains),
214*d83cc019SAndroid Build Coastguard Worker 		    I915_GEM_DOMAIN_INSTRUCTION);
215*d83cc019SAndroid Build Coastguard Worker 
216*d83cc019SAndroid Build Coastguard Worker 	relocs = gem_mmap__cpu(fd, reloc_handle, 0, 4096, PROT_READ);
217*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, reloc_handle,
218*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
219*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, reloc_handle);
220*d83cc019SAndroid Build Coastguard Worker 
221*d83cc019SAndroid Build Coastguard Worker 	obj.relocation_count = 1;
222*d83cc019SAndroid Build Coastguard Worker 	obj.relocs_ptr = to_user_pointer(relocs);
223*d83cc019SAndroid Build Coastguard Worker 
224*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
225*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&obj);
226*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
227*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
228*d83cc019SAndroid Build Coastguard Worker 	gem_read(fd, obj.handle, 1024, &value, sizeof(value));
229*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, obj.handle);
230*d83cc019SAndroid Build Coastguard Worker 
231*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq_u64(value, obj.offset);
232*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq_u64(relocs->presumed_offset, obj.offset);
233*d83cc019SAndroid Build Coastguard Worker 	munmap(relocs, 4096);
234*d83cc019SAndroid Build Coastguard Worker }
235*d83cc019SAndroid Build Coastguard Worker 
check_bo(int fd,uint32_t handle)236*d83cc019SAndroid Build Coastguard Worker static void check_bo(int fd, uint32_t handle)
237*d83cc019SAndroid Build Coastguard Worker {
238*d83cc019SAndroid Build Coastguard Worker 	uint32_t *map;
239*d83cc019SAndroid Build Coastguard Worker 	int i;
240*d83cc019SAndroid Build Coastguard Worker 
241*d83cc019SAndroid Build Coastguard Worker 	igt_debug("Verifying result\n");
242*d83cc019SAndroid Build Coastguard Worker 	map = gem_mmap__cpu(fd, handle, 0, 4096, PROT_READ);
243*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, 0);
244*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < 1024; i++)
245*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(map[i], i);
246*d83cc019SAndroid Build Coastguard Worker 	munmap(map, 4096);
247*d83cc019SAndroid Build Coastguard Worker }
248*d83cc019SAndroid Build Coastguard Worker 
active(int fd,unsigned engine)249*d83cc019SAndroid Build Coastguard Worker static void active(int fd, unsigned engine)
250*d83cc019SAndroid Build Coastguard Worker {
251*d83cc019SAndroid Build Coastguard Worker 	const int gen = intel_gen(intel_get_drm_devid(fd));
252*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_relocation_entry reloc;
253*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 obj[2];
254*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
255*d83cc019SAndroid Build Coastguard Worker 	unsigned engines[16];
256*d83cc019SAndroid Build Coastguard Worker 	unsigned nengine;
257*d83cc019SAndroid Build Coastguard Worker 	int pass;
258*d83cc019SAndroid Build Coastguard Worker 
259*d83cc019SAndroid Build Coastguard Worker 	nengine = 0;
260*d83cc019SAndroid Build Coastguard Worker 	if (engine == ALL_ENGINES) {
261*d83cc019SAndroid Build Coastguard Worker 		for_each_physical_engine(fd, engine) {
262*d83cc019SAndroid Build Coastguard Worker 			if (gem_can_store_dword(fd, engine))
263*d83cc019SAndroid Build Coastguard Worker 				engines[nengine++] = engine;
264*d83cc019SAndroid Build Coastguard Worker 		}
265*d83cc019SAndroid Build Coastguard Worker 	} else {
266*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_has_ring(fd, engine));
267*d83cc019SAndroid Build Coastguard Worker 		igt_require(gem_can_store_dword(fd, engine));
268*d83cc019SAndroid Build Coastguard Worker 		engines[nengine++] = engine;
269*d83cc019SAndroid Build Coastguard Worker 	}
270*d83cc019SAndroid Build Coastguard Worker 	igt_require(nengine);
271*d83cc019SAndroid Build Coastguard Worker 
272*d83cc019SAndroid Build Coastguard Worker 	memset(obj, 0, sizeof(obj));
273*d83cc019SAndroid Build Coastguard Worker 	obj[0].handle = gem_create(fd, 4096);
274*d83cc019SAndroid Build Coastguard Worker 	obj[1].handle = gem_create(fd, 64*1024);
275*d83cc019SAndroid Build Coastguard Worker 	obj[1].relocs_ptr = to_user_pointer(&reloc);
276*d83cc019SAndroid Build Coastguard Worker 	obj[1].relocation_count = 1;
277*d83cc019SAndroid Build Coastguard Worker 
278*d83cc019SAndroid Build Coastguard Worker 	memset(&reloc, 0, sizeof(reloc));
279*d83cc019SAndroid Build Coastguard Worker 	reloc.offset = sizeof(uint32_t);
280*d83cc019SAndroid Build Coastguard Worker 	reloc.target_handle = obj[0].handle;
281*d83cc019SAndroid Build Coastguard Worker 	if (gen < 8 && gen >= 4)
282*d83cc019SAndroid Build Coastguard Worker 		reloc.offset += sizeof(uint32_t);
283*d83cc019SAndroid Build Coastguard Worker 	reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
284*d83cc019SAndroid Build Coastguard Worker 	reloc.write_domain = I915_GEM_DOMAIN_INSTRUCTION;
285*d83cc019SAndroid Build Coastguard Worker 
286*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
287*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(obj);
288*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 2;
289*d83cc019SAndroid Build Coastguard Worker 	if (gen < 6)
290*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags |= I915_EXEC_SECURE;
291*d83cc019SAndroid Build Coastguard Worker 
292*d83cc019SAndroid Build Coastguard Worker 	for (pass = 0; pass < 1024; pass++) {
293*d83cc019SAndroid Build Coastguard Worker 		uint32_t batch[16];
294*d83cc019SAndroid Build Coastguard Worker 		int i = 0;
295*d83cc019SAndroid Build Coastguard Worker 		batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
296*d83cc019SAndroid Build Coastguard Worker 		if (gen >= 8) {
297*d83cc019SAndroid Build Coastguard Worker 			batch[++i] = 0;
298*d83cc019SAndroid Build Coastguard Worker 			batch[++i] = 0;
299*d83cc019SAndroid Build Coastguard Worker 		} else if (gen >= 4) {
300*d83cc019SAndroid Build Coastguard Worker 			batch[++i] = 0;
301*d83cc019SAndroid Build Coastguard Worker 			batch[++i] = 0;
302*d83cc019SAndroid Build Coastguard Worker 		} else {
303*d83cc019SAndroid Build Coastguard Worker 			batch[i]--;
304*d83cc019SAndroid Build Coastguard Worker 			batch[++i] = 0;
305*d83cc019SAndroid Build Coastguard Worker 		}
306*d83cc019SAndroid Build Coastguard Worker 		batch[++i] = pass;
307*d83cc019SAndroid Build Coastguard Worker 		batch[++i] = MI_BATCH_BUFFER_END;
308*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, obj[1].handle, pass*sizeof(batch),
309*d83cc019SAndroid Build Coastguard Worker 			  batch, sizeof(batch));
310*d83cc019SAndroid Build Coastguard Worker 	}
311*d83cc019SAndroid Build Coastguard Worker 
312*d83cc019SAndroid Build Coastguard Worker 	for (pass = 0; pass < 1024; pass++) {
313*d83cc019SAndroid Build Coastguard Worker 		reloc.delta = 4*pass;
314*d83cc019SAndroid Build Coastguard Worker 		reloc.presumed_offset = -1;
315*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags &= ~ENGINE_MASK;
316*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags |= engines[rand() % nengine];
317*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
318*d83cc019SAndroid Build Coastguard Worker 		execbuf.batch_start_offset += 64;
319*d83cc019SAndroid Build Coastguard Worker 		reloc.offset += 64;
320*d83cc019SAndroid Build Coastguard Worker 	}
321*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, obj[1].handle);
322*d83cc019SAndroid Build Coastguard Worker 
323*d83cc019SAndroid Build Coastguard Worker 	check_bo(fd, obj[0].handle);
324*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, obj[0].handle);
325*d83cc019SAndroid Build Coastguard Worker }
326*d83cc019SAndroid Build Coastguard Worker 
has_64b_reloc(int fd)327*d83cc019SAndroid Build Coastguard Worker static bool has_64b_reloc(int fd)
328*d83cc019SAndroid Build Coastguard Worker {
329*d83cc019SAndroid Build Coastguard Worker 	return intel_gen(intel_get_drm_devid(fd)) >= 8;
330*d83cc019SAndroid Build Coastguard Worker }
331*d83cc019SAndroid Build Coastguard Worker 
332*d83cc019SAndroid Build Coastguard Worker #define NORELOC 1
333*d83cc019SAndroid Build Coastguard Worker #define ACTIVE 2
334*d83cc019SAndroid Build Coastguard Worker #define HANG 4
basic_reloc(int fd,unsigned before,unsigned after,unsigned flags)335*d83cc019SAndroid Build Coastguard Worker static void basic_reloc(int fd, unsigned before, unsigned after, unsigned flags)
336*d83cc019SAndroid Build Coastguard Worker {
337*d83cc019SAndroid Build Coastguard Worker #define OBJSZ 8192
338*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_relocation_entry reloc;
339*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 obj;
340*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
341*d83cc019SAndroid Build Coastguard Worker 	uint64_t address_mask = has_64b_reloc(fd) ? ~(uint64_t)0 : ~(uint32_t)0;
342*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
343*d83cc019SAndroid Build Coastguard Worker 	unsigned int reloc_offset;
344*d83cc019SAndroid Build Coastguard Worker 
345*d83cc019SAndroid Build Coastguard Worker 	memset(&obj, 0, sizeof(obj));
346*d83cc019SAndroid Build Coastguard Worker 	obj.handle = gem_create(fd, OBJSZ);
347*d83cc019SAndroid Build Coastguard Worker 	obj.relocs_ptr = to_user_pointer(&reloc);
348*d83cc019SAndroid Build Coastguard Worker 	obj.relocation_count = 1;
349*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
350*d83cc019SAndroid Build Coastguard Worker 
351*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
352*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&obj);
353*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
354*d83cc019SAndroid Build Coastguard Worker 	if (flags & NORELOC)
355*d83cc019SAndroid Build Coastguard Worker 		execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
356*d83cc019SAndroid Build Coastguard Worker 
357*d83cc019SAndroid Build Coastguard Worker 	for (reloc_offset = 4096 - 8; reloc_offset <= 4096 + 8; reloc_offset += 4) {
358*d83cc019SAndroid Build Coastguard Worker 		igt_spin_t *spin = NULL;
359*d83cc019SAndroid Build Coastguard Worker 		uint32_t trash = 0;
360*d83cc019SAndroid Build Coastguard Worker 		uint64_t offset;
361*d83cc019SAndroid Build Coastguard Worker 
362*d83cc019SAndroid Build Coastguard Worker 		obj.offset = -1;
363*d83cc019SAndroid Build Coastguard Worker 
364*d83cc019SAndroid Build Coastguard Worker 		memset(&reloc, 0, sizeof(reloc));
365*d83cc019SAndroid Build Coastguard Worker 		reloc.offset = reloc_offset;
366*d83cc019SAndroid Build Coastguard Worker 		reloc.target_handle = obj.handle;
367*d83cc019SAndroid Build Coastguard Worker 		reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
368*d83cc019SAndroid Build Coastguard Worker 		reloc.presumed_offset = -1;
369*d83cc019SAndroid Build Coastguard Worker 
370*d83cc019SAndroid Build Coastguard Worker 		if (before) {
371*d83cc019SAndroid Build Coastguard Worker 			char *wc;
372*d83cc019SAndroid Build Coastguard Worker 
373*d83cc019SAndroid Build Coastguard Worker 			if (before == I915_GEM_DOMAIN_CPU)
374*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__cpu(fd, obj.handle, 0, OBJSZ, PROT_WRITE);
375*d83cc019SAndroid Build Coastguard Worker 			else if (before == I915_GEM_DOMAIN_GTT)
376*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__gtt(fd, obj.handle, OBJSZ, PROT_WRITE);
377*d83cc019SAndroid Build Coastguard Worker 			else if (before == I915_GEM_DOMAIN_WC)
378*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__wc(fd, obj.handle, 0, OBJSZ, PROT_WRITE);
379*d83cc019SAndroid Build Coastguard Worker 			else
380*d83cc019SAndroid Build Coastguard Worker 				igt_assert(0);
381*d83cc019SAndroid Build Coastguard Worker 			gem_set_domain(fd, obj.handle, before, before);
382*d83cc019SAndroid Build Coastguard Worker 			offset = -1;
383*d83cc019SAndroid Build Coastguard Worker 			memcpy(wc + reloc_offset, &offset, sizeof(offset));
384*d83cc019SAndroid Build Coastguard Worker 			munmap(wc, OBJSZ);
385*d83cc019SAndroid Build Coastguard Worker 		} else {
386*d83cc019SAndroid Build Coastguard Worker 			offset = -1;
387*d83cc019SAndroid Build Coastguard Worker 			gem_write(fd, obj.handle, reloc_offset, &offset, sizeof(offset));
388*d83cc019SAndroid Build Coastguard Worker 		}
389*d83cc019SAndroid Build Coastguard Worker 
390*d83cc019SAndroid Build Coastguard Worker 		if (flags & ACTIVE) {
391*d83cc019SAndroid Build Coastguard Worker 			spin = igt_spin_new(fd,
392*d83cc019SAndroid Build Coastguard Worker 					    .engine = I915_EXEC_DEFAULT,
393*d83cc019SAndroid Build Coastguard Worker 					    .dependency = obj.handle);
394*d83cc019SAndroid Build Coastguard Worker 			if (!(flags & HANG))
395*d83cc019SAndroid Build Coastguard Worker 				igt_spin_set_timeout(spin, NSEC_PER_SEC/100);
396*d83cc019SAndroid Build Coastguard Worker 			igt_assert(gem_bo_busy(fd, obj.handle));
397*d83cc019SAndroid Build Coastguard Worker 		}
398*d83cc019SAndroid Build Coastguard Worker 
399*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
400*d83cc019SAndroid Build Coastguard Worker 
401*d83cc019SAndroid Build Coastguard Worker 		if (after) {
402*d83cc019SAndroid Build Coastguard Worker 			char *wc;
403*d83cc019SAndroid Build Coastguard Worker 
404*d83cc019SAndroid Build Coastguard Worker 			if (after == I915_GEM_DOMAIN_CPU)
405*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__cpu(fd, obj.handle, 0, OBJSZ, PROT_READ);
406*d83cc019SAndroid Build Coastguard Worker 			else if (after == I915_GEM_DOMAIN_GTT)
407*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__gtt(fd, obj.handle, OBJSZ, PROT_READ);
408*d83cc019SAndroid Build Coastguard Worker 			else if (after == I915_GEM_DOMAIN_WC)
409*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__wc(fd, obj.handle, 0, OBJSZ, PROT_READ);
410*d83cc019SAndroid Build Coastguard Worker 			else
411*d83cc019SAndroid Build Coastguard Worker 				igt_assert(0);
412*d83cc019SAndroid Build Coastguard Worker 			gem_set_domain(fd, obj.handle, after, 0);
413*d83cc019SAndroid Build Coastguard Worker 			offset = ~reloc.presumed_offset & address_mask;
414*d83cc019SAndroid Build Coastguard Worker 			memcpy(&offset, wc + reloc_offset, has_64b_reloc(fd) ? 8 : 4);
415*d83cc019SAndroid Build Coastguard Worker 			munmap(wc, OBJSZ);
416*d83cc019SAndroid Build Coastguard Worker 		} else {
417*d83cc019SAndroid Build Coastguard Worker 			offset = ~reloc.presumed_offset & address_mask;
418*d83cc019SAndroid Build Coastguard Worker 			gem_read(fd, obj.handle, reloc_offset, &offset, has_64b_reloc(fd) ? 8 : 4);
419*d83cc019SAndroid Build Coastguard Worker 		}
420*d83cc019SAndroid Build Coastguard Worker 
421*d83cc019SAndroid Build Coastguard Worker 		if (reloc.presumed_offset == -1)
422*d83cc019SAndroid Build Coastguard Worker 			igt_warn("reloc.presumed_offset == -1\n");
423*d83cc019SAndroid Build Coastguard Worker 		else
424*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq_u64(reloc.presumed_offset, offset);
425*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq_u64(obj.offset, offset);
426*d83cc019SAndroid Build Coastguard Worker 
427*d83cc019SAndroid Build Coastguard Worker 		igt_spin_free(fd, spin);
428*d83cc019SAndroid Build Coastguard Worker 
429*d83cc019SAndroid Build Coastguard Worker 		/* Simulate relocation */
430*d83cc019SAndroid Build Coastguard Worker 		if (flags & NORELOC) {
431*d83cc019SAndroid Build Coastguard Worker 			obj.offset += OBJSZ;
432*d83cc019SAndroid Build Coastguard Worker 			reloc.presumed_offset += OBJSZ;
433*d83cc019SAndroid Build Coastguard Worker 		} else {
434*d83cc019SAndroid Build Coastguard Worker 			trash = obj.handle;
435*d83cc019SAndroid Build Coastguard Worker 			obj.handle = gem_create(fd, OBJSZ);
436*d83cc019SAndroid Build Coastguard Worker 			gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
437*d83cc019SAndroid Build Coastguard Worker 			reloc.target_handle = obj.handle;
438*d83cc019SAndroid Build Coastguard Worker 		}
439*d83cc019SAndroid Build Coastguard Worker 
440*d83cc019SAndroid Build Coastguard Worker 		if (before) {
441*d83cc019SAndroid Build Coastguard Worker 			char *wc;
442*d83cc019SAndroid Build Coastguard Worker 
443*d83cc019SAndroid Build Coastguard Worker 			if (before == I915_GEM_DOMAIN_CPU)
444*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__cpu(fd, obj.handle, 0, OBJSZ, PROT_WRITE);
445*d83cc019SAndroid Build Coastguard Worker 			else if (before == I915_GEM_DOMAIN_GTT)
446*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__gtt(fd, obj.handle, OBJSZ, PROT_WRITE);
447*d83cc019SAndroid Build Coastguard Worker 			else if (before == I915_GEM_DOMAIN_WC)
448*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__wc(fd, obj.handle, 0, OBJSZ, PROT_WRITE);
449*d83cc019SAndroid Build Coastguard Worker 			else
450*d83cc019SAndroid Build Coastguard Worker 				igt_assert(0);
451*d83cc019SAndroid Build Coastguard Worker 			gem_set_domain(fd, obj.handle, before, before);
452*d83cc019SAndroid Build Coastguard Worker 			memcpy(wc + reloc_offset, &reloc.presumed_offset, sizeof(reloc.presumed_offset));
453*d83cc019SAndroid Build Coastguard Worker 			munmap(wc, OBJSZ);
454*d83cc019SAndroid Build Coastguard Worker 		} else {
455*d83cc019SAndroid Build Coastguard Worker 			gem_write(fd, obj.handle, reloc_offset, &reloc.presumed_offset, sizeof(reloc.presumed_offset));
456*d83cc019SAndroid Build Coastguard Worker 		}
457*d83cc019SAndroid Build Coastguard Worker 
458*d83cc019SAndroid Build Coastguard Worker 		if (flags & ACTIVE) {
459*d83cc019SAndroid Build Coastguard Worker 			spin = igt_spin_new(fd,
460*d83cc019SAndroid Build Coastguard Worker 					    .engine = I915_EXEC_DEFAULT,
461*d83cc019SAndroid Build Coastguard Worker 					    .dependency = obj.handle);
462*d83cc019SAndroid Build Coastguard Worker 			if (!(flags & HANG))
463*d83cc019SAndroid Build Coastguard Worker 				igt_spin_set_timeout(spin, NSEC_PER_SEC/100);
464*d83cc019SAndroid Build Coastguard Worker 			igt_assert(gem_bo_busy(fd, obj.handle));
465*d83cc019SAndroid Build Coastguard Worker 		}
466*d83cc019SAndroid Build Coastguard Worker 
467*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &execbuf);
468*d83cc019SAndroid Build Coastguard Worker 
469*d83cc019SAndroid Build Coastguard Worker 		if (after) {
470*d83cc019SAndroid Build Coastguard Worker 			char *wc;
471*d83cc019SAndroid Build Coastguard Worker 
472*d83cc019SAndroid Build Coastguard Worker 			if (after == I915_GEM_DOMAIN_CPU)
473*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__cpu(fd, obj.handle, 0, OBJSZ, PROT_READ);
474*d83cc019SAndroid Build Coastguard Worker 			else if (after == I915_GEM_DOMAIN_GTT)
475*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__gtt(fd, obj.handle, OBJSZ, PROT_READ);
476*d83cc019SAndroid Build Coastguard Worker 			else if (after == I915_GEM_DOMAIN_WC)
477*d83cc019SAndroid Build Coastguard Worker 				wc = gem_mmap__wc(fd, obj.handle, 0, OBJSZ, PROT_READ);
478*d83cc019SAndroid Build Coastguard Worker 			else
479*d83cc019SAndroid Build Coastguard Worker 				igt_assert(0);
480*d83cc019SAndroid Build Coastguard Worker 			gem_set_domain(fd, obj.handle, after, 0);
481*d83cc019SAndroid Build Coastguard Worker 			offset = ~reloc.presumed_offset & address_mask;
482*d83cc019SAndroid Build Coastguard Worker 			memcpy(&offset, wc + reloc_offset, has_64b_reloc(fd) ? 8 : 4);
483*d83cc019SAndroid Build Coastguard Worker 			munmap(wc, OBJSZ);
484*d83cc019SAndroid Build Coastguard Worker 		} else {
485*d83cc019SAndroid Build Coastguard Worker 			offset = ~reloc.presumed_offset & address_mask;
486*d83cc019SAndroid Build Coastguard Worker 			gem_read(fd, obj.handle, reloc_offset, &offset, has_64b_reloc(fd) ? 8 : 4);
487*d83cc019SAndroid Build Coastguard Worker 		}
488*d83cc019SAndroid Build Coastguard Worker 
489*d83cc019SAndroid Build Coastguard Worker 		if (reloc.presumed_offset == -1)
490*d83cc019SAndroid Build Coastguard Worker 			igt_warn("reloc.presumed_offset == -1\n");
491*d83cc019SAndroid Build Coastguard Worker 		else
492*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq_u64(reloc.presumed_offset, offset);
493*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq_u64(obj.offset, offset);
494*d83cc019SAndroid Build Coastguard Worker 
495*d83cc019SAndroid Build Coastguard Worker 		igt_spin_free(fd, spin);
496*d83cc019SAndroid Build Coastguard Worker 		if (trash)
497*d83cc019SAndroid Build Coastguard Worker 			gem_close(fd, trash);
498*d83cc019SAndroid Build Coastguard Worker 	}
499*d83cc019SAndroid Build Coastguard Worker 
500*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, obj.handle);
501*d83cc019SAndroid Build Coastguard Worker }
502*d83cc019SAndroid Build Coastguard Worker 
sign_extend(uint64_t x,int index)503*d83cc019SAndroid Build Coastguard Worker static inline uint64_t sign_extend(uint64_t x, int index)
504*d83cc019SAndroid Build Coastguard Worker {
505*d83cc019SAndroid Build Coastguard Worker 	int shift = 63 - index;
506*d83cc019SAndroid Build Coastguard Worker 	return (int64_t)(x << shift) >> shift;
507*d83cc019SAndroid Build Coastguard Worker }
508*d83cc019SAndroid Build Coastguard Worker 
gen8_canonical_address(uint64_t address)509*d83cc019SAndroid Build Coastguard Worker static uint64_t gen8_canonical_address(uint64_t address)
510*d83cc019SAndroid Build Coastguard Worker {
511*d83cc019SAndroid Build Coastguard Worker 	return sign_extend(address, 47);
512*d83cc019SAndroid Build Coastguard Worker }
513*d83cc019SAndroid Build Coastguard Worker 
basic_range(int fd,unsigned flags)514*d83cc019SAndroid Build Coastguard Worker static void basic_range(int fd, unsigned flags)
515*d83cc019SAndroid Build Coastguard Worker {
516*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_relocation_entry reloc[128];
517*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 obj[128];
518*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
519*d83cc019SAndroid Build Coastguard Worker 	uint64_t address_mask = has_64b_reloc(fd) ? ~(uint64_t)0 : ~(uint32_t)0;
520*d83cc019SAndroid Build Coastguard Worker 	uint64_t gtt_size = gem_aperture_size(fd);
521*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = MI_BATCH_BUFFER_END;
522*d83cc019SAndroid Build Coastguard Worker 	igt_spin_t *spin = NULL;
523*d83cc019SAndroid Build Coastguard Worker 	int count, n;
524*d83cc019SAndroid Build Coastguard Worker 
525*d83cc019SAndroid Build Coastguard Worker 	igt_require(gem_has_softpin(fd));
526*d83cc019SAndroid Build Coastguard Worker 
527*d83cc019SAndroid Build Coastguard Worker 	for (count = 12; gtt_size >> (count + 1); count++)
528*d83cc019SAndroid Build Coastguard Worker 		;
529*d83cc019SAndroid Build Coastguard Worker 
530*d83cc019SAndroid Build Coastguard Worker 	count -= 12;
531*d83cc019SAndroid Build Coastguard Worker 
532*d83cc019SAndroid Build Coastguard Worker 	memset(obj, 0, sizeof(obj));
533*d83cc019SAndroid Build Coastguard Worker 	memset(reloc, 0, sizeof(reloc));
534*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
535*d83cc019SAndroid Build Coastguard Worker 
536*d83cc019SAndroid Build Coastguard Worker 	n = 0;
537*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i <= count; i++) {
538*d83cc019SAndroid Build Coastguard Worker 		obj[n].handle = gem_create(fd, 4096);
539*d83cc019SAndroid Build Coastguard Worker 		obj[n].offset = (1ull << (i + 12)) - 4096;
540*d83cc019SAndroid Build Coastguard Worker 		obj[n].offset = gen8_canonical_address(obj[n].offset);
541*d83cc019SAndroid Build Coastguard Worker 		obj[n].flags = EXEC_OBJECT_PINNED | EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
542*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, obj[n].handle, 0, &bbe, sizeof(bbe));
543*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffers_ptr = to_user_pointer(&obj[n]);
544*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 1;
545*d83cc019SAndroid Build Coastguard Worker 		if (__gem_execbuf(fd, &execbuf))
546*d83cc019SAndroid Build Coastguard Worker 			continue;
547*d83cc019SAndroid Build Coastguard Worker 
548*d83cc019SAndroid Build Coastguard Worker 		igt_debug("obj[%d] handle=%d, address=%llx\n",
549*d83cc019SAndroid Build Coastguard Worker 			  n, obj[n].handle, (long long)obj[n].offset);
550*d83cc019SAndroid Build Coastguard Worker 
551*d83cc019SAndroid Build Coastguard Worker 		reloc[n].offset = 8 * (n + 1);
552*d83cc019SAndroid Build Coastguard Worker 		reloc[n].target_handle = obj[n].handle;
553*d83cc019SAndroid Build Coastguard Worker 		reloc[n].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
554*d83cc019SAndroid Build Coastguard Worker 		reloc[n].presumed_offset = -1;
555*d83cc019SAndroid Build Coastguard Worker 		n++;
556*d83cc019SAndroid Build Coastguard Worker 	}
557*d83cc019SAndroid Build Coastguard Worker 	for (int i = 1; i < count; i++) {
558*d83cc019SAndroid Build Coastguard Worker 		obj[n].handle = gem_create(fd, 4096);
559*d83cc019SAndroid Build Coastguard Worker 		obj[n].offset = 1ull << (i + 12);
560*d83cc019SAndroid Build Coastguard Worker 		obj[n].offset = gen8_canonical_address(obj[n].offset);
561*d83cc019SAndroid Build Coastguard Worker 		obj[n].flags = EXEC_OBJECT_PINNED | EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
562*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, obj[n].handle, 0, &bbe, sizeof(bbe));
563*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffers_ptr = to_user_pointer(&obj[n]);
564*d83cc019SAndroid Build Coastguard Worker 		execbuf.buffer_count = 1;
565*d83cc019SAndroid Build Coastguard Worker 		if (__gem_execbuf(fd, &execbuf))
566*d83cc019SAndroid Build Coastguard Worker 			continue;
567*d83cc019SAndroid Build Coastguard Worker 
568*d83cc019SAndroid Build Coastguard Worker 		igt_debug("obj[%d] handle=%d, address=%llx\n",
569*d83cc019SAndroid Build Coastguard Worker 			  n, obj[n].handle, (long long)obj[n].offset);
570*d83cc019SAndroid Build Coastguard Worker 
571*d83cc019SAndroid Build Coastguard Worker 		reloc[n].offset = 8 * (n + 1);
572*d83cc019SAndroid Build Coastguard Worker 		reloc[n].target_handle = obj[n].handle;
573*d83cc019SAndroid Build Coastguard Worker 		reloc[n].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
574*d83cc019SAndroid Build Coastguard Worker 		reloc[n].presumed_offset = -1;
575*d83cc019SAndroid Build Coastguard Worker 		n++;
576*d83cc019SAndroid Build Coastguard Worker 	}
577*d83cc019SAndroid Build Coastguard Worker 	igt_require(n);
578*d83cc019SAndroid Build Coastguard Worker 
579*d83cc019SAndroid Build Coastguard Worker 	obj[n].handle = gem_create(fd, 4096);
580*d83cc019SAndroid Build Coastguard Worker 	obj[n].relocs_ptr = to_user_pointer(reloc);
581*d83cc019SAndroid Build Coastguard Worker 	obj[n].relocation_count = n;
582*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, obj[n].handle, 0, &bbe, sizeof(bbe));
583*d83cc019SAndroid Build Coastguard Worker 
584*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(obj);
585*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = n + 1;
586*d83cc019SAndroid Build Coastguard Worker 
587*d83cc019SAndroid Build Coastguard Worker 	if (flags & ACTIVE) {
588*d83cc019SAndroid Build Coastguard Worker 		spin = igt_spin_new(fd, .dependency = obj[n].handle);
589*d83cc019SAndroid Build Coastguard Worker 		if (!(flags & HANG))
590*d83cc019SAndroid Build Coastguard Worker 			igt_spin_set_timeout(spin, NSEC_PER_SEC/100);
591*d83cc019SAndroid Build Coastguard Worker 		igt_assert(gem_bo_busy(fd, obj[n].handle));
592*d83cc019SAndroid Build Coastguard Worker 	}
593*d83cc019SAndroid Build Coastguard Worker 
594*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
595*d83cc019SAndroid Build Coastguard Worker 	igt_spin_free(fd, spin);
596*d83cc019SAndroid Build Coastguard Worker 
597*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < n; i++) {
598*d83cc019SAndroid Build Coastguard Worker 		uint64_t offset;
599*d83cc019SAndroid Build Coastguard Worker 
600*d83cc019SAndroid Build Coastguard Worker 		offset = ~reloc[i].presumed_offset & address_mask;
601*d83cc019SAndroid Build Coastguard Worker 		gem_read(fd, obj[n].handle, reloc[i].offset,
602*d83cc019SAndroid Build Coastguard Worker 			 &offset, has_64b_reloc(fd) ? 8 : 4);
603*d83cc019SAndroid Build Coastguard Worker 
604*d83cc019SAndroid Build Coastguard Worker 		igt_debug("obj[%d] handle=%d, offset=%llx, found=%llx, presumed=%llx\n",
605*d83cc019SAndroid Build Coastguard Worker 			  i, obj[i].handle,
606*d83cc019SAndroid Build Coastguard Worker 			  (long long)obj[i].offset,
607*d83cc019SAndroid Build Coastguard Worker 			  (long long)offset,
608*d83cc019SAndroid Build Coastguard Worker 			  (long long)reloc[i].presumed_offset);
609*d83cc019SAndroid Build Coastguard Worker 
610*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq_u64(obj[i].offset, offset);
611*d83cc019SAndroid Build Coastguard Worker 		if (reloc[i].presumed_offset == -1)
612*d83cc019SAndroid Build Coastguard Worker 			igt_warn("reloc.presumed_offset == -1\n");
613*d83cc019SAndroid Build Coastguard Worker 		else
614*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq_u64(reloc[i].presumed_offset, offset);
615*d83cc019SAndroid Build Coastguard Worker 	}
616*d83cc019SAndroid Build Coastguard Worker 
617*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i <= n; i++)
618*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, obj[i].handle);
619*d83cc019SAndroid Build Coastguard Worker }
620*d83cc019SAndroid Build Coastguard Worker 
basic_softpin(int fd)621*d83cc019SAndroid Build Coastguard Worker static void basic_softpin(int fd)
622*d83cc019SAndroid Build Coastguard Worker {
623*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 obj[2];
624*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 execbuf;
625*d83cc019SAndroid Build Coastguard Worker 	uint64_t offset;
626*d83cc019SAndroid Build Coastguard Worker 	uint32_t bbe = MI_BATCH_BUFFER_END;
627*d83cc019SAndroid Build Coastguard Worker 
628*d83cc019SAndroid Build Coastguard Worker 	igt_require(gem_has_softpin(fd));
629*d83cc019SAndroid Build Coastguard Worker 
630*d83cc019SAndroid Build Coastguard Worker 	memset(obj, 0, sizeof(obj));
631*d83cc019SAndroid Build Coastguard Worker 	obj[1].handle = gem_create(fd, 4096);
632*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe));
633*d83cc019SAndroid Build Coastguard Worker 
634*d83cc019SAndroid Build Coastguard Worker 	memset(&execbuf, 0, sizeof(execbuf));
635*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&obj[1]);
636*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 1;
637*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
638*d83cc019SAndroid Build Coastguard Worker 
639*d83cc019SAndroid Build Coastguard Worker 	offset = obj[1].offset;
640*d83cc019SAndroid Build Coastguard Worker 
641*d83cc019SAndroid Build Coastguard Worker 	obj[0].handle = gem_create(fd, 4096);
642*d83cc019SAndroid Build Coastguard Worker 	obj[0].offset = obj[1].offset;
643*d83cc019SAndroid Build Coastguard Worker 	obj[0].flags = EXEC_OBJECT_PINNED;
644*d83cc019SAndroid Build Coastguard Worker 
645*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffers_ptr = to_user_pointer(&obj[0]);
646*d83cc019SAndroid Build Coastguard Worker 	execbuf.buffer_count = 2;
647*d83cc019SAndroid Build Coastguard Worker 
648*d83cc019SAndroid Build Coastguard Worker 	gem_execbuf(fd, &execbuf);
649*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq_u64(obj[0].offset, offset);
650*d83cc019SAndroid Build Coastguard Worker 
651*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, obj[0].handle);
652*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, obj[1].handle);
653*d83cc019SAndroid Build Coastguard Worker }
654*d83cc019SAndroid Build Coastguard Worker 
655*d83cc019SAndroid Build Coastguard Worker igt_main
656*d83cc019SAndroid Build Coastguard Worker {
657*d83cc019SAndroid Build Coastguard Worker 	const struct mode {
658*d83cc019SAndroid Build Coastguard Worker 		const char *name;
659*d83cc019SAndroid Build Coastguard Worker 		unsigned before, after;
660*d83cc019SAndroid Build Coastguard Worker 	} modes[] = {
661*d83cc019SAndroid Build Coastguard Worker 		{ "cpu", I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU },
662*d83cc019SAndroid Build Coastguard Worker 		{ "gtt", I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT },
663*d83cc019SAndroid Build Coastguard Worker 		{ "wc", I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC },
664*d83cc019SAndroid Build Coastguard Worker 		{ "cpu-gtt", I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_GTT },
665*d83cc019SAndroid Build Coastguard Worker 		{ "gtt-cpu", I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_CPU },
666*d83cc019SAndroid Build Coastguard Worker 		{ "cpu-wc", I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_WC },
667*d83cc019SAndroid Build Coastguard Worker 		{ "wc-cpu", I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_CPU },
668*d83cc019SAndroid Build Coastguard Worker 		{ "gtt-wc", I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_WC },
669*d83cc019SAndroid Build Coastguard Worker 		{ "wc-gtt", I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_GTT },
670*d83cc019SAndroid Build Coastguard Worker 		{ "cpu-read", I915_GEM_DOMAIN_CPU, 0 },
671*d83cc019SAndroid Build Coastguard Worker 		{ "gtt-read", I915_GEM_DOMAIN_GTT, 0 },
672*d83cc019SAndroid Build Coastguard Worker 		{ "wc-read", I915_GEM_DOMAIN_WC, 0 },
673*d83cc019SAndroid Build Coastguard Worker 		{ "write-cpu", 0, I915_GEM_DOMAIN_CPU },
674*d83cc019SAndroid Build Coastguard Worker 		{ "write-gtt", 0, I915_GEM_DOMAIN_GTT },
675*d83cc019SAndroid Build Coastguard Worker 		{ "write-wc", 0, I915_GEM_DOMAIN_WC },
676*d83cc019SAndroid Build Coastguard Worker 		{ "write-read", 0, 0 },
677*d83cc019SAndroid Build Coastguard Worker 		{ },
678*d83cc019SAndroid Build Coastguard Worker 	}, *m;
679*d83cc019SAndroid Build Coastguard Worker 	const struct flags {
680*d83cc019SAndroid Build Coastguard Worker 		const char *name;
681*d83cc019SAndroid Build Coastguard Worker 		unsigned flags;
682*d83cc019SAndroid Build Coastguard Worker 		bool basic;
683*d83cc019SAndroid Build Coastguard Worker 	} flags[] = {
684*d83cc019SAndroid Build Coastguard Worker 		{ "", 0 , true},
685*d83cc019SAndroid Build Coastguard Worker 		{ "-noreloc", NORELOC, true },
686*d83cc019SAndroid Build Coastguard Worker 		{ "-active", ACTIVE, true },
687*d83cc019SAndroid Build Coastguard Worker 		{ "-hang", ACTIVE | HANG },
688*d83cc019SAndroid Build Coastguard Worker 		{ },
689*d83cc019SAndroid Build Coastguard Worker 	}, *f;
690*d83cc019SAndroid Build Coastguard Worker 	uint64_t size;
691*d83cc019SAndroid Build Coastguard Worker 	int fd = -1;
692*d83cc019SAndroid Build Coastguard Worker 
693*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
694*d83cc019SAndroid Build Coastguard Worker 		fd = drm_open_driver_master(DRIVER_INTEL);
695*d83cc019SAndroid Build Coastguard Worker 		igt_require_gem(fd);
696*d83cc019SAndroid Build Coastguard Worker 	}
697*d83cc019SAndroid Build Coastguard Worker 
698*d83cc019SAndroid Build Coastguard Worker 	for (f = flags; f->name; f++) {
699*d83cc019SAndroid Build Coastguard Worker 		igt_hang_t hang;
700*d83cc019SAndroid Build Coastguard Worker 
701*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_group {
702*d83cc019SAndroid Build Coastguard Worker 			igt_fixture {
703*d83cc019SAndroid Build Coastguard Worker 				if (f->flags & HANG)
704*d83cc019SAndroid Build Coastguard Worker 					hang = igt_allow_hang(fd, 0, 0);
705*d83cc019SAndroid Build Coastguard Worker 			}
706*d83cc019SAndroid Build Coastguard Worker 
707*d83cc019SAndroid Build Coastguard Worker 			for (m = modes; m->name; m++) {
708*d83cc019SAndroid Build Coastguard Worker 				igt_subtest_f("%s%s%s",
709*d83cc019SAndroid Build Coastguard Worker 					      f->basic ? "basic-" : "",
710*d83cc019SAndroid Build Coastguard Worker 					      m->name,
711*d83cc019SAndroid Build Coastguard Worker 					      f->name) {
712*d83cc019SAndroid Build Coastguard Worker 					if ((m->before | m->after) & I915_GEM_DOMAIN_WC)
713*d83cc019SAndroid Build Coastguard Worker 						igt_require(gem_mmap__has_wc(fd));
714*d83cc019SAndroid Build Coastguard Worker 					basic_reloc(fd, m->before, m->after, f->flags);
715*d83cc019SAndroid Build Coastguard Worker 				}
716*d83cc019SAndroid Build Coastguard Worker 			}
717*d83cc019SAndroid Build Coastguard Worker 
718*d83cc019SAndroid Build Coastguard Worker 			if (!(f->flags & NORELOC)) {
719*d83cc019SAndroid Build Coastguard Worker 				igt_subtest_f("%srange%s",
720*d83cc019SAndroid Build Coastguard Worker 					      f->basic ? "basic-" : "", f->name)
721*d83cc019SAndroid Build Coastguard Worker 					basic_range(fd, f->flags);
722*d83cc019SAndroid Build Coastguard Worker 			}
723*d83cc019SAndroid Build Coastguard Worker 
724*d83cc019SAndroid Build Coastguard Worker 			igt_fixture {
725*d83cc019SAndroid Build Coastguard Worker 				if (f->flags & HANG)
726*d83cc019SAndroid Build Coastguard Worker 					igt_disallow_hang(fd, hang);
727*d83cc019SAndroid Build Coastguard Worker 			}
728*d83cc019SAndroid Build Coastguard Worker 		}
729*d83cc019SAndroid Build Coastguard Worker 	}
730*d83cc019SAndroid Build Coastguard Worker 
731*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-softpin")
732*d83cc019SAndroid Build Coastguard Worker 		basic_softpin(fd);
733*d83cc019SAndroid Build Coastguard Worker 
734*d83cc019SAndroid Build Coastguard Worker 	for (size = 4096; size <= 4ull*1024*1024*1024; size <<= 1) {
735*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("mmap-%u", find_last_set(size) - 1)
736*d83cc019SAndroid Build Coastguard Worker 			from_mmap(fd, size, MEM);
737*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("readonly-%u", find_last_set(size) - 1)
738*d83cc019SAndroid Build Coastguard Worker 			from_mmap(fd, size, MEM | RO);
739*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("cpu-%u", find_last_set(size) - 1)
740*d83cc019SAndroid Build Coastguard Worker 			from_mmap(fd, size, CPU);
find_last_set(size)741*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("wc-%u", find_last_set(size) - 1) {
742*d83cc019SAndroid Build Coastguard Worker 			igt_require(gem_mmap__has_wc(fd));
743*d83cc019SAndroid Build Coastguard Worker 			from_mmap(fd, size, WC);
744*d83cc019SAndroid Build Coastguard Worker 		}
745*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("gtt-%u", find_last_set(size) - 1)
746*d83cc019SAndroid Build Coastguard Worker 			from_mmap(fd, size, GTT);
747*d83cc019SAndroid Build Coastguard Worker 	}
748*d83cc019SAndroid Build Coastguard Worker 
749*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("gpu")
750*d83cc019SAndroid Build Coastguard Worker 		from_gpu(fd);
751*d83cc019SAndroid Build Coastguard Worker 
752*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("active")
753*d83cc019SAndroid Build Coastguard Worker 		active(fd, ALL_ENGINES);
754*d83cc019SAndroid Build Coastguard Worker 	for (const struct intel_execution_engine *e = intel_execution_engines;
755*d83cc019SAndroid Build Coastguard Worker 	     e->name; e++) {
756*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("active-%s", e->name)
757*d83cc019SAndroid Build Coastguard Worker 			active(fd, e->exec_id | e->flags);
758*d83cc019SAndroid Build Coastguard Worker 	}
759*d83cc019SAndroid Build Coastguard Worker 	igt_fixture
760*d83cc019SAndroid Build Coastguard Worker 		close(fd);
761*d83cc019SAndroid Build Coastguard Worker }
762