2 * Copyright © 2013 Intel Corporation
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:
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
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
24 * Daniel Vetter <daniel.vetter@ffwll.ch>
42 #include "ioctl_wrappers.h"
44 #include "intel_chipset.h"
46 #include "igt_debugfs.h"
50 * Testcase: Persistent relocations as used by uxa/libva
54 static drm_intel_bufmgr *bufmgr;
55 struct intel_batchbuffer *batch;
57 uint32_t blob[2048*2048];
58 #define NUM_TARGET_BOS 16
59 drm_intel_bo *pc_target_bo[NUM_TARGET_BOS];
60 drm_intel_bo *dummy_bo;
61 drm_intel_bo *special_bos[NUM_TARGET_BOS];
62 uint32_t relocs_bo_handle[NUM_TARGET_BOS];
63 void *gtt_relocs_ptr[NUM_TARGET_BOS];
65 int special_reloc_ofs;
67 int special_batch_len;
71 static drm_intel_bo *create_special_bo(void)
76 #define BATCH(dw) data[len++] = (dw);
78 memset(data, 0, 4096);
79 bo = drm_intel_bo_alloc(bufmgr, "special batch", 4096, 4096);
81 if (intel_gen(devid) >= 8) {
83 BATCH(XY_COLOR_BLT_CMD_NOLEN | 5 |
84 COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
86 BATCH(XY_COLOR_BLT_CMD_NOLEN | 4 |
87 COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
90 BATCH((3 << 24) | (0xf0 << 16) | small_pitch);
91 special_line_ofs = 4*len;
94 special_reloc_ofs = 4*len;
96 if (intel_gen(devid) >= 8)
100 #define CMD_POLY_STIPPLE_OFFSET 0x7906
101 /* batchbuffer end */
102 if (IS_GEN5(batch->devid)) {
103 BATCH(CMD_POLY_STIPPLE_OFFSET << 16);
106 igt_assert(len % 2 == 0);
108 BATCH(MI_BATCH_BUFFER_END);
110 drm_intel_bo_subdata(bo, 0, 4096, data);
111 special_batch_len = len*4;
116 static void emit_dummy_load(int pitch)
119 uint32_t tile_flags = 0;
123 tile_flags = XY_SRC_COPY_BLT_SRC_TILED |
124 XY_SRC_COPY_BLT_DST_TILED;
127 for (i = 0; i < 5; i++) {
128 BLIT_COPY_BATCH_START(devid, tile_flags);
129 OUT_BATCH((3 << 24) | /* 32 bits */
130 (0xcc << 16) | /* copy ROP */
132 OUT_BATCH(0 << 16 | 1024);
133 OUT_BATCH((2048) << 16 | (2048));
134 OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
135 BLIT_RELOC_UDW(devid);
136 OUT_BATCH(0 << 16 | 0);
138 OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
139 BLIT_RELOC_UDW(devid);
142 if (intel_gen(devid) >= 6) {
144 OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
150 intel_batchbuffer_flush(batch);
153 static void faulting_reloc_and_emit(int fd, drm_intel_bo *target_bo,
154 void *gtt_relocs, drm_intel_bo *special_bo)
156 struct drm_i915_gem_execbuffer2 execbuf;
157 struct drm_i915_gem_exec_object2 exec[2];
160 if (intel_gen(devid) >= 6)
161 ring = I915_EXEC_BLT;
165 exec[0].handle = target_bo->handle;
166 exec[0].relocation_count = 0;
167 exec[0].relocs_ptr = 0;
168 exec[0].alignment = 0;
174 exec[1].handle = special_bo->handle;
175 exec[1].relocation_count = 1;
176 /* A newly mmap gtt bo will fault on first access. */
177 exec[1].relocs_ptr = (uintptr_t)gtt_relocs;
178 exec[1].alignment = 0;
184 execbuf.buffers_ptr = (uintptr_t)exec;
185 execbuf.buffer_count = 2;
186 execbuf.batch_start_offset = 0;
187 execbuf.batch_len = special_batch_len;
188 execbuf.cliprects_ptr = 0;
189 execbuf.num_cliprects = 0;
192 execbuf.flags = ring;
193 i915_execbuffer2_set_context_id(execbuf, 0);
196 gem_execbuf(fd, &execbuf);
199 static void do_test(int fd, bool faulting_reloc)
201 uint32_t tiling_mode = I915_TILING_X;
202 unsigned long pitch, act_size;
207 igt_disable_prefault();
210 dummy_bo = drm_intel_bo_alloc_tiled(bufmgr, "tiled dummy_bo", act_size, act_size,
211 4, &tiling_mode, &pitch, 0);
213 drm_intel_bo_subdata(dummy_bo, 0, act_size*act_size*4, blob);
215 for (i = 0; i < NUM_TARGET_BOS; i++) {
216 struct drm_i915_gem_relocation_entry reloc[1];
218 special_bos[i] = create_special_bo();
219 pc_target_bo[i] = drm_intel_bo_alloc(bufmgr, "special batch", 4096, 4096);
220 igt_assert(pc_target_bo[i]->offset == 0);
222 reloc[0].offset = special_reloc_ofs;
224 reloc[0].target_handle = pc_target_bo[i]->handle;
225 reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
226 reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
227 reloc[0].presumed_offset = 0;
229 relocs_bo_handle[i] = gem_create(fd, 4096);
230 gem_write(fd, relocs_bo_handle[i], 0, reloc, sizeof(reloc));
231 gtt_relocs_ptr[i] = gem_mmap(fd, relocs_bo_handle[i], 4096,
232 PROT_READ | PROT_WRITE);
233 igt_assert(gtt_relocs_ptr[i]);
237 /* repeat must be smaller than 4096/small_pitch */
238 for (repeat = 0; repeat < 8; repeat++) {
239 for (i = 0; i < NUM_TARGET_BOS; i++) {
242 ((repeat + 1) << 16) | 1
245 drm_intel_bo_subdata(special_bos[i], special_line_ofs, 8, &data);
247 emit_dummy_load(pitch);
248 faulting_reloc_and_emit(fd, pc_target_bo[i],
254 /* Only check at the end to avoid unnecessarily synchronous behaviour. */
255 for (i = 0; i < NUM_TARGET_BOS; i++) {
256 /* repeat must be smaller than 4096/small_pitch */
257 for (repeat = 0; repeat < 8; repeat++) {
258 drm_intel_bo_get_subdata(pc_target_bo[i],
259 repeat*small_pitch, 4, &test);
260 igt_assert_f(test == 0xdeadbeef,
261 "mismatch in buffer %i: 0x%08x instead of 0xdeadbeef at offset %i\n",
262 i, test, repeat*small_pitch);
264 drm_intel_bo_unreference(pc_target_bo[i]);
265 drm_intel_bo_unreference(special_bos[i]);
266 gem_close(fd, relocs_bo_handle[i]);
267 munmap(gtt_relocs_ptr[i], 4096);
270 drm_intel_gem_bo_map_gtt(dummy_bo);
271 drm_intel_gem_bo_unmap_gtt(dummy_bo);
273 drm_intel_bo_unreference(dummy_bo);
276 igt_enable_prefault();
279 #define INTERRUPT (1 << 0)
280 #define FAULTING (1 << 1)
281 #define THRASH (1 << 2)
282 #define THRASH_INACTIVE (1 << 3)
283 #define ALL_FLAGS (INTERRUPT | FAULTING | THRASH | THRASH_INACTIVE)
284 static void do_forked_test(int fd, unsigned flags)
286 int num_threads = sysconf(_SC_NPROCESSORS_ONLN);
287 struct igt_helper_process thrasher = {};
289 if (flags & (THRASH | THRASH_INACTIVE)) {
290 uint64_t val = (flags & THRASH_INACTIVE) ?
291 (DROP_RETIRE | DROP_BOUND | DROP_UNBOUND) : DROP_ALL;
293 igt_fork_helper(&thrasher) {
296 igt_drop_caches_set(val);
301 igt_fork(i, num_threads) {
302 /* re-create process local data */
303 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
304 batch = intel_batchbuffer_alloc(bufmgr, devid);
306 if (flags & INTERRUPT)
307 igt_fork_signal_helper();
309 do_test(fd, flags & FAULTING);
311 if (flags & INTERRUPT)
312 igt_stop_signal_helper();
316 if (flags & (THRASH | THRASH_INACTIVE))
317 igt_stop_helper(&thrasher);
322 #define MAX_BLT_SIZE 128
325 igt_skip_on_simulation();
327 memset(blob, 'A', sizeof(blob));
332 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
333 /* disable reuse, otherwise the test fails */
334 //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
335 devid = intel_get_drm_devid(fd);
336 batch = intel_batchbuffer_alloc(bufmgr, devid);
339 igt_subtest("normal")
342 igt_fork_signal_helper();
343 igt_subtest("interruptible")
345 igt_stop_signal_helper();
347 for (unsigned flags = 0; flags <= ALL_FLAGS; flags++) {
348 if ((flags & THRASH) && (flags & THRASH_INACTIVE))
351 igt_subtest_f("forked%s%s%s%s",
352 flags & INTERRUPT ? "-interruptible" : "",
353 flags & FAULTING ? "-faulting-reloc" : "",
354 flags & THRASH ? "-thrashing" : "",
355 flags & THRASH_INACTIVE ? "-thrash-inactive" : "")
356 do_forked_test(fd, flags);
360 intel_batchbuffer_free(batch);
361 drm_intel_bufmgr_destroy(bufmgr);