blob: a73ece5daaaad082cbf4c6060bb6d07c0ef5b986 [file] [log] [blame]
Chris Wilsona27c7432016-12-03 10:21:08 +00001/*
2 * Copyright © 2016 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#include "igt_sysfs.h"
26
27#define LOCAL_OBJECT_CAPTURE (1 << 7)
28#define LOCAL_PARAM_HAS_EXEC_CAPTURE 45
29
30IGT_TEST_DESCRIPTION("Check that we capture the user specified objects on a hang");
31
32static void check_error_state(int dir, struct drm_i915_gem_exec_object2 *obj)
33{
34 char *error, *str;
35 bool found = false;
36
37 error = igt_sysfs_get(dir, "error");
38 igt_sysfs_set(dir, "error", "Begone!");
39
40 igt_assert(error);
41 igt_debug("%s\n", error);
42
43 /* render ring --- user = 0x00000000 ffffd000 */
44 for (str = error; (str = strstr(str, "--- user = ")); str++) {
45 uint64_t addr;
46 uint32_t hi, lo;
47
48 igt_assert(sscanf(str, "--- user = 0x%x %x", &hi, &lo) == 2);
49 addr = hi;
50 addr <<= 32;
51 addr |= lo;
52 igt_assert_eq_u64(addr, obj->offset);
53 found = true;
54 }
55
56 igt_assert(found);
57}
58
59static void capture(int fd, int dir, unsigned ring)
60{
61 const int gen = intel_gen(intel_get_drm_devid(fd));
62 struct drm_i915_gem_exec_object2 obj[4];
63#define SCRATCH 0
64#define CAPTURE 1
65#define NOCAPTURE 2
66#define BATCH 3
Chris Wilsonb5959302017-08-07 13:36:35 +010067 struct drm_i915_gem_relocation_entry reloc[2];
Chris Wilsona27c7432016-12-03 10:21:08 +000068 struct drm_i915_gem_execbuffer2 execbuf;
Chris Wilsonb5959302017-08-07 13:36:35 +010069 uint32_t *batch, *seqno;
Chris Wilsona27c7432016-12-03 10:21:08 +000070 int i;
71
72 memset(obj, 0, sizeof(obj));
73 obj[SCRATCH].handle = gem_create(fd, 4096);
74 obj[CAPTURE].handle = gem_create(fd, 4096);
75 obj[CAPTURE].flags = LOCAL_OBJECT_CAPTURE;
76 obj[NOCAPTURE].handle = gem_create(fd, 4096);
77
78 obj[BATCH].handle = gem_create(fd, 4096);
Chris Wilsonb5959302017-08-07 13:36:35 +010079 obj[BATCH].relocs_ptr = (uintptr_t)reloc;
80 obj[BATCH].relocation_count = ARRAY_SIZE(reloc);
Chris Wilsona27c7432016-12-03 10:21:08 +000081
Chris Wilsonb5959302017-08-07 13:36:35 +010082 memset(reloc, 0, sizeof(reloc));
83 reloc[0].target_handle = obj[BATCH].handle; /* recurse */
84 reloc[0].presumed_offset = 0;
85 reloc[0].offset = 5*sizeof(uint32_t);
86 reloc[0].delta = 0;
87 reloc[0].read_domains = I915_GEM_DOMAIN_COMMAND;
88 reloc[0].write_domain = 0;
89
90 reloc[1].target_handle = obj[SCRATCH].handle; /* breadcrumb */
91 reloc[1].presumed_offset = 0;
92 reloc[1].offset = sizeof(uint32_t);
93 reloc[1].delta = 0;
94 reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
95 reloc[1].write_domain = I915_GEM_DOMAIN_RENDER;
96
97 seqno = gem_mmap__wc(fd, obj[SCRATCH].handle, 0, 4096, PROT_READ);
98 gem_set_domain(fd, obj[SCRATCH].handle,
99 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
Chris Wilsona27c7432016-12-03 10:21:08 +0000100
101 batch = gem_mmap__cpu(fd, obj[BATCH].handle, 0, 4096, PROT_WRITE);
102 gem_set_domain(fd, obj[BATCH].handle,
103 I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
104
105 i = 0;
Chris Wilsonb5959302017-08-07 13:36:35 +0100106 batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
107 if (gen >= 8) {
108 batch[++i] = 0;
109 batch[++i] = 0;
110 } else if (gen >= 4) {
111 batch[++i] = 0;
112 batch[++i] = 0;
113 reloc[1].offset += sizeof(uint32_t);
114 } else {
115 batch[i]--;
116 batch[++i] = 0;
117 }
118 batch[++i] = 0xc0ffee;
119 if (gen < 3)
120 batch[++i] = MI_NOOP;
121
122 batch[++i] = MI_BATCH_BUFFER_START; /* not crashed? try again! */
Chris Wilsona27c7432016-12-03 10:21:08 +0000123 if (gen >= 8) {
124 batch[i] |= 1 << 8 | 1;
125 batch[++i] = 0;
126 batch[++i] = 0;
127 } else if (gen >= 6) {
128 batch[i] |= 1 << 8;
129 batch[++i] = 0;
130 } else {
131 batch[i] |= 2 << 6;
132 batch[++i] = 0;
133 if (gen < 4) {
134 batch[i] |= 1;
Chris Wilsonb5959302017-08-07 13:36:35 +0100135 reloc[0].delta = 1;
Chris Wilsona27c7432016-12-03 10:21:08 +0000136 }
137 }
138 munmap(batch, 4096);
139
140 memset(&execbuf, 0, sizeof(execbuf));
141 execbuf.buffers_ptr = (uintptr_t)obj;
142 execbuf.buffer_count = ARRAY_SIZE(obj);
143 execbuf.flags = ring;
144 gem_execbuf(fd, &execbuf);
145
Chris Wilsonb5959302017-08-07 13:36:35 +0100146 /* Wait for the request to start */
147 while (*(volatile uint32_t *)seqno != 0xc0ffee)
148 igt_assert(gem_bo_busy(fd, obj[SCRATCH].handle));
149 munmap(seqno, 4096);
150
Chris Wilsona27c7432016-12-03 10:21:08 +0000151 /* Check that only the buffer we marked is reported in the error */
152 igt_force_gpu_reset(fd);
153 check_error_state(dir, &obj[CAPTURE]);
154
Chris Wilsonb5959302017-08-07 13:36:35 +0100155 gem_sync(fd, obj[BATCH].handle);
156
Chris Wilsona27c7432016-12-03 10:21:08 +0000157 gem_close(fd, obj[BATCH].handle);
158 gem_close(fd, obj[NOCAPTURE].handle);
159 gem_close(fd, obj[CAPTURE].handle);
160 gem_close(fd, obj[SCRATCH].handle);
161}
162
163static bool has_capture(int fd)
164{
165 drm_i915_getparam_t gp;
166 int async = -1;
167
168 gp.param = LOCAL_PARAM_HAS_EXEC_CAPTURE;
169 gp.value = &async;
170 drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
171
172 return async > 0;
173}
174
175igt_main
176{
177 const struct intel_execution_engine *e;
178 igt_hang_t hang;
179 int fd = -1;
180 int dir = -1;
181
182 igt_skip_on_simulation();
183
184 igt_fixture {
185 fd = drm_open_driver(DRIVER_INTEL);
186 igt_require_gem(fd);
187 gem_require_mmap_wc(fd);
188 igt_require(has_capture(fd));
189 igt_allow_hang(fd, 0, HANG_ALLOW_CAPTURE);
190
191 dir = igt_sysfs_open(fd, NULL);
192 igt_require(igt_sysfs_set(dir, "error", "Begone!"));
193 }
194
195 for (e = intel_execution_engines; e->name; e++) {
196 /* default exec-id is purely symbolic */
197 if (e->exec_id == 0)
198 continue;
199
200 igt_subtest_f("capture-%s", e->name) {
201 gem_require_ring(fd, e->exec_id | e->flags);
Chris Wilsonb5959302017-08-07 13:36:35 +0100202 igt_require(gem_can_store_dword(fd, e->exec_id | e->flags));
Chris Wilsona27c7432016-12-03 10:21:08 +0000203 capture(fd, dir, e->exec_id | e->flags);
204 }
205 }
206
207 igt_fixture {
208 close(dir);
209 igt_disallow_hang(fd, hang);
210 close(fd);
211 }
212}