To exercise the new I915_CONTEXT_PARAM_ENGINES and interactions with gem_execbuf(). Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- tests/Makefile.sources | 1 + tests/gem_ctx_engines.c | 236 ++++++++++++++++++++++++++++++++++++++++ tests/meson.build | 1 + 3 files changed, 238 insertions(+) create mode 100644 tests/gem_ctx_engines.c diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 0c2befe72..4e42a4f05 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -52,6 +52,7 @@ TESTS_progs = \ gem_cs_tlb \ gem_ctx_bad_destroy \ gem_ctx_create \ + gem_ctx_engines \ gem_ctx_exec \ gem_ctx_isolation \ gem_ctx_param \ diff --git a/tests/gem_ctx_engines.c b/tests/gem_ctx_engines.c new file mode 100644 index 000000000..5dcbc3c90 --- /dev/null +++ b/tests/gem_ctx_engines.c @@ -0,0 +1,236 @@ +/* + * 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 <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> + +#include <drm.h> + +#include "i915/gem_context.h" + +struct i915_user_extension { + uint64_t next_extension; + uint64_t name; +}; + +struct i915_context_param_engines { + uint64_t extensions; + + struct { + uint32_t class; + uint32_t instance; + } class_instance[0]; +}; +#define I915_CONTEXT_PARAM_ENGINES 0x7 + +static bool has_context_engines(int i915) +{ + struct drm_i915_gem_context_param param = { + .ctx_id = 0, + .param = I915_CONTEXT_PARAM_ENGINES, + }; + return __gem_context_set_param(i915, ¶m) == 0; +} + +static void invalid_engines(int i915) +{ + struct i915_context_param_engines stack = {}, *engines; + struct drm_i915_gem_context_param param = { + .ctx_id = gem_context_create(i915), + .param = I915_CONTEXT_PARAM_ENGINES, + .value = to_user_pointer(&stack), + }; + void *ptr; + + param.size = 0; + igt_assert_eq(__gem_context_set_param(i915, ¶m), 0); + + param.size = 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EINVAL); + + param.size = sizeof(stack) - 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EINVAL); + + param.size = sizeof(stack) + 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EINVAL); + + param.size = 0; + igt_assert_eq(__gem_context_set_param(i915, ¶m), 0); + + /* Create a single page surrounded by inaccessible nothingness */ + ptr = mmap(NULL, 3 * 4096, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + igt_assert(ptr != MAP_FAILED); + + munmap(ptr, 4096); + engines = ptr + 4096; + munmap(ptr + 2 *4096, 4096); + + param.size = sizeof(*engines) + sizeof(*engines->class_instance); + param.value = to_user_pointer(engines); + + engines->class_instance[0].class = -1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -ENOENT); + + mprotect(engines, 4096, PROT_READ); + igt_assert_eq(__gem_context_set_param(i915, ¶m), -ENOENT); + + mprotect(engines, 4096, PROT_WRITE); + engines->class_instance[0].class = 0; + if (__gem_context_set_param(i915, ¶m)) /* XXX needs RCS */ + goto out; + + engines->extensions = to_user_pointer(ptr); + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + engines->extensions = 0; + igt_assert_eq(__gem_context_set_param(i915, ¶m), 0); + + param.value = to_user_pointer(engines - 1); + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) - 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) - param.size + 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) + 4096; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) - param.size + 4096; + igt_assert_eq(__gem_context_set_param(i915, ¶m), 0); + + param.value = to_user_pointer(engines) - param.size + 4096 + 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) + 4096; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) + 4096 - 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines) - 1; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines - 1); + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines - 1) + 4096; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + + param.value = to_user_pointer(engines - 1) + 4096 - sizeof(*engines->class_instance) / 2; + igt_assert_eq(__gem_context_set_param(i915, ¶m), -EFAULT); + +out: + munmap(engines, 4096); + gem_context_destroy(i915, param.ctx_id); +} + +static void execute_one(int i915) +{ + struct one_engine { + uint64_t extensions; + uint32_t class; + uint32_t instance; + } engines; + struct drm_i915_gem_context_param param = { + .ctx_id = gem_context_create(i915), + .param = I915_CONTEXT_PARAM_ENGINES, + .size = sizeof(engines), + .value = to_user_pointer(&engines), + }; + struct drm_i915_gem_exec_object2 obj = { + .handle = gem_create(i915, 4096), + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + .rsvd1 = param.ctx_id, + }; + const uint32_t bbe = MI_BATCH_BUFFER_END; + const struct intel_execution_engine2 *e; + + gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe)); + memset(&engines, 0, sizeof(engines)); + + /* Unadulterated I915_EXEC_DEFAULT should work */ + execbuf.flags = 0; + igt_assert_eq(__gem_execbuf(i915, &execbuf), 0); + + for_each_engine_class_instance(i915, e) { + engines.class = e->class; + engines.instance = e->instance; + gem_context_set_param(i915, ¶m); + + execbuf.flags = 0; + igt_assert_eq(__gem_execbuf(i915, &execbuf), -EINVAL); + + execbuf.flags = 1; + igt_assert_eq(__gem_execbuf(i915, &execbuf), 0); + + execbuf.flags = 2; + igt_assert_eq(__gem_execbuf(i915, &execbuf), -EINVAL); + + /* XXX prove we used the right engine! */ + } + + /* Restore the defaults and check I915_EXEC_DEFAULT works again. */ + param.size = 0; + gem_context_set_param(i915, ¶m); + execbuf.flags = 0; + igt_assert_eq(__gem_execbuf(i915, &execbuf), 0); + + gem_close(i915, obj.handle); + gem_context_destroy(i915, param.ctx_id); +} + +igt_main +{ + int i915 = -1; + + igt_fixture { + i915 = drm_open_driver_render(DRIVER_INTEL); + igt_require_gem(i915); + + gem_require_contexts(i915); + igt_require(has_context_engines(i915)); + } + + igt_subtest("invalid-engines") + invalid_engines(i915); + + igt_subtest("execute-one") + execute_one(i915); +} diff --git a/tests/meson.build b/tests/meson.build index d22d59e08..b6da4f479 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -29,6 +29,7 @@ test_progs = [ 'gem_cs_tlb', 'gem_ctx_bad_destroy', 'gem_ctx_create', + 'gem_ctx_engines', 'gem_ctx_exec', 'gem_ctx_isolation', 'gem_ctx_param', -- 2.19.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx