drv_cgroup exercises both valid and invalid usage of the i915 cgroup
parameter ioctl.

v2:
 - Add support for display boost
 - Drop cgroup permissions test (the kernel no longer bases access
   control on fs permissions)

Signed-off-by: Matt Roper <matthew.d.ro...@intel.com>
---
 tests/Makefile.sources |   1 +
 tests/drv_cgroup.c     | 262 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 263 insertions(+)
 create mode 100644 tests/drv_cgroup.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 4e6f5319..ba4b00bb 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -37,6 +37,7 @@ TESTS_progs = \
        drm_vma_limiter_cached \
        drm_vma_limiter_cpu \
        drm_vma_limiter_gtt \
+       drv_cgroup \
        drv_getparams_basic \
        drv_hangman \
        drv_missed_irq \
diff --git a/tests/drv_cgroup.c b/tests/drv_cgroup.c
new file mode 100644
index 00000000..457daf7b
--- /dev/null
+++ b/tests/drv_cgroup.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright © 2018 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_debugfs.h"
+#include "igt_aux.h"
+#include "igt_kmod.h"
+#include "igt_sysfs.h"
+#include "igt_core.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <signal.h>
+#include <stdio.h>
+#include <linux/limits.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+
+/* libdrm support is not yet upstream, so duplicate defs here for now */
+
+struct INTERNAL_drm_i915_cgroup_param {
+       __s32 cgroup_fd;
+       __u32 flags;
+       __u64 param;
+#define I915_CGROUP_PARAM_PRIORITY_OFFSET       0x1
+#define I915_CGROUP_PARAM_DISPBOOST_PRIORITY    0x2
+       __s64 value;
+};
+
+#define INTERNAL_IOCTL_I915_CGROUP_SETPARAM  \
+       DRM_IOW(DRM_COMMAND_BASE + 0x3a, struct INTERNAL_drm_i915_cgroup_param)
+
+static char tmp[PATH_MAX], *cgrp2dir = NULL;
+static int cgrp2fd = -1;
+static int drm_fd = -1;
+
+/* Figure out where (if) cgroups-v2 is mounted on this machine. */
+static void
+find_cgroup2(void)
+{
+       FILE *f;
+       char *from, *path, *type;
+
+       f = fopen("/proc/mounts", "r");
+       igt_assert(f);
+
+       while (fgets(tmp, sizeof(tmp), f)) {
+               from = strtok(tmp, " ");
+               if (!from) continue;
+
+               path = strtok(NULL, " ");
+               if (!path) continue;
+
+               type = strtok(NULL, " ");
+               if (strcmp(type, "cgroup2") == 0) {
+                       cgrp2dir = path;
+                       cgrp2fd = open(cgrp2dir, O_DIRECTORY|O_RDONLY);
+                       break;
+               }
+       }
+
+       fclose(f);
+
+       igt_skip_on_f(!cgrp2dir, "cgroups-v2 is not mounted\n");
+       igt_skip_on_f(!cgrp2fd, "Insufficient fs permissions on cgroup2 dir\n");
+}
+
+static char tmp_cgroup[PATH_MAX];
+
+static int
+create_tmp_cgroup(void)
+{
+       char *dirname;
+       int fd;
+
+       snprintf(tmp_cgroup, sizeof(tmp_cgroup), "%s/igt_cgroup_XXXXXX",
+                cgrp2dir);
+       dirname = mkdtemp(tmp_cgroup);
+       igt_assert(dirname);
+
+       fd = open(dirname, O_DIRECTORY|O_RDONLY);
+       igt_assert(fd >= 0);
+
+       return fd;
+}
+
+static void
+rm_tmp_cgroup(int fd)
+{
+       close(fd);
+       rmdir(tmp_cgroup);
+}
+
+static int
+set_prio(int fd, int prio)
+{
+       struct INTERNAL_drm_i915_cgroup_param req;
+
+       req.cgroup_fd = fd;
+       req.flags = 0;
+       req.param = I915_CGROUP_PARAM_PRIORITY_OFFSET;
+       req.value = prio;
+
+       return drmIoctl(drm_fd, INTERNAL_IOCTL_I915_CGROUP_SETPARAM, &req);
+}
+
+static int
+set_boost(int fd, int boost)
+{
+       struct INTERNAL_drm_i915_cgroup_param req;
+
+       req.cgroup_fd = fd;
+       req.flags = 0;
+       req.param = I915_CGROUP_PARAM_DISPBOOST_PRIORITY;
+       req.value = boost;
+
+       return drmIoctl(drm_fd, INTERNAL_IOCTL_I915_CGROUP_SETPARAM, &req);
+}
+
+igt_main
+{
+       char other_file[PATH_MAX];
+       int ret, fd;
+
+       igt_fixture {
+               find_cgroup2();
+               drm_fd = drm_open_driver_master(DRIVER_INTEL);
+       }
+
+       /* Standard request to set priority.  Should succeed */
+       igt_subtest_f("set-prio") {
+               fd = create_tmp_cgroup();
+               ret = set_prio(fd, 123);
+               igt_fail_on(ret);
+               rm_tmp_cgroup(fd);
+       }
+
+       /* Set priority outside valid range.  Should fail */
+       igt_subtest_f("prio-out-of-range") {
+               fd = create_tmp_cgroup();
+               ret = set_prio(fd, 0x800000);
+               igt_assert(ret < 0 && errno == EINVAL);
+               rm_tmp_cgroup(fd);
+       }
+
+       /* Set display boost to valid value.  Should succeed */
+       igt_subtest_f("set-dispboost") {
+               fd = create_tmp_cgroup();
+               ret = set_boost(fd, 0x3000);
+               igt_fail_on(ret);
+               rm_tmp_cgroup(fd);
+       }
+
+       /* Set display boost outside valid range.  Should fail */
+       igt_subtest_f("dispboost-out-of-range") {
+               fd = create_tmp_cgroup();
+               ret = set_boost(fd, 0x800001);
+               igt_assert(ret < 0 && errno == EINVAL);
+               rm_tmp_cgroup(fd);
+       }
+
+       /* Use an invalid parameter ID.  Should fail. */
+       igt_subtest_f("bad-param") {
+               struct INTERNAL_drm_i915_cgroup_param req;
+
+               fd = create_tmp_cgroup();
+               req.cgroup_fd = fd;
+               req.flags = 0;
+               req.param = 0xDEADBEEF;
+               req.value = 123;
+
+               ret = drmIoctl(drm_fd, INTERNAL_IOCTL_I915_CGROUP_SETPARAM, 
&req);
+               igt_assert(ret < 0 && errno == EINVAL);
+
+               rm_tmp_cgroup(fd);
+       }
+
+       /*
+        * Pass fd for a cgroup control file instead of cgroup directory itself.
+        * Should fail.
+        */
+       igt_subtest_f("control-file-fd") {
+               int fd2;
+
+               fd = create_tmp_cgroup();
+               snprintf(other_file, sizeof(other_file),
+                        "%s/cgroup.procs", tmp_cgroup);
+               fd2 = open(other_file, O_RDONLY);
+               igt_assert(fd2 >= 0);
+
+               ret = set_prio(fd2, 123);
+               igt_assert(ret < 0 && errno == EBADF);
+
+               close(fd2);
+               rm_tmp_cgroup(fd);
+       }
+
+       /*
+        * Pass an fd for a non-cgroup directory.  Should fail.
+        * Note that we rely on /tmp being available and writable.
+        */
+       igt_subtest_f("non-cgroup-fd") {
+               char *dirname;
+
+               strcpy(other_file, "/tmp/igt_XXXXXX");
+               dirname = mkdtemp(other_file);
+               igt_assert(dirname);
+
+               fd = open(dirname, O_DIRECTORY|O_RDONLY);
+               igt_assert(fd >= 0);
+
+               ret = set_prio(fd, 123);
+               igt_assert(ret < 0 && errno == EBADF);
+
+               close(fd);
+               rmdir(dirname);
+       }
+
+       /*
+        * Reload driver after setting priority.  Should pass.
+        *
+        * The priority data will be lost across reload, but the goal is to
+        * make sure we don't panic during driver removal or subsequent
+        * assignment of a new priority to the existing cgroup.
+        */
+       igt_subtest_f("cgroup-reload") {
+               fd = create_tmp_cgroup();
+               ret = set_prio(fd, 123);
+               igt_fail_on(ret);
+
+               ret = igt_i915_driver_unload();
+               igt_fail_on(ret);
+               ret = igt_i915_driver_load(NULL);
+               igt_fail_on(ret);
+
+               ret = set_prio(fd, 456);
+               igt_fail_on(ret);
+
+               rm_tmp_cgroup(fd);
+       }
+}
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to