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