Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 1 | /* |
| 2 | * Copyright © 2014 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 | * Authors: |
| 24 | * Mika Kuoppala <mika.kuoppala@intel.com> |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 25 | * Oscar Mateo <oscar.mateo@intel.com> |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 26 | * |
| 27 | */ |
| 28 | |
Thomas Wood | 804e11f | 2015-08-17 17:57:43 +0100 | [diff] [blame] | 29 | #include "igt.h" |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 30 | #include <limits.h> |
| 31 | #include <sys/types.h> |
| 32 | #include <sys/stat.h> |
| 33 | #include <fcntl.h> |
| 34 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 35 | #include "igt_sysfs.h" |
Chris Wilson | 800aedb | 2016-10-20 10:02:38 +0100 | [diff] [blame] | 36 | #include "igt_debugfs.h" |
| 37 | |
Brad Volkin | e34240d | 2014-11-04 14:00:43 -0800 | [diff] [blame] | 38 | #ifndef I915_PARAM_CMD_PARSER_VERSION |
| 39 | #define I915_PARAM_CMD_PARSER_VERSION 28 |
| 40 | #endif |
| 41 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 42 | static int device = -1; |
| 43 | static int sysfs = -1; |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 44 | |
| 45 | static void test_sysfs_error_exists(void) |
| 46 | { |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 47 | char *error; |
| 48 | |
| 49 | error = igt_sysfs_get(sysfs, "error"); |
| 50 | igt_assert(error); |
| 51 | free(error); |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 52 | } |
| 53 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 54 | static void assert_entry(const char *s, bool expect) |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 55 | { |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 56 | char *error; |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 57 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 58 | error = igt_sysfs_get(sysfs, "error"); |
| 59 | igt_assert(error); |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 60 | |
Michel Thierry | d204f2d | 2017-02-23 07:27:36 +0000 | [diff] [blame] | 61 | igt_assert_f(!!strcasecmp(error, s) != expect, |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 62 | "contents of error: '%s' (expected %s '%s')\n", |
| 63 | error, expect ? "": "not", s); |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 64 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 65 | free(error); |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 66 | } |
| 67 | |
| 68 | static void assert_error_state_clear(void) |
| 69 | { |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 70 | assert_entry("no error state collected", true); |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 71 | } |
| 72 | |
| 73 | static void assert_error_state_collected(void) |
| 74 | { |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 75 | assert_entry("no error state collected", false); |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 76 | } |
| 77 | |
| 78 | static void clear_error_state(void) |
| 79 | { |
Chris Wilson | 5d037bd | 2017-02-23 02:06:22 +0000 | [diff] [blame] | 80 | igt_sysfs_write(sysfs, "error", "", 1); |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | static void test_error_state_basic(void) |
| 84 | { |
| 85 | int fd; |
| 86 | |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 87 | clear_error_state(); |
| 88 | assert_error_state_clear(); |
| 89 | |
Chris Wilson | 800aedb | 2016-10-20 10:02:38 +0100 | [diff] [blame] | 90 | /* Manually trigger a hang by request a reset */ |
Chris Wilson | 83884e9 | 2017-03-21 17:16:03 +0000 | [diff] [blame] | 91 | fd = igt_debugfs_open(device, "i915_wedged", O_WRONLY); |
Chris Wilson | 800aedb | 2016-10-20 10:02:38 +0100 | [diff] [blame] | 92 | igt_ignore_warn(write(fd, "1\n", 2)); |
| 93 | close(fd); |
| 94 | |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 95 | assert_error_state_collected(); |
Chris Wilson | 800aedb | 2016-10-20 10:02:38 +0100 | [diff] [blame] | 96 | |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 97 | clear_error_state(); |
| 98 | assert_error_state_clear(); |
| 99 | } |
| 100 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 101 | static FILE *open_error(void) |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 102 | { |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 103 | int fd; |
| 104 | |
| 105 | fd = openat(sysfs, "error", O_RDONLY); |
| 106 | if (fd < 0) |
| 107 | return NULL; |
| 108 | |
| 109 | return fdopen(fd, "r"); |
| 110 | } |
| 111 | |
| 112 | static bool uses_cmd_parser(void) |
| 113 | { |
| 114 | int parser_version = 0; |
| 115 | drm_i915_getparam_t gp; |
| 116 | |
| 117 | gp.param = I915_PARAM_CMD_PARSER_VERSION; |
| 118 | gp.value = &parser_version; |
| 119 | drmIoctl(device, DRM_IOCTL_I915_GETPARAM, &gp); |
| 120 | |
| 121 | return parser_version > 0; |
| 122 | } |
| 123 | |
| 124 | static void check_error_state(const char *expected_ring_name, |
| 125 | uint64_t expected_offset, |
| 126 | const uint32_t *batch) |
| 127 | { |
| 128 | bool cmd_parser = uses_cmd_parser(); |
| 129 | FILE *file = open_error(); |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 130 | char *line = NULL; |
| 131 | size_t line_size = 0; |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 132 | |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 133 | while (getline(&line, &line_size, file) > 0) { |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 134 | char *dashes; |
Mika Kuoppala | c37b235 | 2015-08-18 17:44:38 +0300 | [diff] [blame] | 135 | uint32_t gtt_offset_upper, gtt_offset_lower; |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 136 | int matched; |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 137 | |
| 138 | dashes = strstr(line, "---"); |
| 139 | if (!dashes) |
| 140 | continue; |
| 141 | |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 142 | matched = sscanf(dashes, "--- gtt_offset = 0x%08x %08x\n", |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 143 | >t_offset_upper, >t_offset_lower); |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 144 | if (matched) { |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 145 | char expected_line[128]; |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 146 | uint64_t gtt_offset; |
| 147 | int i; |
Mika Kuoppala | c37b235 | 2015-08-18 17:44:38 +0300 | [diff] [blame] | 148 | |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 149 | strncpy(expected_line, line, dashes - line); |
| 150 | expected_line[dashes - line - 1] = '\0'; |
| 151 | igt_assert(strstr(expected_line, expected_ring_name)); |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 152 | |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 153 | gtt_offset = gtt_offset_upper; |
| 154 | if (matched == 2) { |
| 155 | gtt_offset <<= 32; |
| 156 | gtt_offset |= gtt_offset_lower; |
| 157 | } |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 158 | if (!cmd_parser) |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 159 | igt_assert_eq_u64(gtt_offset, expected_offset); |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 160 | |
Chris Wilson | 0753057 | 2015-12-11 13:27:49 +0000 | [diff] [blame] | 161 | for (i = 0; i < 1024; i++) { |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 162 | igt_assert(getline(&line, &line_size, file) > 0); |
Chris Wilson | c2fb6b8 | 2016-10-21 12:55:09 +0100 | [diff] [blame] | 163 | if (line[0] == ':' || line[0] == '~') |
| 164 | break; |
| 165 | |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 166 | snprintf(expected_line, sizeof(expected_line), |
| 167 | "%08x : %08x", |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 168 | 4*i, batch[i]); |
| 169 | igt_assert(strstr(line, expected_line)); |
| 170 | } |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 171 | break; |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 172 | } |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 173 | } |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 174 | |
| 175 | free(line); |
Chris Wilson | 01e467a | 2016-01-01 11:29:51 +0000 | [diff] [blame] | 176 | fclose(file); |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | static void test_error_state_capture(unsigned ring_id, |
| 180 | const char *ring_name) |
| 181 | { |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 182 | uint32_t *batch; |
| 183 | igt_hang_t hang; |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 184 | uint64_t offset; |
| 185 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 186 | igt_require(gem_has_ring(device, ring_id)); |
Chris Wilson | 12ee485 | 2017-10-20 23:34:33 +0100 | [diff] [blame] | 187 | |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 188 | clear_error_state(); |
| 189 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 190 | hang = igt_hang_ctx(device, 0, ring_id, HANG_ALLOW_CAPTURE, &offset); |
| 191 | batch = gem_mmap__cpu(device, hang.handle, 0, 4096, PROT_READ); |
| 192 | gem_set_domain(device, hang.handle, I915_GEM_DOMAIN_CPU, 0); |
| 193 | igt_post_hang_ring(device, hang); |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 194 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 195 | check_error_state(ring_name, offset, batch); |
| 196 | munmap(batch, 4096); |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 197 | } |
| 198 | |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 199 | /* This test covers the case where we end up in an uninitialised area of the |
| 200 | * ppgtt and keep executing through it. This is particularly relevant if 48b |
| 201 | * ppgtt is enabled because the ppgtt is massively bigger compared to the 32b |
| 202 | * case and it takes a lot more time to wrap, so the acthd can potentially keep |
| 203 | * increasing for a long time |
| 204 | */ |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 205 | static void hangcheck_unterminated(void) |
| 206 | { |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 207 | /* timeout needs to be greater than ~5*hangcheck */ |
Chris Wilson | cb214ef | 2016-11-29 14:49:26 +0000 | [diff] [blame] | 208 | int64_t timeout_ns = 100ull * NSEC_PER_SEC; /* 100 seconds */ |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 209 | struct drm_i915_gem_execbuffer2 execbuf; |
| 210 | struct drm_i915_gem_exec_object2 gem_exec; |
| 211 | uint32_t handle; |
| 212 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 213 | igt_require(gem_uses_full_ppgtt(device)); |
| 214 | igt_require_hang_ring(device, 0); |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 215 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 216 | handle = gem_create(device, 4096); |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 217 | |
| 218 | memset(&gem_exec, 0, sizeof(gem_exec)); |
| 219 | gem_exec.handle = handle; |
| 220 | |
| 221 | memset(&execbuf, 0, sizeof(execbuf)); |
| 222 | execbuf.buffers_ptr = (uintptr_t)&gem_exec; |
| 223 | execbuf.buffer_count = 1; |
| 224 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 225 | gem_execbuf(device, &execbuf); |
| 226 | if (gem_wait(device, handle, &timeout_ns) != 0) { |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 227 | /* need to manually trigger an hang to clean before failing */ |
Chris Wilson | 83884e9 | 2017-03-21 17:16:03 +0000 | [diff] [blame] | 228 | igt_force_gpu_reset(device); |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 229 | igt_assert_f(0, "unterminated batch did not trigger an hang!"); |
| 230 | } |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 231 | } |
| 232 | |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 233 | igt_main |
| 234 | { |
Chris Wilson | 38fe49d | 2016-02-04 11:17:42 +0000 | [diff] [blame] | 235 | const struct intel_execution_engine *e; |
| 236 | |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 237 | igt_skip_on_simulation(); |
| 238 | |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 239 | igt_fixture { |
| 240 | int idx; |
| 241 | |
| 242 | device = drm_open_driver(DRIVER_INTEL); |
Chris Wilson | 9518cb5 | 2017-02-22 15:24:54 +0000 | [diff] [blame] | 243 | igt_require_gem(device); |
Chris Wilson | 79c6a84 | 2017-01-31 11:56:08 +0000 | [diff] [blame] | 244 | sysfs = igt_sysfs_open(device, &idx); |
| 245 | igt_assert(sysfs != -1); |
| 246 | } |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 247 | |
| 248 | igt_subtest("error-state-sysfs-entry") |
| 249 | test_sysfs_error_exists(); |
| 250 | |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 251 | igt_subtest("error-state-basic") |
| 252 | test_error_state_basic(); |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 253 | |
Chris Wilson | 38fe49d | 2016-02-04 11:17:42 +0000 | [diff] [blame] | 254 | for (e = intel_execution_engines; e->name; e++) { |
| 255 | if (e->exec_id == 0) |
| 256 | continue; |
| 257 | |
Chris Wilson | 12ee485 | 2017-10-20 23:34:33 +0100 | [diff] [blame] | 258 | /* |
| 259 | * If the device has 2 BSD rings then due to obtuse aliasing |
| 260 | * in the API, we can not determine which ring I915_EXEC_BSD |
| 261 | * will map to, and so must skip the test; as the matching name |
| 262 | * may be either bsd or bsd2 depending on the kernel/test |
| 263 | * ordering. |
| 264 | * |
| 265 | * Here we are not checking that executing on every ABI engine |
| 266 | * results in a detectable hang, but that a hang generated |
| 267 | * from a specific HW engine gives an indentifiable result. |
| 268 | */ |
| 269 | if (e->exec_id == I915_EXEC_BSD && e->flags == 0) |
| 270 | continue; |
| 271 | |
Chris Wilson | 38fe49d | 2016-02-04 11:17:42 +0000 | [diff] [blame] | 272 | igt_subtest_f("error-state-capture-%s", e->name) |
| 273 | test_error_state_capture(e->exec_id | e->flags, |
| 274 | e->full_name); |
Mika Kuoppala | 6fa1934 | 2014-05-20 11:25:48 +0300 | [diff] [blame] | 275 | } |
Daniele Ceraolo Spurio | 95ca764 | 2016-03-01 11:01:33 +0000 | [diff] [blame] | 276 | |
| 277 | igt_subtest("hangcheck-unterminated") |
| 278 | hangcheck_unterminated(); |
Mika Kuoppala | 9b0d348 | 2014-05-19 17:42:21 +0300 | [diff] [blame] | 279 | } |