blob: 21bdbc9b67aaa48900dacbf863f2e579a4a10978 [file] [log] [blame]
Chris Wilson99c015a2016-05-19 15:20:38 +01001/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Chris Wilson <chris@chris-wilson.co.uk>
25 *
26 */
27
28/* Measure the time it to takes to bind/unbind objects from the ppGTT */
29
30#include <unistd.h>
31#include <stdlib.h>
32#include <stdint.h>
33#include <stdio.h>
34#include <string.h>
35#include <fcntl.h>
36#include <inttypes.h>
37#include <errno.h>
38#include <sys/stat.h>
39#include <sys/ioctl.h>
40#include <sys/time.h>
41#include <time.h>
42
43#include "drm.h"
44#include "ioctl_wrappers.h"
45#include "drmtest.h"
46#include "intel_io.h"
47#include "igt_stats.h"
48
49#define LOCAL_I915_EXEC_NO_RELOC (1<<11)
50#define LOCAL_I915_EXEC_HANDLE_LUT (1<<12)
51
52#define LOCAL_I915_EXEC_BSD_SHIFT (13)
53#define LOCAL_I915_EXEC_BSD_MASK (3 << LOCAL_I915_EXEC_BSD_SHIFT)
54
55#define ENGINE_FLAGS (I915_EXEC_RING_MASK | LOCAL_I915_EXEC_BSD_MASK)
56
57static double elapsed(const struct timespec *start,
58 const struct timespec *end)
59{
60 return (end->tv_sec - start->tv_sec) + 1e-9*(end->tv_nsec - start->tv_nsec);
61}
62
Chris Wilson3df22e02017-09-08 10:46:24 +010063static uint32_t batch(int fd, uint64_t size)
Chris Wilson99c015a2016-05-19 15:20:38 +010064{
Chris Wilson3df22e02017-09-08 10:46:24 +010065 const uint32_t bbe = MI_BATCH_BUFFER_END;
Chris Wilson99c015a2016-05-19 15:20:38 +010066 uint32_t handle = gem_create(fd, size);
Chris Wilson3df22e02017-09-08 10:46:24 +010067 gem_write(fd, handle, 0, &bbe, sizeof(bbe));
Chris Wilson99c015a2016-05-19 15:20:38 +010068 return handle;
69}
70
Chris Wilson3df22e02017-09-08 10:46:24 +010071static int loop(uint64_t size, unsigned ring, int reps, int ncpus, unsigned flags)
Chris Wilson99c015a2016-05-19 15:20:38 +010072{
73 struct drm_i915_gem_execbuffer2 execbuf;
74 struct drm_i915_gem_exec_object2 obj;
75 unsigned engines[16];
76 unsigned nengine;
77 double *shared;
78 int fd;
79
80 shared = mmap(0, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
81
82 fd = drm_open_driver(DRIVER_INTEL);
83
84 memset(&obj, 0, sizeof(obj));
Chris Wilson3df22e02017-09-08 10:46:24 +010085 obj.handle = batch(fd, 4096);
Chris Wilson99c015a2016-05-19 15:20:38 +010086
87 memset(&execbuf, 0, sizeof(execbuf));
88 execbuf.buffers_ptr = (uintptr_t)&obj;
89 execbuf.buffer_count = 1;
90 execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT;
91 execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
92 if (__gem_execbuf(fd, &execbuf)) {
93 execbuf.flags = 0;
94 if (__gem_execbuf(fd, &execbuf))
95 return 77;
96 }
Chris Wilson3df22e02017-09-08 10:46:24 +010097 /* let the small object leak; ideally blocking the low address */
Chris Wilson99c015a2016-05-19 15:20:38 +010098
99 nengine = 0;
100 if (ring == -1) {
101 for (ring = 1; ring < 16; ring++) {
102 execbuf.flags &= ~ENGINE_FLAGS;
103 execbuf.flags |= ring;
104 if (__gem_execbuf(fd, &execbuf) == 0)
105 engines[nengine++] = ring;
106 }
107 } else
108 engines[nengine++] = ring;
109
Chris Wilson3df22e02017-09-08 10:46:24 +0100110 if (size > 1ul << 31)
111 obj.flags |= 1 << 3;
112
Chris Wilson99c015a2016-05-19 15:20:38 +0100113 while (reps--) {
114 memset(shared, 0, 4096);
115
116 igt_fork(child, ncpus) {
117 struct timespec start, end;
118 unsigned count = 0;
119
120 obj.handle = batch(fd, size);
Chris Wilson3df22e02017-09-08 10:46:24 +0100121 obj.offset = -1;
Chris Wilson99c015a2016-05-19 15:20:38 +0100122
123 clock_gettime(CLOCK_MONOTONIC, &start);
124 do {
125 for (int inner = 0; inner < 1024; inner++) {
126 execbuf.flags &= ~ENGINE_FLAGS;
127 execbuf.flags |= engines[count++ % nengine];
128 /* fault in */
Chris Wilsonbde2aee2016-05-19 16:59:37 +0100129 obj.alignment = 0;
Chris Wilson99c015a2016-05-19 15:20:38 +0100130 gem_execbuf(fd, &execbuf);
131
132 /* fault out */
133 obj.alignment = 1ull << 63;
134 __gem_execbuf(fd, &execbuf);
135 }
136
137 clock_gettime(CLOCK_MONOTONIC, &end);
138 } while (elapsed(&start, &end) < 2.);
139
140 gem_sync(fd, obj.handle);
141 clock_gettime(CLOCK_MONOTONIC, &end);
142 shared[child] = 1e6*elapsed(&start, &end) / count / 2;
143
144 gem_close(fd, obj.handle);
145 }
146 igt_waitchildren();
147
148 for (int child = 0; child < ncpus; child++)
149 shared[ncpus] += shared[child];
150 printf("%7.3f\n", shared[ncpus] / ncpus);
151 }
152 return 0;
153}
154
155int main(int argc, char **argv)
156{
157 unsigned ring = I915_EXEC_RENDER;
158 unsigned flags = 0;
Chris Wilson3df22e02017-09-08 10:46:24 +0100159 uint64_t size = 4096;
Chris Wilson99c015a2016-05-19 15:20:38 +0100160 int reps = 1;
161 int ncpus = 1;
162 int c;
163
164 while ((c = getopt (argc, argv, "e:r:s:f")) != -1) {
165 switch (c) {
166 case 'e':
167 if (strcmp(optarg, "rcs") == 0)
168 ring = I915_EXEC_RENDER;
169 else if (strcmp(optarg, "vcs") == 0)
170 ring = I915_EXEC_BSD;
171 else if (strcmp(optarg, "bcs") == 0)
172 ring = I915_EXEC_BLT;
173 else if (strcmp(optarg, "vecs") == 0)
174 ring = I915_EXEC_VEBOX;
175 else if (strcmp(optarg, "all") == 0)
176 ring = -1;
177 else
178 ring = atoi(optarg);
179 break;
180
181 case 'r':
182 reps = atoi(optarg);
183 if (reps < 1)
184 reps = 1;
185 break;
186
187 case 'f':
188 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
189 break;
190
191 case 's':
Chris Wilson3df22e02017-09-08 10:46:24 +0100192 size = strtoull(optarg, NULL, 0);
Chris Wilson99c015a2016-05-19 15:20:38 +0100193 if (size < 4096)
194 size = 4096;
195 break;
196
197 default:
198 break;
199 }
200 }
201
202 return loop(size, ring, reps, ncpus, flags);
203}