edf5e608c76346f4231cf4f0b2291a4d5374582c
[platform/upstream/intel-gpu-tools.git] / tests / gem_pin.c
1 /*
2  * Copyright © 20013 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 /* Exercises pinning of small bo */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <fcntl.h>
35 #include <inttypes.h>
36 #include <errno.h>
37 #include <sys/stat.h>
38 #include <sys/time.h>
39 #include "drm.h"
40 #include "i915_drm.h"
41 #include "drmtest.h"
42 #include "intel_chipset.h"
43 #include "intel_gpu_tools.h"
44
45 #define COPY_BLT_CMD            (2<<29|0x53<<22|0x6)
46 #define BLT_WRITE_ALPHA         (1<<21)
47 #define BLT_WRITE_RGB           (1<<20)
48
49 static void exec(int fd, uint32_t handle, uint32_t offset)
50 {
51         struct drm_i915_gem_execbuffer2 execbuf;
52         struct drm_i915_gem_exec_object2 gem_exec[1];
53         struct drm_i915_gem_relocation_entry gem_reloc[1];
54
55         gem_reloc[0].offset = 1024;
56         gem_reloc[0].delta = 0;
57         gem_reloc[0].target_handle = handle;
58         gem_reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
59         gem_reloc[0].write_domain = 0;
60         gem_reloc[0].presumed_offset = 0;
61
62         gem_exec[0].handle = handle;
63         gem_exec[0].relocation_count = 1;
64         gem_exec[0].relocs_ptr = (uintptr_t) gem_reloc;
65         gem_exec[0].alignment = 0;
66         gem_exec[0].offset = 0;
67         gem_exec[0].flags = 0;
68         gem_exec[0].rsvd1 = 0;
69         gem_exec[0].rsvd2 = 0;
70
71         execbuf.buffers_ptr = (uintptr_t)gem_exec;
72         execbuf.buffer_count = 1;
73         execbuf.batch_start_offset = 0;
74         execbuf.batch_len = 8;
75         execbuf.cliprects_ptr = 0;
76         execbuf.num_cliprects = 0;
77         execbuf.DR1 = 0;
78         execbuf.DR4 = 0;
79         execbuf.flags = 0;
80         i915_execbuffer2_set_context_id(execbuf, 0);
81         execbuf.rsvd2 = 0;
82
83         do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
84         assert(gem_exec[0].offset == offset);
85 }
86
87 static int gem_linear_blt(uint32_t *batch,
88                           uint32_t src,
89                           uint32_t dst,
90                           uint32_t length,
91                           struct drm_i915_gem_relocation_entry *reloc)
92 {
93         uint32_t *b = batch;
94
95         b[0] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB;
96         b[1] = 0x66 << 16 | 1 << 25 | 1 << 24 | (4*1024);
97         b[2] = 0;
98         b[3] = (length / (4*1024)) << 16 | 1024;
99         b[4] = 0;
100         reloc->offset = (b-batch+4) * sizeof(uint32_t);
101         reloc->delta = 0;
102         reloc->target_handle = dst;
103         reloc->read_domains = I915_GEM_DOMAIN_RENDER;
104         reloc->write_domain = I915_GEM_DOMAIN_RENDER;
105         reloc->presumed_offset = 0;
106         reloc++;
107
108         b[5] = 0;
109         b[6] = 4*1024;
110         b[7] = 0;
111         reloc->offset = (b-batch+7) * sizeof(uint32_t);
112         reloc->delta = 0;
113         reloc->target_handle = src;
114         reloc->read_domains = I915_GEM_DOMAIN_RENDER;
115         reloc->write_domain = 0;
116         reloc->presumed_offset = 0;
117         reloc++;
118
119         b += 8;
120
121         b[0] = MI_BATCH_BUFFER_END;
122         b[1] = 0;
123
124         return (b+2 - batch) * sizeof(uint32_t);
125 }
126
127 static void make_busy(int fd, uint32_t handle)
128 {
129         struct drm_i915_gem_execbuffer2 execbuf;
130         struct drm_i915_gem_exec_object2 obj[2];
131         struct drm_i915_gem_relocation_entry reloc[2];
132         uint32_t batch[20];
133         uint32_t tmp;
134         int count;
135
136         tmp = gem_create(fd, 1024*1024);
137
138         obj[0].handle = tmp;
139         obj[0].relocation_count = 0;
140         obj[0].relocs_ptr = 0;
141         obj[0].alignment = 0;
142         obj[0].offset = 0;
143         obj[0].flags = 0;
144         obj[0].rsvd1 = 0;
145         obj[0].rsvd2 = 0;
146
147         obj[1].handle = handle;
148         obj[1].relocation_count = 2;
149         obj[1].relocs_ptr = (uintptr_t) reloc;
150         obj[1].alignment = 0;
151         obj[1].offset = 0;
152         obj[1].flags = 0;
153         obj[1].rsvd1 = 0;
154         obj[1].rsvd2 = 0;
155
156         execbuf.buffers_ptr = (uintptr_t)obj;
157         execbuf.buffer_count = 2;
158         execbuf.batch_start_offset = 0;
159         execbuf.batch_len = gem_linear_blt(batch, tmp, tmp, 1024*1024,reloc);
160         execbuf.cliprects_ptr = 0;
161         execbuf.num_cliprects = 0;
162         execbuf.DR1 = 0;
163         execbuf.DR4 = 0;
164         execbuf.flags = 0;
165         if (HAS_BLT_RING(intel_get_drm_devid(fd)))
166                 execbuf.flags |= I915_EXEC_BLT;
167         i915_execbuffer2_set_context_id(execbuf, 0);
168         execbuf.rsvd2 = 0;
169
170         gem_write(fd, handle, 0, batch, execbuf.batch_len);
171         for (count = 0; count < 10; count++)
172                 do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
173         gem_close(fd, tmp);
174 }
175
176 static int test_can_pin(int fd)
177 {
178         struct drm_i915_gem_pin pin;
179         int ret;
180
181         pin.handle = gem_create(fd, 4096);;
182         pin.alignment = 0;
183         ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PIN, &pin);
184         gem_close(fd, pin.handle);
185
186         return ret == 0;;
187 }
188
189 static uint32_t gem_pin(int fd, int handle, int alignment)
190 {
191         struct drm_i915_gem_pin pin;
192
193         pin.handle = handle;
194         pin.alignment = alignment;
195         do_ioctl(fd, DRM_IOCTL_I915_GEM_PIN, &pin);
196         return pin.offset;
197 }
198
199 int main(int argc, char **argv)
200 {
201         const uint32_t batch[2] = {MI_BATCH_BUFFER_END};
202         struct timeval start, now;
203         uint32_t *handle, *offset;
204         int fd, i;
205
206         fd = drm_open_any();
207
208         if (!test_can_pin(fd))
209                 return 77;
210
211         handle = malloc(sizeof(uint32_t)*100);
212         offset = malloc(sizeof(uint32_t)*100);
213
214         /* Race creation/use against interrupts */
215         drmtest_fork_signal_helper();
216         gettimeofday(&start, NULL);
217         do {
218                 for (i = 0; i < 100; i++) {
219                         if (i & 1) {
220                                 /* pin anidle bo */
221                                 handle[i] = gem_create(fd, 4096);
222                                 offset[i] = gem_pin(fd, handle[i], 0);
223                                 assert(offset[i]);
224                                 gem_write(fd, handle[i], 0, batch, sizeof(batch));
225                         } else {
226                                 /* try to pin an anidle bo */
227                                 handle[i] = gem_create(fd, 4096);
228                                 make_busy(fd, handle[i]);
229                                 offset[i] = gem_pin(fd, handle[i], 256*1024);
230                                 assert(offset[i]);
231                                 assert((offset[i] & (256*1024-1)) == 0);
232                                 gem_write(fd, handle[i], 0, batch, sizeof(batch));
233                         }
234                 }
235                 for (i = 0; i < 1000; i++) {
236                         int j = rand() % 100;
237                         exec(fd, handle[j], offset[j]);
238                 }
239                 for (i = 0; i < 100; i++)
240                         gem_close(fd, handle[i]);
241                 gettimeofday(&now, NULL);
242         } while ((now.tv_sec - start.tv_sec)*1000 + (now.tv_usec - start.tv_usec) / 1000 < 10000);
243         drmtest_stop_signal_helper();
244
245         return 0;
246 }