1 /*
2 * Copyright © 2017 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "igt.h"
25
test_many_handles(int fd)26 static void test_many_handles(int fd)
27 {
28 uint32_t bbe = MI_BATCH_BUFFER_END;
29 struct drm_i915_gem_execbuffer2 execbuf;
30 struct drm_i915_gem_exec_object2 obj[2];
31 uint32_t clones[1024];
32 uint32_t original;
33
34 original = gem_create(fd, 4096);
35 gem_write(fd, original, 0, &bbe, sizeof(bbe));
36
37 memset(&execbuf, 0, sizeof(execbuf));
38 execbuf.buffers_ptr = to_user_pointer(obj);
39 execbuf.buffer_count = 1;
40
41 memset(obj, 0, sizeof(obj));
42 obj[0].handle = original;
43 gem_execbuf(fd, &execbuf);
44
45 for (int i = 0; i < ARRAY_SIZE(clones); i++) {
46 clones[i] = gem_open(fd, gem_flink(fd, original));
47 obj[0].handle = clones[i];
48 gem_execbuf(fd, &execbuf);
49 }
50
51 /* We do not allow the sam object to be referenced multiple times
52 * within an execbuf; hence why this practice of cloning a handle
53 * is only found within test cases.
54 */
55 execbuf.buffer_count = 2;
56 obj[0].handle = original;
57 for (int i = 0; i < ARRAY_SIZE(clones); i++) {
58 obj[1].handle = clones[i];
59 igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
60 }
61 /* Any other clone pair should also be detected */
62 obj[1].handle = clones[0]; /* (last, first) */
63 igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
64 execbuf.buffer_count = 1;
65
66 /* Now close the original having used every clone */
67 obj[0].handle = original;
68 gem_close(fd, original);
69 igt_assert_eq(__gem_execbuf(fd, &execbuf), -ENOENT);
70
71 /* All clones should still be operational */
72 for (int i = 0; i < ARRAY_SIZE(clones); i++) {
73 obj[0].handle = clones[i];
74 gem_execbuf(fd, &execbuf);
75
76 /* ... until closed */
77 gem_close(fd, clones[i]);
78 igt_assert_eq(__gem_execbuf(fd, &execbuf), -ENOENT);
79 }
80 }
81
82 igt_main
83 {
84 int fd = -1;
85
86 igt_fixture {
87 /* Create an flink requires DRM_AUTH */
88 fd = drm_open_driver_master(DRIVER_INTEL);
89 igt_require_gem(fd);
90 }
91
92 igt_subtest("basic")
93 gem_close(fd, gem_create(fd, 4096));
94
95 igt_subtest("many-handles-one-vma")
96 test_many_handles(fd);
97 }
98