static void exec1(int fd, uint32_t handle, uint64_t reloc_ofs, unsigned flags, char *ptr) { struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 gem_exec[1]; struct drm_i915_gem_relocation_entry gem_reloc[1]; gem_reloc[0].offset = reloc_ofs; gem_reloc[0].delta = 0; gem_reloc[0].target_handle = handle; gem_reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; gem_reloc[0].write_domain = 0; gem_reloc[0].presumed_offset = 0; gem_exec[0].handle = handle; gem_exec[0].relocation_count = 1; gem_exec[0].relocs_ptr = (uintptr_t) gem_reloc; gem_exec[0].alignment = 0; gem_exec[0].offset = 0; gem_exec[0].flags = 0; gem_exec[0].rsvd1 = 0; gem_exec[0].rsvd2 = 0; execbuf.buffers_ptr = (uintptr_t)gem_exec; execbuf.buffer_count = 1; execbuf.batch_start_offset = 0; execbuf.batch_len = 8; execbuf.cliprects_ptr = 0; execbuf.num_cliprects = 0; execbuf.DR1 = 0; execbuf.DR4 = 0; execbuf.flags = flags; i915_execbuffer2_set_context_id(execbuf, 0); execbuf.rsvd2 = 0; /* Avoid hitting slowpaths in the reloc processing which might yield a * presumed_offset of -1. Happens when the batch is still busy from the * last round. */ gem_sync(fd, handle); gem_execbuf(fd, &execbuf); igt_warn_on(gem_reloc[0].presumed_offset == -1); if (use_64bit_relocs) { uint64_t tmp; if (ptr) tmp = *(uint64_t *)(ptr+reloc_ofs); else gem_read(fd, handle, reloc_ofs, &tmp, sizeof(tmp)); igt_assert_eq(tmp, gem_reloc[0].presumed_offset); } else { uint32_t tmp; if (ptr) tmp = *(uint32_t *)(ptr+reloc_ofs); else gem_read(fd, handle, reloc_ofs, &tmp, sizeof(tmp)); igt_assert_eq(tmp, gem_reloc[0].presumed_offset); } }
static void scratch_buf_check(data_t *data, struct igt_buf *buf, int x, int y, uint8_t color) { uint8_t val; gem_read(data->drm_fd, buf->bo->handle, 0, data->linear, sizeof(data->linear)); val = data->linear[y * WIDTH + x]; igt_assert_f(val == color, "Expected 0x%02x, found 0x%02x at (%d,%d)\n", color, val, x, y); }
static void check_bo(int fd, uint32_t handle, uint32_t val) { int i; gem_read(fd, handle, 0, linear, sizeof(linear)); for (i = 0; i < WIDTH*HEIGHT; i++) { igt_assert_f(linear[i] == val, "Expected 0x%08x, found 0x%08x " "at offset 0x%08x\n", val, linear[i], i * 4); val++; } }
static void test_read(int fd) { void *dst; uint32_t src; /* copy from a fresh src to fresh dst to force pagefault on both */ dst = create_pointer(fd); src = gem_create(fd, OBJECT_SIZE); gem_read(fd, src, 0, dst, OBJECT_SIZE); gem_close(fd, src); munmap(dst, OBJECT_SIZE); }
static void check_bo(int fd, uint32_t handle, uint32_t val) { int i; gem_read(fd, handle, 0, linear, sizeof(linear)); for (i = 0; i < WIDTH*HEIGHT; i++) { if (linear[i] != val) { fprintf(stderr, "Expected 0x%08x, found 0x%08x " "at offset 0x%08x\n", val, linear[i], i * 4); abort(); } val++; } }
static void check_bo(int fd, drm_intel_bo *bo, uint32_t start_val) { int i; gem_read(fd, bo->handle, 0, linear, sizeof(linear)); for (i = 0; i < 1024 * 1024 / 4; i++) { if (linear[i] != start_val) { fprintf(stderr, "Expected 0x%08x, found 0x%08x " "at offset 0x%08x\n", start_val, linear[i], i * 4); abort(); } start_val++; } }
int main(int argc, char **argv) { struct timeval start, end; uint8_t *buf; uint32_t handle; int size = OBJECT_SIZE; int loop, i, tiling; int fd; if (argc > 1) size = atoi(argv[1]); if (size == 0) { fprintf(stderr, "Invalid object size specified\n"); return 1; } buf = malloc(size); memset(buf, 0, size); fd = drm_open_any(); handle = gem_create(fd, size); assert(handle); for (tiling = I915_TILING_NONE; tiling <= I915_TILING_Y; tiling++) { if (tiling != I915_TILING_NONE) { printf("\nSetting tiling mode to %s\n", tiling == I915_TILING_X ? "X" : "Y"); gem_set_tiling(fd, handle, tiling, 512); } if (tiling == I915_TILING_NONE) { gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); { uint32_t *base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE); volatile uint32_t *ptr = base; int x = 0; for (i = 0; i < size/sizeof(*ptr); i++) x += ptr[i]; /* force overtly clever gcc to actually compute x */ ptr[0] = x; munmap(base, size); /* mmap read */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE); ptr = base; x = 0; for (i = 0; i < size/sizeof(*ptr); i++) x += ptr[i]; /* force overtly clever gcc to actually compute x */ ptr[0] = x; munmap(base, size); } gettimeofday(&end, NULL); printf("Time to read %dk through a CPU map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* mmap write */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE); ptr = base; for (i = 0; i < size/sizeof(*ptr); i++) ptr[i] = i; munmap(base, size); } gettimeofday(&end, NULL); printf("Time to write %dk through a CPU map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE); memset(base, 0, size); munmap(base, size); } gettimeofday(&end, NULL); printf("Time to clear %dk through a CPU map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); gettimeofday(&start, NULL); base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE); for (loop = 0; loop < 1000; loop++) memset(base, 0, size); munmap(base, size); gettimeofday(&end, NULL); printf("Time to clear %dk through a cached CPU map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); } /* CPU pwrite */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) gem_write(fd, handle, 0, buf, size); gettimeofday(&end, NULL); printf("Time to pwrite %dk through the CPU: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* CPU pread */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) gem_read(fd, handle, 0, buf, size); gettimeofday(&end, NULL); printf("Time to pread %dk through the CPU: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); } /* prefault into gtt */ { uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE); volatile uint32_t *ptr = base; int x = 0; for (i = 0; i < size/sizeof(*ptr); i++) x += ptr[i]; /* force overtly clever gcc to actually compute x */ ptr[0] = x; munmap(base, size); } /* mmap read */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE); volatile uint32_t *ptr = base; int x = 0; for (i = 0; i < size/sizeof(*ptr); i++) x += ptr[i]; /* force overtly clever gcc to actually compute x */ ptr[0] = x; munmap(base, size); } gettimeofday(&end, NULL); printf("Time to read %dk through a GTT map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* mmap write */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE); volatile uint32_t *ptr = base; for (i = 0; i < size/sizeof(*ptr); i++) ptr[i] = i; munmap(base, size); } gettimeofday(&end, NULL); printf("Time to write %dk through a GTT map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* mmap clear */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE); memset(base, 0, size); munmap(base, size); } gettimeofday(&end, NULL); printf("Time to clear %dk through a GTT map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); gettimeofday(&start, NULL);{ uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE); for (loop = 0; loop < 1000; loop++) memset(base, 0, size); munmap(base, size); } gettimeofday(&end, NULL); printf("Time to clear %dk through a cached GTT map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* mmap read */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE); volatile uint32_t *ptr = base; int x = 0; for (i = 0; i < size/sizeof(*ptr); i++) x += ptr[i]; /* force overtly clever gcc to actually compute x */ ptr[0] = x; munmap(base, size); } gettimeofday(&end, NULL); printf("Time to read %dk (again) through a GTT map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); if (tiling == I915_TILING_NONE) { /* GTT pwrite */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) gem_write(fd, handle, 0, buf, size); gettimeofday(&end, NULL); printf("Time to pwrite %dk through the GTT: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* GTT pread */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) gem_read(fd, handle, 0, buf, size); gettimeofday(&end, NULL); printf("Time to pread %dk through the GTT: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* GTT pwrite, including clflush */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { gem_write(fd, handle, 0, buf, size); gem_sync(fd, handle); } gettimeofday(&end, NULL); printf("Time to pwrite %dk through the GTT (clflush): %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* GTT pread, including clflush */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { gem_sync(fd, handle); gem_read(fd, handle, 0, buf, size); } gettimeofday(&end, NULL); printf("Time to pread %dk through the GTT (clflush): %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* partial writes */ printf("Now partial writes.\n"); size /= 4; /* partial GTT pwrite, including clflush */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { gem_write(fd, handle, 0, buf, size); gem_sync(fd, handle); } gettimeofday(&end, NULL); printf("Time to pwrite %dk through the GTT (clflush): %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* partial GTT pread, including clflush */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { gem_sync(fd, handle); gem_read(fd, handle, 0, buf, size); } gettimeofday(&end, NULL); printf("Time to pread %dk through the GTT (clflush): %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); size *= 4; } } gem_close(fd, handle); close(fd); return 0; }
int main(int argc, char **argv) { data_t data = {0, }; struct intel_batchbuffer *batch = NULL; struct igt_buf src, dst; igt_render_copyfunc_t render_copy = NULL; int opt_dump_aub = igt_aub_dump_enabled(); igt_simple_init_parse_opts(&argc, argv, "da", NULL, NULL, opt_handler, NULL); igt_fixture { data.drm_fd = drm_open_any_render(); data.devid = intel_get_drm_devid(data.drm_fd); data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096); igt_assert(data.bufmgr); render_copy = igt_get_render_copyfunc(data.devid); igt_require_f(render_copy, "no render-copy function\n"); batch = intel_batchbuffer_alloc(data.bufmgr, data.devid); igt_assert(batch); } scratch_buf_init(&data, &src, WIDTH, HEIGHT, STRIDE, SRC_COLOR); scratch_buf_init(&data, &dst, WIDTH, HEIGHT, STRIDE, DST_COLOR); scratch_buf_check(&data, &src, WIDTH / 2, HEIGHT / 2, SRC_COLOR); scratch_buf_check(&data, &dst, WIDTH / 2, HEIGHT / 2, DST_COLOR); if (opt_dump_png) { scratch_buf_write_to_png(&src, "source.png"); scratch_buf_write_to_png(&dst, "destination.png"); } if (opt_dump_aub) { drm_intel_bufmgr_gem_set_aub_filename(data.bufmgr, "rendercopy.aub"); drm_intel_bufmgr_gem_set_aub_dump(data.bufmgr, true); } /* This will copy the src to the mid point of the dst buffer. Presumably * the out of bounds accesses will get clipped. * Resulting buffer should look like: * _______ * |dst|dst| * |dst|src| * ------- */ render_copy(batch, NULL, &src, 0, 0, WIDTH, HEIGHT, &dst, WIDTH / 2, HEIGHT / 2); if (opt_dump_png) scratch_buf_write_to_png(&dst, "result.png"); if (opt_dump_aub) { drm_intel_gem_bo_aub_dump_bmp(dst.bo, 0, 0, WIDTH, HEIGHT, AUB_DUMP_BMP_FORMAT_ARGB_8888, STRIDE, 0); drm_intel_bufmgr_gem_set_aub_dump(data.bufmgr, false); } else if (check_all_pixels) { uint32_t val; int i, j; gem_read(data.drm_fd, dst.bo->handle, 0, data.linear, sizeof(data.linear)); for (i = 0; i < WIDTH; i++) { for (j = 0; j < HEIGHT; j++) { uint32_t color = DST_COLOR; val = data.linear[j * WIDTH + i]; if (j >= HEIGHT/2 && i >= WIDTH/2) color = SRC_COLOR; igt_assert_f(val == color, "Expected 0x%08x, found 0x%08x at (%d,%d)\n", color, val, i, j); } } } else { scratch_buf_check(&data, &dst, 10, 10, DST_COLOR); scratch_buf_check(&data, &dst, WIDTH - 10, HEIGHT - 10, SRC_COLOR); } igt_exit(); }
static void check_gpu(int fd, uint32_t handle, uint32_t val) { gem_read(fd, handle, 0, linear, sizeof(linear)); check_cpu(linear, val); }
/* Simulates SNA behaviour using negative self-relocations for * STATE_BASE_ADDRESS command packets. If they wrap around (to values greater * than the total size of the GTT), the GPU will hang. * See https://bugs.freedesktop.org/show_bug.cgi?id=78533 */ static int negative_reloc(int fd, unsigned flags) { struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 gem_exec[2]; struct drm_i915_gem_relocation_entry gem_reloc[1000]; uint64_t gtt_max = get_page_table_size(fd); uint32_t buf[1024] = {MI_BATCH_BUFFER_END}; int i; #define BIAS (256*1024) igt_require(intel_gen(intel_get_drm_devid(fd)) >= 7); memset(gem_exec, 0, sizeof(gem_exec)); gem_exec[0].handle = gem_create(fd, 4096); gem_write(fd, gem_exec[0].handle, 0, buf, 8); gem_reloc[0].offset = 1024; gem_reloc[0].delta = 0; gem_reloc[0].target_handle = gem_exec[0].handle; gem_reloc[0].read_domains = I915_GEM_DOMAIN_COMMAND; gem_exec[1].handle = gem_create(fd, 4096); gem_write(fd, gem_exec[1].handle, 0, buf, 8); gem_exec[1].relocation_count = 1; gem_exec[1].relocs_ptr = (uintptr_t)gem_reloc; memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = (uintptr_t)gem_exec; execbuf.buffer_count = 2; execbuf.batch_len = 8; do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); gem_close(fd, gem_exec[1].handle); igt_info("Found offset %lld for 4k batch\n", (long long)gem_exec[0].offset); /* * Ideally we'd like to be able to control where the kernel is going to * place the buffer. We don't SKIP here because it causes the test * to "randomly" flip-flop between the SKIP and PASS states. */ if (gem_exec[0].offset < BIAS) { igt_info("Offset is below BIAS, not testing anything\n"); return 0; } memset(gem_reloc, 0, sizeof(gem_reloc)); for (i = 0; i < sizeof(gem_reloc)/sizeof(gem_reloc[0]); i++) { gem_reloc[i].offset = 8 + 4*i; gem_reloc[i].delta = -BIAS*i/1024; gem_reloc[i].target_handle = flags & USE_LUT ? 0 : gem_exec[0].handle; gem_reloc[i].read_domains = I915_GEM_DOMAIN_COMMAND; } gem_exec[0].relocation_count = sizeof(gem_reloc)/sizeof(gem_reloc[0]); gem_exec[0].relocs_ptr = (uintptr_t)gem_reloc; execbuf.buffer_count = 1; execbuf.flags = flags & USE_LUT; do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); igt_info("Batch is now at offset %lld\n", (long long)gem_exec[0].offset); gem_read(fd, gem_exec[0].handle, 0, buf, sizeof(buf)); gem_close(fd, gem_exec[0].handle); for (i = 0; i < sizeof(gem_reloc)/sizeof(gem_reloc[0]); i++) igt_assert(buf[2 + i] < gtt_max); return 0; }
static int negative_reloc_blt(int fd) { const int gen = intel_gen(intel_get_drm_devid(fd)); struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 gem_exec[1024][2]; struct drm_i915_gem_relocation_entry gem_reloc; uint32_t buf[1024], *b; int i; memset(&gem_reloc, 0, sizeof(gem_reloc)); gem_reloc.offset = 4 * sizeof(uint32_t); gem_reloc.presumed_offset = ~0ULL; gem_reloc.delta = -4096; gem_reloc.target_handle = 0; gem_reloc.read_domains = I915_GEM_DOMAIN_RENDER; gem_reloc.write_domain = I915_GEM_DOMAIN_RENDER; for (i = 0; i < 1024; i++) { memset(gem_exec[i], 0, sizeof(gem_exec[i])); gem_exec[i][0].handle = gem_create(fd, 4096); gem_exec[i][0].flags = EXEC_OBJECT_NEEDS_FENCE; b = buf; *b++ = XY_COLOR_BLT_CMD_NOLEN | ((gen >= 8) ? 5 : 4) | COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB; *b++ = 0xf0 << 16 | 1 << 25 | 1 << 24 | 4096; *b++ = 1 << 16 | 0; *b++ = 2 << 16 | 1024; *b++ = ~0; if (gen >= 8) *b++ = ~0; *b++ = 0xc0ffee ^ i; *b++ = MI_BATCH_BUFFER_END; if ((b - buf) & 1) *b++ = 0; gem_exec[i][1].handle = gem_create(fd, 4096); gem_write(fd, gem_exec[i][1].handle, 0, buf, (b - buf) * sizeof(uint32_t)); gem_exec[i][1].relocation_count = 1; gem_exec[i][1].relocs_ptr = (uintptr_t)&gem_reloc; } memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffer_count = 2; execbuf.batch_len = (b - buf) * sizeof(uint32_t); execbuf.flags = USE_LUT; if (gen >= 6) execbuf.flags |= I915_EXEC_BLT; for (i = 0; i < 1024; i++) { execbuf.buffers_ptr = (uintptr_t)gem_exec[i]; gem_execbuf(fd, &execbuf); } for (i = 1024; i--;) { gem_read(fd, gem_exec[i][0].handle, i*sizeof(uint32_t), buf + i, sizeof(uint32_t)); gem_close(fd, gem_exec[i][0].handle); gem_close(fd, gem_exec[i][1].handle); } if (0) { for (i = 0; i < 1024; i += 8) igt_info("%08x %08x %08x %08x %08x %08x %08x %08x\n", buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]); } for (i = 0; i < 1024; i++) igt_assert_eq(buf[i], 0xc0ffee ^ i); return 0; }
static void execN(int fd, uint32_t handle, uint64_t batch_size, unsigned flags, char *ptr) { #define reloc_ofs(N, T) ((((N)+1) << 12) - 4*(1 + ((N) == ((T)-1)))) struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 gem_exec[1]; struct drm_i915_gem_relocation_entry *gem_reloc; uint64_t n, nreloc = batch_size >> 12; gem_reloc = calloc(nreloc, sizeof(*gem_reloc)); igt_assert(gem_reloc); for (n = 0; n < nreloc; n++) { gem_reloc[n].offset = reloc_ofs(n, nreloc); gem_reloc[n].target_handle = handle; gem_reloc[n].read_domains = I915_GEM_DOMAIN_RENDER; gem_reloc[n].presumed_offset = n ^ 0xbeefdeaddeadbeef; if (ptr) { if (use_64bit_relocs) *(uint64_t *)(ptr + gem_reloc[n].offset) = gem_reloc[n].presumed_offset; else *(uint32_t *)(ptr + gem_reloc[n].offset) = gem_reloc[n].presumed_offset; } else gem_write(fd, handle, gem_reloc[n].offset, &gem_reloc[n].presumed_offset, 4*(1+use_64bit_relocs)); } memset(gem_exec, 0, sizeof(gem_exec)); gem_exec[0].handle = handle; gem_exec[0].relocation_count = nreloc; gem_exec[0].relocs_ptr = (uintptr_t)gem_reloc; memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = (uintptr_t)gem_exec; execbuf.buffer_count = 1; execbuf.batch_start_offset = 0; execbuf.batch_len = 8; execbuf.flags = flags; /* Avoid hitting slowpaths in the reloc processing which might yield a * presumed_offset of -1. Happens when the batch is still busy from the * last round. */ gem_sync(fd, handle); gem_execbuf(fd, &execbuf); for (n = 0; n < nreloc; n++) igt_warn_on(gem_reloc[n].presumed_offset == -1); if (use_64bit_relocs) { for (n = 0; n < nreloc; n++) { uint64_t tmp; if (ptr) tmp = *(uint64_t *)(ptr+reloc_ofs(n, nreloc)); else gem_read(fd, handle, reloc_ofs(n, nreloc), &tmp, sizeof(tmp)); igt_assert_eq(tmp, gem_reloc[n].presumed_offset); } } else { for (n = 0; n < nreloc; n++) { uint32_t tmp; if (ptr) tmp = *(uint32_t *)(ptr+reloc_ofs(n, nreloc)); else gem_read(fd, handle, reloc_ofs(n, nreloc), &tmp, sizeof(tmp)); igt_assert_eq(tmp, gem_reloc[n].presumed_offset); } } free(gem_reloc); #undef reloc_ofs }
int main(int argc, char **argv) { int fd; int i, iter = 100; uint32_t tiling, swizzle; uint32_t handle; uint32_t devid; fd = drm_open_any(); handle = create_bo(fd); gem_get_tiling(fd, handle, &tiling, &swizzle); devid = intel_get_drm_devid(fd); if (IS_GEN2(devid)) { tile_height = 16; tile_width = 128; tile_size = 2048; } else { tile_height = 8; tile_width = 512; tile_size = PAGE_SIZE; } /* Read a bunch of random subsets of the data and check that they come * out right. */ for (i = 0; i < iter; i++) { int size = WIDTH * HEIGHT * 4; int offset = (random() % size) & ~3; int len = (random() % size) & ~3; int j; if (len == 0) len = 4; if (offset + len > size) len = size - offset; if (i == 0) { offset = 0; len = size; } gem_read(fd, handle, offset, linear, len); /* Translate from offsets in the read buffer to the swizzled * address that it corresponds to. This is the opposite of * what Mesa does (calculate offset to be read given the linear * offset it's looking for). */ for (j = offset; j < offset + len; j += 4) { uint32_t expected_val, found_val; int swizzled_offset; const char *swizzle_str; switch (swizzle) { case I915_BIT_6_SWIZZLE_NONE: swizzled_offset = j; swizzle_str = "none"; break; case I915_BIT_6_SWIZZLE_9: swizzled_offset = j ^ swizzle_bit(9, j); swizzle_str = "bit9"; break; case I915_BIT_6_SWIZZLE_9_10: swizzled_offset = j ^ swizzle_bit(9, j) ^ swizzle_bit(10, j); swizzle_str = "bit9^10"; break; case I915_BIT_6_SWIZZLE_9_11: swizzled_offset = j ^ swizzle_bit(9, j) ^ swizzle_bit(11, j); swizzle_str = "bit9^11"; break; case I915_BIT_6_SWIZZLE_9_10_11: swizzled_offset = j ^ swizzle_bit(9, j) ^ swizzle_bit(10, j) ^ swizzle_bit(11, j); swizzle_str = "bit9^10^11"; break; default: fprintf(stderr, "Bad swizzle bits; %d\n", swizzle); abort(); } expected_val = calculate_expected(swizzled_offset); found_val = linear[(j - offset) / 4]; if (expected_val != found_val) { fprintf(stderr, "Bad read [%d]: %d instead of %d at 0x%08x " "for read from 0x%08x to 0x%08x, swizzle=%s\n", i, found_val, expected_val, j, offset, offset + len, swizzle_str); abort(); } } } close(fd); return 0; }
int main(int argc, char **argv) { int fd = drm_open_driver(DRIVER_INTEL); int domain = I915_GEM_DOMAIN_GTT; enum dir { READ, WRITE } dir = READ; void *buf = malloc(OBJECT_SIZE); uint32_t handle; int reps = 13; int c, size; while ((c = getopt (argc, argv, "D:d:r:")) != -1) { switch (c) { case 'd': if (strcmp(optarg, "cpu") == 0) domain = I915_GEM_DOMAIN_CPU; else if (strcmp(optarg, "gtt") == 0) domain = I915_GEM_DOMAIN_GTT; break; case 'D': if (strcmp(optarg, "read") == 0) dir = READ; else if (strcmp(optarg, "write") == 0) dir = WRITE; else abort(); break; case 'r': reps = atoi(optarg); if (reps < 1) reps = 1; break; default: break; } } handle = gem_create(fd, OBJECT_SIZE); for (size = 1; size <= OBJECT_SIZE; size <<= 1) { igt_stats_t stats; int n; igt_stats_init_with_size(&stats, reps); for (n = 0; n < reps; n++) { struct timespec start, end; gem_set_domain(fd, handle, domain, domain); clock_gettime(CLOCK_MONOTONIC, &start); if (dir == READ) gem_read(fd, handle, 0, buf, size); else gem_write(fd, handle, 0, buf, size); clock_gettime(CLOCK_MONOTONIC, &end); igt_stats_push(&stats, elapsed(&start, &end)); } printf("%7.3f\n", igt_stats_get_trimean(&stats)/1000); igt_stats_fini(&stats); } return 0; }