Merge drm/drm-next into drm-intel-next-queued
[linux-block.git] / drivers / gpu / drm / i915 / selftests / intel_workarounds.c
1 /*
2  * SPDX-License-Identifier: MIT
3  *
4  * Copyright © 2018 Intel Corporation
5  */
6
7 #include "../i915_selftest.h"
8
9 #include "igt_flush_test.h"
10 #include "igt_reset.h"
11 #include "igt_spinner.h"
12 #include "igt_wedge_me.h"
13 #include "mock_context.h"
14
15 static struct drm_i915_gem_object *
16 read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
17 {
18         struct drm_i915_gem_object *result;
19         struct i915_request *rq;
20         struct i915_vma *vma;
21         const u32 base = engine->mmio_base;
22         u32 srm, *cs;
23         int err;
24         int i;
25
26         result = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
27         if (IS_ERR(result))
28                 return result;
29
30         i915_gem_object_set_cache_level(result, I915_CACHE_LLC);
31
32         cs = i915_gem_object_pin_map(result, I915_MAP_WB);
33         if (IS_ERR(cs)) {
34                 err = PTR_ERR(cs);
35                 goto err_obj;
36         }
37         memset(cs, 0xc5, PAGE_SIZE);
38         i915_gem_object_unpin_map(result);
39
40         vma = i915_vma_instance(result, &engine->i915->ggtt.vm, NULL);
41         if (IS_ERR(vma)) {
42                 err = PTR_ERR(vma);
43                 goto err_obj;
44         }
45
46         err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL);
47         if (err)
48                 goto err_obj;
49
50         intel_runtime_pm_get(engine->i915);
51         rq = i915_request_alloc(engine, ctx);
52         intel_runtime_pm_put(engine->i915);
53         if (IS_ERR(rq)) {
54                 err = PTR_ERR(rq);
55                 goto err_pin;
56         }
57
58         err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
59         if (err)
60                 goto err_req;
61
62         srm = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
63         if (INTEL_GEN(ctx->i915) >= 8)
64                 srm++;
65
66         cs = intel_ring_begin(rq, 4 * RING_MAX_NONPRIV_SLOTS);
67         if (IS_ERR(cs)) {
68                 err = PTR_ERR(cs);
69                 goto err_req;
70         }
71
72         for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
73                 *cs++ = srm;
74                 *cs++ = i915_mmio_reg_offset(RING_FORCE_TO_NONPRIV(base, i));
75                 *cs++ = i915_ggtt_offset(vma) + sizeof(u32) * i;
76                 *cs++ = 0;
77         }
78         intel_ring_advance(rq, cs);
79
80         i915_gem_object_get(result);
81         i915_gem_object_set_active_reference(result);
82
83         i915_request_add(rq);
84         i915_vma_unpin(vma);
85
86         return result;
87
88 err_req:
89         i915_request_add(rq);
90 err_pin:
91         i915_vma_unpin(vma);
92 err_obj:
93         i915_gem_object_put(result);
94         return ERR_PTR(err);
95 }
96
97 static u32
98 get_whitelist_reg(const struct intel_engine_cs *engine, unsigned int i)
99 {
100         i915_reg_t reg = i < engine->whitelist.count ?
101                          engine->whitelist.list[i].reg :
102                          RING_NOPID(engine->mmio_base);
103
104         return i915_mmio_reg_offset(reg);
105 }
106
107 static void
108 print_results(const struct intel_engine_cs *engine, const u32 *results)
109 {
110         unsigned int i;
111
112         for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
113                 u32 expected = get_whitelist_reg(engine, i);
114                 u32 actual = results[i];
115
116                 pr_info("RING_NONPRIV[%d]: expected 0x%08x, found 0x%08x\n",
117                         i, expected, actual);
118         }
119 }
120
121 static int check_whitelist(struct i915_gem_context *ctx,
122                            struct intel_engine_cs *engine)
123 {
124         struct drm_i915_gem_object *results;
125         struct igt_wedge_me wedge;
126         u32 *vaddr;
127         int err;
128         int i;
129
130         results = read_nonprivs(ctx, engine);
131         if (IS_ERR(results))
132                 return PTR_ERR(results);
133
134         err = 0;
135         igt_wedge_on_timeout(&wedge, ctx->i915, HZ / 5) /* a safety net! */
136                 err = i915_gem_object_set_to_cpu_domain(results, false);
137         if (i915_terminally_wedged(&ctx->i915->gpu_error))
138                 err = -EIO;
139         if (err)
140                 goto out_put;
141
142         vaddr = i915_gem_object_pin_map(results, I915_MAP_WB);
143         if (IS_ERR(vaddr)) {
144                 err = PTR_ERR(vaddr);
145                 goto out_put;
146         }
147
148         for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
149                 u32 expected = get_whitelist_reg(engine, i);
150                 u32 actual = vaddr[i];
151
152                 if (expected != actual) {
153                         print_results(engine, vaddr);
154                         pr_err("Invalid RING_NONPRIV[%d], expected 0x%08x, found 0x%08x\n",
155                                i, expected, actual);
156
157                         err = -EINVAL;
158                         break;
159                 }
160         }
161
162         i915_gem_object_unpin_map(results);
163 out_put:
164         i915_gem_object_put(results);
165         return err;
166 }
167
168 static int do_device_reset(struct intel_engine_cs *engine)
169 {
170         set_bit(I915_RESET_HANDOFF, &engine->i915->gpu_error.flags);
171         i915_reset(engine->i915, ENGINE_MASK(engine->id), "live_workarounds");
172         return 0;
173 }
174
175 static int do_engine_reset(struct intel_engine_cs *engine)
176 {
177         return i915_reset_engine(engine, "live_workarounds");
178 }
179
180 static int
181 switch_to_scratch_context(struct intel_engine_cs *engine,
182                           struct igt_spinner *spin)
183 {
184         struct i915_gem_context *ctx;
185         struct i915_request *rq;
186         int err = 0;
187
188         ctx = kernel_context(engine->i915);
189         if (IS_ERR(ctx))
190                 return PTR_ERR(ctx);
191
192         intel_runtime_pm_get(engine->i915);
193
194         if (spin)
195                 rq = igt_spinner_create_request(spin, ctx, engine, MI_NOOP);
196         else
197                 rq = i915_request_alloc(engine, ctx);
198
199         intel_runtime_pm_put(engine->i915);
200
201         kernel_context_close(ctx);
202
203         if (IS_ERR(rq)) {
204                 spin = NULL;
205                 err = PTR_ERR(rq);
206                 goto err;
207         }
208
209         i915_request_add(rq);
210
211         if (spin && !igt_wait_for_spinner(spin, rq)) {
212                 pr_err("Spinner failed to start\n");
213                 err = -ETIMEDOUT;
214         }
215
216 err:
217         if (err && spin)
218                 igt_spinner_end(spin);
219
220         return err;
221 }
222
223 static int check_whitelist_across_reset(struct intel_engine_cs *engine,
224                                         int (*reset)(struct intel_engine_cs *),
225                                         const char *name)
226 {
227         struct drm_i915_private *i915 = engine->i915;
228         bool want_spin = reset == do_engine_reset;
229         struct i915_gem_context *ctx;
230         struct igt_spinner spin;
231         int err;
232
233         pr_info("Checking %d whitelisted registers (RING_NONPRIV) [%s]\n",
234                 engine->whitelist.count, name);
235
236         if (want_spin) {
237                 err = igt_spinner_init(&spin, i915);
238                 if (err)
239                         return err;
240         }
241
242         ctx = kernel_context(i915);
243         if (IS_ERR(ctx))
244                 return PTR_ERR(ctx);
245
246         err = check_whitelist(ctx, engine);
247         if (err) {
248                 pr_err("Invalid whitelist *before* %s reset!\n", name);
249                 goto out;
250         }
251
252         err = switch_to_scratch_context(engine, want_spin ? &spin : NULL);
253         if (err)
254                 goto out;
255
256         intel_runtime_pm_get(i915);
257         err = reset(engine);
258         intel_runtime_pm_put(i915);
259
260         if (want_spin) {
261                 igt_spinner_end(&spin);
262                 igt_spinner_fini(&spin);
263         }
264
265         if (err) {
266                 pr_err("%s reset failed\n", name);
267                 goto out;
268         }
269
270         err = check_whitelist(ctx, engine);
271         if (err) {
272                 pr_err("Whitelist not preserved in context across %s reset!\n",
273                        name);
274                 goto out;
275         }
276
277         kernel_context_close(ctx);
278
279         ctx = kernel_context(i915);
280         if (IS_ERR(ctx))
281                 return PTR_ERR(ctx);
282
283         err = check_whitelist(ctx, engine);
284         if (err) {
285                 pr_err("Invalid whitelist *after* %s reset in fresh context!\n",
286                        name);
287                 goto out;
288         }
289
290 out:
291         kernel_context_close(ctx);
292         return err;
293 }
294
295 static int live_reset_whitelist(void *arg)
296 {
297         struct drm_i915_private *i915 = arg;
298         struct intel_engine_cs *engine = i915->engine[RCS];
299         int err = 0;
300
301         /* If we reset the gpu, we should not lose the RING_NONPRIV */
302
303         if (!engine || engine->whitelist.count == 0)
304                 return 0;
305
306         igt_global_reset_lock(i915);
307
308         if (intel_has_reset_engine(i915)) {
309                 err = check_whitelist_across_reset(engine,
310                                                    do_engine_reset,
311                                                    "engine");
312                 if (err)
313                         goto out;
314         }
315
316         if (intel_has_gpu_reset(i915)) {
317                 err = check_whitelist_across_reset(engine,
318                                                    do_device_reset,
319                                                    "device");
320                 if (err)
321                         goto out;
322         }
323
324 out:
325         igt_global_reset_unlock(i915);
326         return err;
327 }
328
329 static bool verify_gt_engine_wa(struct drm_i915_private *i915, const char *str)
330 {
331         struct intel_engine_cs *engine;
332         enum intel_engine_id id;
333         bool ok = true;
334
335         ok &= intel_gt_verify_workarounds(i915, str);
336         for_each_engine(engine, i915, id)
337                 ok &= intel_engine_verify_workarounds(engine, str);
338
339         return ok;
340 }
341
342 static int
343 live_gpu_reset_gt_engine_workarounds(void *arg)
344 {
345         struct drm_i915_private *i915 = arg;
346         struct i915_gpu_error *error = &i915->gpu_error;
347         bool ok;
348
349         if (!intel_has_gpu_reset(i915))
350                 return 0;
351
352         pr_info("Verifying after GPU reset...\n");
353
354         igt_global_reset_lock(i915);
355         intel_runtime_pm_get(i915);
356
357         ok = verify_gt_engine_wa(i915, "before reset");
358         if (!ok)
359                 goto out;
360
361         set_bit(I915_RESET_HANDOFF, &error->flags);
362         i915_reset(i915, ALL_ENGINES, "live_workarounds");
363
364         ok = verify_gt_engine_wa(i915, "after reset");
365
366 out:
367         intel_runtime_pm_put(i915);
368         igt_global_reset_unlock(i915);
369
370         return ok ? 0 : -ESRCH;
371 }
372
373 static int
374 live_engine_reset_gt_engine_workarounds(void *arg)
375 {
376         struct drm_i915_private *i915 = arg;
377         struct intel_engine_cs *engine;
378         struct i915_gem_context *ctx;
379         struct igt_spinner spin;
380         enum intel_engine_id id;
381         struct i915_request *rq;
382         int ret = 0;
383
384         if (!intel_has_reset_engine(i915))
385                 return 0;
386
387         ctx = kernel_context(i915);
388         if (IS_ERR(ctx))
389                 return PTR_ERR(ctx);
390
391         igt_global_reset_lock(i915);
392         intel_runtime_pm_get(i915);
393
394         for_each_engine(engine, i915, id) {
395                 bool ok;
396
397                 pr_info("Verifying after %s reset...\n", engine->name);
398
399                 ok = verify_gt_engine_wa(i915, "before reset");
400                 if (!ok) {
401                         ret = -ESRCH;
402                         goto err;
403                 }
404
405                 i915_reset_engine(engine, "live_workarounds");
406
407                 ok = verify_gt_engine_wa(i915, "after idle reset");
408                 if (!ok) {
409                         ret = -ESRCH;
410                         goto err;
411                 }
412
413                 ret = igt_spinner_init(&spin, i915);
414                 if (ret)
415                         goto err;
416
417                 rq = igt_spinner_create_request(&spin, ctx, engine, MI_NOOP);
418                 if (IS_ERR(rq)) {
419                         ret = PTR_ERR(rq);
420                         igt_spinner_fini(&spin);
421                         goto err;
422                 }
423
424                 i915_request_add(rq);
425
426                 if (!igt_wait_for_spinner(&spin, rq)) {
427                         pr_err("Spinner failed to start\n");
428                         igt_spinner_fini(&spin);
429                         ret = -ETIMEDOUT;
430                         goto err;
431                 }
432
433                 i915_reset_engine(engine, "live_workarounds");
434
435                 igt_spinner_end(&spin);
436                 igt_spinner_fini(&spin);
437
438                 ok = verify_gt_engine_wa(i915, "after busy reset");
439                 if (!ok) {
440                         ret = -ESRCH;
441                         goto err;
442                 }
443         }
444
445 err:
446         intel_runtime_pm_put(i915);
447         igt_global_reset_unlock(i915);
448         kernel_context_close(ctx);
449
450         igt_flush_test(i915, I915_WAIT_LOCKED);
451
452         return ret;
453 }
454
455 int intel_workarounds_live_selftests(struct drm_i915_private *i915)
456 {
457         static const struct i915_subtest tests[] = {
458                 SUBTEST(live_reset_whitelist),
459                 SUBTEST(live_gpu_reset_gt_engine_workarounds),
460                 SUBTEST(live_engine_reset_gt_engine_workarounds),
461         };
462         int err;
463
464         if (i915_terminally_wedged(&i915->gpu_error))
465                 return 0;
466
467         mutex_lock(&i915->drm.struct_mutex);
468         err = i915_subtests(tests, i915);
469         mutex_unlock(&i915->drm.struct_mutex);
470
471         return err;
472 }