static void test_read_write2(int fd, enum test_read_write order) { uint32_t handle; void *r, *w; volatile uint32_t val = 0; handle = gem_create(fd, OBJECT_SIZE); r = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ); w = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); if (order == READ_BEFORE_WRITE) { val = *(uint32_t *)r; *(uint32_t *)w = val; } else { *(uint32_t *)w = val; val = *(uint32_t *)r; } gem_close(fd, handle); munmap(r, OBJECT_SIZE); munmap(w, OBJECT_SIZE); }
static void run(data_t *data, int child) { const int size = 4096 * (256 + child * child); const int tiling = child % 2; const int write = child % 2; uint32_t handle = gem_create(data->fd, size); uint32_t *ptr; uint32_t x; igt_assert(handle); if (tiling != I915_TILING_NONE) gem_set_tiling(data->fd, handle, tiling, 4096); /* load up the unfaulted bo */ busy(data, handle, size, 100); /* Note that we ignore the API and rely on the implict * set-to-gtt-domain within the fault handler. */ if (write) { ptr = gem_mmap__gtt(data->fd, handle, size, PROT_READ | PROT_WRITE); ptr[rand() % (size / 4)] = canary; } else { ptr = gem_mmap__gtt(data->fd, handle, size, PROT_READ); } x = ptr[rand() % (size / 4)]; munmap(ptr, size); igt_assert_eq_u32(x, canary); }
static void * mmap_bo(int fd, uint32_t handle) { void *ptr; ptr = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); return ptr; }
static void create_cairo_surface__gtt(int fd, struct igt_fb *fb) { void *ptr = gem_mmap__gtt(fd, fb->gem_handle, fb->size, PROT_READ | PROT_WRITE); fb->cairo_surface = cairo_image_surface_create_for_data(ptr, drm_format_to_cairo(fb->drm_format), fb->width, fb->height, fb->stride); cairo_surface_set_user_data(fb->cairo_surface, (cairo_user_data_key_t *)create_cairo_surface__gtt, fb, destroy_cairo_surface__gtt); }
static void draw_rect_mmap_gtt(int fd, struct buf_data *buf, struct rect *rect, uint32_t color) { uint32_t *ptr; gem_set_domain(fd, buf->handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); ptr = gem_mmap__gtt(fd, buf->handle, buf->size, PROT_READ | PROT_WRITE); draw_rect_ptr_linear(ptr, buf->stride, rect, color, buf->bpp); igt_assert(munmap(ptr, buf->size) == 0); }
static void check_bo(int fd1, uint32_t handle1, int fd2, uint32_t handle2) { char *ptr1, *ptr2; int i; ptr1 = gem_mmap__gtt(fd1, handle1, BO_SIZE, PROT_READ | PROT_WRITE); ptr2 = gem_mmap__gtt(fd2, handle2, BO_SIZE, PROT_READ | PROT_WRITE); /* check whether it's still our old object first. */ for (i = 0; i < BO_SIZE; i++) { igt_assert(ptr1[i] == counter); igt_assert(ptr2[i] == counter); } counter++; memset(ptr1, counter, BO_SIZE); igt_assert(memcmp(ptr1, ptr2, BO_SIZE) == 0); munmap(ptr1, BO_SIZE); munmap(ptr2, BO_SIZE); }
static void * mmap_coherent(int fd, uint32_t handle, int size) { if (gem_has_llc(fd)) { coherent_domain = I915_GEM_DOMAIN_CPU; return gem_mmap__cpu(fd, handle, 0, size, PROT_WRITE); } coherent_domain = I915_GEM_DOMAIN_GTT; if (gem_mmap__has_wc(fd)) return gem_mmap__wc(fd, handle, 0, size, PROT_WRITE); else return gem_mmap__gtt(fd, handle, size, PROT_WRITE); }
static void check_bo(int fd, uint32_t handle, uint32_t val) { uint32_t *v; int i; v = gem_mmap__gtt(fd, handle, WIDTH * HEIGHT * 4, PROT_READ); for (i = 0; i < WIDTH*HEIGHT; i++) { igt_assert_f(v[i] == val, "Expected 0x%08x, found 0x%08x " "at offset 0x%08x\n", val, v[i], i * 4); val++; } munmap(v, WIDTH*HEIGHT*4); }
static uint32_t create_bo(int fd, uint32_t val) { uint32_t handle; uint32_t *v; int i; handle = gem_create(fd, WIDTH*HEIGHT*4); gem_set_tiling(fd, handle, I915_TILING_X, WIDTH*4); /* Fill the BO with dwords starting at val */ v = gem_mmap__gtt(fd, handle, WIDTH * HEIGHT * 4, PROT_READ | PROT_WRITE); for (i = 0; i < WIDTH*HEIGHT; i++) v[i] = val++; munmap(v, WIDTH*HEIGHT*4); return handle; }
static void paint_color_key(struct igt_fb *fb_info) { int i, j; uint32_t *fb_ptr; fb_ptr = gem_mmap__gtt(drm_fd, fb_info->gem_handle, fb_info->size, PROT_READ | PROT_WRITE); for (i = crtc_y; i < crtc_y + crtc_h; i++) for (j = crtc_x; j < crtc_x + crtc_w; j++) { uint32_t offset; offset = (i * fb_info->stride / 4) + j; fb_ptr[offset] = SPRITE_COLOR_KEY; } munmap(fb_ptr, fb_info->size); }
static uint32_t create_bo(int fd) { uint32_t handle; uint32_t *data; int i; handle = gem_create(fd, SIZE); gem_set_tiling(fd, handle, I915_TILING_X, WIDTH * sizeof(uint32_t)); /* Write throught the fence to tiled the data. * We then manually detile on reading back through the mmap(wc). */ data = gem_mmap__gtt(fd, handle, SIZE, PROT_READ | PROT_WRITE); for (i = 0; i < WIDTH*HEIGHT; i++) data[i] = i; munmap(data, SIZE); gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, 0); return handle; }
static void create_and_map_bo(int fd) { uint32_t handle; char *ptr; handle = gem_create(fd, OBJECT_SIZE); ptr = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); /* touch it to force it into the gtt */ *ptr = 0; /* but then unmap it again because we only have limited address space on * 32 bit */ munmap(ptr, OBJECT_SIZE); /* we happily leak objects to exhaust mmap offset space, the kernel will * reap backing storage. */ gem_madvise(fd, handle, I915_MADV_DONTNEED); }
static void test_write_cpu_read_gtt(int fd) { uint32_t handle; uint32_t *src, *dst; igt_require(gem_has_llc(fd)); handle = gem_create(fd, OBJECT_SIZE); dst = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_READ); src = gem_mmap__cpu(fd, handle, 0, OBJECT_SIZE, PROT_WRITE); gem_close(fd, handle); memset(src, 0xaa, OBJECT_SIZE); igt_assert(memcmp(dst, src, OBJECT_SIZE) == 0); munmap(src, OBJECT_SIZE); munmap(dst, OBJECT_SIZE); }
static void test_huge_bo(int fd, int huge, int tiling) { uint32_t bo; char *ptr; char *tiled_pattern; char *linear_pattern; uint64_t size, last_offset; int pitch = tiling == I915_TILING_Y ? 128 : 512; int i; switch (huge) { case -1: size = gem_mappable_aperture_size() / 2; break; case 0: size = gem_mappable_aperture_size() + PAGE_SIZE; break; default: size = gem_aperture_size(fd) + PAGE_SIZE; break; } intel_require_memory(1, size, CHECK_RAM); last_offset = size - PAGE_SIZE; /* Create pattern */ bo = gem_create(fd, PAGE_SIZE); if (tiling) gem_set_tiling(fd, bo, tiling, pitch); linear_pattern = gem_mmap__gtt(fd, bo, PAGE_SIZE, PROT_READ | PROT_WRITE); for (i = 0; i < PAGE_SIZE; i++) linear_pattern[i] = i; tiled_pattern = gem_mmap__cpu(fd, bo, 0, PAGE_SIZE, PROT_READ); gem_set_domain(fd, bo, I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT, 0); gem_close(fd, bo); bo = gem_create(fd, size); if (tiling) gem_set_tiling(fd, bo, tiling, pitch); /* Initialise first/last page through CPU mmap */ ptr = gem_mmap__cpu(fd, bo, 0, size, PROT_READ | PROT_WRITE); memcpy(ptr, tiled_pattern, PAGE_SIZE); memcpy(ptr + last_offset, tiled_pattern, PAGE_SIZE); munmap(ptr, size); /* Obtain mapping for the object through GTT. */ ptr = __gem_mmap__gtt(fd, bo, size, PROT_READ | PROT_WRITE); igt_require_f(ptr, "Huge BO GTT mapping not supported.\n"); set_domain_gtt(fd, bo); /* Access through GTT should still provide the CPU written values. */ igt_assert(memcmp(ptr , linear_pattern, PAGE_SIZE) == 0); igt_assert(memcmp(ptr + last_offset, linear_pattern, PAGE_SIZE) == 0); gem_set_tiling(fd, bo, I915_TILING_NONE, 0); igt_assert(memcmp(ptr , tiled_pattern, PAGE_SIZE) == 0); igt_assert(memcmp(ptr + last_offset, tiled_pattern, PAGE_SIZE) == 0); munmap(ptr, size); gem_close(fd, bo); munmap(tiled_pattern, PAGE_SIZE); munmap(linear_pattern, PAGE_SIZE); }
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; igt_simple_init(argc, argv); igt_skip_on_simulation(); if (argc > 1) size = atoi(argv[1]); if (size == 0) { igt_warn("Invalid object size specified\n"); return 1; } buf = malloc(size); memset(buf, 0, size); fd = drm_open_driver(DRIVER_INTEL); handle = gem_create(fd, size); igt_assert(handle); for (tiling = I915_TILING_NONE; tiling <= I915_TILING_Y; tiling++) { if (tiling != I915_TILING_NONE) { igt_info("\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, 0, 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, 0, 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); igt_info("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, 0, size, PROT_READ | PROT_WRITE); ptr = base; for (i = 0; i < size/sizeof(*ptr); i++) ptr[i] = i; munmap(base, size); } gettimeofday(&end, NULL); igt_info("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, 0, size, PROT_READ | PROT_WRITE); memset(base, 0, size); munmap(base, size); } gettimeofday(&end, NULL); igt_info("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, 0, size, PROT_READ | PROT_WRITE); for (loop = 0; loop < 1000; loop++) memset(base, 0, size); munmap(base, size); gettimeofday(&end, NULL); igt_info("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); igt_info("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); igt_info("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__gtt(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__gtt(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); igt_info("Time to read %dk through a GTT map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); if (gem_mmap__has_wc(fd)) { gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { uint32_t *base = gem_mmap__wc(fd, handle, 0, 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); igt_info("Time to read %dk through a WC 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__gtt(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); igt_info("Time to write %dk through a GTT map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); if (gem_mmap__has_wc(fd)) { /* mmap write */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { uint32_t *base = gem_mmap__wc(fd, handle, 0, 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); igt_info("Time to write %dk through a WC 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__gtt(fd, handle, size, PROT_READ | PROT_WRITE); memset(base, 0, size); munmap(base, size); } gettimeofday(&end, NULL); igt_info("Time to clear %dk through a GTT map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); if (gem_mmap__has_wc(fd)) { /* mmap clear */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) { uint32_t *base = gem_mmap__wc(fd, handle, 0, size, PROT_READ | PROT_WRITE); memset(base, 0, size); munmap(base, size); } gettimeofday(&end, NULL); igt_info("Time to clear %dk through a WC map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); } gettimeofday(&start, NULL);{ uint32_t *base = gem_mmap__gtt(fd, handle, size, PROT_READ | PROT_WRITE); for (loop = 0; loop < 1000; loop++) memset(base, 0, size); munmap(base, size); } gettimeofday(&end, NULL); igt_info("Time to clear %dk through a cached GTT map: %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); if (gem_mmap__has_wc(fd)) { gettimeofday(&start, NULL);{ uint32_t *base = gem_mmap__wc(fd, handle, 0, size, PROT_READ | PROT_WRITE); for (loop = 0; loop < 1000; loop++) memset(base, 0, size); munmap(base, size); } gettimeofday(&end, NULL); igt_info("Time to clear %dk through a cached WC 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__gtt(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); igt_info("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); igt_info("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); igt_info("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); igt_info("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); igt_info("Time to pread %dk through the GTT (clflush): %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* partial writes */ igt_info("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); igt_info("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); igt_info("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); igt_exit(); }
static void test_huge_copy(int fd, int huge, int tiling_a, int tiling_b) { uint64_t huge_object_size, i; uint32_t bo, *pattern_a, *pattern_b; char *a, *b; switch (huge) { case -2: huge_object_size = gem_mappable_aperture_size() / 4; break; case -1: huge_object_size = gem_mappable_aperture_size() / 2; break; case 0: huge_object_size = gem_mappable_aperture_size() + PAGE_SIZE; break; default: huge_object_size = gem_aperture_size(fd) + PAGE_SIZE; break; } intel_require_memory(2, huge_object_size, CHECK_RAM); pattern_a = malloc(PAGE_SIZE); for (i = 0; i < PAGE_SIZE/4; i++) pattern_a[i] = i; pattern_b = malloc(PAGE_SIZE); for (i = 0; i < PAGE_SIZE/4; i++) pattern_b[i] = ~i; bo = gem_create(fd, huge_object_size); if (tiling_a) gem_set_tiling(fd, bo, tiling_a, tiling_a == I915_TILING_Y ? 128 : 512); a = gem_mmap__gtt(fd, bo, huge_object_size, PROT_READ | PROT_WRITE); igt_require(a); gem_close(fd, bo); for (i = 0; i < huge_object_size / PAGE_SIZE; i++) memcpy(a + PAGE_SIZE*i, pattern_a, PAGE_SIZE); bo = gem_create(fd, huge_object_size); if (tiling_b) gem_set_tiling(fd, bo, tiling_b, tiling_b == I915_TILING_Y ? 128 : 512); b = gem_mmap__gtt(fd, bo, huge_object_size, PROT_READ | PROT_WRITE); igt_require(b); gem_close(fd, bo); for (i = 0; i < huge_object_size / PAGE_SIZE; i++) memcpy(b + PAGE_SIZE*i, pattern_b, PAGE_SIZE); for (i = 0; i < huge_object_size / PAGE_SIZE; i++) { if (i & 1) memcpy(a + i *PAGE_SIZE, b + i*PAGE_SIZE, PAGE_SIZE); else memcpy(b + i *PAGE_SIZE, a + i*PAGE_SIZE, PAGE_SIZE); } for (i = 0; i < huge_object_size / PAGE_SIZE; i++) { if (i & 1) igt_assert(memcmp(pattern_b, a + PAGE_SIZE*i, PAGE_SIZE) == 0); else igt_assert(memcmp(pattern_a, a + PAGE_SIZE*i, PAGE_SIZE) == 0); } munmap(a, huge_object_size); for (i = 0; i < huge_object_size / PAGE_SIZE; i++) { if (i & 1) igt_assert(memcmp(pattern_b, b + PAGE_SIZE*i, PAGE_SIZE) == 0); else igt_assert(memcmp(pattern_a, b + PAGE_SIZE*i, PAGE_SIZE) == 0); } munmap(b, huge_object_size); free(pattern_a); free(pattern_b); }
int main(int argc, char **argv) { int fd = drm_open_driver(DRIVER_INTEL); enum map {CPU, GTT, WC} map = CPU; enum dir {READ, WRITE, CLEAR, FAULT} dir = READ; int tiling = I915_TILING_NONE; void *buf = malloc(OBJECT_SIZE); uint32_t handle; void *ptr, *src, *dst; int reps = 13; int c, size; while ((c = getopt (argc, argv, "m:d:r:t:")) != -1) { switch (c) { case 'm': if (strcmp(optarg, "cpu") == 0) map = CPU; else if (strcmp(optarg, "gtt") == 0) map = GTT; else if (strcmp(optarg, "wc") == 0) map = WC; else abort(); break; case 'd': if (strcmp(optarg, "read") == 0) dir = READ; else if (strcmp(optarg, "write") == 0) dir = WRITE; else if (strcmp(optarg, "clear") == 0) dir = CLEAR; else if (strcmp(optarg, "fault") == 0) dir = FAULT; else abort(); break; case 't': if (strcmp(optarg, "x") == 0) tiling = I915_TILING_X; else if (strcmp(optarg, "y") == 0) tiling = I915_TILING_Y; else if (strcmp(optarg, "none") == 0) tiling = I915_TILING_NONE; else abort(); break; case 'r': reps = atoi(optarg); if (reps < 1) reps = 1; break; default: break; } } handle = gem_create(fd, OBJECT_SIZE); switch (map) { case CPU: ptr = gem_mmap__cpu(fd, handle, 0, OBJECT_SIZE, PROT_WRITE); gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); break; case GTT: ptr = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_WRITE); gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); break; case WC: ptr = gem_mmap__wc(fd, handle, 0, OBJECT_SIZE, PROT_WRITE); gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); break; default: abort(); } gem_set_tiling(fd, handle, tiling, 512); if (dir == READ) { src = ptr; dst = buf; } else { src = buf; dst = ptr; } 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; int page; clock_gettime(CLOCK_MONOTONIC, &start); switch (dir) { case CLEAR: memset(dst, 0, size); break; case FAULT: for (page = 0; page < OBJECT_SIZE; page += 4096) { uint32_t *x = (uint32_t *)ptr + page/4; page += *x; /* should be zero! */ } break; default: memcpy(dst, src, size); break; } 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; }
int main(int argc, char **argv) { int fd = drm_open_driver(DRIVER_INTEL); enum map {CPU, GTT, WC} map = CPU; enum dir {READ, WRITE, CLEAR, FAULT} dir = READ; int tiling = I915_TILING_NONE; struct timespec start, end; void *buf = malloc(OBJECT_SIZE); uint32_t handle; void *ptr, *src, *dst; int reps = 1; int loops; int c; while ((c = getopt (argc, argv, "m:d:r:t:")) != -1) { switch (c) { case 'm': if (strcmp(optarg, "cpu") == 0) map = CPU; else if (strcmp(optarg, "gtt") == 0) map = GTT; else if (strcmp(optarg, "wc") == 0) map = WC; else abort(); break; case 'd': if (strcmp(optarg, "read") == 0) dir = READ; else if (strcmp(optarg, "write") == 0) dir = WRITE; else if (strcmp(optarg, "clear") == 0) dir = CLEAR; else if (strcmp(optarg, "fault") == 0) dir = FAULT; else abort(); break; case 't': if (strcmp(optarg, "x") == 0) tiling = I915_TILING_X; else if (strcmp(optarg, "y") == 0) tiling = I915_TILING_Y; else if (strcmp(optarg, "none") == 0) tiling = I915_TILING_NONE; else abort(); break; case 'r': reps = atoi(optarg); if (reps < 1) reps = 1; break; default: break; } } handle = gem_create(fd, OBJECT_SIZE); switch (map) { case CPU: ptr = gem_mmap__cpu(fd, handle, 0, OBJECT_SIZE, PROT_WRITE); gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); break; case GTT: ptr = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_WRITE); gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); break; case WC: ptr = gem_mmap__wc(fd, handle, 0, OBJECT_SIZE, PROT_WRITE); gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); break; default: abort(); } gem_set_tiling(fd, handle, tiling, 512); if (dir == READ) { src = ptr; dst = buf; } else { src = buf; dst = ptr; } clock_gettime(CLOCK_MONOTONIC, &start); switch (dir) { case CLEAR: case FAULT: memset(dst, 0, OBJECT_SIZE); break; default: memcpy(dst, src, OBJECT_SIZE); break; } clock_gettime(CLOCK_MONOTONIC, &end); loops = 2 / elapsed(&start, &end); while (reps--) { clock_gettime(CLOCK_MONOTONIC, &start); for (c = 0; c < loops; c++) { int page; switch (dir) { case CLEAR: memset(dst, 0, OBJECT_SIZE); break; case FAULT: munmap(ptr, OBJECT_SIZE); switch (map) { case CPU: ptr = gem_mmap__cpu(fd, handle, 0, OBJECT_SIZE, PROT_WRITE); break; case GTT: ptr = gem_mmap__gtt(fd, handle, OBJECT_SIZE, PROT_WRITE); break; case WC: ptr = gem_mmap__wc(fd, handle, 0, OBJECT_SIZE, PROT_WRITE); break; default: abort(); } for (page = 0; page < OBJECT_SIZE; page += 4096) { uint32_t *x = (uint32_t *)ptr + page/4; __asm__ __volatile__("": : :"memory"); page += *x; /* should be zero! */ } break; default: memcpy(dst, src, OBJECT_SIZE); break; } } clock_gettime(CLOCK_MONOTONIC, &end); printf("%7.3f\n", OBJECT_SIZE / elapsed(&start, &end) * loops / (1024*1024)); } return 0; }