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 #include "igt.h"
26*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
27*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
28*d83cc019SAndroid Build Coastguard Worker #include <stdint.h>
29*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
30*d83cc019SAndroid Build Coastguard Worker #include <string.h>
31*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
32*d83cc019SAndroid Build Coastguard Worker #include <ftw.h>
33*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
34*d83cc019SAndroid Build Coastguard Worker #include <pthread.h>
35*d83cc019SAndroid Build Coastguard Worker #include <sched.h>
36*d83cc019SAndroid Build Coastguard Worker #include <signal.h>
37*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
38*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
39*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
40*d83cc019SAndroid Build Coastguard Worker #include <sys/time.h>
41*d83cc019SAndroid Build Coastguard Worker #include <time.h>
42*d83cc019SAndroid Build Coastguard Worker #include <limits.h>
43*d83cc019SAndroid Build Coastguard Worker #include "drm.h"
44*d83cc019SAndroid Build Coastguard Worker
45*d83cc019SAndroid Build Coastguard Worker #include <linux/unistd.h>
46*d83cc019SAndroid Build Coastguard Worker
47*d83cc019SAndroid Build Coastguard Worker #define sigev_notify_thread_id _sigev_un._tid
48*d83cc019SAndroid Build Coastguard Worker
49*d83cc019SAndroid Build Coastguard Worker static volatile int done;
50*d83cc019SAndroid Build Coastguard Worker
51*d83cc019SAndroid Build Coastguard Worker struct gem_busyspin {
52*d83cc019SAndroid Build Coastguard Worker pthread_t thread;
53*d83cc019SAndroid Build Coastguard Worker unsigned long sz;
54*d83cc019SAndroid Build Coastguard Worker unsigned long count;
55*d83cc019SAndroid Build Coastguard Worker bool leak;
56*d83cc019SAndroid Build Coastguard Worker bool interrupts;
57*d83cc019SAndroid Build Coastguard Worker };
58*d83cc019SAndroid Build Coastguard Worker
59*d83cc019SAndroid Build Coastguard Worker struct sys_wait {
60*d83cc019SAndroid Build Coastguard Worker pthread_t thread;
61*d83cc019SAndroid Build Coastguard Worker struct igt_mean mean;
62*d83cc019SAndroid Build Coastguard Worker };
63*d83cc019SAndroid Build Coastguard Worker
force_low_latency(void)64*d83cc019SAndroid Build Coastguard Worker static void force_low_latency(void)
65*d83cc019SAndroid Build Coastguard Worker {
66*d83cc019SAndroid Build Coastguard Worker int32_t target = 0;
67*d83cc019SAndroid Build Coastguard Worker int fd = open("/dev/cpu_dma_latency", O_RDWR);
68*d83cc019SAndroid Build Coastguard Worker if (fd < 0 || write(fd, &target, sizeof(target)) < 0)
69*d83cc019SAndroid Build Coastguard Worker fprintf(stderr,
70*d83cc019SAndroid Build Coastguard Worker "Unable to prevent CPU sleeps and force low latency using /dev/cpu_dma_latency: %s\n",
71*d83cc019SAndroid Build Coastguard Worker strerror(errno));
72*d83cc019SAndroid Build Coastguard Worker }
73*d83cc019SAndroid Build Coastguard Worker
74*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_NO_RELOC (1<<11)
75*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_HANDLE_LUT (1<<12)
76*d83cc019SAndroid Build Coastguard Worker
77*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_BSD_SHIFT (13)
78*d83cc019SAndroid Build Coastguard Worker #define LOCAL_I915_EXEC_BSD_MASK (3 << LOCAL_I915_EXEC_BSD_SHIFT)
79*d83cc019SAndroid Build Coastguard Worker
80*d83cc019SAndroid Build Coastguard Worker #define ENGINE_FLAGS (I915_EXEC_RING_MASK | LOCAL_I915_EXEC_BSD_MASK)
81*d83cc019SAndroid Build Coastguard Worker
ignore_engine(int fd,unsigned engine)82*d83cc019SAndroid Build Coastguard Worker static bool ignore_engine(int fd, unsigned engine)
83*d83cc019SAndroid Build Coastguard Worker {
84*d83cc019SAndroid Build Coastguard Worker if (engine == 0)
85*d83cc019SAndroid Build Coastguard Worker return true;
86*d83cc019SAndroid Build Coastguard Worker
87*d83cc019SAndroid Build Coastguard Worker if (gem_has_bsd2(fd) && engine == I915_EXEC_BSD)
88*d83cc019SAndroid Build Coastguard Worker return true;
89*d83cc019SAndroid Build Coastguard Worker
90*d83cc019SAndroid Build Coastguard Worker return false;
91*d83cc019SAndroid Build Coastguard Worker }
92*d83cc019SAndroid Build Coastguard Worker
gem_busyspin(void * arg)93*d83cc019SAndroid Build Coastguard Worker static void *gem_busyspin(void *arg)
94*d83cc019SAndroid Build Coastguard Worker {
95*d83cc019SAndroid Build Coastguard Worker const uint32_t bbe = MI_BATCH_BUFFER_END;
96*d83cc019SAndroid Build Coastguard Worker struct gem_busyspin *bs = arg;
97*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf;
98*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 obj[2];
99*d83cc019SAndroid Build Coastguard Worker const unsigned sz =
100*d83cc019SAndroid Build Coastguard Worker bs->sz ? bs->sz + sizeof(bbe) : bs->leak ? 16 << 20 : 4 << 10;
101*d83cc019SAndroid Build Coastguard Worker unsigned engines[16];
102*d83cc019SAndroid Build Coastguard Worker unsigned nengine;
103*d83cc019SAndroid Build Coastguard Worker unsigned engine;
104*d83cc019SAndroid Build Coastguard Worker int fd;
105*d83cc019SAndroid Build Coastguard Worker
106*d83cc019SAndroid Build Coastguard Worker fd = drm_open_driver(DRIVER_INTEL);
107*d83cc019SAndroid Build Coastguard Worker
108*d83cc019SAndroid Build Coastguard Worker nengine = 0;
109*d83cc019SAndroid Build Coastguard Worker for_each_engine(fd, engine)
110*d83cc019SAndroid Build Coastguard Worker if (!ignore_engine(fd, engine)) engines[nengine++] = engine;
111*d83cc019SAndroid Build Coastguard Worker
112*d83cc019SAndroid Build Coastguard Worker memset(obj, 0, sizeof(obj));
113*d83cc019SAndroid Build Coastguard Worker obj[0].handle = gem_create(fd, 4096);
114*d83cc019SAndroid Build Coastguard Worker obj[0].flags = EXEC_OBJECT_WRITE;
115*d83cc019SAndroid Build Coastguard Worker obj[1].handle = gem_create(fd, sz);
116*d83cc019SAndroid Build Coastguard Worker gem_write(fd, obj[1].handle, bs->sz, &bbe, sizeof(bbe));
117*d83cc019SAndroid Build Coastguard Worker
118*d83cc019SAndroid Build Coastguard Worker memset(&execbuf, 0, sizeof(execbuf));
119*d83cc019SAndroid Build Coastguard Worker if (bs->interrupts) {
120*d83cc019SAndroid Build Coastguard Worker execbuf.buffers_ptr = (uintptr_t)&obj[0];
121*d83cc019SAndroid Build Coastguard Worker execbuf.buffer_count = 2;
122*d83cc019SAndroid Build Coastguard Worker } else {
123*d83cc019SAndroid Build Coastguard Worker execbuf.buffers_ptr = (uintptr_t)&obj[1];
124*d83cc019SAndroid Build Coastguard Worker execbuf.buffer_count = 1;
125*d83cc019SAndroid Build Coastguard Worker }
126*d83cc019SAndroid Build Coastguard Worker execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT;
127*d83cc019SAndroid Build Coastguard Worker execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
128*d83cc019SAndroid Build Coastguard Worker if (__gem_execbuf(fd, &execbuf)) {
129*d83cc019SAndroid Build Coastguard Worker execbuf.flags = 0;
130*d83cc019SAndroid Build Coastguard Worker gem_execbuf(fd, &execbuf);
131*d83cc019SAndroid Build Coastguard Worker }
132*d83cc019SAndroid Build Coastguard Worker
133*d83cc019SAndroid Build Coastguard Worker while (!done) {
134*d83cc019SAndroid Build Coastguard Worker for (int n = 0; n < nengine; n++) {
135*d83cc019SAndroid Build Coastguard Worker const int m = rand() % nengine;
136*d83cc019SAndroid Build Coastguard Worker unsigned int tmp = engines[n];
137*d83cc019SAndroid Build Coastguard Worker engines[n] = engines[m];
138*d83cc019SAndroid Build Coastguard Worker engines[m] = tmp;
139*d83cc019SAndroid Build Coastguard Worker }
140*d83cc019SAndroid Build Coastguard Worker for (int n = 0; n < nengine; n++) {
141*d83cc019SAndroid Build Coastguard Worker execbuf.flags &= ~ENGINE_FLAGS;
142*d83cc019SAndroid Build Coastguard Worker execbuf.flags |= engines[n];
143*d83cc019SAndroid Build Coastguard Worker gem_execbuf(fd, &execbuf);
144*d83cc019SAndroid Build Coastguard Worker }
145*d83cc019SAndroid Build Coastguard Worker bs->count += nengine;
146*d83cc019SAndroid Build Coastguard Worker if (bs->leak) {
147*d83cc019SAndroid Build Coastguard Worker gem_madvise(fd, obj[1].handle, I915_MADV_DONTNEED);
148*d83cc019SAndroid Build Coastguard Worker obj[1].handle = gem_create(fd, sz);
149*d83cc019SAndroid Build Coastguard Worker gem_write(fd, obj[1].handle, bs->sz, &bbe, sizeof(bbe));
150*d83cc019SAndroid Build Coastguard Worker }
151*d83cc019SAndroid Build Coastguard Worker }
152*d83cc019SAndroid Build Coastguard Worker
153*d83cc019SAndroid Build Coastguard Worker close(fd);
154*d83cc019SAndroid Build Coastguard Worker return NULL;
155*d83cc019SAndroid Build Coastguard Worker }
156*d83cc019SAndroid Build Coastguard Worker
elapsed(const struct timespec * a,const struct timespec * b)157*d83cc019SAndroid Build Coastguard Worker static double elapsed(const struct timespec *a, const struct timespec *b)
158*d83cc019SAndroid Build Coastguard Worker {
159*d83cc019SAndroid Build Coastguard Worker return 1e9*(b->tv_sec - a->tv_sec) + (b->tv_nsec - a ->tv_nsec);
160*d83cc019SAndroid Build Coastguard Worker }
161*d83cc019SAndroid Build Coastguard Worker
sys_wait(void * arg)162*d83cc019SAndroid Build Coastguard Worker static void *sys_wait(void *arg)
163*d83cc019SAndroid Build Coastguard Worker {
164*d83cc019SAndroid Build Coastguard Worker struct sys_wait *w = arg;
165*d83cc019SAndroid Build Coastguard Worker struct sigevent sev;
166*d83cc019SAndroid Build Coastguard Worker timer_t timer;
167*d83cc019SAndroid Build Coastguard Worker sigset_t mask;
168*d83cc019SAndroid Build Coastguard Worker struct timespec now;
169*d83cc019SAndroid Build Coastguard Worker #define SIG SIGRTMIN
170*d83cc019SAndroid Build Coastguard Worker
171*d83cc019SAndroid Build Coastguard Worker sigemptyset(&mask);
172*d83cc019SAndroid Build Coastguard Worker sigaddset(&mask, SIG);
173*d83cc019SAndroid Build Coastguard Worker sigprocmask(SIG_SETMASK, &mask, NULL);
174*d83cc019SAndroid Build Coastguard Worker
175*d83cc019SAndroid Build Coastguard Worker sev.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID;
176*d83cc019SAndroid Build Coastguard Worker sev.sigev_notify_thread_id = gettid();
177*d83cc019SAndroid Build Coastguard Worker sev.sigev_signo = SIG;
178*d83cc019SAndroid Build Coastguard Worker timer_create(CLOCK_MONOTONIC, &sev, &timer);
179*d83cc019SAndroid Build Coastguard Worker
180*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &now);
181*d83cc019SAndroid Build Coastguard Worker while (!done) {
182*d83cc019SAndroid Build Coastguard Worker struct itimerspec its;
183*d83cc019SAndroid Build Coastguard Worker int sigs;
184*d83cc019SAndroid Build Coastguard Worker
185*d83cc019SAndroid Build Coastguard Worker its.it_value = now;
186*d83cc019SAndroid Build Coastguard Worker its.it_value.tv_nsec += 100 * 1000;
187*d83cc019SAndroid Build Coastguard Worker its.it_value.tv_nsec += rand() % (NSEC_PER_SEC / 1000);
188*d83cc019SAndroid Build Coastguard Worker if (its.it_value.tv_nsec >= NSEC_PER_SEC) {
189*d83cc019SAndroid Build Coastguard Worker its.it_value.tv_nsec -= NSEC_PER_SEC;
190*d83cc019SAndroid Build Coastguard Worker its.it_value.tv_sec += 1;
191*d83cc019SAndroid Build Coastguard Worker }
192*d83cc019SAndroid Build Coastguard Worker its.it_interval.tv_sec = its.it_interval.tv_nsec = 0;
193*d83cc019SAndroid Build Coastguard Worker timer_settime(timer, TIMER_ABSTIME, &its, NULL);
194*d83cc019SAndroid Build Coastguard Worker
195*d83cc019SAndroid Build Coastguard Worker sigwait(&mask, &sigs);
196*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &now);
197*d83cc019SAndroid Build Coastguard Worker igt_mean_add(&w->mean, elapsed(&its.it_value, &now));
198*d83cc019SAndroid Build Coastguard Worker }
199*d83cc019SAndroid Build Coastguard Worker
200*d83cc019SAndroid Build Coastguard Worker sigprocmask(SIG_UNBLOCK, &mask, NULL);
201*d83cc019SAndroid Build Coastguard Worker timer_delete(timer);
202*d83cc019SAndroid Build Coastguard Worker
203*d83cc019SAndroid Build Coastguard Worker return NULL;
204*d83cc019SAndroid Build Coastguard Worker }
205*d83cc019SAndroid Build Coastguard Worker
206*d83cc019SAndroid Build Coastguard Worker #define PAGE_SIZE 4096
sys_thp_alloc(void * arg)207*d83cc019SAndroid Build Coastguard Worker static void *sys_thp_alloc(void *arg)
208*d83cc019SAndroid Build Coastguard Worker {
209*d83cc019SAndroid Build Coastguard Worker struct sys_wait *w = arg;
210*d83cc019SAndroid Build Coastguard Worker struct timespec now;
211*d83cc019SAndroid Build Coastguard Worker
212*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &now);
213*d83cc019SAndroid Build Coastguard Worker while (!done) {
214*d83cc019SAndroid Build Coastguard Worker const size_t sz = 2 << 20;
215*d83cc019SAndroid Build Coastguard Worker const struct timespec start = now;
216*d83cc019SAndroid Build Coastguard Worker void *ptr;
217*d83cc019SAndroid Build Coastguard Worker
218*d83cc019SAndroid Build Coastguard Worker ptr = mmap(NULL, sz,
219*d83cc019SAndroid Build Coastguard Worker PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
220*d83cc019SAndroid Build Coastguard Worker -1, 0);
221*d83cc019SAndroid Build Coastguard Worker assert(ptr != MAP_FAILED);
222*d83cc019SAndroid Build Coastguard Worker madvise(ptr, sz, MADV_HUGEPAGE);
223*d83cc019SAndroid Build Coastguard Worker for (size_t page = 0; page < sz; page += PAGE_SIZE)
224*d83cc019SAndroid Build Coastguard Worker *(volatile uint32_t *)((unsigned char *)ptr + page) = 0;
225*d83cc019SAndroid Build Coastguard Worker munmap(ptr, sz);
226*d83cc019SAndroid Build Coastguard Worker
227*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &now);
228*d83cc019SAndroid Build Coastguard Worker igt_mean_add(&w->mean, elapsed(&start, &now));
229*d83cc019SAndroid Build Coastguard Worker }
230*d83cc019SAndroid Build Coastguard Worker
231*d83cc019SAndroid Build Coastguard Worker return NULL;
232*d83cc019SAndroid Build Coastguard Worker }
233*d83cc019SAndroid Build Coastguard Worker
bind_cpu(pthread_attr_t * attr,int cpu)234*d83cc019SAndroid Build Coastguard Worker static void bind_cpu(pthread_attr_t *attr, int cpu)
235*d83cc019SAndroid Build Coastguard Worker {
236*d83cc019SAndroid Build Coastguard Worker #ifdef __USE_GNU
237*d83cc019SAndroid Build Coastguard Worker cpu_set_t mask;
238*d83cc019SAndroid Build Coastguard Worker
239*d83cc019SAndroid Build Coastguard Worker if (cpu == -1)
240*d83cc019SAndroid Build Coastguard Worker return;
241*d83cc019SAndroid Build Coastguard Worker
242*d83cc019SAndroid Build Coastguard Worker CPU_ZERO(&mask);
243*d83cc019SAndroid Build Coastguard Worker CPU_SET(cpu, &mask);
244*d83cc019SAndroid Build Coastguard Worker
245*d83cc019SAndroid Build Coastguard Worker pthread_attr_setaffinity_np(attr, sizeof(mask), &mask);
246*d83cc019SAndroid Build Coastguard Worker #endif
247*d83cc019SAndroid Build Coastguard Worker }
248*d83cc019SAndroid Build Coastguard Worker
rtprio(pthread_attr_t * attr,int prio)249*d83cc019SAndroid Build Coastguard Worker static void rtprio(pthread_attr_t *attr, int prio)
250*d83cc019SAndroid Build Coastguard Worker {
251*d83cc019SAndroid Build Coastguard Worker #ifdef PTHREAD_EXPLICIT_SCHED
252*d83cc019SAndroid Build Coastguard Worker struct sched_param param = { .sched_priority = 99 };
253*d83cc019SAndroid Build Coastguard Worker pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
254*d83cc019SAndroid Build Coastguard Worker pthread_attr_setschedpolicy(attr, SCHED_FIFO);
255*d83cc019SAndroid Build Coastguard Worker pthread_attr_setschedparam(attr, ¶m);
256*d83cc019SAndroid Build Coastguard Worker #endif
257*d83cc019SAndroid Build Coastguard Worker }
258*d83cc019SAndroid Build Coastguard Worker
l_estimate(igt_stats_t * stats)259*d83cc019SAndroid Build Coastguard Worker static double l_estimate(igt_stats_t *stats)
260*d83cc019SAndroid Build Coastguard Worker {
261*d83cc019SAndroid Build Coastguard Worker if (stats->n_values > 9)
262*d83cc019SAndroid Build Coastguard Worker return igt_stats_get_trimean(stats);
263*d83cc019SAndroid Build Coastguard Worker else if (stats->n_values > 5)
264*d83cc019SAndroid Build Coastguard Worker return igt_stats_get_median(stats);
265*d83cc019SAndroid Build Coastguard Worker else
266*d83cc019SAndroid Build Coastguard Worker return igt_stats_get_mean(stats);
267*d83cc019SAndroid Build Coastguard Worker }
268*d83cc019SAndroid Build Coastguard Worker
min_measurement_error(void)269*d83cc019SAndroid Build Coastguard Worker static double min_measurement_error(void)
270*d83cc019SAndroid Build Coastguard Worker {
271*d83cc019SAndroid Build Coastguard Worker struct timespec start, end;
272*d83cc019SAndroid Build Coastguard Worker int n;
273*d83cc019SAndroid Build Coastguard Worker
274*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &start);
275*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < 1024; n++)
276*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &end);
277*d83cc019SAndroid Build Coastguard Worker
278*d83cc019SAndroid Build Coastguard Worker return elapsed(&start, &end) / n;
279*d83cc019SAndroid Build Coastguard Worker }
280*d83cc019SAndroid Build Coastguard Worker
print_entry(const char * filepath,const struct stat * info,const int typeflag,struct FTW * pathinfo)281*d83cc019SAndroid Build Coastguard Worker static int print_entry(const char *filepath, const struct stat *info,
282*d83cc019SAndroid Build Coastguard Worker const int typeflag, struct FTW *pathinfo)
283*d83cc019SAndroid Build Coastguard Worker {
284*d83cc019SAndroid Build Coastguard Worker int fd;
285*d83cc019SAndroid Build Coastguard Worker
286*d83cc019SAndroid Build Coastguard Worker fd = open(filepath, O_RDONLY);
287*d83cc019SAndroid Build Coastguard Worker if (fd != -1) {
288*d83cc019SAndroid Build Coastguard Worker void *ptr;
289*d83cc019SAndroid Build Coastguard Worker
290*d83cc019SAndroid Build Coastguard Worker ptr = mmap(NULL, info->st_size,
291*d83cc019SAndroid Build Coastguard Worker PROT_READ, MAP_SHARED | MAP_POPULATE,
292*d83cc019SAndroid Build Coastguard Worker fd, 0);
293*d83cc019SAndroid Build Coastguard Worker if (ptr != MAP_FAILED)
294*d83cc019SAndroid Build Coastguard Worker munmap(ptr, info->st_size);
295*d83cc019SAndroid Build Coastguard Worker
296*d83cc019SAndroid Build Coastguard Worker close(fd);
297*d83cc019SAndroid Build Coastguard Worker }
298*d83cc019SAndroid Build Coastguard Worker
299*d83cc019SAndroid Build Coastguard Worker return 0;
300*d83cc019SAndroid Build Coastguard Worker }
301*d83cc019SAndroid Build Coastguard Worker
background_fs(void * path)302*d83cc019SAndroid Build Coastguard Worker static void *background_fs(void *path)
303*d83cc019SAndroid Build Coastguard Worker {
304*d83cc019SAndroid Build Coastguard Worker while (1)
305*d83cc019SAndroid Build Coastguard Worker nftw(path, print_entry, 20, FTW_PHYS | FTW_MOUNT);
306*d83cc019SAndroid Build Coastguard Worker return NULL;
307*d83cc019SAndroid Build Coastguard Worker }
308*d83cc019SAndroid Build Coastguard Worker
calibrate_nop(unsigned int target_us,unsigned int tolerance_pct)309*d83cc019SAndroid Build Coastguard Worker static unsigned long calibrate_nop(unsigned int target_us,
310*d83cc019SAndroid Build Coastguard Worker unsigned int tolerance_pct)
311*d83cc019SAndroid Build Coastguard Worker {
312*d83cc019SAndroid Build Coastguard Worker const uint32_t bbe = MI_BATCH_BUFFER_END;
313*d83cc019SAndroid Build Coastguard Worker const unsigned int loops = 100;
314*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 obj = {};
315*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 eb =
316*d83cc019SAndroid Build Coastguard Worker { .buffer_count = 1, .buffers_ptr = (uintptr_t)&obj};
317*d83cc019SAndroid Build Coastguard Worker struct timespec t_0, t_end;
318*d83cc019SAndroid Build Coastguard Worker long sz, prev;
319*d83cc019SAndroid Build Coastguard Worker int fd;
320*d83cc019SAndroid Build Coastguard Worker
321*d83cc019SAndroid Build Coastguard Worker fd = drm_open_driver(DRIVER_INTEL);
322*d83cc019SAndroid Build Coastguard Worker
323*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &t_0);
324*d83cc019SAndroid Build Coastguard Worker
325*d83cc019SAndroid Build Coastguard Worker sz = 256 * 1024;
326*d83cc019SAndroid Build Coastguard Worker do {
327*d83cc019SAndroid Build Coastguard Worker struct timespec t_start;
328*d83cc019SAndroid Build Coastguard Worker
329*d83cc019SAndroid Build Coastguard Worker obj.handle = gem_create(fd, sz + sizeof(bbe));
330*d83cc019SAndroid Build Coastguard Worker gem_write(fd, obj.handle, sz, &bbe, sizeof(bbe));
331*d83cc019SAndroid Build Coastguard Worker gem_execbuf(fd, &eb);
332*d83cc019SAndroid Build Coastguard Worker gem_sync(fd, obj.handle);
333*d83cc019SAndroid Build Coastguard Worker
334*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &t_start);
335*d83cc019SAndroid Build Coastguard Worker for (int loop = 0; loop < loops; loop++)
336*d83cc019SAndroid Build Coastguard Worker gem_execbuf(fd, &eb);
337*d83cc019SAndroid Build Coastguard Worker gem_sync(fd, obj.handle);
338*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &t_end);
339*d83cc019SAndroid Build Coastguard Worker
340*d83cc019SAndroid Build Coastguard Worker gem_close(fd, obj.handle);
341*d83cc019SAndroid Build Coastguard Worker
342*d83cc019SAndroid Build Coastguard Worker prev = sz;
343*d83cc019SAndroid Build Coastguard Worker sz = loops * sz / elapsed(&t_start, &t_end) * 1e3 * target_us;
344*d83cc019SAndroid Build Coastguard Worker sz = ALIGN(sz, sizeof(uint32_t));
345*d83cc019SAndroid Build Coastguard Worker } while (elapsed(&t_0, &t_end) < 5 ||
346*d83cc019SAndroid Build Coastguard Worker abs(sz - prev) > (sz * tolerance_pct / 100));
347*d83cc019SAndroid Build Coastguard Worker
348*d83cc019SAndroid Build Coastguard Worker close(fd);
349*d83cc019SAndroid Build Coastguard Worker
350*d83cc019SAndroid Build Coastguard Worker return sz;
351*d83cc019SAndroid Build Coastguard Worker }
352*d83cc019SAndroid Build Coastguard Worker
main(int argc,char ** argv)353*d83cc019SAndroid Build Coastguard Worker int main(int argc, char **argv)
354*d83cc019SAndroid Build Coastguard Worker {
355*d83cc019SAndroid Build Coastguard Worker struct gem_busyspin *busy;
356*d83cc019SAndroid Build Coastguard Worker struct sys_wait *wait;
357*d83cc019SAndroid Build Coastguard Worker void *sys_fn = sys_wait;
358*d83cc019SAndroid Build Coastguard Worker pthread_attr_t attr;
359*d83cc019SAndroid Build Coastguard Worker pthread_t bg_fs = 0;
360*d83cc019SAndroid Build Coastguard Worker int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
361*d83cc019SAndroid Build Coastguard Worker igt_stats_t cycles, mean, max;
362*d83cc019SAndroid Build Coastguard Worker double min;
363*d83cc019SAndroid Build Coastguard Worker int time = 10;
364*d83cc019SAndroid Build Coastguard Worker int field = -1;
365*d83cc019SAndroid Build Coastguard Worker int enable_gem_sysbusy = 1;
366*d83cc019SAndroid Build Coastguard Worker bool leak = false;
367*d83cc019SAndroid Build Coastguard Worker bool interrupts = false;
368*d83cc019SAndroid Build Coastguard Worker long batch = 0;
369*d83cc019SAndroid Build Coastguard Worker int n, c;
370*d83cc019SAndroid Build Coastguard Worker
371*d83cc019SAndroid Build Coastguard Worker while ((c = getopt(argc, argv, "r:t:f:bmni1")) != -1) {
372*d83cc019SAndroid Build Coastguard Worker switch (c) {
373*d83cc019SAndroid Build Coastguard Worker case '1':
374*d83cc019SAndroid Build Coastguard Worker ncpus = 1;
375*d83cc019SAndroid Build Coastguard Worker break;
376*d83cc019SAndroid Build Coastguard Worker case 'n': /* dry run, measure baseline system latency */
377*d83cc019SAndroid Build Coastguard Worker enable_gem_sysbusy = 0;
378*d83cc019SAndroid Build Coastguard Worker break;
379*d83cc019SAndroid Build Coastguard Worker case 'i': /* interrupts ahoy! */
380*d83cc019SAndroid Build Coastguard Worker interrupts = true;
381*d83cc019SAndroid Build Coastguard Worker break;
382*d83cc019SAndroid Build Coastguard Worker case 't':
383*d83cc019SAndroid Build Coastguard Worker /* How long to run the benchmark for (seconds) */
384*d83cc019SAndroid Build Coastguard Worker time = atoi(optarg);
385*d83cc019SAndroid Build Coastguard Worker if (time < 0)
386*d83cc019SAndroid Build Coastguard Worker time = INT_MAX;
387*d83cc019SAndroid Build Coastguard Worker break;
388*d83cc019SAndroid Build Coastguard Worker case 'r':
389*d83cc019SAndroid Build Coastguard Worker /* Duration of each batch (microseconds) */
390*d83cc019SAndroid Build Coastguard Worker batch = atoi(optarg);
391*d83cc019SAndroid Build Coastguard Worker break;
392*d83cc019SAndroid Build Coastguard Worker case 'f':
393*d83cc019SAndroid Build Coastguard Worker /* Select an output field */
394*d83cc019SAndroid Build Coastguard Worker field = atoi(optarg);
395*d83cc019SAndroid Build Coastguard Worker break;
396*d83cc019SAndroid Build Coastguard Worker case 'b':
397*d83cc019SAndroid Build Coastguard Worker pthread_create(&bg_fs, NULL,
398*d83cc019SAndroid Build Coastguard Worker background_fs, (void *)"/");
399*d83cc019SAndroid Build Coastguard Worker sleep(5);
400*d83cc019SAndroid Build Coastguard Worker break;
401*d83cc019SAndroid Build Coastguard Worker case 'm':
402*d83cc019SAndroid Build Coastguard Worker sys_fn = sys_thp_alloc;
403*d83cc019SAndroid Build Coastguard Worker leak = true;
404*d83cc019SAndroid Build Coastguard Worker break;
405*d83cc019SAndroid Build Coastguard Worker default:
406*d83cc019SAndroid Build Coastguard Worker break;
407*d83cc019SAndroid Build Coastguard Worker }
408*d83cc019SAndroid Build Coastguard Worker }
409*d83cc019SAndroid Build Coastguard Worker
410*d83cc019SAndroid Build Coastguard Worker /* Prevent CPU sleeps so that busy and idle loads are consistent. */
411*d83cc019SAndroid Build Coastguard Worker force_low_latency();
412*d83cc019SAndroid Build Coastguard Worker min = min_measurement_error();
413*d83cc019SAndroid Build Coastguard Worker
414*d83cc019SAndroid Build Coastguard Worker if (batch > 0)
415*d83cc019SAndroid Build Coastguard Worker batch = calibrate_nop(batch, 2);
416*d83cc019SAndroid Build Coastguard Worker else
417*d83cc019SAndroid Build Coastguard Worker batch = -batch;
418*d83cc019SAndroid Build Coastguard Worker
419*d83cc019SAndroid Build Coastguard Worker busy = calloc(ncpus, sizeof(*busy));
420*d83cc019SAndroid Build Coastguard Worker pthread_attr_init(&attr);
421*d83cc019SAndroid Build Coastguard Worker if (enable_gem_sysbusy) {
422*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < ncpus; n++) {
423*d83cc019SAndroid Build Coastguard Worker bind_cpu(&attr, n);
424*d83cc019SAndroid Build Coastguard Worker busy[n].sz = batch;
425*d83cc019SAndroid Build Coastguard Worker busy[n].leak = leak;
426*d83cc019SAndroid Build Coastguard Worker busy[n].interrupts = interrupts;
427*d83cc019SAndroid Build Coastguard Worker pthread_create(&busy[n].thread, &attr,
428*d83cc019SAndroid Build Coastguard Worker gem_busyspin, &busy[n]);
429*d83cc019SAndroid Build Coastguard Worker }
430*d83cc019SAndroid Build Coastguard Worker }
431*d83cc019SAndroid Build Coastguard Worker
432*d83cc019SAndroid Build Coastguard Worker wait = calloc(ncpus, sizeof(*wait));
433*d83cc019SAndroid Build Coastguard Worker pthread_attr_init(&attr);
434*d83cc019SAndroid Build Coastguard Worker rtprio(&attr, 99);
435*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < ncpus; n++) {
436*d83cc019SAndroid Build Coastguard Worker igt_mean_init(&wait[n].mean);
437*d83cc019SAndroid Build Coastguard Worker bind_cpu(&attr, n);
438*d83cc019SAndroid Build Coastguard Worker pthread_create(&wait[n].thread, &attr, sys_fn, &wait[n]);
439*d83cc019SAndroid Build Coastguard Worker }
440*d83cc019SAndroid Build Coastguard Worker
441*d83cc019SAndroid Build Coastguard Worker sleep(time);
442*d83cc019SAndroid Build Coastguard Worker done = 1;
443*d83cc019SAndroid Build Coastguard Worker
444*d83cc019SAndroid Build Coastguard Worker igt_stats_init_with_size(&cycles, ncpus);
445*d83cc019SAndroid Build Coastguard Worker if (enable_gem_sysbusy) {
446*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < ncpus; n++) {
447*d83cc019SAndroid Build Coastguard Worker pthread_join(busy[n].thread, NULL);
448*d83cc019SAndroid Build Coastguard Worker igt_stats_push(&cycles, busy[n].count);
449*d83cc019SAndroid Build Coastguard Worker }
450*d83cc019SAndroid Build Coastguard Worker }
451*d83cc019SAndroid Build Coastguard Worker
452*d83cc019SAndroid Build Coastguard Worker igt_stats_init_with_size(&mean, ncpus);
453*d83cc019SAndroid Build Coastguard Worker igt_stats_init_with_size(&max, ncpus);
454*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < ncpus; n++) {
455*d83cc019SAndroid Build Coastguard Worker pthread_join(wait[n].thread, NULL);
456*d83cc019SAndroid Build Coastguard Worker igt_stats_push_float(&mean, wait[n].mean.mean);
457*d83cc019SAndroid Build Coastguard Worker igt_stats_push_float(&max, wait[n].mean.max);
458*d83cc019SAndroid Build Coastguard Worker }
459*d83cc019SAndroid Build Coastguard Worker if (bg_fs) {
460*d83cc019SAndroid Build Coastguard Worker pthread_cancel(bg_fs);
461*d83cc019SAndroid Build Coastguard Worker pthread_join(bg_fs, NULL);
462*d83cc019SAndroid Build Coastguard Worker }
463*d83cc019SAndroid Build Coastguard Worker
464*d83cc019SAndroid Build Coastguard Worker switch (field) {
465*d83cc019SAndroid Build Coastguard Worker default:
466*d83cc019SAndroid Build Coastguard Worker printf("gem_syslatency: cycles=%.0f, latency mean=%.3fus max=%.0fus\n",
467*d83cc019SAndroid Build Coastguard Worker igt_stats_get_mean(&cycles),
468*d83cc019SAndroid Build Coastguard Worker (igt_stats_get_mean(&mean) - min)/ 1000,
469*d83cc019SAndroid Build Coastguard Worker (l_estimate(&max) - min) / 1000);
470*d83cc019SAndroid Build Coastguard Worker break;
471*d83cc019SAndroid Build Coastguard Worker case 0:
472*d83cc019SAndroid Build Coastguard Worker printf("%.0f\n", igt_stats_get_mean(&cycles));
473*d83cc019SAndroid Build Coastguard Worker break;
474*d83cc019SAndroid Build Coastguard Worker case 1:
475*d83cc019SAndroid Build Coastguard Worker printf("%.3f\n", (igt_stats_get_mean(&mean) - min) / 1000);
476*d83cc019SAndroid Build Coastguard Worker break;
477*d83cc019SAndroid Build Coastguard Worker case 2:
478*d83cc019SAndroid Build Coastguard Worker printf("%.0f\n", (l_estimate(&max) - min) / 1000);
479*d83cc019SAndroid Build Coastguard Worker break;
480*d83cc019SAndroid Build Coastguard Worker }
481*d83cc019SAndroid Build Coastguard Worker
482*d83cc019SAndroid Build Coastguard Worker return 0;
483*d83cc019SAndroid Build Coastguard Worker
484*d83cc019SAndroid Build Coastguard Worker }
485