tests: remove unused getopt header includes
[platform/upstream/intel-gpu-tools.git] / tests / gem_cpu_reloc.c
1 /*
2  * Copyright © 2012 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 /*
29  * Testcase: Test the relocations through the CPU domain
30  *
31  * Attempt to stress test performing relocations whilst the batch is in the
32  * CPU domain.
33  *
34  * A freshly allocated buffer starts in the CPU domain, and the pwrite
35  * should also be performed whilst in the CPU domain and so we should
36  * execute the relocations within the CPU domain. If for any reason one of
37  * those steps should land it in the GTT domain, we take the secondary
38  * precaution of filling the mappable portion of the GATT.
39  *
40  * In order to detect whether a relocation fails, we first fill a target
41  * buffer with a sequence of invalid commands that would cause the GPU to
42  * immediate hang, and then attempt to overwrite them with a legal, if
43  * short, batchbuffer using a BLT. Then we come to execute the bo, if the
44  * relocation fail and we either copy across all zeros or garbage, then the
45  * GPU will hang.
46  */
47
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <fcntl.h>
52 #include <inttypes.h>
53 #include <errno.h>
54 #include <sys/stat.h>
55 #include <sys/time.h>
56
57 #include <drm.h>
58
59 #include "ioctl_wrappers.h"
60 #include "drmtest.h"
61 #include "intel_bufmgr.h"
62 #include "intel_batchbuffer.h"
63 #include "intel_io.h"
64 #include "intel_chipset.h"
65 #include "igt_aux.h"
66
67 static uint32_t use_blt;
68
69 static void copy(int fd, uint32_t batch, uint32_t src, uint32_t dst)
70 {
71         struct drm_i915_gem_execbuffer2 execbuf;
72         struct drm_i915_gem_relocation_entry gem_reloc[2];
73         struct drm_i915_gem_exec_object2 gem_exec[3];
74
75         gem_reloc[0].offset = 4 * sizeof(uint32_t);
76         gem_reloc[0].delta = 0;
77         gem_reloc[0].target_handle = dst;
78         gem_reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
79         gem_reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
80         gem_reloc[0].presumed_offset = 0;
81
82         gem_reloc[1].offset = 7 * sizeof(uint32_t);
83         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
84                 gem_reloc[1].offset += sizeof(uint32_t);
85         gem_reloc[1].delta = 0;
86         gem_reloc[1].target_handle = src;
87         gem_reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
88         gem_reloc[1].write_domain = 0;
89         gem_reloc[1].presumed_offset = 0;
90
91         memset(gem_exec, 0, sizeof(gem_exec));
92         gem_exec[0].handle = src;
93         gem_exec[1].handle = dst;
94         gem_exec[2].handle = batch;
95         gem_exec[2].relocation_count = 2;
96         gem_exec[2].relocs_ptr = (uintptr_t)gem_reloc;
97
98         memset(&execbuf, 0, sizeof(execbuf));
99         execbuf.buffers_ptr = (uintptr_t)gem_exec;
100         execbuf.buffer_count = 3;
101         execbuf.batch_len = 4096;
102         execbuf.flags = use_blt;
103
104         do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
105 }
106
107 static void exec(int fd, uint32_t handle)
108 {
109         struct drm_i915_gem_execbuffer2 execbuf;
110         struct drm_i915_gem_exec_object2 gem_exec;
111
112         memset(&gem_exec, 0, sizeof(gem_exec));
113         gem_exec.handle = handle;
114
115         memset(&execbuf, 0, sizeof(execbuf));
116         execbuf.buffers_ptr = (uintptr_t)&gem_exec;
117         execbuf.buffer_count = 1;
118         execbuf.batch_len = 4096;
119
120         do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
121 }
122
123 uint32_t gen6_batch[] = {
124         (XY_SRC_COPY_BLT_CMD | 6 |
125          XY_SRC_COPY_BLT_WRITE_ALPHA |
126          XY_SRC_COPY_BLT_WRITE_RGB),
127         (3 << 24 | /* 32 bits */
128          0xcc << 16 | /* copy ROP */
129          4096),
130         0 << 16 | 0, /* dst x1, y1 */
131         1 << 16 | 2,
132         0, /* dst relocation */
133         0 << 16 | 0, /* src x1, y1 */
134         4096,
135         0, /* src relocation */
136         MI_BATCH_BUFFER_END,
137 };
138
139 uint32_t gen8_batch[] = {
140         (XY_SRC_COPY_BLT_CMD | 8 |
141          XY_SRC_COPY_BLT_WRITE_ALPHA |
142          XY_SRC_COPY_BLT_WRITE_RGB),
143         (3 << 24 | /* 32 bits */
144          0xcc << 16 | /* copy ROP */
145          4096),
146         0 << 16 | 0, /* dst x1, y1 */
147         1 << 16 | 2,
148         0, /* dst relocation */
149         0, /* FIXME */
150         0 << 16 | 0, /* src x1, y1 */
151         4096,
152         0, /* src relocation */
153         0, /* FIXME */
154         MI_BATCH_BUFFER_END,
155 };
156
157 uint32_t *batch = gen6_batch;
158 uint32_t batch_size = sizeof(gen6_batch);
159
160 igt_simple_main
161 {
162         const uint32_t hang[] = {-1, -1, -1, -1};
163         const uint32_t end[] = {MI_BATCH_BUFFER_END, 0};
164         uint64_t aper_size;
165         uint32_t noop;
166         uint32_t *handles;
167         int fd, i, count;
168
169         fd = drm_open_any();
170         noop = intel_get_drm_devid(fd);
171
172         use_blt = 0;
173         if (intel_gen(noop) >= 6)
174                 use_blt = I915_EXEC_BLT;
175
176         if (intel_gen(noop) >= 8) {
177                 batch = gen8_batch;
178                 batch_size += 2 * 4;
179         }
180
181         aper_size = gem_mappable_aperture_size();
182         igt_skip_on_f(intel_get_total_ram_mb() < aper_size / (1024*1024) * 2,
183                       "not enough mem to run test\n");
184
185         count = aper_size / 4096 * 2;
186         if (igt_run_in_simulation())
187                 count = 10;
188
189         handles = malloc (count * sizeof(uint32_t));
190         igt_assert(handles);
191
192         noop = gem_create(fd, 4096);
193         gem_write(fd, noop, 0, end, sizeof(end));
194
195         /* fill the entire gart with batches and run them */
196         for (i = 0; i < count; i++) {
197                 uint32_t bad;
198
199                 handles[i] = gem_create(fd, 4096);
200                 gem_write(fd, handles[i], 0, batch, batch_size);
201
202                 bad = gem_create(fd, 4096);
203                 gem_write(fd, bad, 0, hang, sizeof(hang));
204
205                 /* launch the newly created batch */
206                 copy(fd, handles[i], noop, bad);
207                 exec(fd, bad);
208                 gem_close(fd, bad);
209
210                 igt_progress("gem_cpu_reloc: ", i, 2*count);
211         }
212
213         /* And again in reverse to try and catch the relocation code out */
214         for (i = 0; i < count; i++) {
215                 uint32_t bad;
216
217                 bad = gem_create(fd, 4096);
218                 gem_write(fd, bad, 0, hang, sizeof(hang));
219
220                 /* launch the newly created batch */
221                 copy(fd, handles[count-i-1], noop, bad);
222                 exec(fd, bad);
223                 gem_close(fd, bad);
224
225                 igt_progress("gem_cpu_reloc: ", count+i, 3*count);
226         }
227
228         /* Third time lucky? */
229         for (i = 0; i < count; i++) {
230                 uint32_t bad;
231
232                 bad = gem_create(fd, 4096);
233                 gem_write(fd, bad, 0, hang, sizeof(hang));
234
235                 /* launch the newly created batch */
236                 gem_set_domain(fd, handles[i],
237                                I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
238                 copy(fd, handles[i], noop, bad);
239                 exec(fd, bad);
240                 gem_close(fd, bad);
241
242                 igt_progress("gem_cpu_reloc: ", 2*count+i, 3*count);
243         }
244
245         igt_info("Test suceeded, cleanup up - this might take a while.\n");
246         close(fd);
247 }