1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright © 2016 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker *
4*d83cc019SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker *
11*d83cc019SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker * Software.
14*d83cc019SAndroid Build Coastguard Worker *
15*d83cc019SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker *
23*d83cc019SAndroid Build Coastguard Worker */
24*d83cc019SAndroid Build Coastguard Worker
25*d83cc019SAndroid Build Coastguard Worker /** @file gem_shrink.c
26*d83cc019SAndroid Build Coastguard Worker *
27*d83cc019SAndroid Build Coastguard Worker * Exercise the shrinker by overallocating GEM objects
28*d83cc019SAndroid Build Coastguard Worker */
29*d83cc019SAndroid Build Coastguard Worker
30*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
31*d83cc019SAndroid Build Coastguard Worker #include "igt_gt.h"
32*d83cc019SAndroid Build Coastguard Worker #include "igt_debugfs.h"
33*d83cc019SAndroid Build Coastguard Worker #include "igt_sysfs.h"
34*d83cc019SAndroid Build Coastguard Worker
35*d83cc019SAndroid Build Coastguard Worker #ifndef MADV_FREE
36*d83cc019SAndroid Build Coastguard Worker #define MADV_FREE 8
37*d83cc019SAndroid Build Coastguard Worker #endif
38*d83cc019SAndroid Build Coastguard Worker
39*d83cc019SAndroid Build Coastguard Worker static unsigned int engines[16], nengine;
40*d83cc019SAndroid Build Coastguard Worker
get_pages(int fd,uint64_t alloc)41*d83cc019SAndroid Build Coastguard Worker static void get_pages(int fd, uint64_t alloc)
42*d83cc019SAndroid Build Coastguard Worker {
43*d83cc019SAndroid Build Coastguard Worker uint32_t handle = gem_create(fd, alloc);
44*d83cc019SAndroid Build Coastguard Worker gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, 0);
45*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, handle, I915_MADV_DONTNEED);
46*d83cc019SAndroid Build Coastguard Worker }
47*d83cc019SAndroid Build Coastguard Worker
get_pages_dirty(int fd,uint64_t alloc)48*d83cc019SAndroid Build Coastguard Worker static void get_pages_dirty(int fd, uint64_t alloc)
49*d83cc019SAndroid Build Coastguard Worker {
50*d83cc019SAndroid Build Coastguard Worker uint32_t handle = gem_create(fd, alloc);
51*d83cc019SAndroid Build Coastguard Worker gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
52*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, handle, I915_MADV_DONTNEED);
53*d83cc019SAndroid Build Coastguard Worker }
54*d83cc019SAndroid Build Coastguard Worker
pwrite_(int fd,uint64_t alloc)55*d83cc019SAndroid Build Coastguard Worker static void pwrite_(int fd, uint64_t alloc)
56*d83cc019SAndroid Build Coastguard Worker {
57*d83cc019SAndroid Build Coastguard Worker uint32_t tmp;
58*d83cc019SAndroid Build Coastguard Worker uint32_t handle = gem_create(fd, alloc);
59*d83cc019SAndroid Build Coastguard Worker for (int page = 0; page < alloc>>12; page++)
60*d83cc019SAndroid Build Coastguard Worker gem_write(fd, handle, (page + page % 4095) & ~3, &tmp, 4);
61*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, handle, I915_MADV_DONTNEED);
62*d83cc019SAndroid Build Coastguard Worker }
63*d83cc019SAndroid Build Coastguard Worker
pread_(int fd,uint64_t alloc)64*d83cc019SAndroid Build Coastguard Worker static void pread_(int fd, uint64_t alloc)
65*d83cc019SAndroid Build Coastguard Worker {
66*d83cc019SAndroid Build Coastguard Worker uint32_t tmp;
67*d83cc019SAndroid Build Coastguard Worker uint32_t handle = gem_create(fd, alloc);
68*d83cc019SAndroid Build Coastguard Worker for (int page = 0; page < alloc>>12; page++)
69*d83cc019SAndroid Build Coastguard Worker gem_read(fd, handle, (page + page % 4095) & ~3, &tmp, 4);
70*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, handle, I915_MADV_DONTNEED);
71*d83cc019SAndroid Build Coastguard Worker }
72*d83cc019SAndroid Build Coastguard Worker
mmap_gtt(int fd,uint64_t alloc)73*d83cc019SAndroid Build Coastguard Worker static void mmap_gtt(int fd, uint64_t alloc)
74*d83cc019SAndroid Build Coastguard Worker {
75*d83cc019SAndroid Build Coastguard Worker uint32_t handle = gem_create(fd, alloc);
76*d83cc019SAndroid Build Coastguard Worker uint32_t *ptr = gem_mmap__gtt(fd, handle, alloc, PROT_WRITE);
77*d83cc019SAndroid Build Coastguard Worker for (int page = 0; page < alloc>>12; page++)
78*d83cc019SAndroid Build Coastguard Worker ptr[page<<10] = 0;
79*d83cc019SAndroid Build Coastguard Worker munmap(ptr, alloc);
80*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, handle, I915_MADV_DONTNEED);
81*d83cc019SAndroid Build Coastguard Worker }
82*d83cc019SAndroid Build Coastguard Worker
mmap_cpu(int fd,uint64_t alloc)83*d83cc019SAndroid Build Coastguard Worker static void mmap_cpu(int fd, uint64_t alloc)
84*d83cc019SAndroid Build Coastguard Worker {
85*d83cc019SAndroid Build Coastguard Worker uint32_t handle = gem_create(fd, alloc);
86*d83cc019SAndroid Build Coastguard Worker uint32_t *ptr = gem_mmap__cpu(fd, handle, 0, alloc, PROT_WRITE);
87*d83cc019SAndroid Build Coastguard Worker for (int page = 0; page < alloc>>12; page++)
88*d83cc019SAndroid Build Coastguard Worker ptr[page<<10] = 0;
89*d83cc019SAndroid Build Coastguard Worker munmap(ptr, alloc);
90*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, handle, I915_MADV_DONTNEED);
91*d83cc019SAndroid Build Coastguard Worker }
92*d83cc019SAndroid Build Coastguard Worker
execbuf1(int fd,uint64_t alloc)93*d83cc019SAndroid Build Coastguard Worker static void execbuf1(int fd, uint64_t alloc)
94*d83cc019SAndroid Build Coastguard Worker {
95*d83cc019SAndroid Build Coastguard Worker const uint32_t bbe = MI_BATCH_BUFFER_END;
96*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 obj;
97*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf;
98*d83cc019SAndroid Build Coastguard Worker
99*d83cc019SAndroid Build Coastguard Worker memset(&obj, 0, sizeof(obj));
100*d83cc019SAndroid Build Coastguard Worker memset(&execbuf, 0, sizeof(execbuf));
101*d83cc019SAndroid Build Coastguard Worker execbuf.buffers_ptr = to_user_pointer(&obj);
102*d83cc019SAndroid Build Coastguard Worker execbuf.buffer_count = 1;
103*d83cc019SAndroid Build Coastguard Worker
104*d83cc019SAndroid Build Coastguard Worker obj.handle = gem_create(fd, alloc);
105*d83cc019SAndroid Build Coastguard Worker gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
106*d83cc019SAndroid Build Coastguard Worker gem_execbuf(fd, &execbuf);
107*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, obj.handle, I915_MADV_DONTNEED);
108*d83cc019SAndroid Build Coastguard Worker }
109*d83cc019SAndroid Build Coastguard Worker
110*d83cc019SAndroid Build Coastguard Worker /* Since we want to trigger oom (SIGKILL), we don't want small allocations
111*d83cc019SAndroid Build Coastguard Worker * to fail and generate a false error (SIGSEGV)! So we redirect allocations
112*d83cc019SAndroid Build Coastguard Worker * though GEM objects, which should be much more likely to trigger oom. There
113*d83cc019SAndroid Build Coastguard Worker * are still small allocations within the kernel, so still a small chance of
114*d83cc019SAndroid Build Coastguard Worker * ENOMEM instead of a full oom.
115*d83cc019SAndroid Build Coastguard Worker */
__gem_calloc(int fd,size_t count,size_t size,uint64_t * out_size)116*d83cc019SAndroid Build Coastguard Worker static void *__gem_calloc(int fd, size_t count, size_t size, uint64_t *out_size)
117*d83cc019SAndroid Build Coastguard Worker {
118*d83cc019SAndroid Build Coastguard Worker uint32_t handle;
119*d83cc019SAndroid Build Coastguard Worker uint64_t total;
120*d83cc019SAndroid Build Coastguard Worker void *ptr;
121*d83cc019SAndroid Build Coastguard Worker
122*d83cc019SAndroid Build Coastguard Worker total = count * size;
123*d83cc019SAndroid Build Coastguard Worker total = (total + 4095) & -4096;
124*d83cc019SAndroid Build Coastguard Worker
125*d83cc019SAndroid Build Coastguard Worker handle = gem_create(fd, total);
126*d83cc019SAndroid Build Coastguard Worker ptr = gem_mmap__cpu(fd, handle, 0, total, PROT_WRITE);
127*d83cc019SAndroid Build Coastguard Worker gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
128*d83cc019SAndroid Build Coastguard Worker gem_close(fd, handle);
129*d83cc019SAndroid Build Coastguard Worker
130*d83cc019SAndroid Build Coastguard Worker *out_size = total;
131*d83cc019SAndroid Build Coastguard Worker return ptr;
132*d83cc019SAndroid Build Coastguard Worker }
133*d83cc019SAndroid Build Coastguard Worker
execbufN(int fd,uint64_t alloc)134*d83cc019SAndroid Build Coastguard Worker static void execbufN(int fd, uint64_t alloc)
135*d83cc019SAndroid Build Coastguard Worker {
136*d83cc019SAndroid Build Coastguard Worker const uint32_t bbe = MI_BATCH_BUFFER_END;
137*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 *obj;
138*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf;
139*d83cc019SAndroid Build Coastguard Worker int count = alloc >> 20;
140*d83cc019SAndroid Build Coastguard Worker uint64_t obj_size;
141*d83cc019SAndroid Build Coastguard Worker
142*d83cc019SAndroid Build Coastguard Worker obj = __gem_calloc(fd, alloc + 1, sizeof(*obj), &obj_size);
143*d83cc019SAndroid Build Coastguard Worker memset(&execbuf, 0, sizeof(execbuf));
144*d83cc019SAndroid Build Coastguard Worker
145*d83cc019SAndroid Build Coastguard Worker obj[count].handle = gem_create(fd, 4096);
146*d83cc019SAndroid Build Coastguard Worker gem_write(fd, obj[count].handle, 0, &bbe, sizeof(bbe));
147*d83cc019SAndroid Build Coastguard Worker
148*d83cc019SAndroid Build Coastguard Worker for (int i = 1; i <= count; i++) {
149*d83cc019SAndroid Build Coastguard Worker int j = count - i;
150*d83cc019SAndroid Build Coastguard Worker
151*d83cc019SAndroid Build Coastguard Worker obj[j].handle = gem_create(fd, 1 << 20);
152*d83cc019SAndroid Build Coastguard Worker execbuf.buffers_ptr = to_user_pointer(&obj[j]);
153*d83cc019SAndroid Build Coastguard Worker execbuf.buffer_count = i + 1;
154*d83cc019SAndroid Build Coastguard Worker gem_execbuf(fd, &execbuf);
155*d83cc019SAndroid Build Coastguard Worker }
156*d83cc019SAndroid Build Coastguard Worker
157*d83cc019SAndroid Build Coastguard Worker for (int i = 0; i <= count; i++)
158*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, obj[i].handle, I915_MADV_DONTNEED);
159*d83cc019SAndroid Build Coastguard Worker munmap(obj, obj_size);
160*d83cc019SAndroid Build Coastguard Worker }
161*d83cc019SAndroid Build Coastguard Worker
execbufX(int fd,uint64_t alloc)162*d83cc019SAndroid Build Coastguard Worker static void execbufX(int fd, uint64_t alloc)
163*d83cc019SAndroid Build Coastguard Worker {
164*d83cc019SAndroid Build Coastguard Worker const uint32_t bbe = MI_BATCH_BUFFER_END;
165*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 *obj;
166*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf;
167*d83cc019SAndroid Build Coastguard Worker int count = alloc >> 20;
168*d83cc019SAndroid Build Coastguard Worker uint64_t obj_size;
169*d83cc019SAndroid Build Coastguard Worker
170*d83cc019SAndroid Build Coastguard Worker obj = __gem_calloc(fd, alloc + 1, sizeof(*obj), &obj_size);
171*d83cc019SAndroid Build Coastguard Worker memset(&execbuf, 0, sizeof(execbuf));
172*d83cc019SAndroid Build Coastguard Worker
173*d83cc019SAndroid Build Coastguard Worker obj[count].handle = gem_create(fd, 4096);
174*d83cc019SAndroid Build Coastguard Worker gem_write(fd, obj[count].handle, 0, &bbe, sizeof(bbe));
175*d83cc019SAndroid Build Coastguard Worker
176*d83cc019SAndroid Build Coastguard Worker for (int i = 1; i <= count; i++) {
177*d83cc019SAndroid Build Coastguard Worker int j = count - i;
178*d83cc019SAndroid Build Coastguard Worker
179*d83cc019SAndroid Build Coastguard Worker obj[j+1].flags = 0;
180*d83cc019SAndroid Build Coastguard Worker
181*d83cc019SAndroid Build Coastguard Worker obj[j].handle = gem_create(fd, 1 << 20);
182*d83cc019SAndroid Build Coastguard Worker obj[j].flags = EXEC_OBJECT_WRITE;
183*d83cc019SAndroid Build Coastguard Worker
184*d83cc019SAndroid Build Coastguard Worker execbuf.buffers_ptr = to_user_pointer(&obj[j]);
185*d83cc019SAndroid Build Coastguard Worker execbuf.buffer_count = i + 1;
186*d83cc019SAndroid Build Coastguard Worker execbuf.flags = engines[j % nengine];
187*d83cc019SAndroid Build Coastguard Worker gem_execbuf(fd, &execbuf);
188*d83cc019SAndroid Build Coastguard Worker }
189*d83cc019SAndroid Build Coastguard Worker
190*d83cc019SAndroid Build Coastguard Worker for (int i = 0; i <= count; i++)
191*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, obj[i].handle, I915_MADV_DONTNEED);
192*d83cc019SAndroid Build Coastguard Worker munmap(obj, obj_size);
193*d83cc019SAndroid Build Coastguard Worker }
194*d83cc019SAndroid Build Coastguard Worker
hang(int fd,uint64_t alloc)195*d83cc019SAndroid Build Coastguard Worker static void hang(int fd, uint64_t alloc)
196*d83cc019SAndroid Build Coastguard Worker {
197*d83cc019SAndroid Build Coastguard Worker const uint32_t bbe = MI_BATCH_BUFFER_END;
198*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 *obj;
199*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf;
200*d83cc019SAndroid Build Coastguard Worker int count = alloc >> 20;
201*d83cc019SAndroid Build Coastguard Worker uint64_t obj_size;
202*d83cc019SAndroid Build Coastguard Worker
203*d83cc019SAndroid Build Coastguard Worker obj = __gem_calloc(fd, alloc + 1, sizeof(*obj), &obj_size);
204*d83cc019SAndroid Build Coastguard Worker memset(&execbuf, 0, sizeof(execbuf));
205*d83cc019SAndroid Build Coastguard Worker
206*d83cc019SAndroid Build Coastguard Worker obj[count].handle = gem_create(fd, 4096);
207*d83cc019SAndroid Build Coastguard Worker gem_write(fd, obj[count].handle, 0, &bbe, sizeof(bbe));
208*d83cc019SAndroid Build Coastguard Worker
209*d83cc019SAndroid Build Coastguard Worker for (int i = 1; i <= count; i++) {
210*d83cc019SAndroid Build Coastguard Worker int j = count - i;
211*d83cc019SAndroid Build Coastguard Worker
212*d83cc019SAndroid Build Coastguard Worker obj[j].handle = gem_create(fd, 1 << 20);
213*d83cc019SAndroid Build Coastguard Worker execbuf.buffers_ptr = to_user_pointer(&obj[j]);
214*d83cc019SAndroid Build Coastguard Worker execbuf.buffer_count = i + 1;
215*d83cc019SAndroid Build Coastguard Worker gem_execbuf(fd, &execbuf);
216*d83cc019SAndroid Build Coastguard Worker }
217*d83cc019SAndroid Build Coastguard Worker
218*d83cc019SAndroid Build Coastguard Worker gem_close(fd, igt_hang_ring(fd, 0).spin->handle);
219*d83cc019SAndroid Build Coastguard Worker for (int i = 0; i <= count; i++)
220*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, obj[i].handle, I915_MADV_DONTNEED);
221*d83cc019SAndroid Build Coastguard Worker munmap(obj, obj_size);
222*d83cc019SAndroid Build Coastguard Worker }
223*d83cc019SAndroid Build Coastguard Worker
userptr(int fd,uint64_t alloc,unsigned int flags)224*d83cc019SAndroid Build Coastguard Worker static void userptr(int fd, uint64_t alloc, unsigned int flags)
225*d83cc019SAndroid Build Coastguard Worker #define UDIRTY (1 << 0)
226*d83cc019SAndroid Build Coastguard Worker {
227*d83cc019SAndroid Build Coastguard Worker struct local_i915_gem_userptr userptr;
228*d83cc019SAndroid Build Coastguard Worker void *ptr;
229*d83cc019SAndroid Build Coastguard Worker
230*d83cc019SAndroid Build Coastguard Worker igt_assert((alloc & 4095) == 0);
231*d83cc019SAndroid Build Coastguard Worker
232*d83cc019SAndroid Build Coastguard Worker ptr = mmap(NULL, alloc,
233*d83cc019SAndroid Build Coastguard Worker PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
234*d83cc019SAndroid Build Coastguard Worker -1, 0);
235*d83cc019SAndroid Build Coastguard Worker igt_assert(ptr != (void *)-1);
236*d83cc019SAndroid Build Coastguard Worker
237*d83cc019SAndroid Build Coastguard Worker memset(&userptr, 0, sizeof(userptr));
238*d83cc019SAndroid Build Coastguard Worker userptr.user_size = alloc;
239*d83cc019SAndroid Build Coastguard Worker userptr.user_ptr = to_user_pointer(ptr);
240*d83cc019SAndroid Build Coastguard Worker do_ioctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
241*d83cc019SAndroid Build Coastguard Worker
242*d83cc019SAndroid Build Coastguard Worker if (flags & UDIRTY)
243*d83cc019SAndroid Build Coastguard Worker gem_set_domain(fd, userptr.handle,
244*d83cc019SAndroid Build Coastguard Worker I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
245*d83cc019SAndroid Build Coastguard Worker else
246*d83cc019SAndroid Build Coastguard Worker gem_set_domain(fd, userptr.handle, I915_GEM_DOMAIN_GTT, 0);
247*d83cc019SAndroid Build Coastguard Worker
248*d83cc019SAndroid Build Coastguard Worker madvise(ptr, alloc, MADV_FREE);
249*d83cc019SAndroid Build Coastguard Worker }
250*d83cc019SAndroid Build Coastguard Worker
has_userptr(void)251*d83cc019SAndroid Build Coastguard Worker static bool has_userptr(void)
252*d83cc019SAndroid Build Coastguard Worker {
253*d83cc019SAndroid Build Coastguard Worker struct local_i915_gem_userptr userptr;
254*d83cc019SAndroid Build Coastguard Worker int fd = drm_open_driver(DRIVER_INTEL);
255*d83cc019SAndroid Build Coastguard Worker int err;
256*d83cc019SAndroid Build Coastguard Worker
257*d83cc019SAndroid Build Coastguard Worker memset(&userptr, 0, sizeof(userptr));
258*d83cc019SAndroid Build Coastguard Worker userptr.user_size = 8192;
259*d83cc019SAndroid Build Coastguard Worker userptr.user_ptr = -4096;
260*d83cc019SAndroid Build Coastguard Worker
261*d83cc019SAndroid Build Coastguard Worker err = 0;
262*d83cc019SAndroid Build Coastguard Worker if (drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr))
263*d83cc019SAndroid Build Coastguard Worker err = errno;
264*d83cc019SAndroid Build Coastguard Worker
265*d83cc019SAndroid Build Coastguard Worker close(fd);
266*d83cc019SAndroid Build Coastguard Worker
267*d83cc019SAndroid Build Coastguard Worker return err == EFAULT;
268*d83cc019SAndroid Build Coastguard Worker }
269*d83cc019SAndroid Build Coastguard Worker
leak(int fd,uint64_t alloc)270*d83cc019SAndroid Build Coastguard Worker static void leak(int fd, uint64_t alloc)
271*d83cc019SAndroid Build Coastguard Worker {
272*d83cc019SAndroid Build Coastguard Worker char *ptr;
273*d83cc019SAndroid Build Coastguard Worker
274*d83cc019SAndroid Build Coastguard Worker ptr = mmap(NULL, alloc, PROT_READ | PROT_WRITE,
275*d83cc019SAndroid Build Coastguard Worker MAP_ANON | MAP_PRIVATE | MAP_POPULATE,
276*d83cc019SAndroid Build Coastguard Worker -1, 0);
277*d83cc019SAndroid Build Coastguard Worker if (ptr != (char *)-1)
278*d83cc019SAndroid Build Coastguard Worker return;
279*d83cc019SAndroid Build Coastguard Worker
280*d83cc019SAndroid Build Coastguard Worker while (alloc) {
281*d83cc019SAndroid Build Coastguard Worker alloc -= 4096;
282*d83cc019SAndroid Build Coastguard Worker ptr[alloc] = 0;
283*d83cc019SAndroid Build Coastguard Worker }
284*d83cc019SAndroid Build Coastguard Worker }
285*d83cc019SAndroid Build Coastguard Worker
286*d83cc019SAndroid Build Coastguard Worker #define SOLO 1
287*d83cc019SAndroid Build Coastguard Worker #define USERPTR 2
288*d83cc019SAndroid Build Coastguard Worker #define USERPTR_DIRTY 4
289*d83cc019SAndroid Build Coastguard Worker #define OOM 8
290*d83cc019SAndroid Build Coastguard Worker
run_test(int nchildren,uint64_t alloc,void (* func)(int,uint64_t),unsigned flags)291*d83cc019SAndroid Build Coastguard Worker static void run_test(int nchildren, uint64_t alloc,
292*d83cc019SAndroid Build Coastguard Worker void (*func)(int, uint64_t), unsigned flags)
293*d83cc019SAndroid Build Coastguard Worker {
294*d83cc019SAndroid Build Coastguard Worker const int timeout = flags & SOLO ? 1 : 20;
295*d83cc019SAndroid Build Coastguard Worker
296*d83cc019SAndroid Build Coastguard Worker /* Each pass consumes alloc bytes and doesn't drop
297*d83cc019SAndroid Build Coastguard Worker * its reference to object (i.e. calls
298*d83cc019SAndroid Build Coastguard Worker * gem_madvise(DONTNEED) instead of gem_close()).
299*d83cc019SAndroid Build Coastguard Worker * After nchildren passes we expect each process
300*d83cc019SAndroid Build Coastguard Worker * to have enough objects to consume all of memory
301*d83cc019SAndroid Build Coastguard Worker * if left unchecked.
302*d83cc019SAndroid Build Coastguard Worker */
303*d83cc019SAndroid Build Coastguard Worker
304*d83cc019SAndroid Build Coastguard Worker if (flags & SOLO)
305*d83cc019SAndroid Build Coastguard Worker nchildren = 1;
306*d83cc019SAndroid Build Coastguard Worker
307*d83cc019SAndroid Build Coastguard Worker /* Background load */
308*d83cc019SAndroid Build Coastguard Worker if (flags & OOM) {
309*d83cc019SAndroid Build Coastguard Worker igt_fork(child, nchildren) {
310*d83cc019SAndroid Build Coastguard Worker igt_until_timeout(timeout) {
311*d83cc019SAndroid Build Coastguard Worker int fd = drm_open_driver(DRIVER_INTEL);
312*d83cc019SAndroid Build Coastguard Worker for (int pass = 0; pass < nchildren; pass++)
313*d83cc019SAndroid Build Coastguard Worker leak(fd, alloc);
314*d83cc019SAndroid Build Coastguard Worker close(fd);
315*d83cc019SAndroid Build Coastguard Worker }
316*d83cc019SAndroid Build Coastguard Worker }
317*d83cc019SAndroid Build Coastguard Worker }
318*d83cc019SAndroid Build Coastguard Worker
319*d83cc019SAndroid Build Coastguard Worker if (flags & USERPTR) {
320*d83cc019SAndroid Build Coastguard Worker igt_require(has_userptr());
321*d83cc019SAndroid Build Coastguard Worker igt_fork(child, (nchildren + 1)/2) {
322*d83cc019SAndroid Build Coastguard Worker igt_until_timeout(timeout) {
323*d83cc019SAndroid Build Coastguard Worker int fd = drm_open_driver(DRIVER_INTEL);
324*d83cc019SAndroid Build Coastguard Worker for (int pass = 0; pass < nchildren; pass++)
325*d83cc019SAndroid Build Coastguard Worker userptr(fd, alloc, 0);
326*d83cc019SAndroid Build Coastguard Worker close(fd);
327*d83cc019SAndroid Build Coastguard Worker }
328*d83cc019SAndroid Build Coastguard Worker }
329*d83cc019SAndroid Build Coastguard Worker nchildren = (nchildren + 1)/2;
330*d83cc019SAndroid Build Coastguard Worker }
331*d83cc019SAndroid Build Coastguard Worker
332*d83cc019SAndroid Build Coastguard Worker if (flags & USERPTR_DIRTY) {
333*d83cc019SAndroid Build Coastguard Worker igt_require(has_userptr());
334*d83cc019SAndroid Build Coastguard Worker igt_fork(child, (nchildren + 1)/2) {
335*d83cc019SAndroid Build Coastguard Worker igt_until_timeout(timeout) {
336*d83cc019SAndroid Build Coastguard Worker int fd = drm_open_driver(DRIVER_INTEL);
337*d83cc019SAndroid Build Coastguard Worker for (int pass = 0; pass < nchildren; pass++)
338*d83cc019SAndroid Build Coastguard Worker userptr(fd, alloc, UDIRTY);
339*d83cc019SAndroid Build Coastguard Worker close(fd);
340*d83cc019SAndroid Build Coastguard Worker }
341*d83cc019SAndroid Build Coastguard Worker }
342*d83cc019SAndroid Build Coastguard Worker nchildren = (nchildren + 1)/2;
343*d83cc019SAndroid Build Coastguard Worker }
344*d83cc019SAndroid Build Coastguard Worker
345*d83cc019SAndroid Build Coastguard Worker /* Exercise major ioctls */
346*d83cc019SAndroid Build Coastguard Worker igt_fork(child, nchildren) {
347*d83cc019SAndroid Build Coastguard Worker igt_until_timeout(timeout) {
348*d83cc019SAndroid Build Coastguard Worker int fd = drm_open_driver(DRIVER_INTEL);
349*d83cc019SAndroid Build Coastguard Worker for (int pass = 0; pass < nchildren; pass++)
350*d83cc019SAndroid Build Coastguard Worker func(fd, alloc);
351*d83cc019SAndroid Build Coastguard Worker close(fd);
352*d83cc019SAndroid Build Coastguard Worker }
353*d83cc019SAndroid Build Coastguard Worker }
354*d83cc019SAndroid Build Coastguard Worker igt_waitchildren();
355*d83cc019SAndroid Build Coastguard Worker }
356*d83cc019SAndroid Build Coastguard Worker
reclaim(unsigned engine,int timeout)357*d83cc019SAndroid Build Coastguard Worker static void reclaim(unsigned engine, int timeout)
358*d83cc019SAndroid Build Coastguard Worker {
359*d83cc019SAndroid Build Coastguard Worker const uint64_t timeout_100ms = 100000000LL;
360*d83cc019SAndroid Build Coastguard Worker int fd = drm_open_driver(DRIVER_INTEL);
361*d83cc019SAndroid Build Coastguard Worker int debugfs = igt_debugfs_dir(fd);
362*d83cc019SAndroid Build Coastguard Worker igt_spin_t *spin;
363*d83cc019SAndroid Build Coastguard Worker volatile uint32_t *shared;
364*d83cc019SAndroid Build Coastguard Worker
365*d83cc019SAndroid Build Coastguard Worker shared = mmap(0, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
366*d83cc019SAndroid Build Coastguard Worker igt_assert(shared != MAP_FAILED);
367*d83cc019SAndroid Build Coastguard Worker
368*d83cc019SAndroid Build Coastguard Worker igt_fork(child, sysconf(_SC_NPROCESSORS_ONLN)) {
369*d83cc019SAndroid Build Coastguard Worker do {
370*d83cc019SAndroid Build Coastguard Worker igt_sysfs_printf(debugfs, "i915_drop_caches",
371*d83cc019SAndroid Build Coastguard Worker "%d", DROP_BOUND | DROP_UNBOUND);
372*d83cc019SAndroid Build Coastguard Worker } while (!*shared);
373*d83cc019SAndroid Build Coastguard Worker }
374*d83cc019SAndroid Build Coastguard Worker
375*d83cc019SAndroid Build Coastguard Worker spin = igt_spin_new(fd, .engine = engine);
376*d83cc019SAndroid Build Coastguard Worker igt_until_timeout(timeout) {
377*d83cc019SAndroid Build Coastguard Worker igt_spin_t *next = __igt_spin_new(fd, .engine = engine);
378*d83cc019SAndroid Build Coastguard Worker
379*d83cc019SAndroid Build Coastguard Worker igt_spin_set_timeout(spin, timeout_100ms);
380*d83cc019SAndroid Build Coastguard Worker gem_sync(fd, spin->handle);
381*d83cc019SAndroid Build Coastguard Worker
382*d83cc019SAndroid Build Coastguard Worker igt_spin_free(fd, spin);
383*d83cc019SAndroid Build Coastguard Worker spin = next;
384*d83cc019SAndroid Build Coastguard Worker }
385*d83cc019SAndroid Build Coastguard Worker igt_spin_free(fd, spin);
386*d83cc019SAndroid Build Coastguard Worker
387*d83cc019SAndroid Build Coastguard Worker *shared = 1;
388*d83cc019SAndroid Build Coastguard Worker igt_waitchildren();
389*d83cc019SAndroid Build Coastguard Worker
390*d83cc019SAndroid Build Coastguard Worker munmap((void *)shared, 4096);
391*d83cc019SAndroid Build Coastguard Worker close(debugfs);
392*d83cc019SAndroid Build Coastguard Worker close(fd);
393*d83cc019SAndroid Build Coastguard Worker }
394*d83cc019SAndroid Build Coastguard Worker
395*d83cc019SAndroid Build Coastguard Worker igt_main
396*d83cc019SAndroid Build Coastguard Worker {
397*d83cc019SAndroid Build Coastguard Worker const struct test {
398*d83cc019SAndroid Build Coastguard Worker const char *name;
399*d83cc019SAndroid Build Coastguard Worker void (*func)(int, uint64_t);
400*d83cc019SAndroid Build Coastguard Worker } tests[] = {
401*d83cc019SAndroid Build Coastguard Worker { "get-pages", get_pages },
402*d83cc019SAndroid Build Coastguard Worker { "get-pages-dirty", get_pages_dirty },
403*d83cc019SAndroid Build Coastguard Worker { "pwrite", pwrite_ },
404*d83cc019SAndroid Build Coastguard Worker { "pread", pread_ },
405*d83cc019SAndroid Build Coastguard Worker { "mmap-gtt", mmap_gtt },
406*d83cc019SAndroid Build Coastguard Worker { "mmap-cpu", mmap_cpu },
407*d83cc019SAndroid Build Coastguard Worker { "execbuf1", execbuf1 },
408*d83cc019SAndroid Build Coastguard Worker { "execbufN", execbufN },
409*d83cc019SAndroid Build Coastguard Worker { "execbufX", execbufX },
410*d83cc019SAndroid Build Coastguard Worker { "hang", hang },
411*d83cc019SAndroid Build Coastguard Worker { NULL },
412*d83cc019SAndroid Build Coastguard Worker };
413*d83cc019SAndroid Build Coastguard Worker const struct mode {
414*d83cc019SAndroid Build Coastguard Worker const char *suffix;
415*d83cc019SAndroid Build Coastguard Worker unsigned flags;
416*d83cc019SAndroid Build Coastguard Worker } modes[] = {
417*d83cc019SAndroid Build Coastguard Worker { "-sanitycheck", SOLO },
418*d83cc019SAndroid Build Coastguard Worker { "", 0 },
419*d83cc019SAndroid Build Coastguard Worker { "-userptr", USERPTR },
420*d83cc019SAndroid Build Coastguard Worker { "-userptr-dirty", USERPTR | USERPTR_DIRTY },
421*d83cc019SAndroid Build Coastguard Worker { "-oom", USERPTR | OOM },
422*d83cc019SAndroid Build Coastguard Worker { NULL },
423*d83cc019SAndroid Build Coastguard Worker };
424*d83cc019SAndroid Build Coastguard Worker uint64_t alloc_size = 0;
425*d83cc019SAndroid Build Coastguard Worker int num_processes = 0;
426*d83cc019SAndroid Build Coastguard Worker
427*d83cc019SAndroid Build Coastguard Worker igt_skip_on_simulation();
428*d83cc019SAndroid Build Coastguard Worker
429*d83cc019SAndroid Build Coastguard Worker igt_fixture {
430*d83cc019SAndroid Build Coastguard Worker uint64_t mem_size = intel_get_total_ram_mb();
431*d83cc019SAndroid Build Coastguard Worker unsigned int engine;
432*d83cc019SAndroid Build Coastguard Worker int fd;
433*d83cc019SAndroid Build Coastguard Worker
434*d83cc019SAndroid Build Coastguard Worker fd = drm_open_driver(DRIVER_INTEL);
435*d83cc019SAndroid Build Coastguard Worker igt_require_gem(fd);
436*d83cc019SAndroid Build Coastguard Worker
437*d83cc019SAndroid Build Coastguard Worker /*
438*d83cc019SAndroid Build Coastguard Worker * Spawn enough processes to use all memory, but each only
439*d83cc019SAndroid Build Coastguard Worker * uses half the available mappable aperture ~128MiB.
440*d83cc019SAndroid Build Coastguard Worker * Individually the processes would be ok, but en masse
441*d83cc019SAndroid Build Coastguard Worker * we expect the shrinker to start purging objects,
442*d83cc019SAndroid Build Coastguard Worker * and possibly fail.
443*d83cc019SAndroid Build Coastguard Worker */
444*d83cc019SAndroid Build Coastguard Worker alloc_size = gem_mappable_aperture_size() / 2;
445*d83cc019SAndroid Build Coastguard Worker num_processes = 1 + (mem_size / (alloc_size >> 20));
446*d83cc019SAndroid Build Coastguard Worker
447*d83cc019SAndroid Build Coastguard Worker igt_info("Using %d processes and %'lluMiB per process\n",
448*d83cc019SAndroid Build Coastguard Worker num_processes, (long long)(alloc_size >> 20));
449*d83cc019SAndroid Build Coastguard Worker
450*d83cc019SAndroid Build Coastguard Worker intel_require_memory(num_processes, alloc_size,
451*d83cc019SAndroid Build Coastguard Worker CHECK_SWAP | CHECK_RAM);
452*d83cc019SAndroid Build Coastguard Worker
453*d83cc019SAndroid Build Coastguard Worker nengine = 0;
454*d83cc019SAndroid Build Coastguard Worker for_each_engine(fd, engine)
455*d83cc019SAndroid Build Coastguard Worker engines[nengine++] = engine;
456*d83cc019SAndroid Build Coastguard Worker igt_require(nengine);
457*d83cc019SAndroid Build Coastguard Worker
458*d83cc019SAndroid Build Coastguard Worker close(fd);
459*d83cc019SAndroid Build Coastguard Worker }
460*d83cc019SAndroid Build Coastguard Worker
461*d83cc019SAndroid Build Coastguard Worker igt_subtest("reclaim")
462*d83cc019SAndroid Build Coastguard Worker reclaim(I915_EXEC_DEFAULT, 2);
463*d83cc019SAndroid Build Coastguard Worker
464*d83cc019SAndroid Build Coastguard Worker for(const struct test *t = tests; t->name; t++) {
465*d83cc019SAndroid Build Coastguard Worker for(const struct mode *m = modes; m->suffix; m++) {
466*d83cc019SAndroid Build Coastguard Worker igt_subtest_f("%s%s", t->name, m->suffix)
467*d83cc019SAndroid Build Coastguard Worker run_test(num_processes, alloc_size,
468*d83cc019SAndroid Build Coastguard Worker t->func, m->flags);
469*d83cc019SAndroid Build Coastguard Worker }
470*d83cc019SAndroid Build Coastguard Worker }
471*d83cc019SAndroid Build Coastguard Worker }
472