diff options
Diffstat (limited to 'tests/i915/gem_stolen.c')
-rw-r--r-- | tests/i915/gem_stolen.c | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/tests/i915/gem_stolen.c b/tests/i915/gem_stolen.c new file mode 100644 index 00000000..1d489976 --- /dev/null +++ b/tests/i915/gem_stolen.c @@ -0,0 +1,455 @@ +/* + * Copyright © 2015 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: + * Ankitprasad Sharma <ankitprasad.r.sharma at intel.com> + * + */ + +/** @file gem_create_stolen.c + * + * This is a test for the extended gem_create ioctl, that includes allocation + * of object from stolen memory. + * + * The goal is to simply ensure the basics work, and invalid input combinations + * are rejected. + */ + +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <getopt.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" +#include "drmtest.h" +#include "drm.h" +#include "i915_drm.h" + +IGT_TEST_DESCRIPTION("This test verifies the exetended gem_create ioctl," + " that includes allocation of obj from stolen region"); +#define CLEAR(s) memset(&s, 0, sizeof(s)) +#define SIZE 1024*1024 +#define DWORD_SIZE 4 +#define DATA 0xdead +#define LARGE_SIZE 0xffffffff +#define MAX_OBJECTS 100 + +static drm_intel_bufmgr *bufmgr; +static struct intel_batchbuffer *batch; + +static void verify_copy_op(drm_intel_bo *src, drm_intel_bo *dest) +{ + uint32_t *virt, i, ret; + /* Fill the src BO with dwords */ + ret = drm_intel_gem_bo_map_gtt(src); + igt_assert(!ret); + + virt = src->virtual; + for (i = 0; i < SIZE/DWORD_SIZE; i++) + virt[i] = i; + + intel_copy_bo(batch, dest, src, SIZE); + + ret = drm_intel_gem_bo_map_gtt(dest); + igt_assert(!ret); + + virt = dest->virtual; + /* verify */ + for (i = 0; i < SIZE/DWORD_SIZE; i++) + igt_assert_eq(virt[i], i); + + drm_intel_bo_unmap(src); + drm_intel_bo_unmap(dest); +} + +static void stolen_pwrite(int fd) +{ + drm_intel_bo *bo; + uint32_t buf[SIZE/DWORD_SIZE]; + uint32_t handle = 0; + uint32_t *virt; + int i, ret = 0; + + for (i = 0; i < SIZE/DWORD_SIZE; i++) + buf[i] = DATA; + + gem_require_stolen_support(fd); + + handle = gem_create_stolen(fd, SIZE); + + gem_write(fd, handle, 0, buf, SIZE); + bo = gem_handle_to_libdrm_bo(bufmgr, fd, "bo", handle); + + ret = drm_intel_gem_bo_map_gtt(bo); + igt_assert(!ret); + + virt = bo->virtual; + + for (i = 0; i < SIZE/DWORD_SIZE; i++) + igt_assert_eq(virt[i], DATA); + + drm_intel_bo_unmap(bo); + drm_intel_bo_unreference(bo); + gem_close(fd, handle); +} + +static void stolen_pread(int fd) +{ + drm_intel_bo *bo; + uint32_t buf[SIZE/DWORD_SIZE]; + uint32_t handle = 0; + uint32_t *virt; + int i, ret = 0; + + CLEAR(buf); + + gem_require_stolen_support(fd); + + handle = gem_create_stolen(fd, SIZE); + + bo = gem_handle_to_libdrm_bo(bufmgr, fd, "bo", handle); + + ret = drm_intel_gem_bo_map_gtt(bo); + igt_assert(!ret); + + virt = bo->virtual; + + for (i = 0; i < SIZE/DWORD_SIZE; i++) + virt[i] = DATA; + + drm_intel_bo_unmap(bo); + drm_intel_bo_unreference(bo); + + gem_read(fd, handle, 0, buf, SIZE); + + for (i = 0; i < SIZE/DWORD_SIZE; i++) + igt_assert_eq(buf[i], DATA); + + gem_close(fd, handle); +} + +static void copy_test(int fd) +{ + drm_intel_bo *src, *dest; + uint32_t src_handle = 0, dest_handle = 0; + + gem_require_stolen_support(fd); + + src_handle = gem_create_stolen(fd, SIZE); + dest_handle = gem_create_stolen(fd, SIZE); + + src = gem_handle_to_libdrm_bo(bufmgr, fd, "src_bo", src_handle); + dest = gem_handle_to_libdrm_bo(bufmgr, fd, "dst_bo", dest_handle); + + igt_assert(src != NULL); + igt_assert(dest != NULL); + + verify_copy_op(src, dest); + + drm_intel_bo_unreference(src); + drm_intel_bo_unreference(dest); + gem_close(fd, src_handle); + gem_close(fd, dest_handle); +} + +static void verify_object_clear(int fd) +{ + drm_intel_bo *bo; + uint32_t handle = 0; + uint32_t *virt; + int i, ret; + + gem_require_stolen_support(fd); + + handle = gem_create_stolen(fd, SIZE); + + bo = gem_handle_to_libdrm_bo(bufmgr, fd, "verify_bo", handle); + igt_assert(bo != NULL); + + ret = drm_intel_gem_bo_map_gtt(bo); + igt_assert(!ret); + + /* Verify if the BO is zeroed */ + virt = bo->virtual; + for (i = 0; i < SIZE / DWORD_SIZE; i++) + igt_assert(!virt[i]); + + drm_intel_bo_unmap(bo); + drm_intel_bo_unreference(bo); + gem_close(fd, handle); +} + +static void stolen_large_obj_alloc(int fd) +{ + uint32_t handle = 0; + + gem_require_stolen_support(fd); + handle = __gem_create_stolen(fd, (unsigned long long) LARGE_SIZE + 4096); + igt_assert(!handle); +} + +static void stolen_fill_purge_test(int fd) +{ + drm_intel_bo *bo; + int obj_count = 0, i = 0; + int _ret = 0, j = 0; + uint32_t handle[MAX_OBJECTS]; + uint32_t new_handle; + uint32_t *virt; + int retained; + + gem_require_stolen_support(fd); + + /* Exhaust Stolen space */ + do { + handle[i] = __gem_create_stolen(fd, SIZE); + if (handle[i] != 0) { + bo = gem_handle_to_libdrm_bo(bufmgr, fd, + "verify_bo", handle[i]); + igt_assert(bo != NULL); + + _ret = drm_intel_gem_bo_map_gtt(bo); + igt_assert(!_ret); + + virt = bo->virtual; + for (j = 0; j < SIZE/DWORD_SIZE; j++) + virt[j] = DATA; + + drm_intel_bo_unmap(bo); + drm_intel_bo_unreference(bo); + + obj_count++; + } + + i++; + } while (handle[i-1] && i < MAX_OBJECTS); + + igt_assert(obj_count > 0); + + /* Mark all stolen objects purgeable */ + for (i = 0; i < obj_count; i++) + retained = gem_madvise(fd, handle[i], I915_MADV_DONTNEED); + + /* Try to allocate one more object */ + new_handle = gem_create_stolen(fd, SIZE); + + /* Check if the retained object's memory contents are intact */ + for (i = 0; i < obj_count; i++) { + retained = gem_madvise(fd, handle[i], I915_MADV_WILLNEED); + if (retained) { + bo = gem_handle_to_libdrm_bo(bufmgr, fd, + "verify_bo", handle[i]); + igt_assert(bo != NULL); + + _ret = drm_intel_gem_bo_map_gtt(bo); + igt_assert(!_ret); + + virt = bo->virtual; + for (j = 0; j < SIZE/DWORD_SIZE; j++) + igt_assert_eq(virt[j], DATA); + + drm_intel_bo_unmap(bo); + drm_intel_bo_unreference(bo); + } + } + + gem_close(fd, new_handle); + for (i = 0; i < obj_count; i++) + gem_close(fd, handle[i]); +} + +static void stolen_hibernate(int fd) +{ + drm_intel_bo *bo; + drm_intel_bo *src, *dest; + int obj_count = 0, i = 0; + int ret, j; + uint32_t handle[MAX_OBJECTS], src_handle; + uint32_t *virt; + + gem_require_stolen_support(fd); + + src_handle = gem_create(fd, SIZE); + src = gem_handle_to_libdrm_bo(bufmgr, fd, + "bo", src_handle); + igt_assert(src != NULL); + + ret = drm_intel_gem_bo_map_gtt(src); + igt_assert_eq(ret, 0); + + virt = src->virtual; + for (j = 0; j < SIZE/DWORD_SIZE; j++) { + igt_assert_eq(virt[j], 0); + virt[j] = j; + } + + drm_intel_bo_unmap(src); + /* Exhaust Stolen space */ + for (i = 0; i < MAX_OBJECTS; i++) { + handle[i] = __gem_create_stolen(fd, SIZE); + if (!handle[i]) + break; + + bo = gem_handle_to_libdrm_bo(bufmgr, fd, + "verify_bo", handle[i]); + igt_assert(bo != NULL); + ret = drm_intel_gem_bo_map_gtt(bo); + igt_assert_eq(ret, 0); + + virt = bo->virtual; + for (j = 0; j < SIZE/DWORD_SIZE; j++) + igt_assert_eq(virt[j], 0); + + drm_intel_bo_unmap(bo); + drm_intel_bo_unreference(bo); + + obj_count++; + } + + /* Assert if atleast one object is allocated from stolen, that + * is good enough to verify the content preservation across + * hibernation. + */ + igt_assert(obj_count > 0); + + /* Copy data to all stolen backed objects */ + for (i = 0; i < obj_count; i++) { + dest = gem_handle_to_libdrm_bo(bufmgr, fd, + "dst_bo", handle[i]); + igt_assert(dest != NULL); + /* Copy contents to stolen backed objects via blt and + * verify post-hibernation, this also helps in identifying + * that the operation was completed before going to + * hibernation. + */ + intel_copy_bo(batch, dest, src, SIZE); + } + + drm_intel_bo_unreference(src); + + igt_system_suspend_autoresume(SUSPEND_STATE_DISK, SUSPEND_TEST_NONE); + /* Check if the object's memory contents are intact + * across hibernation. + */ + for (i = 0; i < obj_count; i++) { + bo = gem_handle_to_libdrm_bo(bufmgr, fd, + "verify_bo", handle[i]); + igt_assert(bo != NULL); + ret = drm_intel_gem_bo_map_gtt(bo); + igt_assert_eq(ret, 0); + virt = bo->virtual; + for (j = 0; j < SIZE/DWORD_SIZE; j++) + igt_assert_eq(virt[j], j); + + drm_intel_bo_unmap(bo); + drm_intel_bo_unreference(bo); + } + + gem_close(fd, src_handle); + for (i = 0; i < obj_count; i++) + gem_close(fd, handle[i]); +} + +static void +stolen_no_mmap(int fd) +{ + void *addr; + uint32_t handle = 0; + + gem_require_stolen_support(fd); + + handle = gem_create_stolen(fd, SIZE); + + addr = __gem_mmap__cpu(fd, handle, 0, SIZE, PROT_READ | PROT_WRITE); + igt_assert(addr == NULL); + + gem_close(fd, handle); +} + +igt_main +{ + int fd; + uint32_t devid; + + igt_skip_on_simulation(); + + igt_fixture { + fd = drm_open_driver(DRIVER_INTEL); + devid = intel_get_drm_devid(fd); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + batch = intel_batchbuffer_alloc(bufmgr, devid); + } + + igt_subtest("stolen-clear") + verify_object_clear(fd); + + /* + * stolen mem special cases - checking for non cpu mappable + */ + igt_subtest("stolen-no-mmap") + stolen_no_mmap(fd); + + /* checking for pread/pwrite interfaces */ + igt_subtest("stolen-pwrite") + stolen_pwrite(fd); + + igt_subtest("stolen-pread") + stolen_pread(fd); + + /* Functional Test - blt copy */ + igt_subtest("stolen-copy") + copy_test(fd); + + igt_subtest("large-object-alloc") + stolen_large_obj_alloc(fd); + + /* Filling stolen completely and marking all the objects + * purgeable. Then trying to add one more object, to verify + * the purging logic. + * Again marking all objects WILLNEED and verifying the + * contents of the retained objects. + */ + igt_subtest("stolen-fill-purge") + stolen_fill_purge_test(fd); + + igt_subtest("stolen-hibernate") + stolen_hibernate(fd); + + igt_fixture { + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + } +} |