1 /*
2 * Copyright © 2011-2015 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 <[email protected]>
25 *
26 */
27
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <inttypes.h>
35 #include <errno.h>
36 #include <sys/stat.h>
37 #include <sys/ioctl.h>
38 #include <sys/time.h>
39 #include <time.h>
40
41 #include "drm.h"
42 #include "ioctl_wrappers.h"
43 #include "drmtest.h"
44 #include "igt_aux.h"
45 #include "igt_stats.h"
46 #include "i915/gem_mman.h"
47
48 #define OBJECT_SIZE (1<<23)
49
elapsed(const struct timespec * start,const struct timespec * end)50 static double elapsed(const struct timespec *start,
51 const struct timespec *end)
52 {
53 return (end->tv_sec - start->tv_sec) + 1e-9*(end->tv_nsec - start->tv_nsec);
54 }
55
main(int argc,char ** argv)56 int main(int argc, char **argv)
57 {
58 int fd = drm_open_driver(DRIVER_INTEL);
59 enum map {CPU, GTT, WC} map = CPU;
60 enum dir {READ, WRITE, CLEAR, FAULT} dir = READ;
61 int tiling = I915_TILING_NONE;
62 struct timespec start, end;
63 void *buf = malloc(OBJECT_SIZE);
64 uint32_t handle;
65 void *ptr, *src, *dst;
66 int reps = 1;
67 int loops;
68 int c;
69
70 while ((c = getopt (argc, argv, "m:d:r:t:")) != -1) {
71 switch (c) {
72 case 'm':
73 if (strcmp(optarg, "cpu") == 0)
74 map = CPU;
75 else if (strcmp(optarg, "gtt") == 0)
76 map = GTT;
77 else if (strcmp(optarg, "wc") == 0)
78 map = WC;
79 else
80 abort();
81 break;
82
83 case 'd':
84 if (strcmp(optarg, "read") == 0)
85 dir = READ;
86 else if (strcmp(optarg, "write") == 0)
87 dir = WRITE;
88 else if (strcmp(optarg, "clear") == 0)
89 dir = CLEAR;
90 else if (strcmp(optarg, "fault") == 0)
91 dir = FAULT;
92 else
93 abort();
94 break;
95
96 case 't':
97 if (strcmp(optarg, "x") == 0)
98 tiling = I915_TILING_X;
99 else if (strcmp(optarg, "y") == 0)
100 tiling = I915_TILING_Y;
101 else if (strcmp(optarg, "none") == 0)
102 tiling = I915_TILING_NONE;
103 else
104 abort();
105 break;
106
107 case 'r':
108 reps = atoi(optarg);
109 if (reps < 1)
110 reps = 1;
111 break;
112
113 default:
114 break;
115 }
116 }
117
118 handle = gem_create(fd, OBJECT_SIZE);
119 switch (map) {
120 case CPU:
121 ptr = gem_mmap__cpu(fd, handle, 0, OBJECT_SIZE, PROT_WRITE);
122 gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
123 break;
124 case GTT:
125 ptr = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_WRITE);
126 gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
127 break;
128 case WC:
129 ptr = gem_mmap__wc(fd, handle, 0, OBJECT_SIZE, PROT_WRITE);
130 gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
131 break;
132 default:
133 abort();
134 }
135
136 gem_set_tiling(fd, handle, tiling, 512);
137
138 if (dir == READ) {
139 src = ptr;
140 dst = buf;
141 } else {
142 src = buf;
143 dst = ptr;
144 }
145
146 clock_gettime(CLOCK_MONOTONIC, &start);
147 switch (dir) {
148 case CLEAR:
149 case FAULT:
150 memset(dst, 0, OBJECT_SIZE);
151 break;
152 default:
153 memcpy(dst, src, OBJECT_SIZE);
154 break;
155 }
156 clock_gettime(CLOCK_MONOTONIC, &end);
157
158 loops = 2 / elapsed(&start, &end);
159 while (reps--) {
160 clock_gettime(CLOCK_MONOTONIC, &start);
161 for (c = 0; c < loops; c++) {
162 int page;
163
164 switch (dir) {
165 case CLEAR:
166 memset(dst, 0, OBJECT_SIZE);
167 break;
168 case FAULT:
169 munmap(ptr, OBJECT_SIZE);
170 switch (map) {
171 case CPU:
172 ptr = gem_mmap__cpu(fd, handle, 0, OBJECT_SIZE, PROT_WRITE);
173 break;
174 case GTT:
175 ptr = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_WRITE);
176 break;
177 case WC:
178 ptr = gem_mmap__wc(fd, handle, 0, OBJECT_SIZE, PROT_WRITE);
179 break;
180 default:
181 abort();
182 }
183 for (page = 0; page < OBJECT_SIZE; page += 4096) {
184 uint32_t *x = (uint32_t *)ptr + page/4;
185 __asm__ __volatile__("": : :"memory");
186 page += *x; /* should be zero! */
187 }
188 break;
189 default:
190 memcpy(dst, src, OBJECT_SIZE);
191 break;
192 }
193 }
194 clock_gettime(CLOCK_MONOTONIC, &end);
195 printf("%7.3f\n", OBJECT_SIZE / elapsed(&start, &end) * loops / (1024*1024));
196 }
197
198 return 0;
199 }
200