Loading...
Note: File does not exist in v4.6.
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2018 Intel Corporation
4 */
5
6#include "gem/i915_gem_pm.h"
7#include "gt/intel_engine_user.h"
8#include "gt/intel_gt.h"
9#include "i915_selftest.h"
10#include "intel_reset.h"
11
12#include "selftests/igt_flush_test.h"
13#include "selftests/igt_reset.h"
14#include "selftests/igt_spinner.h"
15#include "selftests/mock_drm.h"
16
17#include "gem/selftests/igt_gem_utils.h"
18#include "gem/selftests/mock_context.h"
19
20static const struct wo_register {
21 enum intel_platform platform;
22 u32 reg;
23} wo_registers[] = {
24 { INTEL_GEMINILAKE, 0x731c }
25};
26
27struct wa_lists {
28 struct i915_wa_list gt_wa_list;
29 struct {
30 struct i915_wa_list wa_list;
31 struct i915_wa_list ctx_wa_list;
32 } engine[I915_NUM_ENGINES];
33};
34
35static int request_add_sync(struct i915_request *rq, int err)
36{
37 i915_request_get(rq);
38 i915_request_add(rq);
39 if (i915_request_wait(rq, 0, HZ / 5) < 0)
40 err = -EIO;
41 i915_request_put(rq);
42
43 return err;
44}
45
46static int request_add_spin(struct i915_request *rq, struct igt_spinner *spin)
47{
48 int err = 0;
49
50 i915_request_get(rq);
51 i915_request_add(rq);
52 if (spin && !igt_wait_for_spinner(spin, rq))
53 err = -ETIMEDOUT;
54 i915_request_put(rq);
55
56 return err;
57}
58
59static void
60reference_lists_init(struct intel_gt *gt, struct wa_lists *lists)
61{
62 struct intel_engine_cs *engine;
63 enum intel_engine_id id;
64
65 memset(lists, 0, sizeof(*lists));
66
67 wa_init_start(&lists->gt_wa_list, "GT_REF", "global");
68 gt_init_workarounds(gt->i915, &lists->gt_wa_list);
69 wa_init_finish(&lists->gt_wa_list);
70
71 for_each_engine(engine, gt, id) {
72 struct i915_wa_list *wal = &lists->engine[id].wa_list;
73
74 wa_init_start(wal, "REF", engine->name);
75 engine_init_workarounds(engine, wal);
76 wa_init_finish(wal);
77
78 __intel_engine_init_ctx_wa(engine,
79 &lists->engine[id].ctx_wa_list,
80 "CTX_REF");
81 }
82}
83
84static void
85reference_lists_fini(struct intel_gt *gt, struct wa_lists *lists)
86{
87 struct intel_engine_cs *engine;
88 enum intel_engine_id id;
89
90 for_each_engine(engine, gt, id)
91 intel_wa_list_free(&lists->engine[id].wa_list);
92
93 intel_wa_list_free(&lists->gt_wa_list);
94}
95
96static struct drm_i915_gem_object *
97read_nonprivs(struct intel_context *ce)
98{
99 struct intel_engine_cs *engine = ce->engine;
100 const u32 base = engine->mmio_base;
101 struct drm_i915_gem_object *result;
102 struct i915_request *rq;
103 struct i915_vma *vma;
104 u32 srm, *cs;
105 int err;
106 int i;
107
108 result = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
109 if (IS_ERR(result))
110 return result;
111
112 i915_gem_object_set_cache_coherency(result, I915_CACHE_LLC);
113
114 cs = i915_gem_object_pin_map_unlocked(result, I915_MAP_WB);
115 if (IS_ERR(cs)) {
116 err = PTR_ERR(cs);
117 goto err_obj;
118 }
119 memset(cs, 0xc5, PAGE_SIZE);
120 i915_gem_object_flush_map(result);
121 i915_gem_object_unpin_map(result);
122
123 vma = i915_vma_instance(result, &engine->gt->ggtt->vm, NULL);
124 if (IS_ERR(vma)) {
125 err = PTR_ERR(vma);
126 goto err_obj;
127 }
128
129 err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL);
130 if (err)
131 goto err_obj;
132
133 rq = intel_context_create_request(ce);
134 if (IS_ERR(rq)) {
135 err = PTR_ERR(rq);
136 goto err_pin;
137 }
138
139 i915_vma_lock(vma);
140 err = i915_request_await_object(rq, vma->obj, true);
141 if (err == 0)
142 err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
143 i915_vma_unlock(vma);
144 if (err)
145 goto err_req;
146
147 srm = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
148 if (GRAPHICS_VER(engine->i915) >= 8)
149 srm++;
150
151 cs = intel_ring_begin(rq, 4 * RING_MAX_NONPRIV_SLOTS);
152 if (IS_ERR(cs)) {
153 err = PTR_ERR(cs);
154 goto err_req;
155 }
156
157 for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
158 *cs++ = srm;
159 *cs++ = i915_mmio_reg_offset(RING_FORCE_TO_NONPRIV(base, i));
160 *cs++ = i915_ggtt_offset(vma) + sizeof(u32) * i;
161 *cs++ = 0;
162 }
163 intel_ring_advance(rq, cs);
164
165 i915_request_add(rq);
166 i915_vma_unpin(vma);
167
168 return result;
169
170err_req:
171 i915_request_add(rq);
172err_pin:
173 i915_vma_unpin(vma);
174err_obj:
175 i915_gem_object_put(result);
176 return ERR_PTR(err);
177}
178
179static u32
180get_whitelist_reg(const struct intel_engine_cs *engine, unsigned int i)
181{
182 i915_reg_t reg = i < engine->whitelist.count ?
183 engine->whitelist.list[i].reg :
184 RING_NOPID(engine->mmio_base);
185
186 return i915_mmio_reg_offset(reg);
187}
188
189static void
190print_results(const struct intel_engine_cs *engine, const u32 *results)
191{
192 unsigned int i;
193
194 for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
195 u32 expected = get_whitelist_reg(engine, i);
196 u32 actual = results[i];
197
198 pr_info("RING_NONPRIV[%d]: expected 0x%08x, found 0x%08x\n",
199 i, expected, actual);
200 }
201}
202
203static int check_whitelist(struct intel_context *ce)
204{
205 struct intel_engine_cs *engine = ce->engine;
206 struct drm_i915_gem_object *results;
207 struct intel_wedge_me wedge;
208 u32 *vaddr;
209 int err;
210 int i;
211
212 results = read_nonprivs(ce);
213 if (IS_ERR(results))
214 return PTR_ERR(results);
215
216 err = 0;
217 i915_gem_object_lock(results, NULL);
218 intel_wedge_on_timeout(&wedge, engine->gt, HZ / 5) /* safety net! */
219 err = i915_gem_object_set_to_cpu_domain(results, false);
220
221 if (intel_gt_is_wedged(engine->gt))
222 err = -EIO;
223 if (err)
224 goto out_put;
225
226 vaddr = i915_gem_object_pin_map(results, I915_MAP_WB);
227 if (IS_ERR(vaddr)) {
228 err = PTR_ERR(vaddr);
229 goto out_put;
230 }
231
232 for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
233 u32 expected = get_whitelist_reg(engine, i);
234 u32 actual = vaddr[i];
235
236 if (expected != actual) {
237 print_results(engine, vaddr);
238 pr_err("Invalid RING_NONPRIV[%d], expected 0x%08x, found 0x%08x\n",
239 i, expected, actual);
240
241 err = -EINVAL;
242 break;
243 }
244 }
245
246 i915_gem_object_unpin_map(results);
247out_put:
248 i915_gem_object_unlock(results);
249 i915_gem_object_put(results);
250 return err;
251}
252
253static int do_device_reset(struct intel_engine_cs *engine)
254{
255 intel_gt_reset(engine->gt, engine->mask, "live_workarounds");
256 return 0;
257}
258
259static int do_engine_reset(struct intel_engine_cs *engine)
260{
261 return intel_engine_reset(engine, "live_workarounds");
262}
263
264static int
265switch_to_scratch_context(struct intel_engine_cs *engine,
266 struct igt_spinner *spin)
267{
268 struct intel_context *ce;
269 struct i915_request *rq;
270 int err = 0;
271
272 ce = intel_context_create(engine);
273 if (IS_ERR(ce))
274 return PTR_ERR(ce);
275
276 rq = igt_spinner_create_request(spin, ce, MI_NOOP);
277 intel_context_put(ce);
278
279 if (IS_ERR(rq)) {
280 spin = NULL;
281 err = PTR_ERR(rq);
282 goto err;
283 }
284
285 err = request_add_spin(rq, spin);
286err:
287 if (err && spin)
288 igt_spinner_end(spin);
289
290 return err;
291}
292
293static int check_whitelist_across_reset(struct intel_engine_cs *engine,
294 int (*reset)(struct intel_engine_cs *),
295 const char *name)
296{
297 struct intel_context *ce, *tmp;
298 struct igt_spinner spin;
299 intel_wakeref_t wakeref;
300 int err;
301
302 pr_info("Checking %d whitelisted registers on %s (RING_NONPRIV) [%s]\n",
303 engine->whitelist.count, engine->name, name);
304
305 ce = intel_context_create(engine);
306 if (IS_ERR(ce))
307 return PTR_ERR(ce);
308
309 err = igt_spinner_init(&spin, engine->gt);
310 if (err)
311 goto out_ctx;
312
313 err = check_whitelist(ce);
314 if (err) {
315 pr_err("Invalid whitelist *before* %s reset!\n", name);
316 goto out_spin;
317 }
318
319 err = switch_to_scratch_context(engine, &spin);
320 if (err)
321 goto out_spin;
322
323 with_intel_runtime_pm(engine->uncore->rpm, wakeref)
324 err = reset(engine);
325
326 igt_spinner_end(&spin);
327
328 if (err) {
329 pr_err("%s reset failed\n", name);
330 goto out_spin;
331 }
332
333 err = check_whitelist(ce);
334 if (err) {
335 pr_err("Whitelist not preserved in context across %s reset!\n",
336 name);
337 goto out_spin;
338 }
339
340 tmp = intel_context_create(engine);
341 if (IS_ERR(tmp)) {
342 err = PTR_ERR(tmp);
343 goto out_spin;
344 }
345 intel_context_put(ce);
346 ce = tmp;
347
348 err = check_whitelist(ce);
349 if (err) {
350 pr_err("Invalid whitelist *after* %s reset in fresh context!\n",
351 name);
352 goto out_spin;
353 }
354
355out_spin:
356 igt_spinner_fini(&spin);
357out_ctx:
358 intel_context_put(ce);
359 return err;
360}
361
362static struct i915_vma *create_batch(struct i915_address_space *vm)
363{
364 struct drm_i915_gem_object *obj;
365 struct i915_vma *vma;
366 int err;
367
368 obj = i915_gem_object_create_internal(vm->i915, 16 * PAGE_SIZE);
369 if (IS_ERR(obj))
370 return ERR_CAST(obj);
371
372 vma = i915_vma_instance(obj, vm, NULL);
373 if (IS_ERR(vma)) {
374 err = PTR_ERR(vma);
375 goto err_obj;
376 }
377
378 err = i915_vma_pin(vma, 0, 0, PIN_USER);
379 if (err)
380 goto err_obj;
381
382 return vma;
383
384err_obj:
385 i915_gem_object_put(obj);
386 return ERR_PTR(err);
387}
388
389static u32 reg_write(u32 old, u32 new, u32 rsvd)
390{
391 if (rsvd == 0x0000ffff) {
392 old &= ~(new >> 16);
393 old |= new & (new >> 16);
394 } else {
395 old &= ~rsvd;
396 old |= new & rsvd;
397 }
398
399 return old;
400}
401
402static bool wo_register(struct intel_engine_cs *engine, u32 reg)
403{
404 enum intel_platform platform = INTEL_INFO(engine->i915)->platform;
405 int i;
406
407 if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
408 RING_FORCE_TO_NONPRIV_ACCESS_WR)
409 return true;
410
411 for (i = 0; i < ARRAY_SIZE(wo_registers); i++) {
412 if (wo_registers[i].platform == platform &&
413 wo_registers[i].reg == reg)
414 return true;
415 }
416
417 return false;
418}
419
420static bool timestamp(const struct intel_engine_cs *engine, u32 reg)
421{
422 reg = (reg - engine->mmio_base) & ~RING_FORCE_TO_NONPRIV_ACCESS_MASK;
423 switch (reg) {
424 case 0x358:
425 case 0x35c:
426 case 0x3a8:
427 return true;
428
429 default:
430 return false;
431 }
432}
433
434static bool ro_register(u32 reg)
435{
436 if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
437 RING_FORCE_TO_NONPRIV_ACCESS_RD)
438 return true;
439
440 return false;
441}
442
443static int whitelist_writable_count(struct intel_engine_cs *engine)
444{
445 int count = engine->whitelist.count;
446 int i;
447
448 for (i = 0; i < engine->whitelist.count; i++) {
449 u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
450
451 if (ro_register(reg))
452 count--;
453 }
454
455 return count;
456}
457
458static int check_dirty_whitelist(struct intel_context *ce)
459{
460 const u32 values[] = {
461 0x00000000,
462 0x01010101,
463 0x10100101,
464 0x03030303,
465 0x30300303,
466 0x05050505,
467 0x50500505,
468 0x0f0f0f0f,
469 0xf00ff00f,
470 0x10101010,
471 0xf0f01010,
472 0x30303030,
473 0xa0a03030,
474 0x50505050,
475 0xc0c05050,
476 0xf0f0f0f0,
477 0x11111111,
478 0x33333333,
479 0x55555555,
480 0x0000ffff,
481 0x00ff00ff,
482 0xff0000ff,
483 0xffff00ff,
484 0xffffffff,
485 };
486 struct intel_engine_cs *engine = ce->engine;
487 struct i915_vma *scratch;
488 struct i915_vma *batch;
489 int err = 0, i, v, sz;
490 u32 *cs, *results;
491
492 sz = (2 * ARRAY_SIZE(values) + 1) * sizeof(u32);
493 scratch = __vm_create_scratch_for_read_pinned(ce->vm, sz);
494 if (IS_ERR(scratch))
495 return PTR_ERR(scratch);
496
497 batch = create_batch(ce->vm);
498 if (IS_ERR(batch)) {
499 err = PTR_ERR(batch);
500 goto out_scratch;
501 }
502
503 for (i = 0; i < engine->whitelist.count; i++) {
504 u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
505 struct i915_gem_ww_ctx ww;
506 u64 addr = scratch->node.start;
507 struct i915_request *rq;
508 u32 srm, lrm, rsvd;
509 u32 expect;
510 int idx;
511 bool ro_reg;
512
513 if (wo_register(engine, reg))
514 continue;
515
516 if (timestamp(engine, reg))
517 continue; /* timestamps are expected to autoincrement */
518
519 ro_reg = ro_register(reg);
520
521 i915_gem_ww_ctx_init(&ww, false);
522retry:
523 cs = NULL;
524 err = i915_gem_object_lock(scratch->obj, &ww);
525 if (!err)
526 err = i915_gem_object_lock(batch->obj, &ww);
527 if (!err)
528 err = intel_context_pin_ww(ce, &ww);
529 if (err)
530 goto out;
531
532 cs = i915_gem_object_pin_map(batch->obj, I915_MAP_WC);
533 if (IS_ERR(cs)) {
534 err = PTR_ERR(cs);
535 goto out_ctx;
536 }
537
538 results = i915_gem_object_pin_map(scratch->obj, I915_MAP_WB);
539 if (IS_ERR(results)) {
540 err = PTR_ERR(results);
541 goto out_unmap_batch;
542 }
543
544 /* Clear non priv flags */
545 reg &= RING_FORCE_TO_NONPRIV_ADDRESS_MASK;
546
547 srm = MI_STORE_REGISTER_MEM;
548 lrm = MI_LOAD_REGISTER_MEM;
549 if (GRAPHICS_VER(engine->i915) >= 8)
550 lrm++, srm++;
551
552 pr_debug("%s: Writing garbage to %x\n",
553 engine->name, reg);
554
555 /* SRM original */
556 *cs++ = srm;
557 *cs++ = reg;
558 *cs++ = lower_32_bits(addr);
559 *cs++ = upper_32_bits(addr);
560
561 idx = 1;
562 for (v = 0; v < ARRAY_SIZE(values); v++) {
563 /* LRI garbage */
564 *cs++ = MI_LOAD_REGISTER_IMM(1);
565 *cs++ = reg;
566 *cs++ = values[v];
567
568 /* SRM result */
569 *cs++ = srm;
570 *cs++ = reg;
571 *cs++ = lower_32_bits(addr + sizeof(u32) * idx);
572 *cs++ = upper_32_bits(addr + sizeof(u32) * idx);
573 idx++;
574 }
575 for (v = 0; v < ARRAY_SIZE(values); v++) {
576 /* LRI garbage */
577 *cs++ = MI_LOAD_REGISTER_IMM(1);
578 *cs++ = reg;
579 *cs++ = ~values[v];
580
581 /* SRM result */
582 *cs++ = srm;
583 *cs++ = reg;
584 *cs++ = lower_32_bits(addr + sizeof(u32) * idx);
585 *cs++ = upper_32_bits(addr + sizeof(u32) * idx);
586 idx++;
587 }
588 GEM_BUG_ON(idx * sizeof(u32) > scratch->size);
589
590 /* LRM original -- don't leave garbage in the context! */
591 *cs++ = lrm;
592 *cs++ = reg;
593 *cs++ = lower_32_bits(addr);
594 *cs++ = upper_32_bits(addr);
595
596 *cs++ = MI_BATCH_BUFFER_END;
597
598 i915_gem_object_flush_map(batch->obj);
599 i915_gem_object_unpin_map(batch->obj);
600 intel_gt_chipset_flush(engine->gt);
601 cs = NULL;
602
603 rq = i915_request_create(ce);
604 if (IS_ERR(rq)) {
605 err = PTR_ERR(rq);
606 goto out_unmap_scratch;
607 }
608
609 if (engine->emit_init_breadcrumb) { /* Be nice if we hang */
610 err = engine->emit_init_breadcrumb(rq);
611 if (err)
612 goto err_request;
613 }
614
615 err = i915_request_await_object(rq, batch->obj, false);
616 if (err == 0)
617 err = i915_vma_move_to_active(batch, rq, 0);
618 if (err)
619 goto err_request;
620
621 err = i915_request_await_object(rq, scratch->obj, true);
622 if (err == 0)
623 err = i915_vma_move_to_active(scratch, rq,
624 EXEC_OBJECT_WRITE);
625 if (err)
626 goto err_request;
627
628 err = engine->emit_bb_start(rq,
629 batch->node.start, PAGE_SIZE,
630 0);
631 if (err)
632 goto err_request;
633
634err_request:
635 err = request_add_sync(rq, err);
636 if (err) {
637 pr_err("%s: Futzing %x timedout; cancelling test\n",
638 engine->name, reg);
639 intel_gt_set_wedged(engine->gt);
640 goto out_unmap_scratch;
641 }
642
643 GEM_BUG_ON(values[ARRAY_SIZE(values) - 1] != 0xffffffff);
644 if (!ro_reg) {
645 /* detect write masking */
646 rsvd = results[ARRAY_SIZE(values)];
647 if (!rsvd) {
648 pr_err("%s: Unable to write to whitelisted register %x\n",
649 engine->name, reg);
650 err = -EINVAL;
651 goto out_unmap_scratch;
652 }
653 } else {
654 rsvd = 0;
655 }
656
657 expect = results[0];
658 idx = 1;
659 for (v = 0; v < ARRAY_SIZE(values); v++) {
660 if (ro_reg)
661 expect = results[0];
662 else
663 expect = reg_write(expect, values[v], rsvd);
664
665 if (results[idx] != expect)
666 err++;
667 idx++;
668 }
669 for (v = 0; v < ARRAY_SIZE(values); v++) {
670 if (ro_reg)
671 expect = results[0];
672 else
673 expect = reg_write(expect, ~values[v], rsvd);
674
675 if (results[idx] != expect)
676 err++;
677 idx++;
678 }
679 if (err) {
680 pr_err("%s: %d mismatch between values written to whitelisted register [%x], and values read back!\n",
681 engine->name, err, reg);
682
683 if (ro_reg)
684 pr_info("%s: Whitelisted read-only register: %x, original value %08x\n",
685 engine->name, reg, results[0]);
686 else
687 pr_info("%s: Whitelisted register: %x, original value %08x, rsvd %08x\n",
688 engine->name, reg, results[0], rsvd);
689
690 expect = results[0];
691 idx = 1;
692 for (v = 0; v < ARRAY_SIZE(values); v++) {
693 u32 w = values[v];
694
695 if (ro_reg)
696 expect = results[0];
697 else
698 expect = reg_write(expect, w, rsvd);
699 pr_info("Wrote %08x, read %08x, expect %08x\n",
700 w, results[idx], expect);
701 idx++;
702 }
703 for (v = 0; v < ARRAY_SIZE(values); v++) {
704 u32 w = ~values[v];
705
706 if (ro_reg)
707 expect = results[0];
708 else
709 expect = reg_write(expect, w, rsvd);
710 pr_info("Wrote %08x, read %08x, expect %08x\n",
711 w, results[idx], expect);
712 idx++;
713 }
714
715 err = -EINVAL;
716 }
717out_unmap_scratch:
718 i915_gem_object_unpin_map(scratch->obj);
719out_unmap_batch:
720 if (cs)
721 i915_gem_object_unpin_map(batch->obj);
722out_ctx:
723 intel_context_unpin(ce);
724out:
725 if (err == -EDEADLK) {
726 err = i915_gem_ww_ctx_backoff(&ww);
727 if (!err)
728 goto retry;
729 }
730 i915_gem_ww_ctx_fini(&ww);
731 if (err)
732 break;
733 }
734
735 if (igt_flush_test(engine->i915))
736 err = -EIO;
737
738 i915_vma_unpin_and_release(&batch, 0);
739out_scratch:
740 i915_vma_unpin_and_release(&scratch, 0);
741 return err;
742}
743
744static int live_dirty_whitelist(void *arg)
745{
746 struct intel_gt *gt = arg;
747 struct intel_engine_cs *engine;
748 enum intel_engine_id id;
749
750 /* Can the user write to the whitelisted registers? */
751
752 if (GRAPHICS_VER(gt->i915) < 7) /* minimum requirement for LRI, SRM, LRM */
753 return 0;
754
755 for_each_engine(engine, gt, id) {
756 struct intel_context *ce;
757 int err;
758
759 if (engine->whitelist.count == 0)
760 continue;
761
762 ce = intel_context_create(engine);
763 if (IS_ERR(ce))
764 return PTR_ERR(ce);
765
766 err = check_dirty_whitelist(ce);
767 intel_context_put(ce);
768 if (err)
769 return err;
770 }
771
772 return 0;
773}
774
775static int live_reset_whitelist(void *arg)
776{
777 struct intel_gt *gt = arg;
778 struct intel_engine_cs *engine;
779 enum intel_engine_id id;
780 int err = 0;
781
782 /* If we reset the gpu, we should not lose the RING_NONPRIV */
783 igt_global_reset_lock(gt);
784
785 for_each_engine(engine, gt, id) {
786 if (engine->whitelist.count == 0)
787 continue;
788
789 if (intel_has_reset_engine(gt)) {
790 err = check_whitelist_across_reset(engine,
791 do_engine_reset,
792 "engine");
793 if (err)
794 goto out;
795 }
796
797 if (intel_has_gpu_reset(gt)) {
798 err = check_whitelist_across_reset(engine,
799 do_device_reset,
800 "device");
801 if (err)
802 goto out;
803 }
804 }
805
806out:
807 igt_global_reset_unlock(gt);
808 return err;
809}
810
811static int read_whitelisted_registers(struct intel_context *ce,
812 struct i915_vma *results)
813{
814 struct intel_engine_cs *engine = ce->engine;
815 struct i915_request *rq;
816 int i, err = 0;
817 u32 srm, *cs;
818
819 rq = intel_context_create_request(ce);
820 if (IS_ERR(rq))
821 return PTR_ERR(rq);
822
823 i915_vma_lock(results);
824 err = i915_request_await_object(rq, results->obj, true);
825 if (err == 0)
826 err = i915_vma_move_to_active(results, rq, EXEC_OBJECT_WRITE);
827 i915_vma_unlock(results);
828 if (err)
829 goto err_req;
830
831 srm = MI_STORE_REGISTER_MEM;
832 if (GRAPHICS_VER(engine->i915) >= 8)
833 srm++;
834
835 cs = intel_ring_begin(rq, 4 * engine->whitelist.count);
836 if (IS_ERR(cs)) {
837 err = PTR_ERR(cs);
838 goto err_req;
839 }
840
841 for (i = 0; i < engine->whitelist.count; i++) {
842 u64 offset = results->node.start + sizeof(u32) * i;
843 u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
844
845 /* Clear non priv flags */
846 reg &= RING_FORCE_TO_NONPRIV_ADDRESS_MASK;
847
848 *cs++ = srm;
849 *cs++ = reg;
850 *cs++ = lower_32_bits(offset);
851 *cs++ = upper_32_bits(offset);
852 }
853 intel_ring_advance(rq, cs);
854
855err_req:
856 return request_add_sync(rq, err);
857}
858
859static int scrub_whitelisted_registers(struct intel_context *ce)
860{
861 struct intel_engine_cs *engine = ce->engine;
862 struct i915_request *rq;
863 struct i915_vma *batch;
864 int i, err = 0;
865 u32 *cs;
866
867 batch = create_batch(ce->vm);
868 if (IS_ERR(batch))
869 return PTR_ERR(batch);
870
871 cs = i915_gem_object_pin_map_unlocked(batch->obj, I915_MAP_WC);
872 if (IS_ERR(cs)) {
873 err = PTR_ERR(cs);
874 goto err_batch;
875 }
876
877 *cs++ = MI_LOAD_REGISTER_IMM(whitelist_writable_count(engine));
878 for (i = 0; i < engine->whitelist.count; i++) {
879 u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
880
881 if (ro_register(reg))
882 continue;
883
884 /* Clear non priv flags */
885 reg &= RING_FORCE_TO_NONPRIV_ADDRESS_MASK;
886
887 *cs++ = reg;
888 *cs++ = 0xffffffff;
889 }
890 *cs++ = MI_BATCH_BUFFER_END;
891
892 i915_gem_object_flush_map(batch->obj);
893 intel_gt_chipset_flush(engine->gt);
894
895 rq = intel_context_create_request(ce);
896 if (IS_ERR(rq)) {
897 err = PTR_ERR(rq);
898 goto err_unpin;
899 }
900
901 if (engine->emit_init_breadcrumb) { /* Be nice if we hang */
902 err = engine->emit_init_breadcrumb(rq);
903 if (err)
904 goto err_request;
905 }
906
907 i915_vma_lock(batch);
908 err = i915_request_await_object(rq, batch->obj, false);
909 if (err == 0)
910 err = i915_vma_move_to_active(batch, rq, 0);
911 i915_vma_unlock(batch);
912 if (err)
913 goto err_request;
914
915 /* Perform the writes from an unprivileged "user" batch */
916 err = engine->emit_bb_start(rq, batch->node.start, 0, 0);
917
918err_request:
919 err = request_add_sync(rq, err);
920
921err_unpin:
922 i915_gem_object_unpin_map(batch->obj);
923err_batch:
924 i915_vma_unpin_and_release(&batch, 0);
925 return err;
926}
927
928struct regmask {
929 i915_reg_t reg;
930 u8 graphics_ver;
931};
932
933static bool find_reg(struct drm_i915_private *i915,
934 i915_reg_t reg,
935 const struct regmask *tbl,
936 unsigned long count)
937{
938 u32 offset = i915_mmio_reg_offset(reg);
939
940 while (count--) {
941 if (GRAPHICS_VER(i915) == tbl->graphics_ver &&
942 i915_mmio_reg_offset(tbl->reg) == offset)
943 return true;
944 tbl++;
945 }
946
947 return false;
948}
949
950static bool pardon_reg(struct drm_i915_private *i915, i915_reg_t reg)
951{
952 /* Alas, we must pardon some whitelists. Mistakes already made */
953 static const struct regmask pardon[] = {
954 { GEN9_CTX_PREEMPT_REG, 9 },
955 { GEN8_L3SQCREG4, 9 },
956 };
957
958 return find_reg(i915, reg, pardon, ARRAY_SIZE(pardon));
959}
960
961static bool result_eq(struct intel_engine_cs *engine,
962 u32 a, u32 b, i915_reg_t reg)
963{
964 if (a != b && !pardon_reg(engine->i915, reg)) {
965 pr_err("Whitelisted register 0x%4x not context saved: A=%08x, B=%08x\n",
966 i915_mmio_reg_offset(reg), a, b);
967 return false;
968 }
969
970 return true;
971}
972
973static bool writeonly_reg(struct drm_i915_private *i915, i915_reg_t reg)
974{
975 /* Some registers do not seem to behave and our writes unreadable */
976 static const struct regmask wo[] = {
977 { GEN9_SLICE_COMMON_ECO_CHICKEN1, 9 },
978 };
979
980 return find_reg(i915, reg, wo, ARRAY_SIZE(wo));
981}
982
983static bool result_neq(struct intel_engine_cs *engine,
984 u32 a, u32 b, i915_reg_t reg)
985{
986 if (a == b && !writeonly_reg(engine->i915, reg)) {
987 pr_err("Whitelist register 0x%4x:%08x was unwritable\n",
988 i915_mmio_reg_offset(reg), a);
989 return false;
990 }
991
992 return true;
993}
994
995static int
996check_whitelisted_registers(struct intel_engine_cs *engine,
997 struct i915_vma *A,
998 struct i915_vma *B,
999 bool (*fn)(struct intel_engine_cs *engine,
1000 u32 a, u32 b,
1001 i915_reg_t reg))
1002{
1003 u32 *a, *b;
1004 int i, err;
1005
1006 a = i915_gem_object_pin_map_unlocked(A->obj, I915_MAP_WB);
1007 if (IS_ERR(a))
1008 return PTR_ERR(a);
1009
1010 b = i915_gem_object_pin_map_unlocked(B->obj, I915_MAP_WB);
1011 if (IS_ERR(b)) {
1012 err = PTR_ERR(b);
1013 goto err_a;
1014 }
1015
1016 err = 0;
1017 for (i = 0; i < engine->whitelist.count; i++) {
1018 const struct i915_wa *wa = &engine->whitelist.list[i];
1019
1020 if (i915_mmio_reg_offset(wa->reg) &
1021 RING_FORCE_TO_NONPRIV_ACCESS_RD)
1022 continue;
1023
1024 if (!fn(engine, a[i], b[i], wa->reg))
1025 err = -EINVAL;
1026 }
1027
1028 i915_gem_object_unpin_map(B->obj);
1029err_a:
1030 i915_gem_object_unpin_map(A->obj);
1031 return err;
1032}
1033
1034static int live_isolated_whitelist(void *arg)
1035{
1036 struct intel_gt *gt = arg;
1037 struct {
1038 struct i915_vma *scratch[2];
1039 } client[2] = {};
1040 struct intel_engine_cs *engine;
1041 enum intel_engine_id id;
1042 int i, err = 0;
1043
1044 /*
1045 * Check that a write into a whitelist register works, but
1046 * invisible to a second context.
1047 */
1048
1049 if (!intel_engines_has_context_isolation(gt->i915))
1050 return 0;
1051
1052 for (i = 0; i < ARRAY_SIZE(client); i++) {
1053 client[i].scratch[0] =
1054 __vm_create_scratch_for_read_pinned(gt->vm, 4096);
1055 if (IS_ERR(client[i].scratch[0])) {
1056 err = PTR_ERR(client[i].scratch[0]);
1057 goto err;
1058 }
1059
1060 client[i].scratch[1] =
1061 __vm_create_scratch_for_read_pinned(gt->vm, 4096);
1062 if (IS_ERR(client[i].scratch[1])) {
1063 err = PTR_ERR(client[i].scratch[1]);
1064 i915_vma_unpin_and_release(&client[i].scratch[0], 0);
1065 goto err;
1066 }
1067 }
1068
1069 for_each_engine(engine, gt, id) {
1070 struct intel_context *ce[2];
1071
1072 if (!engine->kernel_context->vm)
1073 continue;
1074
1075 if (!whitelist_writable_count(engine))
1076 continue;
1077
1078 ce[0] = intel_context_create(engine);
1079 if (IS_ERR(ce[0])) {
1080 err = PTR_ERR(ce[0]);
1081 break;
1082 }
1083 ce[1] = intel_context_create(engine);
1084 if (IS_ERR(ce[1])) {
1085 err = PTR_ERR(ce[1]);
1086 intel_context_put(ce[0]);
1087 break;
1088 }
1089
1090 /* Read default values */
1091 err = read_whitelisted_registers(ce[0], client[0].scratch[0]);
1092 if (err)
1093 goto err_ce;
1094
1095 /* Try to overwrite registers (should only affect ctx0) */
1096 err = scrub_whitelisted_registers(ce[0]);
1097 if (err)
1098 goto err_ce;
1099
1100 /* Read values from ctx1, we expect these to be defaults */
1101 err = read_whitelisted_registers(ce[1], client[1].scratch[0]);
1102 if (err)
1103 goto err_ce;
1104
1105 /* Verify that both reads return the same default values */
1106 err = check_whitelisted_registers(engine,
1107 client[0].scratch[0],
1108 client[1].scratch[0],
1109 result_eq);
1110 if (err)
1111 goto err_ce;
1112
1113 /* Read back the updated values in ctx0 */
1114 err = read_whitelisted_registers(ce[0], client[0].scratch[1]);
1115 if (err)
1116 goto err_ce;
1117
1118 /* User should be granted privilege to overwhite regs */
1119 err = check_whitelisted_registers(engine,
1120 client[0].scratch[0],
1121 client[0].scratch[1],
1122 result_neq);
1123err_ce:
1124 intel_context_put(ce[1]);
1125 intel_context_put(ce[0]);
1126 if (err)
1127 break;
1128 }
1129
1130err:
1131 for (i = 0; i < ARRAY_SIZE(client); i++) {
1132 i915_vma_unpin_and_release(&client[i].scratch[1], 0);
1133 i915_vma_unpin_and_release(&client[i].scratch[0], 0);
1134 }
1135
1136 if (igt_flush_test(gt->i915))
1137 err = -EIO;
1138
1139 return err;
1140}
1141
1142static bool
1143verify_wa_lists(struct intel_gt *gt, struct wa_lists *lists,
1144 const char *str)
1145{
1146 struct intel_engine_cs *engine;
1147 enum intel_engine_id id;
1148 bool ok = true;
1149
1150 ok &= wa_list_verify(gt->uncore, &lists->gt_wa_list, str);
1151
1152 for_each_engine(engine, gt, id) {
1153 struct intel_context *ce;
1154
1155 ce = intel_context_create(engine);
1156 if (IS_ERR(ce))
1157 return false;
1158
1159 ok &= engine_wa_list_verify(ce,
1160 &lists->engine[id].wa_list,
1161 str) == 0;
1162
1163 ok &= engine_wa_list_verify(ce,
1164 &lists->engine[id].ctx_wa_list,
1165 str) == 0;
1166
1167 intel_context_put(ce);
1168 }
1169
1170 return ok;
1171}
1172
1173static int
1174live_gpu_reset_workarounds(void *arg)
1175{
1176 struct intel_gt *gt = arg;
1177 intel_wakeref_t wakeref;
1178 struct wa_lists lists;
1179 bool ok;
1180
1181 if (!intel_has_gpu_reset(gt))
1182 return 0;
1183
1184 pr_info("Verifying after GPU reset...\n");
1185
1186 igt_global_reset_lock(gt);
1187 wakeref = intel_runtime_pm_get(gt->uncore->rpm);
1188
1189 reference_lists_init(gt, &lists);
1190
1191 ok = verify_wa_lists(gt, &lists, "before reset");
1192 if (!ok)
1193 goto out;
1194
1195 intel_gt_reset(gt, ALL_ENGINES, "live_workarounds");
1196
1197 ok = verify_wa_lists(gt, &lists, "after reset");
1198
1199out:
1200 reference_lists_fini(gt, &lists);
1201 intel_runtime_pm_put(gt->uncore->rpm, wakeref);
1202 igt_global_reset_unlock(gt);
1203
1204 return ok ? 0 : -ESRCH;
1205}
1206
1207static int
1208live_engine_reset_workarounds(void *arg)
1209{
1210 struct intel_gt *gt = arg;
1211 struct intel_engine_cs *engine;
1212 enum intel_engine_id id;
1213 struct intel_context *ce;
1214 struct igt_spinner spin;
1215 struct i915_request *rq;
1216 intel_wakeref_t wakeref;
1217 struct wa_lists lists;
1218 int ret = 0;
1219
1220 if (!intel_has_reset_engine(gt))
1221 return 0;
1222
1223 igt_global_reset_lock(gt);
1224 wakeref = intel_runtime_pm_get(gt->uncore->rpm);
1225
1226 reference_lists_init(gt, &lists);
1227
1228 for_each_engine(engine, gt, id) {
1229 bool ok;
1230
1231 pr_info("Verifying after %s reset...\n", engine->name);
1232 ce = intel_context_create(engine);
1233 if (IS_ERR(ce)) {
1234 ret = PTR_ERR(ce);
1235 break;
1236 }
1237
1238 ok = verify_wa_lists(gt, &lists, "before reset");
1239 if (!ok) {
1240 ret = -ESRCH;
1241 goto err;
1242 }
1243
1244 ret = intel_engine_reset(engine, "live_workarounds:idle");
1245 if (ret) {
1246 pr_err("%s: Reset failed while idle\n", engine->name);
1247 goto err;
1248 }
1249
1250 ok = verify_wa_lists(gt, &lists, "after idle reset");
1251 if (!ok) {
1252 ret = -ESRCH;
1253 goto err;
1254 }
1255
1256 ret = igt_spinner_init(&spin, engine->gt);
1257 if (ret)
1258 goto err;
1259
1260 rq = igt_spinner_create_request(&spin, ce, MI_NOOP);
1261 if (IS_ERR(rq)) {
1262 ret = PTR_ERR(rq);
1263 igt_spinner_fini(&spin);
1264 goto err;
1265 }
1266
1267 ret = request_add_spin(rq, &spin);
1268 if (ret) {
1269 pr_err("%s: Spinner failed to start\n", engine->name);
1270 igt_spinner_fini(&spin);
1271 goto err;
1272 }
1273
1274 ret = intel_engine_reset(engine, "live_workarounds:active");
1275 if (ret) {
1276 pr_err("%s: Reset failed on an active spinner\n",
1277 engine->name);
1278 igt_spinner_fini(&spin);
1279 goto err;
1280 }
1281
1282 igt_spinner_end(&spin);
1283 igt_spinner_fini(&spin);
1284
1285 ok = verify_wa_lists(gt, &lists, "after busy reset");
1286 if (!ok) {
1287 ret = -ESRCH;
1288 goto err;
1289 }
1290
1291err:
1292 intel_context_put(ce);
1293 if (ret)
1294 break;
1295 }
1296
1297 reference_lists_fini(gt, &lists);
1298 intel_runtime_pm_put(gt->uncore->rpm, wakeref);
1299 igt_global_reset_unlock(gt);
1300
1301 igt_flush_test(gt->i915);
1302
1303 return ret;
1304}
1305
1306int intel_workarounds_live_selftests(struct drm_i915_private *i915)
1307{
1308 static const struct i915_subtest tests[] = {
1309 SUBTEST(live_dirty_whitelist),
1310 SUBTEST(live_reset_whitelist),
1311 SUBTEST(live_isolated_whitelist),
1312 SUBTEST(live_gpu_reset_workarounds),
1313 SUBTEST(live_engine_reset_workarounds),
1314 };
1315
1316 if (intel_gt_is_wedged(&i915->gt))
1317 return 0;
1318
1319 return intel_gt_live_subtests(tests, &i915->gt);
1320}