xref: /aosp_15_r20/external/igt-gpu-tools/tests/i915/gem_mmap_gtt.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2011 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  *    Chris Wilson <[email protected]>
25*d83cc019SAndroid Build Coastguard Worker  *
26*d83cc019SAndroid Build Coastguard Worker  */
27*d83cc019SAndroid Build Coastguard Worker 
28*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
29*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
30*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
31*d83cc019SAndroid Build Coastguard Worker #include <string.h>
32*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
33*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
34*d83cc019SAndroid Build Coastguard Worker #include <pthread.h>
35*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
36*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
37*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
38*d83cc019SAndroid Build Coastguard Worker #include "drm.h"
39*d83cc019SAndroid Build Coastguard Worker 
40*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
41*d83cc019SAndroid Build Coastguard Worker #include "igt_sysfs.h"
42*d83cc019SAndroid Build Coastguard Worker #include "igt_x86.h"
43*d83cc019SAndroid Build Coastguard Worker 
44*d83cc019SAndroid Build Coastguard Worker #ifndef PAGE_SIZE
45*d83cc019SAndroid Build Coastguard Worker #define PAGE_SIZE 4096
46*d83cc019SAndroid Build Coastguard Worker #endif
47*d83cc019SAndroid Build Coastguard Worker 
48*d83cc019SAndroid Build Coastguard Worker #define abs(x) ((x) >= 0 ? (x) : -(x))
49*d83cc019SAndroid Build Coastguard Worker 
50*d83cc019SAndroid Build Coastguard Worker static int OBJECT_SIZE = 16*1024*1024;
51*d83cc019SAndroid Build Coastguard Worker 
52*d83cc019SAndroid Build Coastguard Worker static void
set_domain_gtt(int fd,uint32_t handle)53*d83cc019SAndroid Build Coastguard Worker set_domain_gtt(int fd, uint32_t handle)
54*d83cc019SAndroid Build Coastguard Worker {
55*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
56*d83cc019SAndroid Build Coastguard Worker }
57*d83cc019SAndroid Build Coastguard Worker 
58*d83cc019SAndroid Build Coastguard Worker static void *
mmap_bo(int fd,uint32_t handle)59*d83cc019SAndroid Build Coastguard Worker mmap_bo(int fd, uint32_t handle)
60*d83cc019SAndroid Build Coastguard Worker {
61*d83cc019SAndroid Build Coastguard Worker 	void *ptr;
62*d83cc019SAndroid Build Coastguard Worker 
63*d83cc019SAndroid Build Coastguard Worker 	ptr = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
64*d83cc019SAndroid Build Coastguard Worker 
65*d83cc019SAndroid Build Coastguard Worker 	return ptr;
66*d83cc019SAndroid Build Coastguard Worker }
67*d83cc019SAndroid Build Coastguard Worker 
68*d83cc019SAndroid Build Coastguard Worker static void *
create_pointer(int fd)69*d83cc019SAndroid Build Coastguard Worker create_pointer(int fd)
70*d83cc019SAndroid Build Coastguard Worker {
71*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
72*d83cc019SAndroid Build Coastguard Worker 	void *ptr;
73*d83cc019SAndroid Build Coastguard Worker 
74*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, OBJECT_SIZE);
75*d83cc019SAndroid Build Coastguard Worker 
76*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap_bo(fd, handle);
77*d83cc019SAndroid Build Coastguard Worker 
78*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
79*d83cc019SAndroid Build Coastguard Worker 
80*d83cc019SAndroid Build Coastguard Worker 	return ptr;
81*d83cc019SAndroid Build Coastguard Worker }
82*d83cc019SAndroid Build Coastguard Worker 
83*d83cc019SAndroid Build Coastguard Worker static void
test_access(int fd)84*d83cc019SAndroid Build Coastguard Worker test_access(int fd)
85*d83cc019SAndroid Build Coastguard Worker {
86*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle, flink, handle2;
87*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_mmap_gtt mmap_arg;
88*d83cc019SAndroid Build Coastguard Worker 	int fd2;
89*d83cc019SAndroid Build Coastguard Worker 
90*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, OBJECT_SIZE);
91*d83cc019SAndroid Build Coastguard Worker 	igt_assert(handle);
92*d83cc019SAndroid Build Coastguard Worker 
93*d83cc019SAndroid Build Coastguard Worker 	fd2 = drm_open_driver(DRIVER_INTEL);
94*d83cc019SAndroid Build Coastguard Worker 
95*d83cc019SAndroid Build Coastguard Worker 	/* Check that fd1 can mmap. */
96*d83cc019SAndroid Build Coastguard Worker 	mmap_arg.handle = handle;
97*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg);
98*d83cc019SAndroid Build Coastguard Worker 
99*d83cc019SAndroid Build Coastguard Worker 	igt_assert(mmap64(0, OBJECT_SIZE, PROT_READ | PROT_WRITE,
100*d83cc019SAndroid Build Coastguard Worker 			  MAP_SHARED, fd, mmap_arg.offset));
101*d83cc019SAndroid Build Coastguard Worker 
102*d83cc019SAndroid Build Coastguard Worker 	/* Check that the same offset on the other fd doesn't work. */
103*d83cc019SAndroid Build Coastguard Worker 	igt_assert(mmap64(0, OBJECT_SIZE, PROT_READ | PROT_WRITE,
104*d83cc019SAndroid Build Coastguard Worker 			  MAP_SHARED, fd2, mmap_arg.offset) == MAP_FAILED);
105*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == EACCES);
106*d83cc019SAndroid Build Coastguard Worker 
107*d83cc019SAndroid Build Coastguard Worker 	flink = gem_flink(fd, handle);
108*d83cc019SAndroid Build Coastguard Worker 	igt_assert(flink);
109*d83cc019SAndroid Build Coastguard Worker 	handle2 = gem_open(fd2, flink);
110*d83cc019SAndroid Build Coastguard Worker 	igt_assert(handle2);
111*d83cc019SAndroid Build Coastguard Worker 
112*d83cc019SAndroid Build Coastguard Worker 	/* Recheck that it works after flink. */
113*d83cc019SAndroid Build Coastguard Worker 	/* Check that the same offset on the other fd doesn't work. */
114*d83cc019SAndroid Build Coastguard Worker 	igt_assert(mmap64(0, OBJECT_SIZE, PROT_READ | PROT_WRITE,
115*d83cc019SAndroid Build Coastguard Worker 			  MAP_SHARED, fd2, mmap_arg.offset));
116*d83cc019SAndroid Build Coastguard Worker }
117*d83cc019SAndroid Build Coastguard Worker 
118*d83cc019SAndroid Build Coastguard Worker static void
test_short(int fd)119*d83cc019SAndroid Build Coastguard Worker test_short(int fd)
120*d83cc019SAndroid Build Coastguard Worker {
121*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_mmap_gtt mmap_arg;
122*d83cc019SAndroid Build Coastguard Worker 	int pages, p;
123*d83cc019SAndroid Build Coastguard Worker 
124*d83cc019SAndroid Build Coastguard Worker 	mmap_arg.handle = gem_create(fd, OBJECT_SIZE);
125*d83cc019SAndroid Build Coastguard Worker 	igt_assert(mmap_arg.handle);
126*d83cc019SAndroid Build Coastguard Worker 
127*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg);
128*d83cc019SAndroid Build Coastguard Worker 	for (pages = 1; pages <= OBJECT_SIZE / PAGE_SIZE; pages <<= 1) {
129*d83cc019SAndroid Build Coastguard Worker 		uint8_t *r, *w;
130*d83cc019SAndroid Build Coastguard Worker 
131*d83cc019SAndroid Build Coastguard Worker 		w = mmap64(0, pages * PAGE_SIZE, PROT_READ | PROT_WRITE,
132*d83cc019SAndroid Build Coastguard Worker 			   MAP_SHARED, fd, mmap_arg.offset);
133*d83cc019SAndroid Build Coastguard Worker 		igt_assert(w != MAP_FAILED);
134*d83cc019SAndroid Build Coastguard Worker 
135*d83cc019SAndroid Build Coastguard Worker 		r = mmap64(0, pages * PAGE_SIZE, PROT_READ,
136*d83cc019SAndroid Build Coastguard Worker 			   MAP_SHARED, fd, mmap_arg.offset);
137*d83cc019SAndroid Build Coastguard Worker 		igt_assert(r != MAP_FAILED);
138*d83cc019SAndroid Build Coastguard Worker 
139*d83cc019SAndroid Build Coastguard Worker 		for (p = 0; p < pages; p++) {
140*d83cc019SAndroid Build Coastguard Worker 			w[p*PAGE_SIZE] = r[p*PAGE_SIZE];
141*d83cc019SAndroid Build Coastguard Worker 			w[p*PAGE_SIZE+(PAGE_SIZE-1)] =
142*d83cc019SAndroid Build Coastguard Worker 				r[p*PAGE_SIZE+(PAGE_SIZE-1)];
143*d83cc019SAndroid Build Coastguard Worker 		}
144*d83cc019SAndroid Build Coastguard Worker 
145*d83cc019SAndroid Build Coastguard Worker 		munmap(r, pages * PAGE_SIZE);
146*d83cc019SAndroid Build Coastguard Worker 		munmap(w, pages * PAGE_SIZE);
147*d83cc019SAndroid Build Coastguard Worker 	}
148*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, mmap_arg.handle);
149*d83cc019SAndroid Build Coastguard Worker }
150*d83cc019SAndroid Build Coastguard Worker 
151*d83cc019SAndroid Build Coastguard Worker static void
test_copy(int fd)152*d83cc019SAndroid Build Coastguard Worker test_copy(int fd)
153*d83cc019SAndroid Build Coastguard Worker {
154*d83cc019SAndroid Build Coastguard Worker 	void *src, *dst;
155*d83cc019SAndroid Build Coastguard Worker 
156*d83cc019SAndroid Build Coastguard Worker 	/* copy from a fresh src to fresh dst to force pagefault on both */
157*d83cc019SAndroid Build Coastguard Worker 	src = create_pointer(fd);
158*d83cc019SAndroid Build Coastguard Worker 	dst = create_pointer(fd);
159*d83cc019SAndroid Build Coastguard Worker 
160*d83cc019SAndroid Build Coastguard Worker 	memcpy(dst, src, OBJECT_SIZE);
161*d83cc019SAndroid Build Coastguard Worker 	memcpy(src, dst, OBJECT_SIZE);
162*d83cc019SAndroid Build Coastguard Worker 
163*d83cc019SAndroid Build Coastguard Worker 	munmap(dst, OBJECT_SIZE);
164*d83cc019SAndroid Build Coastguard Worker 	munmap(src, OBJECT_SIZE);
165*d83cc019SAndroid Build Coastguard Worker }
166*d83cc019SAndroid Build Coastguard Worker 
167*d83cc019SAndroid Build Coastguard Worker enum test_read_write {
168*d83cc019SAndroid Build Coastguard Worker 	READ_BEFORE_WRITE,
169*d83cc019SAndroid Build Coastguard Worker 	READ_AFTER_WRITE,
170*d83cc019SAndroid Build Coastguard Worker };
171*d83cc019SAndroid Build Coastguard Worker 
172*d83cc019SAndroid Build Coastguard Worker static void
test_read_write(int fd,enum test_read_write order)173*d83cc019SAndroid Build Coastguard Worker test_read_write(int fd, enum test_read_write order)
174*d83cc019SAndroid Build Coastguard Worker {
175*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
176*d83cc019SAndroid Build Coastguard Worker 	void *ptr;
177*d83cc019SAndroid Build Coastguard Worker 	volatile uint32_t val = 0;
178*d83cc019SAndroid Build Coastguard Worker 
179*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, OBJECT_SIZE);
180*d83cc019SAndroid Build Coastguard Worker 
181*d83cc019SAndroid Build Coastguard Worker 	ptr = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
182*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
183*d83cc019SAndroid Build Coastguard Worker 
184*d83cc019SAndroid Build Coastguard Worker 	if (order == READ_BEFORE_WRITE) {
185*d83cc019SAndroid Build Coastguard Worker 		val = *(uint32_t *)ptr;
186*d83cc019SAndroid Build Coastguard Worker 		*(uint32_t *)ptr = val;
187*d83cc019SAndroid Build Coastguard Worker 	} else {
188*d83cc019SAndroid Build Coastguard Worker 		*(uint32_t *)ptr = val;
189*d83cc019SAndroid Build Coastguard Worker 		val = *(uint32_t *)ptr;
190*d83cc019SAndroid Build Coastguard Worker 	}
191*d83cc019SAndroid Build Coastguard Worker 
192*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
193*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, OBJECT_SIZE);
194*d83cc019SAndroid Build Coastguard Worker }
195*d83cc019SAndroid Build Coastguard Worker 
196*d83cc019SAndroid Build Coastguard Worker static void
test_read_write2(int fd,enum test_read_write order)197*d83cc019SAndroid Build Coastguard Worker test_read_write2(int fd, enum test_read_write order)
198*d83cc019SAndroid Build Coastguard Worker {
199*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
200*d83cc019SAndroid Build Coastguard Worker 	void *r, *w;
201*d83cc019SAndroid Build Coastguard Worker 	volatile uint32_t val = 0;
202*d83cc019SAndroid Build Coastguard Worker 
203*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, OBJECT_SIZE);
204*d83cc019SAndroid Build Coastguard Worker 
205*d83cc019SAndroid Build Coastguard Worker 	r = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ);
206*d83cc019SAndroid Build Coastguard Worker 	w = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
207*d83cc019SAndroid Build Coastguard Worker 
208*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
209*d83cc019SAndroid Build Coastguard Worker 
210*d83cc019SAndroid Build Coastguard Worker 	if (order == READ_BEFORE_WRITE) {
211*d83cc019SAndroid Build Coastguard Worker 		val = *(uint32_t *)r;
212*d83cc019SAndroid Build Coastguard Worker 		*(uint32_t *)w = val;
213*d83cc019SAndroid Build Coastguard Worker 	} else {
214*d83cc019SAndroid Build Coastguard Worker 		*(uint32_t *)w = val;
215*d83cc019SAndroid Build Coastguard Worker 		val = *(uint32_t *)r;
216*d83cc019SAndroid Build Coastguard Worker 	}
217*d83cc019SAndroid Build Coastguard Worker 
218*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
219*d83cc019SAndroid Build Coastguard Worker 	munmap(r, OBJECT_SIZE);
220*d83cc019SAndroid Build Coastguard Worker 	munmap(w, OBJECT_SIZE);
221*d83cc019SAndroid Build Coastguard Worker }
222*d83cc019SAndroid Build Coastguard Worker 
223*d83cc019SAndroid Build Coastguard Worker static void
test_write(int fd)224*d83cc019SAndroid Build Coastguard Worker test_write(int fd)
225*d83cc019SAndroid Build Coastguard Worker {
226*d83cc019SAndroid Build Coastguard Worker 	void *src;
227*d83cc019SAndroid Build Coastguard Worker 	uint32_t dst;
228*d83cc019SAndroid Build Coastguard Worker 
229*d83cc019SAndroid Build Coastguard Worker 	/* copy from a fresh src to fresh dst to force pagefault on both */
230*d83cc019SAndroid Build Coastguard Worker 	src = create_pointer(fd);
231*d83cc019SAndroid Build Coastguard Worker 	dst = gem_create(fd, OBJECT_SIZE);
232*d83cc019SAndroid Build Coastguard Worker 
233*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, dst, 0, src, OBJECT_SIZE);
234*d83cc019SAndroid Build Coastguard Worker 
235*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, dst);
236*d83cc019SAndroid Build Coastguard Worker 	munmap(src, OBJECT_SIZE);
237*d83cc019SAndroid Build Coastguard Worker }
238*d83cc019SAndroid Build Coastguard Worker 
239*d83cc019SAndroid Build Coastguard Worker static void
test_wc(int fd)240*d83cc019SAndroid Build Coastguard Worker test_wc(int fd)
241*d83cc019SAndroid Build Coastguard Worker {
242*d83cc019SAndroid Build Coastguard Worker 	unsigned long gtt_reads, gtt_writes, cpu_writes;
243*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
244*d83cc019SAndroid Build Coastguard Worker 	void *gtt, *cpu;
245*d83cc019SAndroid Build Coastguard Worker 
246*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, 4096);
247*d83cc019SAndroid Build Coastguard Worker 	cpu = gem_mmap__cpu(fd, handle, 0, 4096, PROT_READ | PROT_WRITE);
248*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
249*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
250*d83cc019SAndroid Build Coastguard Worker 
251*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, 4096);
252*d83cc019SAndroid Build Coastguard Worker 	gtt = gem_mmap__gtt(fd, handle, 4096, PROT_READ | PROT_WRITE);
253*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
254*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
255*d83cc019SAndroid Build Coastguard Worker 
256*d83cc019SAndroid Build Coastguard Worker 	gtt_reads = 0;
257*d83cc019SAndroid Build Coastguard Worker 	igt_for_milliseconds(200) {
258*d83cc019SAndroid Build Coastguard Worker 		memcpy(cpu, gtt, 4096);
259*d83cc019SAndroid Build Coastguard Worker 		gtt_reads++;
260*d83cc019SAndroid Build Coastguard Worker 	}
261*d83cc019SAndroid Build Coastguard Worker 	igt_debug("%lu GTT reads in 200us\n", gtt_reads);
262*d83cc019SAndroid Build Coastguard Worker 
263*d83cc019SAndroid Build Coastguard Worker 	gtt_writes = 0;
264*d83cc019SAndroid Build Coastguard Worker 	igt_for_milliseconds(200) {
265*d83cc019SAndroid Build Coastguard Worker 		memcpy(gtt, cpu, 4096);
266*d83cc019SAndroid Build Coastguard Worker 		gtt_writes++;
267*d83cc019SAndroid Build Coastguard Worker 	}
268*d83cc019SAndroid Build Coastguard Worker 	igt_debug("%lu GTT writes in 200us\n", gtt_writes);
269*d83cc019SAndroid Build Coastguard Worker 
270*d83cc019SAndroid Build Coastguard Worker 	if (igt_setup_clflush()) {
271*d83cc019SAndroid Build Coastguard Worker 		cpu_writes = 0;
272*d83cc019SAndroid Build Coastguard Worker 		igt_for_milliseconds(200) {
273*d83cc019SAndroid Build Coastguard Worker 			igt_clflush_range(cpu, 4096);
274*d83cc019SAndroid Build Coastguard Worker 			cpu_writes++;
275*d83cc019SAndroid Build Coastguard Worker 		}
276*d83cc019SAndroid Build Coastguard Worker 		igt_debug("%lu CPU writes in 200us\n", cpu_writes);
277*d83cc019SAndroid Build Coastguard Worker 	} else
278*d83cc019SAndroid Build Coastguard Worker 		cpu_writes = gtt_writes;
279*d83cc019SAndroid Build Coastguard Worker 
280*d83cc019SAndroid Build Coastguard Worker 	munmap(cpu, 4096);
281*d83cc019SAndroid Build Coastguard Worker 	munmap(gtt, 4096);
282*d83cc019SAndroid Build Coastguard Worker 
283*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f(gtt_writes > 2*gtt_reads,
284*d83cc019SAndroid Build Coastguard Worker 		     "Write-Combined writes are expected to be much faster than reads: read=%.2fMiB/s, write=%.2fMiB/s\n",
285*d83cc019SAndroid Build Coastguard Worker 		     5*gtt_reads/256., 5*gtt_writes/256.);
286*d83cc019SAndroid Build Coastguard Worker 
287*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f(gtt_writes > cpu_writes/2,
288*d83cc019SAndroid Build Coastguard Worker 		     "Write-Combined writes are expected to be roughly equivalent to WB writes: WC (gtt)=%.2fMiB/s, WB (cpu)=%.2fMiB/s\n",
289*d83cc019SAndroid Build Coastguard Worker 		     5*gtt_writes/256., 5*cpu_writes/256.);
290*d83cc019SAndroid Build Coastguard Worker }
291*d83cc019SAndroid Build Coastguard Worker 
mmap_gtt_version(int i915)292*d83cc019SAndroid Build Coastguard Worker static int mmap_gtt_version(int i915)
293*d83cc019SAndroid Build Coastguard Worker {
294*d83cc019SAndroid Build Coastguard Worker 	int val = 0;
295*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_getparam gp = {
296*d83cc019SAndroid Build Coastguard Worker 		gp.param = 40, /* MMAP_GTT_VERSION */
297*d83cc019SAndroid Build Coastguard Worker 		gp.value = &val,
298*d83cc019SAndroid Build Coastguard Worker 	};
299*d83cc019SAndroid Build Coastguard Worker 
300*d83cc019SAndroid Build Coastguard Worker 	ioctl(i915, DRM_IOCTL_I915_GETPARAM, &gp);
301*d83cc019SAndroid Build Coastguard Worker 	return val;
302*d83cc019SAndroid Build Coastguard Worker }
303*d83cc019SAndroid Build Coastguard Worker 
304*d83cc019SAndroid Build Coastguard Worker static void
test_pf_nonblock(int i915)305*d83cc019SAndroid Build Coastguard Worker test_pf_nonblock(int i915)
306*d83cc019SAndroid Build Coastguard Worker {
307*d83cc019SAndroid Build Coastguard Worker 	igt_spin_t *spin;
308*d83cc019SAndroid Build Coastguard Worker 	uint32_t *ptr;
309*d83cc019SAndroid Build Coastguard Worker 
310*d83cc019SAndroid Build Coastguard Worker 	igt_require(mmap_gtt_version(i915) >= 3);
311*d83cc019SAndroid Build Coastguard Worker 
312*d83cc019SAndroid Build Coastguard Worker 	spin = igt_spin_new(i915);
313*d83cc019SAndroid Build Coastguard Worker 
314*d83cc019SAndroid Build Coastguard Worker 	igt_set_timeout(1, "initial pagefaulting did not complete within 1s");
315*d83cc019SAndroid Build Coastguard Worker 
316*d83cc019SAndroid Build Coastguard Worker 	ptr = gem_mmap__gtt(i915, spin->handle, 4096, PROT_WRITE);
317*d83cc019SAndroid Build Coastguard Worker 	ptr[256] = 0;
318*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, 4096);
319*d83cc019SAndroid Build Coastguard Worker 
320*d83cc019SAndroid Build Coastguard Worker 	igt_reset_timeout();
321*d83cc019SAndroid Build Coastguard Worker 
322*d83cc019SAndroid Build Coastguard Worker 	igt_spin_free(i915, spin);
323*d83cc019SAndroid Build Coastguard Worker }
324*d83cc019SAndroid Build Coastguard Worker 
325*d83cc019SAndroid Build Coastguard Worker static void
test_isolation(int i915)326*d83cc019SAndroid Build Coastguard Worker test_isolation(int i915)
327*d83cc019SAndroid Build Coastguard Worker {
328*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_mmap_gtt mmap_arg;
329*d83cc019SAndroid Build Coastguard Worker 	int A = gem_reopen_driver(i915);
330*d83cc019SAndroid Build Coastguard Worker 	int B = gem_reopen_driver(i915);
331*d83cc019SAndroid Build Coastguard Worker 	uint64_t offset_a, offset_b;
332*d83cc019SAndroid Build Coastguard Worker 	uint32_t a, b;
333*d83cc019SAndroid Build Coastguard Worker 	void *ptr;
334*d83cc019SAndroid Build Coastguard Worker 
335*d83cc019SAndroid Build Coastguard Worker 	a = gem_create(A, 4096);
336*d83cc019SAndroid Build Coastguard Worker 	b = gem_open(B, gem_flink(A, a));
337*d83cc019SAndroid Build Coastguard Worker 
338*d83cc019SAndroid Build Coastguard Worker 	mmap_arg.handle = a;
339*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(A, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg);
340*d83cc019SAndroid Build Coastguard Worker 	offset_a = mmap_arg.offset;
341*d83cc019SAndroid Build Coastguard Worker 
342*d83cc019SAndroid Build Coastguard Worker 	mmap_arg.handle = b;
343*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(B, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg);
344*d83cc019SAndroid Build Coastguard Worker 	offset_b = mmap_arg.offset;
345*d83cc019SAndroid Build Coastguard Worker 
346*d83cc019SAndroid Build Coastguard Worker 	igt_info("A: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
347*d83cc019SAndroid Build Coastguard Worker 		 A, a, offset_a);
348*d83cc019SAndroid Build Coastguard Worker 	igt_info("B: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
349*d83cc019SAndroid Build Coastguard Worker 		 B, b, offset_b);
350*d83cc019SAndroid Build Coastguard Worker 
351*d83cc019SAndroid Build Coastguard Worker 	close(B);
352*d83cc019SAndroid Build Coastguard Worker 
353*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
354*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr != MAP_FAILED);
355*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, 4096);
356*d83cc019SAndroid Build Coastguard Worker 
357*d83cc019SAndroid Build Coastguard Worker 	close(A);
358*d83cc019SAndroid Build Coastguard Worker 
359*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
360*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr == MAP_FAILED);
361*d83cc019SAndroid Build Coastguard Worker }
362*d83cc019SAndroid Build Coastguard Worker 
363*d83cc019SAndroid Build Coastguard Worker static void
test_write_gtt(int fd)364*d83cc019SAndroid Build Coastguard Worker test_write_gtt(int fd)
365*d83cc019SAndroid Build Coastguard Worker {
366*d83cc019SAndroid Build Coastguard Worker 	uint32_t dst;
367*d83cc019SAndroid Build Coastguard Worker 	char *dst_gtt;
368*d83cc019SAndroid Build Coastguard Worker 	void *src;
369*d83cc019SAndroid Build Coastguard Worker 
370*d83cc019SAndroid Build Coastguard Worker 	dst = gem_create(fd, OBJECT_SIZE);
371*d83cc019SAndroid Build Coastguard Worker 
372*d83cc019SAndroid Build Coastguard Worker 	/* prefault object into gtt */
373*d83cc019SAndroid Build Coastguard Worker 	dst_gtt = mmap_bo(fd, dst);
374*d83cc019SAndroid Build Coastguard Worker 	set_domain_gtt(fd, dst);
375*d83cc019SAndroid Build Coastguard Worker 	memset(dst_gtt, 0, OBJECT_SIZE);
376*d83cc019SAndroid Build Coastguard Worker 	munmap(dst_gtt, OBJECT_SIZE);
377*d83cc019SAndroid Build Coastguard Worker 
378*d83cc019SAndroid Build Coastguard Worker 	src = create_pointer(fd);
379*d83cc019SAndroid Build Coastguard Worker 
380*d83cc019SAndroid Build Coastguard Worker 	gem_write(fd, dst, 0, src, OBJECT_SIZE);
381*d83cc019SAndroid Build Coastguard Worker 
382*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, dst);
383*d83cc019SAndroid Build Coastguard Worker 	munmap(src, OBJECT_SIZE);
384*d83cc019SAndroid Build Coastguard Worker }
385*d83cc019SAndroid Build Coastguard Worker 
is_coherent(int i915)386*d83cc019SAndroid Build Coastguard Worker static bool is_coherent(int i915)
387*d83cc019SAndroid Build Coastguard Worker {
388*d83cc019SAndroid Build Coastguard Worker 	int val = 1; /* by default, we assume GTT is coherent, hence the test */
389*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_getparam gp = {
390*d83cc019SAndroid Build Coastguard Worker 		gp.param = 52, /* GTT_COHERENT */
391*d83cc019SAndroid Build Coastguard Worker 		gp.value = &val,
392*d83cc019SAndroid Build Coastguard Worker 	};
393*d83cc019SAndroid Build Coastguard Worker 
394*d83cc019SAndroid Build Coastguard Worker 	ioctl(i915, DRM_IOCTL_I915_GETPARAM, &gp);
395*d83cc019SAndroid Build Coastguard Worker 	return val;
396*d83cc019SAndroid Build Coastguard Worker }
397*d83cc019SAndroid Build Coastguard Worker 
398*d83cc019SAndroid Build Coastguard Worker static void
test_coherency(int fd)399*d83cc019SAndroid Build Coastguard Worker test_coherency(int fd)
400*d83cc019SAndroid Build Coastguard Worker {
401*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
402*d83cc019SAndroid Build Coastguard Worker 	uint32_t *gtt, *cpu;
403*d83cc019SAndroid Build Coastguard Worker 	int i;
404*d83cc019SAndroid Build Coastguard Worker 
405*d83cc019SAndroid Build Coastguard Worker 	igt_require(is_coherent(fd));
406*d83cc019SAndroid Build Coastguard Worker 	igt_require(igt_setup_clflush());
407*d83cc019SAndroid Build Coastguard Worker 
408*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, OBJECT_SIZE);
409*d83cc019SAndroid Build Coastguard Worker 
410*d83cc019SAndroid Build Coastguard Worker 	gtt = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
411*d83cc019SAndroid Build Coastguard Worker 	cpu = gem_mmap__cpu(fd, handle, 0, OBJECT_SIZE, PROT_READ | PROT_WRITE);
412*d83cc019SAndroid Build Coastguard Worker 	set_domain_gtt(fd, handle);
413*d83cc019SAndroid Build Coastguard Worker 
414*d83cc019SAndroid Build Coastguard Worker 	/* On byt/bsw/bxt this detects an interesting behaviour where the
415*d83cc019SAndroid Build Coastguard Worker 	 * CPU cannot flush the iobar and so the read may bypass the write.
416*d83cc019SAndroid Build Coastguard Worker 	 * https://bugs.freedesktop.org/show_bug.cgi?id=94314
417*d83cc019SAndroid Build Coastguard Worker 	 */
418*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < OBJECT_SIZE / 64; i++) {
419*d83cc019SAndroid Build Coastguard Worker 		int x = 16*i + (i%16);
420*d83cc019SAndroid Build Coastguard Worker 		gtt[x] = i;
421*d83cc019SAndroid Build Coastguard Worker 		igt_clflush_range(&cpu[x], sizeof(cpu[x]));
422*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(cpu[x], i);
423*d83cc019SAndroid Build Coastguard Worker 	}
424*d83cc019SAndroid Build Coastguard Worker 
425*d83cc019SAndroid Build Coastguard Worker 	munmap(cpu, OBJECT_SIZE);
426*d83cc019SAndroid Build Coastguard Worker 	munmap(gtt, OBJECT_SIZE);
427*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
428*d83cc019SAndroid Build Coastguard Worker }
429*d83cc019SAndroid Build Coastguard Worker 
430*d83cc019SAndroid Build Coastguard Worker static void
test_clflush(int fd)431*d83cc019SAndroid Build Coastguard Worker test_clflush(int fd)
432*d83cc019SAndroid Build Coastguard Worker {
433*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
434*d83cc019SAndroid Build Coastguard Worker 	uint32_t *gtt;
435*d83cc019SAndroid Build Coastguard Worker 
436*d83cc019SAndroid Build Coastguard Worker 	igt_require(igt_setup_clflush());
437*d83cc019SAndroid Build Coastguard Worker 
438*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, OBJECT_SIZE);
439*d83cc019SAndroid Build Coastguard Worker 
440*d83cc019SAndroid Build Coastguard Worker 	gtt = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
441*d83cc019SAndroid Build Coastguard Worker 	set_domain_gtt(fd, handle);
442*d83cc019SAndroid Build Coastguard Worker 
443*d83cc019SAndroid Build Coastguard Worker 	igt_clflush_range(gtt, OBJECT_SIZE);
444*d83cc019SAndroid Build Coastguard Worker 
445*d83cc019SAndroid Build Coastguard Worker 	munmap(gtt, OBJECT_SIZE);
446*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
447*d83cc019SAndroid Build Coastguard Worker }
448*d83cc019SAndroid Build Coastguard Worker 
449*d83cc019SAndroid Build Coastguard Worker static void
test_hang(int fd)450*d83cc019SAndroid Build Coastguard Worker test_hang(int fd)
451*d83cc019SAndroid Build Coastguard Worker {
452*d83cc019SAndroid Build Coastguard Worker 	const uint32_t patterns[] = {
453*d83cc019SAndroid Build Coastguard Worker 		0, 0xaaaaaaaa, 0x55555555, 0xcccccccc,
454*d83cc019SAndroid Build Coastguard Worker 	};
455*d83cc019SAndroid Build Coastguard Worker 	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
456*d83cc019SAndroid Build Coastguard Worker 	struct {
457*d83cc019SAndroid Build Coastguard Worker 		bool done;
458*d83cc019SAndroid Build Coastguard Worker 		bool error;
459*d83cc019SAndroid Build Coastguard Worker 	} *control;
460*d83cc019SAndroid Build Coastguard Worker 	unsigned long count;
461*d83cc019SAndroid Build Coastguard Worker 	igt_hang_t hang;
462*d83cc019SAndroid Build Coastguard Worker 	int dir;
463*d83cc019SAndroid Build Coastguard Worker 
464*d83cc019SAndroid Build Coastguard Worker 	hang = igt_allow_hang(fd, 0, 0);
465*d83cc019SAndroid Build Coastguard Worker 	igt_require(igt_sysfs_set_parameter(fd, "reset", "1")); /* global */
466*d83cc019SAndroid Build Coastguard Worker 
467*d83cc019SAndroid Build Coastguard Worker 	control = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
468*d83cc019SAndroid Build Coastguard Worker 	igt_assert(control != MAP_FAILED);
469*d83cc019SAndroid Build Coastguard Worker 
470*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, ncpus) {
471*d83cc019SAndroid Build Coastguard Worker 		int last_pattern = 0;
472*d83cc019SAndroid Build Coastguard Worker 		int next_pattern = 1;
473*d83cc019SAndroid Build Coastguard Worker 		uint32_t *gtt[2];
474*d83cc019SAndroid Build Coastguard Worker 
475*d83cc019SAndroid Build Coastguard Worker 		for (int i = 0; i < ARRAY_SIZE(gtt); i++) {
476*d83cc019SAndroid Build Coastguard Worker 			uint32_t handle;
477*d83cc019SAndroid Build Coastguard Worker 
478*d83cc019SAndroid Build Coastguard Worker 			handle = gem_create(fd, OBJECT_SIZE);
479*d83cc019SAndroid Build Coastguard Worker 			gem_set_tiling(fd, handle, I915_TILING_X + i, 2048);
480*d83cc019SAndroid Build Coastguard Worker 
481*d83cc019SAndroid Build Coastguard Worker 			gtt[i] = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_WRITE);
482*d83cc019SAndroid Build Coastguard Worker 			set_domain_gtt(fd, handle);
483*d83cc019SAndroid Build Coastguard Worker 			gem_close(fd, handle);
484*d83cc019SAndroid Build Coastguard Worker 		}
485*d83cc019SAndroid Build Coastguard Worker 
486*d83cc019SAndroid Build Coastguard Worker 		while (!READ_ONCE(control->done)) {
487*d83cc019SAndroid Build Coastguard Worker 			for (int i = 0; i < OBJECT_SIZE / 64; i++) {
488*d83cc019SAndroid Build Coastguard Worker 				const unsigned int x = 16 * i + ( i% 16);
489*d83cc019SAndroid Build Coastguard Worker 				uint32_t expected = patterns[last_pattern];
490*d83cc019SAndroid Build Coastguard Worker 				uint32_t found[2];
491*d83cc019SAndroid Build Coastguard Worker 
492*d83cc019SAndroid Build Coastguard Worker 				found[0] = READ_ONCE(gtt[0][x]);
493*d83cc019SAndroid Build Coastguard Worker 				found[1] = READ_ONCE(gtt[1][x]);
494*d83cc019SAndroid Build Coastguard Worker 
495*d83cc019SAndroid Build Coastguard Worker 				if (found[0] != expected ||
496*d83cc019SAndroid Build Coastguard Worker 				    found[1] != expected) {
497*d83cc019SAndroid Build Coastguard Worker 					igt_warn("child[%d] found (%x, %x), expecting %x\n",
498*d83cc019SAndroid Build Coastguard Worker 						 child,
499*d83cc019SAndroid Build Coastguard Worker 						 found[0], found[1],
500*d83cc019SAndroid Build Coastguard Worker 						 expected);
501*d83cc019SAndroid Build Coastguard Worker 					control->error = true;
502*d83cc019SAndroid Build Coastguard Worker 					exit(0);
503*d83cc019SAndroid Build Coastguard Worker 				}
504*d83cc019SAndroid Build Coastguard Worker 
505*d83cc019SAndroid Build Coastguard Worker 				gtt[0][x] = patterns[next_pattern];
506*d83cc019SAndroid Build Coastguard Worker 				gtt[1][x] = patterns[next_pattern];
507*d83cc019SAndroid Build Coastguard Worker 			}
508*d83cc019SAndroid Build Coastguard Worker 
509*d83cc019SAndroid Build Coastguard Worker 			last_pattern = next_pattern;
510*d83cc019SAndroid Build Coastguard Worker 			next_pattern = (next_pattern + 1) % ARRAY_SIZE(patterns);
511*d83cc019SAndroid Build Coastguard Worker 		}
512*d83cc019SAndroid Build Coastguard Worker 	}
513*d83cc019SAndroid Build Coastguard Worker 
514*d83cc019SAndroid Build Coastguard Worker 	count = 0;
515*d83cc019SAndroid Build Coastguard Worker 	dir = igt_debugfs_dir(fd);
516*d83cc019SAndroid Build Coastguard Worker 	igt_until_timeout(5) {
517*d83cc019SAndroid Build Coastguard Worker 		igt_sysfs_set(dir, "i915_wedged", "-1");
518*d83cc019SAndroid Build Coastguard Worker 		if (READ_ONCE(control->error))
519*d83cc019SAndroid Build Coastguard Worker 			break;
520*d83cc019SAndroid Build Coastguard Worker 		count++;
521*d83cc019SAndroid Build Coastguard Worker 	}
522*d83cc019SAndroid Build Coastguard Worker 	close(dir);
523*d83cc019SAndroid Build Coastguard Worker 	igt_info("%lu resets\n", count);
524*d83cc019SAndroid Build Coastguard Worker 
525*d83cc019SAndroid Build Coastguard Worker 	control->done = true;
526*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren_timeout(2, NULL);
527*d83cc019SAndroid Build Coastguard Worker 
528*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!control->error);
529*d83cc019SAndroid Build Coastguard Worker 	munmap(control, 4096);
530*d83cc019SAndroid Build Coastguard Worker 
531*d83cc019SAndroid Build Coastguard Worker 	igt_disallow_hang(fd, hang);
532*d83cc019SAndroid Build Coastguard Worker }
533*d83cc019SAndroid Build Coastguard Worker 
min_tile_width(uint32_t devid,int tiling)534*d83cc019SAndroid Build Coastguard Worker static int min_tile_width(uint32_t devid, int tiling)
535*d83cc019SAndroid Build Coastguard Worker {
536*d83cc019SAndroid Build Coastguard Worker 	if (tiling < 0) {
537*d83cc019SAndroid Build Coastguard Worker 		if (intel_gen(devid) >= 4)
538*d83cc019SAndroid Build Coastguard Worker 			return 4096 - min_tile_width(devid, -tiling);
539*d83cc019SAndroid Build Coastguard Worker 		else
540*d83cc019SAndroid Build Coastguard Worker 			return 1024;
541*d83cc019SAndroid Build Coastguard Worker 
542*d83cc019SAndroid Build Coastguard Worker 	}
543*d83cc019SAndroid Build Coastguard Worker 
544*d83cc019SAndroid Build Coastguard Worker 	if (intel_gen(devid) == 2)
545*d83cc019SAndroid Build Coastguard Worker 		return 128;
546*d83cc019SAndroid Build Coastguard Worker 	else if (tiling == I915_TILING_X)
547*d83cc019SAndroid Build Coastguard Worker 		return 512;
548*d83cc019SAndroid Build Coastguard Worker 	else if (IS_915(devid))
549*d83cc019SAndroid Build Coastguard Worker 		return 512;
550*d83cc019SAndroid Build Coastguard Worker 	else
551*d83cc019SAndroid Build Coastguard Worker 		return 128;
552*d83cc019SAndroid Build Coastguard Worker }
553*d83cc019SAndroid Build Coastguard Worker 
max_tile_width(uint32_t devid,int tiling)554*d83cc019SAndroid Build Coastguard Worker static int max_tile_width(uint32_t devid, int tiling)
555*d83cc019SAndroid Build Coastguard Worker {
556*d83cc019SAndroid Build Coastguard Worker 	if (tiling < 0) {
557*d83cc019SAndroid Build Coastguard Worker 		if (intel_gen(devid) >= 4)
558*d83cc019SAndroid Build Coastguard Worker 			return 4096 + min_tile_width(devid, -tiling);
559*d83cc019SAndroid Build Coastguard Worker 		else
560*d83cc019SAndroid Build Coastguard Worker 			return 2048;
561*d83cc019SAndroid Build Coastguard Worker 	}
562*d83cc019SAndroid Build Coastguard Worker 
563*d83cc019SAndroid Build Coastguard Worker 	if (intel_gen(devid) >= 7)
564*d83cc019SAndroid Build Coastguard Worker 		return 256 << 10;
565*d83cc019SAndroid Build Coastguard Worker 	else if (intel_gen(devid) >= 4)
566*d83cc019SAndroid Build Coastguard Worker 		return 128 << 10;
567*d83cc019SAndroid Build Coastguard Worker 	else
568*d83cc019SAndroid Build Coastguard Worker 		return 8 << 10;
569*d83cc019SAndroid Build Coastguard Worker }
570*d83cc019SAndroid Build Coastguard Worker 
known_swizzling(int fd,uint32_t handle)571*d83cc019SAndroid Build Coastguard Worker static bool known_swizzling(int fd, uint32_t handle)
572*d83cc019SAndroid Build Coastguard Worker {
573*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_get_tiling2 {
574*d83cc019SAndroid Build Coastguard Worker 		uint32_t handle;
575*d83cc019SAndroid Build Coastguard Worker 		uint32_t tiling_mode;
576*d83cc019SAndroid Build Coastguard Worker 		uint32_t swizzle_mode;
577*d83cc019SAndroid Build Coastguard Worker 		uint32_t phys_swizzle_mode;
578*d83cc019SAndroid Build Coastguard Worker 	} arg = {
579*d83cc019SAndroid Build Coastguard Worker 		.handle = handle,
580*d83cc019SAndroid Build Coastguard Worker 	};
581*d83cc019SAndroid Build Coastguard Worker #define DRM_IOCTL_I915_GEM_GET_TILING2	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling2)
582*d83cc019SAndroid Build Coastguard Worker 
583*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_GET_TILING2, &arg))
584*d83cc019SAndroid Build Coastguard Worker 		return false;
585*d83cc019SAndroid Build Coastguard Worker 
586*d83cc019SAndroid Build Coastguard Worker 	return arg.phys_swizzle_mode == arg.swizzle_mode;
587*d83cc019SAndroid Build Coastguard Worker }
588*d83cc019SAndroid Build Coastguard Worker 
589*d83cc019SAndroid Build Coastguard Worker static void
test_huge_bo(int fd,int huge,int tiling)590*d83cc019SAndroid Build Coastguard Worker test_huge_bo(int fd, int huge, int tiling)
591*d83cc019SAndroid Build Coastguard Worker {
592*d83cc019SAndroid Build Coastguard Worker 	uint32_t bo;
593*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
594*d83cc019SAndroid Build Coastguard Worker 	char *tiled_pattern;
595*d83cc019SAndroid Build Coastguard Worker 	char *linear_pattern;
596*d83cc019SAndroid Build Coastguard Worker 	uint64_t size, last_offset;
597*d83cc019SAndroid Build Coastguard Worker 	uint32_t devid = intel_get_drm_devid(fd);
598*d83cc019SAndroid Build Coastguard Worker 	int pitch = min_tile_width(devid, tiling);
599*d83cc019SAndroid Build Coastguard Worker 	int i;
600*d83cc019SAndroid Build Coastguard Worker 
601*d83cc019SAndroid Build Coastguard Worker 	switch (huge) {
602*d83cc019SAndroid Build Coastguard Worker 	case -1:
603*d83cc019SAndroid Build Coastguard Worker 		size = gem_mappable_aperture_size() / 2;
604*d83cc019SAndroid Build Coastguard Worker 
605*d83cc019SAndroid Build Coastguard Worker 		/* Power of two fence size, natural fence
606*d83cc019SAndroid Build Coastguard Worker 		 * alignment, and the guard page at the end
607*d83cc019SAndroid Build Coastguard Worker 		 * gtt means that if the entire gtt is
608*d83cc019SAndroid Build Coastguard Worker 		 * mappable, we can't usually fit in a tiled
609*d83cc019SAndroid Build Coastguard Worker 		 * object half the size of the gtt. Let's use
610*d83cc019SAndroid Build Coastguard Worker 		 * a quarter size one instead.
611*d83cc019SAndroid Build Coastguard Worker 		 */
612*d83cc019SAndroid Build Coastguard Worker 		if (tiling &&
613*d83cc019SAndroid Build Coastguard Worker 		    intel_gen(intel_get_drm_devid(fd)) < 4 &&
614*d83cc019SAndroid Build Coastguard Worker 		    size >= gem_global_aperture_size(fd) / 2)
615*d83cc019SAndroid Build Coastguard Worker 			size /= 2;
616*d83cc019SAndroid Build Coastguard Worker 		break;
617*d83cc019SAndroid Build Coastguard Worker 	case 0:
618*d83cc019SAndroid Build Coastguard Worker 		size = gem_mappable_aperture_size() + PAGE_SIZE;
619*d83cc019SAndroid Build Coastguard Worker 		break;
620*d83cc019SAndroid Build Coastguard Worker 	default:
621*d83cc019SAndroid Build Coastguard Worker 		size = gem_global_aperture_size(fd) + PAGE_SIZE;
622*d83cc019SAndroid Build Coastguard Worker 		break;
623*d83cc019SAndroid Build Coastguard Worker 	}
624*d83cc019SAndroid Build Coastguard Worker 	intel_require_memory(1, size, CHECK_RAM);
625*d83cc019SAndroid Build Coastguard Worker 
626*d83cc019SAndroid Build Coastguard Worker 	last_offset = size - PAGE_SIZE;
627*d83cc019SAndroid Build Coastguard Worker 
628*d83cc019SAndroid Build Coastguard Worker 	/* Create pattern */
629*d83cc019SAndroid Build Coastguard Worker 	bo = gem_create(fd, PAGE_SIZE);
630*d83cc019SAndroid Build Coastguard Worker 	if (tiling)
631*d83cc019SAndroid Build Coastguard Worker 		igt_require(__gem_set_tiling(fd, bo, tiling, pitch) == 0);
632*d83cc019SAndroid Build Coastguard Worker 	igt_require(known_swizzling(fd, bo));
633*d83cc019SAndroid Build Coastguard Worker 
634*d83cc019SAndroid Build Coastguard Worker 	linear_pattern = gem_mmap__gtt(fd, bo, PAGE_SIZE,
635*d83cc019SAndroid Build Coastguard Worker 				       PROT_READ | PROT_WRITE);
636*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < PAGE_SIZE; i++)
637*d83cc019SAndroid Build Coastguard Worker 		linear_pattern[i] = i;
638*d83cc019SAndroid Build Coastguard Worker 	tiled_pattern = gem_mmap__cpu(fd, bo, 0, PAGE_SIZE, PROT_READ);
639*d83cc019SAndroid Build Coastguard Worker 
640*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, bo, I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT, 0);
641*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, bo);
642*d83cc019SAndroid Build Coastguard Worker 
643*d83cc019SAndroid Build Coastguard Worker 	bo = gem_create(fd, size);
644*d83cc019SAndroid Build Coastguard Worker 	if (tiling)
645*d83cc019SAndroid Build Coastguard Worker 		igt_require(__gem_set_tiling(fd, bo, tiling, pitch) == 0);
646*d83cc019SAndroid Build Coastguard Worker 
647*d83cc019SAndroid Build Coastguard Worker 	/* Initialise first/last page through CPU mmap */
648*d83cc019SAndroid Build Coastguard Worker 	ptr = gem_mmap__cpu(fd, bo, 0, size, PROT_READ | PROT_WRITE);
649*d83cc019SAndroid Build Coastguard Worker 	memcpy(ptr, tiled_pattern, PAGE_SIZE);
650*d83cc019SAndroid Build Coastguard Worker 	memcpy(ptr + last_offset, tiled_pattern, PAGE_SIZE);
651*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, size);
652*d83cc019SAndroid Build Coastguard Worker 
653*d83cc019SAndroid Build Coastguard Worker 	/* Obtain mapping for the object through GTT. */
654*d83cc019SAndroid Build Coastguard Worker 	ptr = __gem_mmap__gtt(fd, bo, size, PROT_READ | PROT_WRITE);
655*d83cc019SAndroid Build Coastguard Worker 	igt_require_f(ptr, "Huge BO GTT mapping not supported.\n");
656*d83cc019SAndroid Build Coastguard Worker 
657*d83cc019SAndroid Build Coastguard Worker 	set_domain_gtt(fd, bo);
658*d83cc019SAndroid Build Coastguard Worker 
659*d83cc019SAndroid Build Coastguard Worker 	/* Access through GTT should still provide the CPU written values. */
660*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr              , linear_pattern, PAGE_SIZE) == 0);
661*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr + last_offset, linear_pattern, PAGE_SIZE) == 0);
662*d83cc019SAndroid Build Coastguard Worker 
663*d83cc019SAndroid Build Coastguard Worker 	gem_set_tiling(fd, bo, I915_TILING_NONE, 0);
664*d83cc019SAndroid Build Coastguard Worker 
665*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr              , tiled_pattern, PAGE_SIZE) == 0);
666*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr + last_offset, tiled_pattern, PAGE_SIZE) == 0);
667*d83cc019SAndroid Build Coastguard Worker 
668*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, size);
669*d83cc019SAndroid Build Coastguard Worker 
670*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, bo);
671*d83cc019SAndroid Build Coastguard Worker 	munmap(tiled_pattern, PAGE_SIZE);
672*d83cc019SAndroid Build Coastguard Worker 	munmap(linear_pattern, PAGE_SIZE);
673*d83cc019SAndroid Build Coastguard Worker }
674*d83cc019SAndroid Build Coastguard Worker 
copy_wc_page(void * dst,const void * src)675*d83cc019SAndroid Build Coastguard Worker static void copy_wc_page(void *dst, const void *src)
676*d83cc019SAndroid Build Coastguard Worker {
677*d83cc019SAndroid Build Coastguard Worker 	igt_memcpy_from_wc(dst, src, PAGE_SIZE);
678*d83cc019SAndroid Build Coastguard Worker }
679*d83cc019SAndroid Build Coastguard Worker 
tile_row_size(int tiling,unsigned int stride)680*d83cc019SAndroid Build Coastguard Worker static unsigned int tile_row_size(int tiling, unsigned int stride)
681*d83cc019SAndroid Build Coastguard Worker {
682*d83cc019SAndroid Build Coastguard Worker 	if (tiling < 0)
683*d83cc019SAndroid Build Coastguard Worker 		tiling = -tiling;
684*d83cc019SAndroid Build Coastguard Worker 
685*d83cc019SAndroid Build Coastguard Worker 	return stride * (tiling == I915_TILING_Y ? 32 : 8);
686*d83cc019SAndroid Build Coastguard Worker }
687*d83cc019SAndroid Build Coastguard Worker 
688*d83cc019SAndroid Build Coastguard Worker #define rounddown(x, y) (x - (x%y))
689*d83cc019SAndroid Build Coastguard Worker 
690*d83cc019SAndroid Build Coastguard Worker static void
test_huge_copy(int fd,int huge,int tiling_a,int tiling_b,int ncpus)691*d83cc019SAndroid Build Coastguard Worker test_huge_copy(int fd, int huge, int tiling_a, int tiling_b, int ncpus)
692*d83cc019SAndroid Build Coastguard Worker {
693*d83cc019SAndroid Build Coastguard Worker 	const uint32_t devid = intel_get_drm_devid(fd);
694*d83cc019SAndroid Build Coastguard Worker 	uint64_t huge_object_size, i;
695*d83cc019SAndroid Build Coastguard Worker 	unsigned mode = CHECK_RAM;
696*d83cc019SAndroid Build Coastguard Worker 
697*d83cc019SAndroid Build Coastguard Worker 	igt_fail_on_f(intel_gen(devid) >= 11 && ncpus > 1,
698*d83cc019SAndroid Build Coastguard Worker 		      "Please adjust your expectations, https://bugs.freedesktop.org/show_bug.cgi?id=110882\n");
699*d83cc019SAndroid Build Coastguard Worker 
700*d83cc019SAndroid Build Coastguard Worker 	switch (huge) {
701*d83cc019SAndroid Build Coastguard Worker 	case -2:
702*d83cc019SAndroid Build Coastguard Worker 		huge_object_size = gem_mappable_aperture_size() / 4;
703*d83cc019SAndroid Build Coastguard Worker 		break;
704*d83cc019SAndroid Build Coastguard Worker 	case -1:
705*d83cc019SAndroid Build Coastguard Worker 		huge_object_size = gem_mappable_aperture_size() / 2;
706*d83cc019SAndroid Build Coastguard Worker 		break;
707*d83cc019SAndroid Build Coastguard Worker 	case 0:
708*d83cc019SAndroid Build Coastguard Worker 		huge_object_size = gem_mappable_aperture_size() + PAGE_SIZE;
709*d83cc019SAndroid Build Coastguard Worker 		break;
710*d83cc019SAndroid Build Coastguard Worker 	case 1:
711*d83cc019SAndroid Build Coastguard Worker 		huge_object_size = gem_global_aperture_size(fd) + PAGE_SIZE;
712*d83cc019SAndroid Build Coastguard Worker 		break;
713*d83cc019SAndroid Build Coastguard Worker 	default:
714*d83cc019SAndroid Build Coastguard Worker 		huge_object_size = (intel_get_total_ram_mb() << 19) + PAGE_SIZE;
715*d83cc019SAndroid Build Coastguard Worker 		mode |= CHECK_SWAP;
716*d83cc019SAndroid Build Coastguard Worker 		break;
717*d83cc019SAndroid Build Coastguard Worker 	}
718*d83cc019SAndroid Build Coastguard Worker 	intel_require_memory(2*ncpus, huge_object_size, mode);
719*d83cc019SAndroid Build Coastguard Worker 
720*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, ncpus) {
721*d83cc019SAndroid Build Coastguard Worker 		uint64_t valid_size = huge_object_size;
722*d83cc019SAndroid Build Coastguard Worker 		uint32_t bo[2];
723*d83cc019SAndroid Build Coastguard Worker 		char *a, *b;
724*d83cc019SAndroid Build Coastguard Worker 
725*d83cc019SAndroid Build Coastguard Worker 		bo[0] = gem_create(fd, huge_object_size);
726*d83cc019SAndroid Build Coastguard Worker 		if (tiling_a) {
727*d83cc019SAndroid Build Coastguard Worker 			igt_require(__gem_set_tiling(fd, bo[0], abs(tiling_a), min_tile_width(devid, tiling_a)) == 0);
728*d83cc019SAndroid Build Coastguard Worker 			valid_size = rounddown(valid_size, tile_row_size(tiling_a, min_tile_width(devid, tiling_a)));
729*d83cc019SAndroid Build Coastguard Worker 		}
730*d83cc019SAndroid Build Coastguard Worker 		a = __gem_mmap__gtt(fd, bo[0], huge_object_size, PROT_READ | PROT_WRITE);
731*d83cc019SAndroid Build Coastguard Worker 		igt_require(a);
732*d83cc019SAndroid Build Coastguard Worker 
733*d83cc019SAndroid Build Coastguard Worker 		bo[1] = gem_create(fd, huge_object_size);
734*d83cc019SAndroid Build Coastguard Worker 		if (tiling_b) {
735*d83cc019SAndroid Build Coastguard Worker 			igt_require(__gem_set_tiling(fd, bo[1], abs(tiling_b), max_tile_width(devid, tiling_b)) == 0);
736*d83cc019SAndroid Build Coastguard Worker 			valid_size = rounddown(valid_size, tile_row_size(tiling_b, max_tile_width(devid, tiling_b)));
737*d83cc019SAndroid Build Coastguard Worker 		}
738*d83cc019SAndroid Build Coastguard Worker 		b = __gem_mmap__gtt(fd, bo[1], huge_object_size, PROT_READ | PROT_WRITE);
739*d83cc019SAndroid Build Coastguard Worker 		igt_require(b);
740*d83cc019SAndroid Build Coastguard Worker 
741*d83cc019SAndroid Build Coastguard Worker 		gem_set_domain(fd, bo[0], I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
742*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < valid_size / PAGE_SIZE; i++) {
743*d83cc019SAndroid Build Coastguard Worker 			uint32_t *ptr = (uint32_t *)(a + PAGE_SIZE*i);
744*d83cc019SAndroid Build Coastguard Worker 			for (int j = 0; j < PAGE_SIZE/4; j++)
745*d83cc019SAndroid Build Coastguard Worker 				ptr[j] = i + j;
746*d83cc019SAndroid Build Coastguard Worker 			igt_progress("Writing a ", i, valid_size / PAGE_SIZE);
747*d83cc019SAndroid Build Coastguard Worker 		}
748*d83cc019SAndroid Build Coastguard Worker 
749*d83cc019SAndroid Build Coastguard Worker 		gem_set_domain(fd, bo[1], I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
750*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < valid_size / PAGE_SIZE; i++) {
751*d83cc019SAndroid Build Coastguard Worker 			uint32_t *ptr = (uint32_t *)(b + PAGE_SIZE*i);
752*d83cc019SAndroid Build Coastguard Worker 			for (int j = 0; j < PAGE_SIZE/4; j++)
753*d83cc019SAndroid Build Coastguard Worker 				ptr[j] = ~(i + j);
754*d83cc019SAndroid Build Coastguard Worker 			igt_progress("Writing b ", i, valid_size / PAGE_SIZE);
755*d83cc019SAndroid Build Coastguard Worker 		}
756*d83cc019SAndroid Build Coastguard Worker 
757*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < valid_size / PAGE_SIZE; i++) {
758*d83cc019SAndroid Build Coastguard Worker 			uint32_t *A = (uint32_t *)(a + PAGE_SIZE*i);
759*d83cc019SAndroid Build Coastguard Worker 			uint32_t *B = (uint32_t *)(b + PAGE_SIZE*i);
760*d83cc019SAndroid Build Coastguard Worker 			uint32_t A_tmp[PAGE_SIZE/sizeof(uint32_t)];
761*d83cc019SAndroid Build Coastguard Worker 			uint32_t B_tmp[PAGE_SIZE/sizeof(uint32_t)];
762*d83cc019SAndroid Build Coastguard Worker 
763*d83cc019SAndroid Build Coastguard Worker 			copy_wc_page(A_tmp, A);
764*d83cc019SAndroid Build Coastguard Worker 			copy_wc_page(B_tmp, B);
765*d83cc019SAndroid Build Coastguard Worker 			for (int j = 0; j < PAGE_SIZE/4; j++)
766*d83cc019SAndroid Build Coastguard Worker 				if ((i +  j) & 1)
767*d83cc019SAndroid Build Coastguard Worker 					A_tmp[j] = B_tmp[j];
768*d83cc019SAndroid Build Coastguard Worker 				else
769*d83cc019SAndroid Build Coastguard Worker 					B_tmp[j] = A_tmp[j];
770*d83cc019SAndroid Build Coastguard Worker 
771*d83cc019SAndroid Build Coastguard Worker 			gem_set_domain(fd, bo[0], I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
772*d83cc019SAndroid Build Coastguard Worker 			memcpy(A, A_tmp, PAGE_SIZE);
773*d83cc019SAndroid Build Coastguard Worker 
774*d83cc019SAndroid Build Coastguard Worker 			gem_set_domain(fd, bo[1], I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
775*d83cc019SAndroid Build Coastguard Worker 			memcpy(B, B_tmp, PAGE_SIZE);
776*d83cc019SAndroid Build Coastguard Worker 
777*d83cc019SAndroid Build Coastguard Worker 			igt_progress("Copying a<->b ", i, valid_size / PAGE_SIZE);
778*d83cc019SAndroid Build Coastguard Worker 		}
779*d83cc019SAndroid Build Coastguard Worker 
780*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, bo[0]);
781*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, bo[1]);
782*d83cc019SAndroid Build Coastguard Worker 
783*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < valid_size / PAGE_SIZE; i++) {
784*d83cc019SAndroid Build Coastguard Worker 			uint32_t page[PAGE_SIZE/sizeof(uint32_t)];
785*d83cc019SAndroid Build Coastguard Worker 			copy_wc_page(page, a + PAGE_SIZE*i);
786*d83cc019SAndroid Build Coastguard Worker 			for (int j = 0; j < PAGE_SIZE/sizeof(uint32_t); j++)
787*d83cc019SAndroid Build Coastguard Worker 				if ((i + j) & 1)
788*d83cc019SAndroid Build Coastguard Worker 					igt_assert_eq_u32(page[j], ~(i + j));
789*d83cc019SAndroid Build Coastguard Worker 				else
790*d83cc019SAndroid Build Coastguard Worker 					igt_assert_eq_u32(page[j], i + j);
791*d83cc019SAndroid Build Coastguard Worker 			igt_progress("Checking a ", i, valid_size / PAGE_SIZE);
792*d83cc019SAndroid Build Coastguard Worker 		}
793*d83cc019SAndroid Build Coastguard Worker 		munmap(a, huge_object_size);
794*d83cc019SAndroid Build Coastguard Worker 
795*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < valid_size / PAGE_SIZE; i++) {
796*d83cc019SAndroid Build Coastguard Worker 			uint32_t page[PAGE_SIZE/sizeof(uint32_t)];
797*d83cc019SAndroid Build Coastguard Worker 			copy_wc_page(page, b + PAGE_SIZE*i);
798*d83cc019SAndroid Build Coastguard Worker 			for (int j = 0; j < PAGE_SIZE/sizeof(uint32_t); j++)
799*d83cc019SAndroid Build Coastguard Worker 				if ((i + j) & 1)
800*d83cc019SAndroid Build Coastguard Worker 					igt_assert_eq_u32(page[j], ~(i + j));
801*d83cc019SAndroid Build Coastguard Worker 				else
802*d83cc019SAndroid Build Coastguard Worker 					igt_assert_eq_u32(page[j], i + j);
803*d83cc019SAndroid Build Coastguard Worker 			igt_progress("Checking b ", i, valid_size / PAGE_SIZE);
804*d83cc019SAndroid Build Coastguard Worker 		}
805*d83cc019SAndroid Build Coastguard Worker 		munmap(b, huge_object_size);
806*d83cc019SAndroid Build Coastguard Worker 	}
807*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren();
808*d83cc019SAndroid Build Coastguard Worker }
809*d83cc019SAndroid Build Coastguard Worker 
810*d83cc019SAndroid Build Coastguard Worker static void
test_read(int fd)811*d83cc019SAndroid Build Coastguard Worker test_read(int fd)
812*d83cc019SAndroid Build Coastguard Worker {
813*d83cc019SAndroid Build Coastguard Worker 	void *dst;
814*d83cc019SAndroid Build Coastguard Worker 	uint32_t src;
815*d83cc019SAndroid Build Coastguard Worker 
816*d83cc019SAndroid Build Coastguard Worker 	/* copy from a fresh src to fresh dst to force pagefault on both */
817*d83cc019SAndroid Build Coastguard Worker 	dst = create_pointer(fd);
818*d83cc019SAndroid Build Coastguard Worker 	src = gem_create(fd, OBJECT_SIZE);
819*d83cc019SAndroid Build Coastguard Worker 
820*d83cc019SAndroid Build Coastguard Worker 	gem_read(fd, src, 0, dst, OBJECT_SIZE);
821*d83cc019SAndroid Build Coastguard Worker 
822*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, src);
823*d83cc019SAndroid Build Coastguard Worker 	munmap(dst, OBJECT_SIZE);
824*d83cc019SAndroid Build Coastguard Worker }
825*d83cc019SAndroid Build Coastguard Worker 
826*d83cc019SAndroid Build Coastguard Worker static void
test_write_cpu_read_gtt(int fd)827*d83cc019SAndroid Build Coastguard Worker test_write_cpu_read_gtt(int fd)
828*d83cc019SAndroid Build Coastguard Worker {
829*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
830*d83cc019SAndroid Build Coastguard Worker 	uint32_t *src, *dst;
831*d83cc019SAndroid Build Coastguard Worker 
832*d83cc019SAndroid Build Coastguard Worker 	igt_require(gem_has_llc(fd));
833*d83cc019SAndroid Build Coastguard Worker 
834*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, OBJECT_SIZE);
835*d83cc019SAndroid Build Coastguard Worker 
836*d83cc019SAndroid Build Coastguard Worker 	dst = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ);
837*d83cc019SAndroid Build Coastguard Worker 
838*d83cc019SAndroid Build Coastguard Worker 	src = gem_mmap__cpu(fd, handle, 0, OBJECT_SIZE, PROT_WRITE);
839*d83cc019SAndroid Build Coastguard Worker 
840*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
841*d83cc019SAndroid Build Coastguard Worker 
842*d83cc019SAndroid Build Coastguard Worker 	memset(src, 0xaa, OBJECT_SIZE);
843*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(dst, src, OBJECT_SIZE) == 0);
844*d83cc019SAndroid Build Coastguard Worker 
845*d83cc019SAndroid Build Coastguard Worker 	munmap(src, OBJECT_SIZE);
846*d83cc019SAndroid Build Coastguard Worker 	munmap(dst, OBJECT_SIZE);
847*d83cc019SAndroid Build Coastguard Worker }
848*d83cc019SAndroid Build Coastguard Worker 
849*d83cc019SAndroid Build Coastguard Worker struct thread_fault_concurrent {
850*d83cc019SAndroid Build Coastguard Worker 	pthread_t thread;
851*d83cc019SAndroid Build Coastguard Worker 	int id;
852*d83cc019SAndroid Build Coastguard Worker 	uint32_t **ptr;
853*d83cc019SAndroid Build Coastguard Worker };
854*d83cc019SAndroid Build Coastguard Worker 
855*d83cc019SAndroid Build Coastguard Worker static void *
thread_fault_concurrent(void * closure)856*d83cc019SAndroid Build Coastguard Worker thread_fault_concurrent(void *closure)
857*d83cc019SAndroid Build Coastguard Worker {
858*d83cc019SAndroid Build Coastguard Worker 	struct thread_fault_concurrent *t = closure;
859*d83cc019SAndroid Build Coastguard Worker 	uint32_t val = 0;
860*d83cc019SAndroid Build Coastguard Worker 	int n;
861*d83cc019SAndroid Build Coastguard Worker 
862*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < 32; n++) {
863*d83cc019SAndroid Build Coastguard Worker 		if (n & 1)
864*d83cc019SAndroid Build Coastguard Worker 			*t->ptr[(n + t->id) % 32] = val;
865*d83cc019SAndroid Build Coastguard Worker 		else
866*d83cc019SAndroid Build Coastguard Worker 			val = *t->ptr[(n + t->id) % 32];
867*d83cc019SAndroid Build Coastguard Worker 	}
868*d83cc019SAndroid Build Coastguard Worker 
869*d83cc019SAndroid Build Coastguard Worker 	return NULL;
870*d83cc019SAndroid Build Coastguard Worker }
871*d83cc019SAndroid Build Coastguard Worker 
872*d83cc019SAndroid Build Coastguard Worker static void
test_fault_concurrent(int fd)873*d83cc019SAndroid Build Coastguard Worker test_fault_concurrent(int fd)
874*d83cc019SAndroid Build Coastguard Worker {
875*d83cc019SAndroid Build Coastguard Worker 	uint32_t *ptr[32];
876*d83cc019SAndroid Build Coastguard Worker 	struct thread_fault_concurrent thread[64];
877*d83cc019SAndroid Build Coastguard Worker 	int n;
878*d83cc019SAndroid Build Coastguard Worker 
879*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < 32; n++) {
880*d83cc019SAndroid Build Coastguard Worker 		ptr[n] = create_pointer(fd);
881*d83cc019SAndroid Build Coastguard Worker 	}
882*d83cc019SAndroid Build Coastguard Worker 
883*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < 64; n++) {
884*d83cc019SAndroid Build Coastguard Worker 		thread[n].ptr = ptr;
885*d83cc019SAndroid Build Coastguard Worker 		thread[n].id = n;
886*d83cc019SAndroid Build Coastguard Worker 		pthread_create(&thread[n].thread, NULL, thread_fault_concurrent, &thread[n]);
887*d83cc019SAndroid Build Coastguard Worker 	}
888*d83cc019SAndroid Build Coastguard Worker 
889*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < 64; n++)
890*d83cc019SAndroid Build Coastguard Worker 		pthread_join(thread[n].thread, NULL);
891*d83cc019SAndroid Build Coastguard Worker 
892*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < 32; n++) {
893*d83cc019SAndroid Build Coastguard Worker 		munmap(ptr[n], OBJECT_SIZE);
894*d83cc019SAndroid Build Coastguard Worker 	}
895*d83cc019SAndroid Build Coastguard Worker }
896*d83cc019SAndroid Build Coastguard Worker 
897*d83cc019SAndroid Build Coastguard Worker static void
run_without_prefault(int fd,void (* func)(int fd))898*d83cc019SAndroid Build Coastguard Worker run_without_prefault(int fd,
899*d83cc019SAndroid Build Coastguard Worker 			void (*func)(int fd))
900*d83cc019SAndroid Build Coastguard Worker {
901*d83cc019SAndroid Build Coastguard Worker 	igt_disable_prefault();
902*d83cc019SAndroid Build Coastguard Worker 	func(fd);
903*d83cc019SAndroid Build Coastguard Worker 	igt_enable_prefault();
904*d83cc019SAndroid Build Coastguard Worker }
905*d83cc019SAndroid Build Coastguard Worker 
mmap_ioctl(int i915,struct drm_i915_gem_mmap_gtt * arg)906*d83cc019SAndroid Build Coastguard Worker static int mmap_ioctl(int i915, struct drm_i915_gem_mmap_gtt *arg)
907*d83cc019SAndroid Build Coastguard Worker {
908*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
909*d83cc019SAndroid Build Coastguard Worker 
910*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_GTT, arg))
911*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
912*d83cc019SAndroid Build Coastguard Worker 
913*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
914*d83cc019SAndroid Build Coastguard Worker 	return err;
915*d83cc019SAndroid Build Coastguard Worker }
916*d83cc019SAndroid Build Coastguard Worker 
917*d83cc019SAndroid Build Coastguard Worker int fd;
918*d83cc019SAndroid Build Coastguard Worker 
919*d83cc019SAndroid Build Coastguard Worker igt_main
920*d83cc019SAndroid Build Coastguard Worker {
921*d83cc019SAndroid Build Coastguard Worker 	if (igt_run_in_simulation())
922*d83cc019SAndroid Build Coastguard Worker 		OBJECT_SIZE = 1 * 1024 * 1024;
923*d83cc019SAndroid Build Coastguard Worker 
924*d83cc019SAndroid Build Coastguard Worker 	igt_fixture
925*d83cc019SAndroid Build Coastguard Worker 		fd = drm_open_driver(DRIVER_INTEL);
926*d83cc019SAndroid Build Coastguard Worker 
927*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("bad-object") {
928*d83cc019SAndroid Build Coastguard Worker 		uint32_t real_handle = gem_create(fd, 4096);
929*d83cc019SAndroid Build Coastguard Worker 		uint32_t handles[20];
930*d83cc019SAndroid Build Coastguard Worker 		size_t i = 0, len;
931*d83cc019SAndroid Build Coastguard Worker 
932*d83cc019SAndroid Build Coastguard Worker 		handles[i++] = 0xdeadbeef;
933*d83cc019SAndroid Build Coastguard Worker 		for(int bit = 0; bit < 16; bit++)
934*d83cc019SAndroid Build Coastguard Worker 			handles[i++] = real_handle | (1 << (bit + 16));
935*d83cc019SAndroid Build Coastguard Worker 		handles[i++] = real_handle + 1;
936*d83cc019SAndroid Build Coastguard Worker 		len = i;
937*d83cc019SAndroid Build Coastguard Worker 
938*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < len; ++i) {
939*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_mmap_gtt arg = {
940*d83cc019SAndroid Build Coastguard Worker 				.handle = handles[i],
941*d83cc019SAndroid Build Coastguard Worker 			};
942*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(mmap_ioctl(fd, &arg), -ENOENT);
943*d83cc019SAndroid Build Coastguard Worker 		}
944*d83cc019SAndroid Build Coastguard Worker 
945*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, real_handle);
946*d83cc019SAndroid Build Coastguard Worker 	}
947*d83cc019SAndroid Build Coastguard Worker 
948*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic")
949*d83cc019SAndroid Build Coastguard Worker 		test_access(fd);
950*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-short")
951*d83cc019SAndroid Build Coastguard Worker 		test_short(fd);
952*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-copy")
953*d83cc019SAndroid Build Coastguard Worker 		test_copy(fd);
954*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-read")
955*d83cc019SAndroid Build Coastguard Worker 		test_read(fd);
956*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-write")
957*d83cc019SAndroid Build Coastguard Worker 		test_write(fd);
958*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-write-gtt")
959*d83cc019SAndroid Build Coastguard Worker 		test_write_gtt(fd);
960*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("coherency")
961*d83cc019SAndroid Build Coastguard Worker 		test_coherency(fd);
962*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("clflush")
963*d83cc019SAndroid Build Coastguard Worker 		test_clflush(fd);
964*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("hang")
965*d83cc019SAndroid Build Coastguard Worker 		test_hang(fd);
966*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-read-write")
967*d83cc019SAndroid Build Coastguard Worker 		test_read_write(fd, READ_BEFORE_WRITE);
968*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-write-read")
969*d83cc019SAndroid Build Coastguard Worker 		test_read_write(fd, READ_AFTER_WRITE);
970*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-read-write-distinct")
971*d83cc019SAndroid Build Coastguard Worker 		test_read_write2(fd, READ_BEFORE_WRITE);
972*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-write-read-distinct")
973*d83cc019SAndroid Build Coastguard Worker 		test_read_write2(fd, READ_AFTER_WRITE);
974*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("fault-concurrent")
975*d83cc019SAndroid Build Coastguard Worker 		test_fault_concurrent(fd);
976*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-read-no-prefault")
977*d83cc019SAndroid Build Coastguard Worker 		run_without_prefault(fd, test_read);
978*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-write-no-prefault")
979*d83cc019SAndroid Build Coastguard Worker 		run_without_prefault(fd, test_write);
980*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-write-gtt-no-prefault")
981*d83cc019SAndroid Build Coastguard Worker 		run_without_prefault(fd, test_write_gtt);
982*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-write-cpu-read-gtt")
983*d83cc019SAndroid Build Coastguard Worker 		test_write_cpu_read_gtt(fd);
984*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-wc")
985*d83cc019SAndroid Build Coastguard Worker 		test_wc(fd);
986*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("isolation")
987*d83cc019SAndroid Build Coastguard Worker 		test_isolation(fd);
988*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("pf-nonblock")
989*d83cc019SAndroid Build Coastguard Worker 		test_pf_nonblock(fd);
990*d83cc019SAndroid Build Coastguard Worker 
991*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-small-bo")
992*d83cc019SAndroid Build Coastguard Worker 		test_huge_bo(fd, -1, I915_TILING_NONE);
993*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-small-bo-tiledX")
994*d83cc019SAndroid Build Coastguard Worker 		test_huge_bo(fd, -1, I915_TILING_X);
995*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("basic-small-bo-tiledY")
996*d83cc019SAndroid Build Coastguard Worker 		test_huge_bo(fd, -1, I915_TILING_Y);
997*d83cc019SAndroid Build Coastguard Worker 
998*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("big-bo")
999*d83cc019SAndroid Build Coastguard Worker 		test_huge_bo(fd, 0, I915_TILING_NONE);
1000*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("big-bo-tiledX")
1001*d83cc019SAndroid Build Coastguard Worker 		test_huge_bo(fd, 0, I915_TILING_X);
1002*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("big-bo-tiledY")
1003*d83cc019SAndroid Build Coastguard Worker 		test_huge_bo(fd, 0, I915_TILING_Y);
1004*d83cc019SAndroid Build Coastguard Worker 
1005*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("huge-bo")
1006*d83cc019SAndroid Build Coastguard Worker 		test_huge_bo(fd, 1, I915_TILING_NONE);
1007*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("huge-bo-tiledX")
1008*d83cc019SAndroid Build Coastguard Worker 		test_huge_bo(fd, 1, I915_TILING_X);
1009*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("huge-bo-tiledY")
1010*d83cc019SAndroid Build Coastguard Worker 		test_huge_bo(fd, 1, I915_TILING_Y);
1011*d83cc019SAndroid Build Coastguard Worker 
1012*d83cc019SAndroid Build Coastguard Worker 	igt_subtest_group {
1013*d83cc019SAndroid Build Coastguard Worker 		const struct copy_size {
1014*d83cc019SAndroid Build Coastguard Worker 			const char *prefix;
1015*d83cc019SAndroid Build Coastguard Worker 			int size;
1016*d83cc019SAndroid Build Coastguard Worker 		} copy_sizes[] = {
1017*d83cc019SAndroid Build Coastguard Worker 			{ "basic-small", -2 },
1018*d83cc019SAndroid Build Coastguard Worker 			{ "medium", -1 },
1019*d83cc019SAndroid Build Coastguard Worker 			{ "big", 0 },
1020*d83cc019SAndroid Build Coastguard Worker 			{ "huge", 1 },
1021*d83cc019SAndroid Build Coastguard Worker 			{ "swap", 2 },
1022*d83cc019SAndroid Build Coastguard Worker 			{ }
1023*d83cc019SAndroid Build Coastguard Worker 		};
1024*d83cc019SAndroid Build Coastguard Worker 		const struct copy_mode {
1025*d83cc019SAndroid Build Coastguard Worker 			const char *suffix;
1026*d83cc019SAndroid Build Coastguard Worker 			int tiling_x, tiling_y;
1027*d83cc019SAndroid Build Coastguard Worker 		} copy_modes[] = {
1028*d83cc019SAndroid Build Coastguard Worker 			{ "", I915_TILING_NONE, I915_TILING_NONE},
1029*d83cc019SAndroid Build Coastguard Worker 			{ "-XY", I915_TILING_X, I915_TILING_Y},
1030*d83cc019SAndroid Build Coastguard Worker 			{ "-odd", -I915_TILING_X, -I915_TILING_Y},
1031*d83cc019SAndroid Build Coastguard Worker 			{}
1032*d83cc019SAndroid Build Coastguard Worker 		};
1033*d83cc019SAndroid Build Coastguard Worker 		const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
1034*d83cc019SAndroid Build Coastguard Worker 
1035*d83cc019SAndroid Build Coastguard Worker 		for (const struct copy_size *s = copy_sizes; s->prefix; s++)
1036*d83cc019SAndroid Build Coastguard Worker 			for (const struct copy_mode *m = copy_modes; m->suffix; m++) {
1037*d83cc019SAndroid Build Coastguard Worker 				igt_subtest_f("%s-copy%s", s->prefix, m->suffix)
1038*d83cc019SAndroid Build Coastguard Worker 					test_huge_copy(fd,
1039*d83cc019SAndroid Build Coastguard Worker 							s->size,
1040*d83cc019SAndroid Build Coastguard Worker 							m->tiling_x,
1041*d83cc019SAndroid Build Coastguard Worker 							m->tiling_y,
1042*d83cc019SAndroid Build Coastguard Worker 							1);
1043*d83cc019SAndroid Build Coastguard Worker 
1044*d83cc019SAndroid Build Coastguard Worker 				igt_subtest_f("forked-%s-copy%s", s->prefix, m->suffix)
1045*d83cc019SAndroid Build Coastguard Worker 					test_huge_copy(fd,
1046*d83cc019SAndroid Build Coastguard Worker 							s->size,
1047*d83cc019SAndroid Build Coastguard Worker 							m->tiling_x,
1048*d83cc019SAndroid Build Coastguard Worker 							m->tiling_y,
1049*d83cc019SAndroid Build Coastguard Worker 							ncpus);
1050*d83cc019SAndroid Build Coastguard Worker 			}
1051*d83cc019SAndroid Build Coastguard Worker 	}
1052*d83cc019SAndroid Build Coastguard Worker 
1053*d83cc019SAndroid Build Coastguard Worker 
1054*d83cc019SAndroid Build Coastguard Worker 	igt_fixture
1055*d83cc019SAndroid Build Coastguard Worker 		close(fd);
1056*d83cc019SAndroid Build Coastguard Worker }
1057