You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
404 lines
9.9 KiB
404 lines
9.9 KiB
/*
|
|
* 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:
|
|
* Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
*/
|
|
|
|
#include <fcntl.h>
|
|
#include <limits.h>
|
|
|
|
#include "igt.h"
|
|
#include "i915/gem_vm.h"
|
|
|
|
IGT_TEST_DESCRIPTION("Basic test for context set/get param input validation.");
|
|
|
|
#define NEW_CTX BIT(0)
|
|
#define USER BIT(1)
|
|
|
|
static void set_priority(int i915)
|
|
{
|
|
static const int64_t test_values[] = {
|
|
/* Test space too big, pick significant values */
|
|
INT_MIN,
|
|
|
|
I915_CONTEXT_MIN_USER_PRIORITY - 1,
|
|
I915_CONTEXT_MIN_USER_PRIORITY,
|
|
I915_CONTEXT_MIN_USER_PRIORITY + 1,
|
|
|
|
I915_CONTEXT_DEFAULT_PRIORITY - 1,
|
|
I915_CONTEXT_DEFAULT_PRIORITY,
|
|
I915_CONTEXT_DEFAULT_PRIORITY + 1,
|
|
|
|
I915_CONTEXT_MAX_USER_PRIORITY - 1,
|
|
I915_CONTEXT_MAX_USER_PRIORITY,
|
|
I915_CONTEXT_MAX_USER_PRIORITY + 1,
|
|
|
|
INT_MAX
|
|
};
|
|
unsigned int size;
|
|
int64_t *values;
|
|
|
|
igt_require(getuid() == 0);
|
|
|
|
size = ARRAY_SIZE(test_values);
|
|
values = malloc(sizeof(test_values) * 8);
|
|
igt_assert(values);
|
|
|
|
for (unsigned i = 0; i < size; i++) {
|
|
values[i + 0*size] = test_values[i];
|
|
values[i + 1*size] = test_values[i] | (uint64_t)1 << 32;
|
|
values[i + 2*size] = test_values[i] | (uint64_t)rand() << 32;
|
|
values[i + 3*size] = test_values[i] ^ rand();
|
|
values[i + 4*size] = rand() % (I915_CONTEXT_MAX_USER_PRIORITY - I915_CONTEXT_MIN_USER_PRIORITY) + I915_CONTEXT_MIN_USER_PRIORITY;
|
|
values[i + 5*size] = rand();
|
|
values[i + 6*size] = rand() | (uint64_t)rand() << 32;
|
|
values[i + 7*size] = (uint64_t)test_values[i] << 32;
|
|
}
|
|
size *= 8;
|
|
|
|
igt_permute_array(values, size, igt_exchange_int64);
|
|
|
|
igt_fork(flags, NEW_CTX | USER) {
|
|
int fd = gem_reopen_driver(i915);
|
|
struct drm_i915_gem_context_param arg = {
|
|
.param = I915_CONTEXT_PARAM_PRIORITY,
|
|
.ctx_id = flags & NEW_CTX ? gem_context_create(fd) : 0,
|
|
};
|
|
int64_t old_prio;
|
|
|
|
if (flags & USER) {
|
|
igt_debug("Dropping root privilege\n");
|
|
igt_drop_root();
|
|
}
|
|
|
|
gem_context_get_param(fd, &arg);
|
|
old_prio = arg.value;
|
|
|
|
for (unsigned i = 0; i < size; i++) {
|
|
int64_t prio = values[i];
|
|
int expected = 0;
|
|
int err;
|
|
|
|
arg.value = prio;
|
|
|
|
if (flags & USER &&
|
|
prio > I915_CONTEXT_DEFAULT_PRIORITY)
|
|
expected = -EPERM;
|
|
|
|
if (prio < I915_CONTEXT_MIN_USER_PRIORITY ||
|
|
prio > I915_CONTEXT_MAX_USER_PRIORITY)
|
|
expected = -EINVAL;
|
|
|
|
err =__gem_context_set_param(fd, &arg);
|
|
igt_assert_f(err == expected,
|
|
"Priority requested %" PRId64 " with flags %x, expected result %d, returned %d\n",
|
|
prio, flags, expected, err);
|
|
|
|
gem_context_get_param(fd, &arg);
|
|
if (!err)
|
|
old_prio = prio;
|
|
igt_assert_eq(arg.value, old_prio);
|
|
}
|
|
|
|
arg.value = 0;
|
|
gem_context_set_param(fd, &arg);
|
|
|
|
if (flags & NEW_CTX)
|
|
gem_context_destroy(fd, arg.ctx_id);
|
|
}
|
|
|
|
igt_waitchildren();
|
|
free(values);
|
|
}
|
|
|
|
static uint32_t __batch_create(int i915, uint32_t offset)
|
|
{
|
|
const uint32_t bbe = MI_BATCH_BUFFER_END;
|
|
uint32_t handle;
|
|
|
|
handle = gem_create(i915, ALIGN(offset + 4, 4096));
|
|
gem_write(i915, handle, offset, &bbe, sizeof(bbe));
|
|
|
|
return handle;
|
|
}
|
|
|
|
static uint32_t batch_create(int i915)
|
|
{
|
|
return __batch_create(i915, 0);
|
|
}
|
|
|
|
static void test_vm(int i915)
|
|
{
|
|
const uint64_t nonzero_offset = 48 << 20;
|
|
struct drm_i915_gem_exec_object2 batch = {
|
|
.handle = batch_create(i915),
|
|
};
|
|
struct drm_i915_gem_execbuffer2 eb = {
|
|
.buffers_ptr = to_user_pointer(&batch),
|
|
.buffer_count = 1,
|
|
};
|
|
struct drm_i915_gem_context_param arg = {
|
|
.param = I915_CONTEXT_PARAM_VM,
|
|
};
|
|
uint32_t parent, child;
|
|
|
|
/*
|
|
* Proving 2 contexts share the same GTT is quite tricky as we have no
|
|
* means of directly comparing them (each handle returned to userspace
|
|
* is unique). What we do instead is rely on a quirk of execbuf that
|
|
* it does not try to move an VMA without good reason, and so that
|
|
* having used an object in one context, it will have the same address
|
|
* in the next context that shared the VM.
|
|
*/
|
|
|
|
arg.value = -1ull;
|
|
igt_require(__gem_context_set_param(i915, &arg) == -ENOENT);
|
|
|
|
parent = gem_context_create(i915);
|
|
child = gem_context_create(i915);
|
|
|
|
/* Using implicit soft-pinning */
|
|
eb.rsvd1 = parent;
|
|
batch.offset = nonzero_offset;
|
|
gem_execbuf(i915, &eb);
|
|
igt_assert_eq_u64(batch.offset, nonzero_offset);
|
|
|
|
eb.rsvd1 = child;
|
|
batch.offset = 0;
|
|
gem_execbuf(i915, &eb);
|
|
igt_assert_eq_u64(batch.offset, 0);
|
|
|
|
eb.rsvd1 = parent;
|
|
gem_execbuf(i915, &eb);
|
|
igt_assert_eq_u64(batch.offset, nonzero_offset);
|
|
|
|
arg.ctx_id = parent;
|
|
gem_context_get_param(i915, &arg);
|
|
gem_context_set_param(i915, &arg);
|
|
|
|
/* Still the same VM, so expect the old VMA again */
|
|
batch.offset = 0;
|
|
gem_execbuf(i915, &eb);
|
|
igt_assert_eq_u64(batch.offset, nonzero_offset);
|
|
|
|
arg.ctx_id = child;
|
|
gem_context_set_param(i915, &arg);
|
|
|
|
eb.rsvd1 = child;
|
|
batch.offset = 0;
|
|
gem_execbuf(i915, &eb);
|
|
igt_assert_eq_u64(batch.offset, nonzero_offset);
|
|
|
|
gem_context_destroy(i915, child);
|
|
gem_context_destroy(i915, parent);
|
|
|
|
/* both contexts destroyed, but we still keep hold of the vm */
|
|
child = gem_context_create(i915);
|
|
|
|
arg.ctx_id = child;
|
|
gem_context_set_param(i915, &arg);
|
|
|
|
eb.rsvd1 = child;
|
|
batch.offset = 0;
|
|
gem_execbuf(i915, &eb);
|
|
igt_assert_eq_u64(batch.offset, nonzero_offset);
|
|
|
|
gem_context_destroy(i915, child);
|
|
gem_vm_destroy(i915, arg.value);
|
|
|
|
gem_sync(i915, batch.handle);
|
|
gem_close(i915, batch.handle);
|
|
}
|
|
|
|
igt_main
|
|
{
|
|
struct drm_i915_gem_context_param arg;
|
|
int fd;
|
|
uint32_t ctx;
|
|
|
|
memset(&arg, 0, sizeof(arg));
|
|
|
|
igt_fixture {
|
|
fd = drm_open_driver_render(DRIVER_INTEL);
|
|
|
|
gem_require_contexts(fd);
|
|
ctx = gem_context_create(fd);
|
|
|
|
arg.param = I915_CONTEXT_PARAM_BAN_PERIOD;
|
|
|
|
/* XXX start to enforce ban period returning -EINVAL when
|
|
* transition has been done */
|
|
if (__gem_context_get_param(fd, &arg) == -EINVAL)
|
|
arg.param = I915_CONTEXT_PARAM_BANNABLE;
|
|
}
|
|
|
|
igt_subtest("basic") {
|
|
arg.ctx_id = ctx;
|
|
gem_context_get_param(fd, &arg);
|
|
gem_context_set_param(fd, &arg);
|
|
}
|
|
|
|
igt_subtest("basic-default") {
|
|
arg.ctx_id = 0;
|
|
gem_context_get_param(fd, &arg);
|
|
gem_context_set_param(fd, &arg);
|
|
}
|
|
|
|
igt_subtest("invalid-ctx-get") {
|
|
arg.ctx_id = 2;
|
|
igt_assert_eq(__gem_context_get_param(fd, &arg), -ENOENT);
|
|
}
|
|
|
|
igt_subtest("invalid-ctx-set") {
|
|
arg.ctx_id = ctx;
|
|
gem_context_get_param(fd, &arg);
|
|
arg.ctx_id = 2;
|
|
igt_assert_eq(__gem_context_set_param(fd, &arg), -ENOENT);
|
|
}
|
|
|
|
igt_subtest("invalid-size-get") {
|
|
arg.ctx_id = ctx;
|
|
arg.size = 8;
|
|
gem_context_get_param(fd, &arg);
|
|
igt_assert(arg.size == 0);
|
|
}
|
|
|
|
igt_subtest("invalid-size-set") {
|
|
arg.ctx_id = ctx;
|
|
gem_context_get_param(fd, &arg);
|
|
arg.size = 8;
|
|
igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL);
|
|
arg.size = 0;
|
|
}
|
|
|
|
igt_subtest("non-root-set") {
|
|
igt_fork(child, 1) {
|
|
igt_drop_root();
|
|
|
|
arg.ctx_id = ctx;
|
|
gem_context_get_param(fd, &arg);
|
|
arg.value--;
|
|
igt_assert_eq(__gem_context_set_param(fd, &arg), -EPERM);
|
|
}
|
|
|
|
igt_waitchildren();
|
|
}
|
|
|
|
igt_subtest("root-set") {
|
|
arg.ctx_id = ctx;
|
|
gem_context_get_param(fd, &arg);
|
|
arg.value--;
|
|
gem_context_set_param(fd, &arg);
|
|
}
|
|
|
|
arg.param = I915_CONTEXT_PARAM_NO_ZEROMAP;
|
|
|
|
igt_subtest("non-root-set-no-zeromap") {
|
|
igt_fork(child, 1) {
|
|
igt_drop_root();
|
|
|
|
arg.ctx_id = ctx;
|
|
gem_context_get_param(fd, &arg);
|
|
arg.value--;
|
|
gem_context_set_param(fd, &arg);
|
|
}
|
|
|
|
igt_waitchildren();
|
|
}
|
|
|
|
igt_subtest("root-set-no-zeromap-enabled") {
|
|
arg.ctx_id = ctx;
|
|
gem_context_get_param(fd, &arg);
|
|
arg.value = 1;
|
|
gem_context_set_param(fd, &arg);
|
|
}
|
|
|
|
igt_subtest("root-set-no-zeromap-disabled") {
|
|
arg.ctx_id = ctx;
|
|
gem_context_get_param(fd, &arg);
|
|
arg.value = 0;
|
|
gem_context_set_param(fd, &arg);
|
|
}
|
|
|
|
igt_subtest("vm")
|
|
test_vm(fd);
|
|
|
|
arg.param = I915_CONTEXT_PARAM_PRIORITY;
|
|
|
|
igt_subtest("set-priority-not-supported") {
|
|
igt_require(!gem_scheduler_has_ctx_priority(fd));
|
|
|
|
arg.ctx_id = ctx;
|
|
arg.size = 0;
|
|
|
|
igt_assert_eq(__gem_context_set_param(fd, &arg), -ENODEV);
|
|
}
|
|
|
|
igt_subtest_group {
|
|
igt_fixture {
|
|
igt_require(gem_scheduler_has_ctx_priority(fd));
|
|
}
|
|
|
|
igt_subtest("get-priority-new-ctx") {
|
|
struct drm_i915_gem_context_param local_arg = arg;
|
|
uint32_t local_ctx = gem_context_create(fd);
|
|
|
|
local_arg.ctx_id = local_ctx;
|
|
|
|
gem_context_get_param(fd, &local_arg);
|
|
igt_assert_eq(local_arg.value, I915_CONTEXT_DEFAULT_PRIORITY);
|
|
|
|
gem_context_destroy(fd, local_ctx);
|
|
}
|
|
|
|
igt_subtest("set-priority-invalid-size") {
|
|
struct drm_i915_gem_context_param local_arg = arg;
|
|
local_arg.ctx_id = ctx;
|
|
local_arg.value = 0;
|
|
local_arg.size = ~0;
|
|
|
|
igt_assert_eq(__gem_context_set_param(fd, &local_arg), -EINVAL);
|
|
}
|
|
|
|
igt_subtest("set-priority-range")
|
|
set_priority(fd);
|
|
}
|
|
|
|
/* I915_CONTEXT_PARAM_SSEU tests are located in gem_ctx_sseu.c */
|
|
|
|
arg.param = -1; /* Should be safely unused for a while */
|
|
|
|
igt_subtest("invalid-param-get") {
|
|
arg.ctx_id = ctx;
|
|
igt_assert_eq(__gem_context_get_param(fd, &arg), -EINVAL);
|
|
}
|
|
|
|
igt_subtest("invalid-param-set") {
|
|
arg.ctx_id = ctx;
|
|
igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL);
|
|
}
|
|
|
|
igt_fixture
|
|
close(fd);
|
|
}
|