diff options
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/gem_cpu_reloc.c | 167 |
3 files changed, 169 insertions, 0 deletions
diff --git a/tests/.gitignore b/tests/.gitignore index cd65f5ac..0d0f178a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -11,6 +11,7 @@ gem_basic gem_cacheing gem_cs_prefetch gem_cpu_concurrent_blit +gem_cpu_reloc gem_ctx_bad_destroy gem_ctx_bad_exec gem_ctx_basic diff --git a/tests/Makefile.am b/tests/Makefile.am index d88a83a3..956a7243 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,6 +50,7 @@ TESTS_progs = \ gem_gtt_speed \ gem_gtt_cpu_tlb \ gem_cs_prefetch \ + gem_cpu_reloc \ gen3_render_linear_blits \ gen3_render_tiledx_blits \ gen3_render_tiledy_blits \ diff --git a/tests/gem_cpu_reloc.c b/tests/gem_cpu_reloc.c new file mode 100644 index 00000000..27784717 --- /dev/null +++ b/tests/gem_cpu_reloc.c @@ -0,0 +1,167 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +/* + * Testcase: Test the relocations through the CPU domain + * + * Attempt to stress test performing relocations whilst the batch is in the + * CPU domain. + * + * A freshly allocated buffer starts in the CPU domain, and the pwrite + * should also be performed whilst in the CPU domain and so we should + * execute the relocations within the CPU domain. If for any reason one of + * those steps should land it in the GTT domain, we take the secondary + * precaution of filling the mappable portion of the GATT. + * + * In order to detect whether a relocation fails, we first fill a target + * buffer with a sequence of invalid commands that would cause the GPU to + * immediate hang, and then attempt to overwrite them with a legal, if + * short, batchbuffer using a BLT. Then we come to execute the bo, if the + * relocation fail and we either copy across all zeros or garbage, then the + * GPU will hang. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include "drm.h" +#include "i915_drm.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_gpu_tools.h" + +static void copy(int fd, uint32_t batch, uint32_t src, uint32_t dst) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_relocation_entry gem_reloc[2]; + struct drm_i915_gem_exec_object2 gem_exec[3]; + + gem_reloc[0].offset = 4 * sizeof(uint32_t); + gem_reloc[0].delta = 0; + gem_reloc[0].target_handle = dst; + gem_reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + gem_reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + gem_reloc[0].presumed_offset = 0; + + gem_reloc[1].offset = 7 * sizeof(uint32_t); + gem_reloc[1].delta = 0; + gem_reloc[1].target_handle = src; + gem_reloc[1].read_domains = I915_GEM_DOMAIN_RENDER; + gem_reloc[1].write_domain = 0; + gem_reloc[1].presumed_offset = 0; + + memset(gem_exec, 0, sizeof(gem_exec)); + gem_exec[0].handle = src; + gem_exec[1].handle = dst; + gem_exec[2].handle = batch; + gem_exec[2].relocation_count = 2; + gem_exec[2].relocs_ptr = (uintptr_t)gem_reloc; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 3; + execbuf.batch_len = 4096; + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); +} + +static void exec(int fd, uint32_t handle) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec; + + memset(&gem_exec, 0, sizeof(gem_exec)); + gem_exec.handle = handle; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)&gem_exec; + execbuf.buffer_count = 1; + execbuf.batch_len = 4096; + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); +} + +int main(int argc, char **argv) +{ + const uint32_t batch[] = { + (XY_SRC_COPY_BLT_CMD | + XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB), + (3 << 24 | /* 32 bits */ + 0xcc << 16 | /* copy ROP */ + 4096), + 0 << 16 | 0, /* dst x1, y1 */ + 1 << 16 | 2, + 0, /* dst relocation */ + 0 << 16 | 0, /* src x1, y1 */ + 4096, + 0, /* src relocation */ + MI_BATCH_BUFFER_END, + }; + const uint32_t hang[] = {-1, -1, -1, -1}; + const uint32_t end[] = {MI_BATCH_BUFFER_END, 0}; + uint64_t aper_size; + uint32_t noop; + int fd, i, count; + + fd = drm_open_any(); + aper_size = gem_aperture_size(fd); + count = aper_size / 4096 * 2; + + noop = gem_create(fd, 4096); + gem_write(fd, noop, 0, end, sizeof(end)); + + /* fill the entire gart with batches and run them */ + for (i = 0; i < count; i++) { + uint32_t handle, bad; + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + bad = gem_create(fd, 4096); + gem_write(fd, bad, 0, hang, sizeof(hang)); + + /* launch the newly created batch */ + copy(fd, handle, noop, bad); + exec(fd, bad); + gem_close(fd, bad); + + drmtest_progress("gem_cpu_reloc: ", i, count); + } + + fprintf(stderr, "Test suceeded, cleanup up - this might take a while.\n"); + close(fd); + + return 0; +} |