Signed-off-by: Chris Wilson chris@chris-wilson.co.uk --- lib/drmtest.c | 47 ++++++++++++++++++++++++++++++++--------------- lib/drmtest.h | 7 ++++--- 2 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/lib/drmtest.c b/lib/drmtest.c index c59cabe..30eae19 100644 --- a/lib/drmtest.c +++ b/lib/drmtest.c @@ -90,24 +90,29 @@ static int __get_drm_device_name(int fd, char *name) return -1; }
-bool is_i915_device(int fd) +static bool __is_device(int fd, const char *expect) { - int ret; char name[5] = "";
- ret = __get_drm_device_name(fd, name); + if (__get_drm_device_name(fd, name)) + return false;
- return !ret && strcmp("i915", name) == 0; + return strcmp(expect, name) == 0; }
-static bool is_vc4_device(int fd) +bool is_i915_device(int fd) { - int ret; - char name[5] = ""; + return __is_device(fd, "i915"); +}
- ret = __get_drm_device_name(fd, name); +static bool is_vc4_device(int fd) +{ + return __is_device(fd, "vc4"); +}
- return !ret && strcmp("vc4", name) == 0; +static bool is_vgem_device(int fd) +{ + return __is_device(fd, "vgem"); }
static bool has_known_intel_chipset(int fd) @@ -213,6 +218,13 @@ int drm_get_card(void) return -1; }
+static void modprobe(const char *driver) +{ + char buf[128]; + snprintf(buf, sizeof(buf), "/sbin/modprobe %s", driver); + system(buf); +} + /** * __drm_open_driver: * @chipset: OR'd flags for each chipset to search, eg. #DRIVER_INTEL @@ -224,23 +236,28 @@ int drm_get_card(void) */ int __drm_open_driver(int chipset) { + if (chipset & DRIVER_VGEM) + modprobe("vgem"); + for (int i = 0; i < 16; i++) { char name[80]; int fd; - bool found_intel, found_vc4;
sprintf(name, "/dev/dri/card%u", i); fd = open(name, O_RDWR); if (fd == -1) continue;
- found_intel = is_i915_device(fd) && - has_known_intel_chipset(fd) && - (chipset & DRIVER_INTEL); + if (chipset & DRIVER_INTEL && is_i915_device(fd) && + has_known_intel_chipset(fd)) + return fd;
- found_vc4 = is_vc4_device(fd) && (chipset & DRIVER_VC4); + if (chipset & DRIVER_VC4 && + is_vc4_device(fd)) + return fd;
- if ((chipset & DRIVER_ANY) || found_intel || found_vc4) + if (chipset & DRIVER_VGEM && + is_vgem_device(fd)) return fd;
close(fd); diff --git a/lib/drmtest.h b/lib/drmtest.h index c391464..8ce32a6 100644 --- a/lib/drmtest.h +++ b/lib/drmtest.h @@ -38,9 +38,10 @@
#include "intel_batchbuffer.h"
-#define DRIVER_ANY 0x1 -#define DRIVER_INTEL (0x1 << 1) -#define DRIVER_VC4 (0x1 << 2) +#define DRIVER_INTEL (1 << 0) +#define DRIVER_VC4 (1 << 1) +#define DRIVER_VGEM (1 << 2) +#define DRIVER_ANY ~(DRIVER_VGEM)
#ifdef ANDROID #if (!(defined HAVE_MMAP64)) && (!(defined __x86_64__))
Signed-off-by: Chris Wilson chris@chris-wilson.co.uk --- lib/Makefile.sources | 2 + lib/igt_vgem.c | 80 ++++++++++++++++++++++++++ lib/igt_vgem.h | 42 ++++++++++++++ tests/Makefile.sources | 2 + tests/vgem_basic.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/vgem_reload_basic | 22 ++++++++ 6 files changed, 293 insertions(+) create mode 100644 lib/igt_vgem.c create mode 100644 lib/igt_vgem.h create mode 100644 tests/vgem_basic.c create mode 100755 tests/vgem_reload_basic
diff --git a/lib/Makefile.sources b/lib/Makefile.sources index f50ff4d..7f3f8c6 100644 --- a/lib/Makefile.sources +++ b/lib/Makefile.sources @@ -18,6 +18,8 @@ libintel_tools_la_SOURCES = \ igt_stats.h \ igt_sysfs.c \ igt_sysfs.h \ + igt_vgem.c \ + igt_vgem.h \ instdone.c \ instdone.h \ intel_batchbuffer.c \ diff --git a/lib/igt_vgem.c b/lib/igt_vgem.c new file mode 100644 index 0000000..9977903 --- /dev/null +++ b/lib/igt_vgem.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2016 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. + */ + +#include "igt.h" +#include "igt_vgem.h" + +#include <sys/mman.h> + +int __vgem_create(int fd, struct vgem_bo *bo) +{ + struct drm_mode_create_dumb arg; + + memset(&arg, 0, sizeof(arg)); + arg.width = bo->width; + arg.height = bo->height; + arg.bpp = bo->bpp; + + if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg)) + return -errno; + + bo->handle = arg.handle; + bo->pitch = arg.pitch; + bo->size = arg.size; + + return 0; +} + +void vgem_create(int fd, struct vgem_bo *bo) +{ + igt_assert_eq(__vgem_create(fd, bo), 0); +} + +void *__vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot) +{ + struct drm_mode_map_dumb arg; + void *ptr; + + memset(&arg, 0, sizeof(arg)); + arg.handle = bo->handle; + if (drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &arg)) + return NULL; + + ptr = mmap(0, bo->size, prot, MAP_SHARED, fd, arg.offset); + if (ptr == MAP_FAILED) + return NULL; + + return ptr; +} + +void *vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot) +{ + void *ptr; + + igt_assert_f((ptr = __vgem_mmap(fd, bo, prot)), + "vgem_map(fd=%d, bo->handle=%d, prot=%x)\n", + fd, bo->handle, prot); + + return ptr; +} + diff --git a/lib/igt_vgem.h b/lib/igt_vgem.h new file mode 100644 index 0000000..9e4a55e --- /dev/null +++ b/lib/igt_vgem.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2016 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. + */ + +#ifndef IGT_VGEM_H +#define IGT_VGEM_H + +#include <stdint.h> + +struct vgem_bo { + uint32_t handle; + uint32_t width, height; + uint32_t bpp, pitch; + uint64_t size; +}; + +int __vgem_create(int fd, struct vgem_bo *bo); +void vgem_create(int fd, struct vgem_bo *bo); + +void *__vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot); +void *vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot); + +#endif /* IGT_VGEM_H */ diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 7d40386..569a6f4 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -123,6 +123,7 @@ TESTS_progs_M = \ prime_mmap_kms \ prime_self_import \ template \ + vgem_basic \ $(NULL)
TESTS_progs_XM = \ @@ -218,6 +219,7 @@ TESTS_scripts = \ sysfs_l3_parity \ test_rte_check \ tools_test \ + vgem_reload_basic \ $(NULL)
# This target contains testcases which support automagic subtest enumeration diff --git a/tests/vgem_basic.c b/tests/vgem_basic.c new file mode 100644 index 0000000..b79ee6f --- /dev/null +++ b/tests/vgem_basic.c @@ -0,0 +1,145 @@ +/* + * Copyright © 2016 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. + */ + +#include "igt.h" +#include "igt_vgem.h" + +#include <sys/mman.h> + +IGT_TEST_DESCRIPTION("Basic sanity check of Virtual GEM module (vGEM)."); + +static void test_create(int fd) +{ + struct vgem_bo bo; + + bo.width = 0; + bo.height = 0; + bo.bpp = 0; + igt_assert_eq(__vgem_create(fd, &bo), -EINVAL); + + bo.width = 1; + bo.height = 1; + bo.bpp = 1; + vgem_create(fd, &bo); + igt_assert_eq(bo.size, 4096); + gem_close(fd, bo.handle); + + bo.width = 1024; + bo.height = 1024; + bo.bpp = 8; + vgem_create(fd, &bo); + igt_assert_eq(bo.size, 1<<20); + gem_close(fd, bo.handle); + + bo.width = 1<<15; + bo.height = 1<<15; + bo.bpp = 16; + vgem_create(fd, &bo); + igt_assert_eq(bo.size, 1<<31); + gem_close(fd, bo.handle); +} + +static void test_mmap(int fd) +{ + struct vgem_bo bo; + uint32_t *ptr; + + bo.width = 1024; + bo.height = 1024; + bo.bpp = 32; + vgem_create(fd, &bo); + + ptr = vgem_mmap(fd, &bo, PROT_WRITE); + gem_close(fd, bo.handle); + + for (int page = 0; page < bo.size >> 12; page++) + ptr[page] = 0; + + munmap(ptr, bo.size); +} + +static void test_dmabuf_mmap(int fd) +{ + struct vgem_bo bo; + uint32_t *ptr; + int export; + + bo.width = 1024; + bo.height = 1024; + bo.bpp = 32; + vgem_create(fd, &bo); + + export = prime_handle_to_fd_for_mmap(fd, bo.handle); + ptr = mmap(NULL, bo.size, PROT_WRITE, MAP_SHARED, export, 0); + close(export); + igt_assert(ptr != MAP_FAILED); + + for (int page = 0; page < bo.size >> 12; page++) + ptr[page] = page; + munmap(ptr, bo.size); + + ptr = vgem_mmap(fd, &bo, PROT_READ); + gem_close(fd, bo.handle); + + for (int page = 0; page < bo.size >> 12; page++) + igt_assert_eq(ptr[page], page); + munmap(ptr, bo.size); +} + +static bool has_prime_export(int fd) +{ + uint64_t value; + + if (drmGetCap(fd, DRM_CAP_PRIME, &value)) + return false; + + return value & DRM_PRIME_CAP_EXPORT; +} + +igt_main +{ + int fd = -1; + + igt_fixture { + fd = drm_open_driver(DRIVER_VGEM); + } + + igt_subtest_f("create") + test_create(fd); + + igt_subtest_f("mmap") + test_mmap(fd); + + igt_subtest_group { + igt_fixture { + igt_require(has_prime_export(fd)); + } + + igt_subtest_f("dmabuf-mmap") + test_dmabuf_mmap(fd); + } + + igt_fixture { + close(fd); + } +} diff --git a/tests/vgem_reload_basic b/tests/vgem_reload_basic new file mode 100755 index 0000000..b150b2c --- /dev/null +++ b/tests/vgem_reload_basic @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Testcase: Reload the vgem module +# +# ... we've broken this way too often :( +# + +function unload() { + /sbin/rmmod vgem + # drm may be used by other devices (nouveau, radeon, udl, etc) + /sbin/rmmod drm &> /dev/null + + if /sbin/lsmod | grep vgem &> /dev/null ; then + echo WARNING: vgem.ko still loaded! + return 1 + fi +} + +unload &> /dev/null + +/sbin/modprobe vgem $* || exit 1 +unload || exit 1
dri-devel@lists.freedesktop.org