2 * Copyright © 2012 Intel Corporation
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:
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
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
24 * Ben Widawsky <ben@bwidawsk.net>
29 * This test covers basic context switch functionality
41 #include <sys/ioctl.h>
46 #include "ioctl_wrappers.h"
49 #include "igt_debugfs.h"
51 struct local_drm_i915_gem_context_destroy {
56 #define CONTEXT_DESTROY_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2e, struct local_drm_i915_gem_context_destroy)
58 static void context_destroy(int fd, uint32_t ctx_id)
60 struct local_drm_i915_gem_context_destroy destroy;
61 destroy.ctx_id = ctx_id;
62 do_ioctl(fd, CONTEXT_DESTROY_IOCTL, &destroy);
66 /* Copied from gem_exec_nop.c */
67 static int exec(int fd, uint32_t handle, int ring, int ctx_id)
69 struct drm_i915_gem_execbuffer2 execbuf;
70 struct drm_i915_gem_exec_object2 gem_exec;
73 gem_exec.handle = handle;
74 gem_exec.relocation_count = 0;
75 gem_exec.relocs_ptr = 0;
76 gem_exec.alignment = 0;
82 execbuf.buffers_ptr = (uintptr_t)&gem_exec;
83 execbuf.buffer_count = 1;
84 execbuf.batch_start_offset = 0;
85 execbuf.batch_len = 8;
86 execbuf.cliprects_ptr = 0;
87 execbuf.num_cliprects = 0;
91 i915_execbuffer2_set_context_id(execbuf, ctx_id);
94 ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2,
100 static void big_exec(int fd, uint32_t handle, int ring)
102 struct drm_i915_gem_execbuffer2 execbuf;
103 struct drm_i915_gem_exec_object2 *gem_exec;
104 uint32_t ctx_id1, ctx_id2;
105 int num_buffers = gem_available_aperture_size(fd) / 4096;
108 /* Make sure we only fill half of RAM with gem objects. */
109 igt_require(intel_get_total_ram_mb() * 1024 / 2 > num_buffers * 4);
111 gem_exec = calloc(num_buffers + 1, sizeof(*gem_exec));
112 igt_assert(gem_exec);
113 memset(gem_exec, 0, (num_buffers + 1) * sizeof(*gem_exec));
116 ctx_id1 = gem_context_create(fd);
117 ctx_id2 = gem_context_create(fd);
119 gem_exec[0].handle = handle;
122 execbuf.buffers_ptr = (uintptr_t)gem_exec;
123 execbuf.buffer_count = num_buffers + 1;
124 execbuf.batch_start_offset = 0;
125 execbuf.batch_len = 8;
126 execbuf.cliprects_ptr = 0;
127 execbuf.num_cliprects = 0;
130 execbuf.flags = ring;
133 execbuf.buffer_count = 1;
134 i915_execbuffer2_set_context_id(execbuf, ctx_id1);
135 igt_assert(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2,
138 for (i = 0; i < num_buffers; i++) {
139 uint32_t tmp_handle = gem_create(fd, 4096);
141 gem_exec[i].handle = tmp_handle;
143 gem_exec[i].handle = handle;
144 execbuf.buffer_count = i + 1;
146 /* figure out how many buffers we can exactly fit */
147 while (drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2,
150 gem_close(fd, gem_exec[i].handle);
151 gem_exec[i].handle = handle;
152 execbuf.buffer_count--;
153 igt_info("trying buffer count %i\n", i - 1);
156 igt_info("reduced buffer count to %i from %i\n",
159 /* double check that it works */
160 igt_assert(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2,
163 i915_execbuffer2_set_context_id(execbuf, ctx_id2);
164 igt_assert(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2,
166 gem_sync(fd, handle);
170 uint32_t batch[2] = {0, MI_BATCH_BUFFER_END};
176 igt_skip_on_simulation();
178 fd = drm_open_any_render();
180 handle = gem_create(fd, 4096);
182 /* check that we can create contexts. */
183 ctx_id = gem_context_create(fd);
184 context_destroy(fd, ctx_id);
185 gem_write(fd, handle, 0, batch, sizeof(batch));
188 igt_subtest("basic") {
189 ctx_id = gem_context_create(fd);
190 igt_assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0);
191 gem_sync(fd, handle);
192 context_destroy(fd, ctx_id);
194 ctx_id = gem_context_create(fd);
195 igt_assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0);
196 gem_sync(fd, handle);
197 context_destroy(fd, ctx_id);
199 igt_assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) < 0);
200 gem_sync(fd, handle);
203 igt_subtest("eviction")
204 big_exec(fd, handle, I915_EXEC_RENDER);
206 igt_subtest("reset-pin-leak") {
210 * Use an explicit context to isolate the test from
211 * any major code changes related to the per-file
212 * default context (eg. if they would be eliminated).
214 ctx_id = gem_context_create(fd);
217 * Iterate enough times that the kernel will
218 * become unhappy if the ggtt pin count for
219 * the last context is leaked at every reset.
221 for (i = 0; i < 20; i++) {
222 igt_set_stop_rings(STOP_RING_DEFAULTS);
223 igt_assert(exec(fd, handle, I915_EXEC_RENDER, 0) == 0);
224 igt_assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0);
225 gem_sync(fd, handle);
228 context_destroy(fd, ctx_id);