]> git.ipfire.org Git - thirdparty/kernel/stable.git/blob - drivers/gpu/drm/i915/selftests/i915_gem_context.c
Merge branch 'drm-next-5.1' of git://people.freedesktop.org/~agd5f/linux into drm...
[thirdparty/kernel/stable.git] / drivers / gpu / drm / i915 / selftests / i915_gem_context.c
1 /*
2 * Copyright © 2017 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
25 #include <linux/prime_numbers.h>
26
27 #include "../i915_reset.h"
28 #include "../i915_selftest.h"
29 #include "i915_random.h"
30 #include "igt_flush_test.h"
31 #include "igt_live_test.h"
32 #include "igt_reset.h"
33 #include "igt_spinner.h"
34
35 #include "mock_drm.h"
36 #include "mock_gem_device.h"
37 #include "huge_gem_object.h"
38
39 #define DW_PER_PAGE (PAGE_SIZE / sizeof(u32))
40
41 static int live_nop_switch(void *arg)
42 {
43 const unsigned int nctx = 1024;
44 struct drm_i915_private *i915 = arg;
45 struct intel_engine_cs *engine;
46 struct i915_gem_context **ctx;
47 enum intel_engine_id id;
48 intel_wakeref_t wakeref;
49 struct igt_live_test t;
50 struct drm_file *file;
51 unsigned long n;
52 int err = -ENODEV;
53
54 /*
55 * Create as many contexts as we can feasibly get away with
56 * and check we can switch between them rapidly.
57 *
58 * Serves as very simple stress test for submission and HW switching
59 * between contexts.
60 */
61
62 if (!DRIVER_CAPS(i915)->has_logical_contexts)
63 return 0;
64
65 file = mock_file(i915);
66 if (IS_ERR(file))
67 return PTR_ERR(file);
68
69 mutex_lock(&i915->drm.struct_mutex);
70 wakeref = intel_runtime_pm_get(i915);
71
72 ctx = kcalloc(nctx, sizeof(*ctx), GFP_KERNEL);
73 if (!ctx) {
74 err = -ENOMEM;
75 goto out_unlock;
76 }
77
78 for (n = 0; n < nctx; n++) {
79 ctx[n] = i915_gem_create_context(i915, file->driver_priv);
80 if (IS_ERR(ctx[n])) {
81 err = PTR_ERR(ctx[n]);
82 goto out_unlock;
83 }
84 }
85
86 for_each_engine(engine, i915, id) {
87 struct i915_request *rq;
88 unsigned long end_time, prime;
89 ktime_t times[2] = {};
90
91 times[0] = ktime_get_raw();
92 for (n = 0; n < nctx; n++) {
93 rq = i915_request_alloc(engine, ctx[n]);
94 if (IS_ERR(rq)) {
95 err = PTR_ERR(rq);
96 goto out_unlock;
97 }
98 i915_request_add(rq);
99 }
100 if (i915_request_wait(rq,
101 I915_WAIT_LOCKED,
102 HZ / 5) < 0) {
103 pr_err("Failed to populated %d contexts\n", nctx);
104 i915_gem_set_wedged(i915);
105 err = -EIO;
106 goto out_unlock;
107 }
108
109 times[1] = ktime_get_raw();
110
111 pr_info("Populated %d contexts on %s in %lluns\n",
112 nctx, engine->name, ktime_to_ns(times[1] - times[0]));
113
114 err = igt_live_test_begin(&t, i915, __func__, engine->name);
115 if (err)
116 goto out_unlock;
117
118 end_time = jiffies + i915_selftest.timeout_jiffies;
119 for_each_prime_number_from(prime, 2, 8192) {
120 times[1] = ktime_get_raw();
121
122 for (n = 0; n < prime; n++) {
123 rq = i915_request_alloc(engine, ctx[n % nctx]);
124 if (IS_ERR(rq)) {
125 err = PTR_ERR(rq);
126 goto out_unlock;
127 }
128
129 /*
130 * This space is left intentionally blank.
131 *
132 * We do not actually want to perform any
133 * action with this request, we just want
134 * to measure the latency in allocation
135 * and submission of our breadcrumbs -
136 * ensuring that the bare request is sufficient
137 * for the system to work (i.e. proper HEAD
138 * tracking of the rings, interrupt handling,
139 * etc). It also gives us the lowest bounds
140 * for latency.
141 */
142
143 i915_request_add(rq);
144 }
145 if (i915_request_wait(rq,
146 I915_WAIT_LOCKED,
147 HZ / 5) < 0) {
148 pr_err("Switching between %ld contexts timed out\n",
149 prime);
150 i915_gem_set_wedged(i915);
151 break;
152 }
153
154 times[1] = ktime_sub(ktime_get_raw(), times[1]);
155 if (prime == 2)
156 times[0] = times[1];
157
158 if (__igt_timeout(end_time, NULL))
159 break;
160 }
161
162 err = igt_live_test_end(&t);
163 if (err)
164 goto out_unlock;
165
166 pr_info("Switch latencies on %s: 1 = %lluns, %lu = %lluns\n",
167 engine->name,
168 ktime_to_ns(times[0]),
169 prime - 1, div64_u64(ktime_to_ns(times[1]), prime - 1));
170 }
171
172 out_unlock:
173 intel_runtime_pm_put(i915, wakeref);
174 mutex_unlock(&i915->drm.struct_mutex);
175 mock_file_free(i915, file);
176 return err;
177 }
178
179 static struct i915_vma *
180 gpu_fill_dw(struct i915_vma *vma, u64 offset, unsigned long count, u32 value)
181 {
182 struct drm_i915_gem_object *obj;
183 const int gen = INTEL_GEN(vma->vm->i915);
184 unsigned long n, size;
185 u32 *cmd;
186 int err;
187
188 size = (4 * count + 1) * sizeof(u32);
189 size = round_up(size, PAGE_SIZE);
190 obj = i915_gem_object_create_internal(vma->vm->i915, size);
191 if (IS_ERR(obj))
192 return ERR_CAST(obj);
193
194 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB);
195 if (IS_ERR(cmd)) {
196 err = PTR_ERR(cmd);
197 goto err;
198 }
199
200 GEM_BUG_ON(offset + (count - 1) * PAGE_SIZE > vma->node.size);
201 offset += vma->node.start;
202
203 for (n = 0; n < count; n++) {
204 if (gen >= 8) {
205 *cmd++ = MI_STORE_DWORD_IMM_GEN4;
206 *cmd++ = lower_32_bits(offset);
207 *cmd++ = upper_32_bits(offset);
208 *cmd++ = value;
209 } else if (gen >= 4) {
210 *cmd++ = MI_STORE_DWORD_IMM_GEN4 |
211 (gen < 6 ? MI_USE_GGTT : 0);
212 *cmd++ = 0;
213 *cmd++ = offset;
214 *cmd++ = value;
215 } else {
216 *cmd++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
217 *cmd++ = offset;
218 *cmd++ = value;
219 }
220 offset += PAGE_SIZE;
221 }
222 *cmd = MI_BATCH_BUFFER_END;
223 i915_gem_object_unpin_map(obj);
224
225 err = i915_gem_object_set_to_gtt_domain(obj, false);
226 if (err)
227 goto err;
228
229 vma = i915_vma_instance(obj, vma->vm, NULL);
230 if (IS_ERR(vma)) {
231 err = PTR_ERR(vma);
232 goto err;
233 }
234
235 err = i915_vma_pin(vma, 0, 0, PIN_USER);
236 if (err)
237 goto err;
238
239 return vma;
240
241 err:
242 i915_gem_object_put(obj);
243 return ERR_PTR(err);
244 }
245
246 static unsigned long real_page_count(struct drm_i915_gem_object *obj)
247 {
248 return huge_gem_object_phys_size(obj) >> PAGE_SHIFT;
249 }
250
251 static unsigned long fake_page_count(struct drm_i915_gem_object *obj)
252 {
253 return huge_gem_object_dma_size(obj) >> PAGE_SHIFT;
254 }
255
256 static int gpu_fill(struct drm_i915_gem_object *obj,
257 struct i915_gem_context *ctx,
258 struct intel_engine_cs *engine,
259 unsigned int dw)
260 {
261 struct drm_i915_private *i915 = to_i915(obj->base.dev);
262 struct i915_address_space *vm =
263 ctx->ppgtt ? &ctx->ppgtt->vm : &i915->ggtt.vm;
264 struct i915_request *rq;
265 struct i915_vma *vma;
266 struct i915_vma *batch;
267 unsigned int flags;
268 int err;
269
270 GEM_BUG_ON(obj->base.size > vm->total);
271 GEM_BUG_ON(!intel_engine_can_store_dword(engine));
272
273 vma = i915_vma_instance(obj, vm, NULL);
274 if (IS_ERR(vma))
275 return PTR_ERR(vma);
276
277 err = i915_gem_object_set_to_gtt_domain(obj, false);
278 if (err)
279 return err;
280
281 err = i915_vma_pin(vma, 0, 0, PIN_HIGH | PIN_USER);
282 if (err)
283 return err;
284
285 /* Within the GTT the huge objects maps every page onto
286 * its 1024 real pages (using phys_pfn = dma_pfn % 1024).
287 * We set the nth dword within the page using the nth
288 * mapping via the GTT - this should exercise the GTT mapping
289 * whilst checking that each context provides a unique view
290 * into the object.
291 */
292 batch = gpu_fill_dw(vma,
293 (dw * real_page_count(obj)) << PAGE_SHIFT |
294 (dw * sizeof(u32)),
295 real_page_count(obj),
296 dw);
297 if (IS_ERR(batch)) {
298 err = PTR_ERR(batch);
299 goto err_vma;
300 }
301
302 rq = i915_request_alloc(engine, ctx);
303 if (IS_ERR(rq)) {
304 err = PTR_ERR(rq);
305 goto err_batch;
306 }
307
308 flags = 0;
309 if (INTEL_GEN(vm->i915) <= 5)
310 flags |= I915_DISPATCH_SECURE;
311
312 err = engine->emit_bb_start(rq,
313 batch->node.start, batch->node.size,
314 flags);
315 if (err)
316 goto err_request;
317
318 err = i915_vma_move_to_active(batch, rq, 0);
319 if (err)
320 goto skip_request;
321
322 err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
323 if (err)
324 goto skip_request;
325
326 i915_gem_object_set_active_reference(batch->obj);
327 i915_vma_unpin(batch);
328 i915_vma_close(batch);
329
330 i915_vma_unpin(vma);
331
332 i915_request_add(rq);
333
334 return 0;
335
336 skip_request:
337 i915_request_skip(rq, err);
338 err_request:
339 i915_request_add(rq);
340 err_batch:
341 i915_vma_unpin(batch);
342 i915_vma_put(batch);
343 err_vma:
344 i915_vma_unpin(vma);
345 return err;
346 }
347
348 static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
349 {
350 const bool has_llc = HAS_LLC(to_i915(obj->base.dev));
351 unsigned int n, m, need_flush;
352 int err;
353
354 err = i915_gem_obj_prepare_shmem_write(obj, &need_flush);
355 if (err)
356 return err;
357
358 for (n = 0; n < real_page_count(obj); n++) {
359 u32 *map;
360
361 map = kmap_atomic(i915_gem_object_get_page(obj, n));
362 for (m = 0; m < DW_PER_PAGE; m++)
363 map[m] = value;
364 if (!has_llc)
365 drm_clflush_virt_range(map, PAGE_SIZE);
366 kunmap_atomic(map);
367 }
368
369 i915_gem_obj_finish_shmem_access(obj);
370 obj->read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU;
371 obj->write_domain = 0;
372 return 0;
373 }
374
375 static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max)
376 {
377 unsigned int n, m, needs_flush;
378 int err;
379
380 err = i915_gem_obj_prepare_shmem_read(obj, &needs_flush);
381 if (err)
382 return err;
383
384 for (n = 0; n < real_page_count(obj); n++) {
385 u32 *map;
386
387 map = kmap_atomic(i915_gem_object_get_page(obj, n));
388 if (needs_flush & CLFLUSH_BEFORE)
389 drm_clflush_virt_range(map, PAGE_SIZE);
390
391 for (m = 0; m < max; m++) {
392 if (map[m] != m) {
393 pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",
394 n, m, map[m], m);
395 err = -EINVAL;
396 goto out_unmap;
397 }
398 }
399
400 for (; m < DW_PER_PAGE; m++) {
401 if (map[m] != STACK_MAGIC) {
402 pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",
403 n, m, map[m], STACK_MAGIC);
404 err = -EINVAL;
405 goto out_unmap;
406 }
407 }
408
409 out_unmap:
410 kunmap_atomic(map);
411 if (err)
412 break;
413 }
414
415 i915_gem_obj_finish_shmem_access(obj);
416 return err;
417 }
418
419 static int file_add_object(struct drm_file *file,
420 struct drm_i915_gem_object *obj)
421 {
422 int err;
423
424 GEM_BUG_ON(obj->base.handle_count);
425
426 /* tie the object to the drm_file for easy reaping */
427 err = idr_alloc(&file->object_idr, &obj->base, 1, 0, GFP_KERNEL);
428 if (err < 0)
429 return err;
430
431 i915_gem_object_get(obj);
432 obj->base.handle_count++;
433 return 0;
434 }
435
436 static struct drm_i915_gem_object *
437 create_test_object(struct i915_gem_context *ctx,
438 struct drm_file *file,
439 struct list_head *objects)
440 {
441 struct drm_i915_gem_object *obj;
442 struct i915_address_space *vm =
443 ctx->ppgtt ? &ctx->ppgtt->vm : &ctx->i915->ggtt.vm;
444 u64 size;
445 int err;
446
447 size = min(vm->total / 2, 1024ull * DW_PER_PAGE * PAGE_SIZE);
448 size = round_down(size, DW_PER_PAGE * PAGE_SIZE);
449
450 obj = huge_gem_object(ctx->i915, DW_PER_PAGE * PAGE_SIZE, size);
451 if (IS_ERR(obj))
452 return obj;
453
454 err = file_add_object(file, obj);
455 i915_gem_object_put(obj);
456 if (err)
457 return ERR_PTR(err);
458
459 err = cpu_fill(obj, STACK_MAGIC);
460 if (err) {
461 pr_err("Failed to fill object with cpu, err=%d\n",
462 err);
463 return ERR_PTR(err);
464 }
465
466 list_add_tail(&obj->st_link, objects);
467 return obj;
468 }
469
470 static unsigned long max_dwords(struct drm_i915_gem_object *obj)
471 {
472 unsigned long npages = fake_page_count(obj);
473
474 GEM_BUG_ON(!IS_ALIGNED(npages, DW_PER_PAGE));
475 return npages / DW_PER_PAGE;
476 }
477
478 static int igt_ctx_exec(void *arg)
479 {
480 struct drm_i915_private *i915 = arg;
481 struct drm_i915_gem_object *obj = NULL;
482 unsigned long ncontexts, ndwords, dw;
483 struct igt_live_test t;
484 struct drm_file *file;
485 IGT_TIMEOUT(end_time);
486 LIST_HEAD(objects);
487 int err = -ENODEV;
488
489 /*
490 * Create a few different contexts (with different mm) and write
491 * through each ctx/mm using the GPU making sure those writes end
492 * up in the expected pages of our obj.
493 */
494
495 if (!DRIVER_CAPS(i915)->has_logical_contexts)
496 return 0;
497
498 file = mock_file(i915);
499 if (IS_ERR(file))
500 return PTR_ERR(file);
501
502 mutex_lock(&i915->drm.struct_mutex);
503
504 err = igt_live_test_begin(&t, i915, __func__, "");
505 if (err)
506 goto out_unlock;
507
508 ncontexts = 0;
509 ndwords = 0;
510 dw = 0;
511 while (!time_after(jiffies, end_time)) {
512 struct intel_engine_cs *engine;
513 struct i915_gem_context *ctx;
514 unsigned int id;
515
516 ctx = i915_gem_create_context(i915, file->driver_priv);
517 if (IS_ERR(ctx)) {
518 err = PTR_ERR(ctx);
519 goto out_unlock;
520 }
521
522 for_each_engine(engine, i915, id) {
523 intel_wakeref_t wakeref;
524
525 if (!engine->context_size)
526 continue; /* No logical context support in HW */
527
528 if (!intel_engine_can_store_dword(engine))
529 continue;
530
531 if (!obj) {
532 obj = create_test_object(ctx, file, &objects);
533 if (IS_ERR(obj)) {
534 err = PTR_ERR(obj);
535 goto out_unlock;
536 }
537 }
538
539 err = 0;
540 with_intel_runtime_pm(i915, wakeref)
541 err = gpu_fill(obj, ctx, engine, dw);
542 if (err) {
543 pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
544 ndwords, dw, max_dwords(obj),
545 engine->name, ctx->hw_id,
546 yesno(!!ctx->ppgtt), err);
547 goto out_unlock;
548 }
549
550 if (++dw == max_dwords(obj)) {
551 obj = NULL;
552 dw = 0;
553 }
554 ndwords++;
555 }
556 ncontexts++;
557 }
558 pr_info("Submitted %lu contexts (across %u engines), filling %lu dwords\n",
559 ncontexts, RUNTIME_INFO(i915)->num_rings, ndwords);
560
561 dw = 0;
562 list_for_each_entry(obj, &objects, st_link) {
563 unsigned int rem =
564 min_t(unsigned int, ndwords - dw, max_dwords(obj));
565
566 err = cpu_check(obj, rem);
567 if (err)
568 break;
569
570 dw += rem;
571 }
572
573 out_unlock:
574 if (igt_live_test_end(&t))
575 err = -EIO;
576 mutex_unlock(&i915->drm.struct_mutex);
577
578 mock_file_free(i915, file);
579 return err;
580 }
581
582 static struct i915_vma *rpcs_query_batch(struct i915_vma *vma)
583 {
584 struct drm_i915_gem_object *obj;
585 u32 *cmd;
586 int err;
587
588 if (INTEL_GEN(vma->vm->i915) < 8)
589 return ERR_PTR(-EINVAL);
590
591 obj = i915_gem_object_create_internal(vma->vm->i915, PAGE_SIZE);
592 if (IS_ERR(obj))
593 return ERR_CAST(obj);
594
595 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB);
596 if (IS_ERR(cmd)) {
597 err = PTR_ERR(cmd);
598 goto err;
599 }
600
601 *cmd++ = MI_STORE_REGISTER_MEM_GEN8;
602 *cmd++ = i915_mmio_reg_offset(GEN8_R_PWR_CLK_STATE);
603 *cmd++ = lower_32_bits(vma->node.start);
604 *cmd++ = upper_32_bits(vma->node.start);
605 *cmd = MI_BATCH_BUFFER_END;
606
607 i915_gem_object_unpin_map(obj);
608
609 err = i915_gem_object_set_to_gtt_domain(obj, false);
610 if (err)
611 goto err;
612
613 vma = i915_vma_instance(obj, vma->vm, NULL);
614 if (IS_ERR(vma)) {
615 err = PTR_ERR(vma);
616 goto err;
617 }
618
619 err = i915_vma_pin(vma, 0, 0, PIN_USER);
620 if (err)
621 goto err;
622
623 return vma;
624
625 err:
626 i915_gem_object_put(obj);
627 return ERR_PTR(err);
628 }
629
630 static int
631 emit_rpcs_query(struct drm_i915_gem_object *obj,
632 struct i915_gem_context *ctx,
633 struct intel_engine_cs *engine,
634 struct i915_request **rq_out)
635 {
636 struct i915_request *rq;
637 struct i915_vma *batch;
638 struct i915_vma *vma;
639 int err;
640
641 GEM_BUG_ON(!intel_engine_can_store_dword(engine));
642
643 vma = i915_vma_instance(obj, &ctx->ppgtt->vm, NULL);
644 if (IS_ERR(vma))
645 return PTR_ERR(vma);
646
647 err = i915_gem_object_set_to_gtt_domain(obj, false);
648 if (err)
649 return err;
650
651 err = i915_vma_pin(vma, 0, 0, PIN_USER);
652 if (err)
653 return err;
654
655 batch = rpcs_query_batch(vma);
656 if (IS_ERR(batch)) {
657 err = PTR_ERR(batch);
658 goto err_vma;
659 }
660
661 rq = i915_request_alloc(engine, ctx);
662 if (IS_ERR(rq)) {
663 err = PTR_ERR(rq);
664 goto err_batch;
665 }
666
667 err = engine->emit_bb_start(rq, batch->node.start, batch->node.size, 0);
668 if (err)
669 goto err_request;
670
671 err = i915_vma_move_to_active(batch, rq, 0);
672 if (err)
673 goto skip_request;
674
675 err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
676 if (err)
677 goto skip_request;
678
679 i915_gem_object_set_active_reference(batch->obj);
680 i915_vma_unpin(batch);
681 i915_vma_close(batch);
682
683 i915_vma_unpin(vma);
684
685 *rq_out = i915_request_get(rq);
686
687 i915_request_add(rq);
688
689 return 0;
690
691 skip_request:
692 i915_request_skip(rq, err);
693 err_request:
694 i915_request_add(rq);
695 err_batch:
696 i915_vma_unpin(batch);
697 err_vma:
698 i915_vma_unpin(vma);
699
700 return err;
701 }
702
703 #define TEST_IDLE BIT(0)
704 #define TEST_BUSY BIT(1)
705 #define TEST_RESET BIT(2)
706
707 static int
708 __sseu_prepare(struct drm_i915_private *i915,
709 const char *name,
710 unsigned int flags,
711 struct i915_gem_context *ctx,
712 struct intel_engine_cs *engine,
713 struct igt_spinner **spin_out)
714 {
715 int ret = 0;
716
717 if (flags & (TEST_BUSY | TEST_RESET)) {
718 struct igt_spinner *spin;
719 struct i915_request *rq;
720
721 spin = kzalloc(sizeof(*spin), GFP_KERNEL);
722 if (!spin) {
723 ret = -ENOMEM;
724 goto out;
725 }
726
727 ret = igt_spinner_init(spin, i915);
728 if (ret)
729 return ret;
730
731 rq = igt_spinner_create_request(spin, ctx, engine, MI_NOOP);
732 if (IS_ERR(rq)) {
733 ret = PTR_ERR(rq);
734 igt_spinner_fini(spin);
735 kfree(spin);
736 goto out;
737 }
738
739 i915_request_add(rq);
740
741 if (!igt_wait_for_spinner(spin, rq)) {
742 pr_err("%s: Spinner failed to start!\n", name);
743 igt_spinner_end(spin);
744 igt_spinner_fini(spin);
745 kfree(spin);
746 ret = -ETIMEDOUT;
747 goto out;
748 }
749
750 *spin_out = spin;
751 }
752
753 out:
754 return ret;
755 }
756
757 static int
758 __read_slice_count(struct drm_i915_private *i915,
759 struct i915_gem_context *ctx,
760 struct intel_engine_cs *engine,
761 struct drm_i915_gem_object *obj,
762 struct igt_spinner *spin,
763 u32 *rpcs)
764 {
765 struct i915_request *rq = NULL;
766 u32 s_mask, s_shift;
767 unsigned int cnt;
768 u32 *buf, val;
769 long ret;
770
771 ret = emit_rpcs_query(obj, ctx, engine, &rq);
772 if (ret)
773 return ret;
774
775 if (spin)
776 igt_spinner_end(spin);
777
778 ret = i915_request_wait(rq, I915_WAIT_LOCKED, MAX_SCHEDULE_TIMEOUT);
779 i915_request_put(rq);
780 if (ret < 0)
781 return ret;
782
783 buf = i915_gem_object_pin_map(obj, I915_MAP_WB);
784 if (IS_ERR(buf)) {
785 ret = PTR_ERR(buf);
786 return ret;
787 }
788
789 if (INTEL_GEN(i915) >= 11) {
790 s_mask = GEN11_RPCS_S_CNT_MASK;
791 s_shift = GEN11_RPCS_S_CNT_SHIFT;
792 } else {
793 s_mask = GEN8_RPCS_S_CNT_MASK;
794 s_shift = GEN8_RPCS_S_CNT_SHIFT;
795 }
796
797 val = *buf;
798 cnt = (val & s_mask) >> s_shift;
799 *rpcs = val;
800
801 i915_gem_object_unpin_map(obj);
802
803 return cnt;
804 }
805
806 static int
807 __check_rpcs(const char *name, u32 rpcs, int slices, unsigned int expected,
808 const char *prefix, const char *suffix)
809 {
810 if (slices == expected)
811 return 0;
812
813 if (slices < 0) {
814 pr_err("%s: %s read slice count failed with %d%s\n",
815 name, prefix, slices, suffix);
816 return slices;
817 }
818
819 pr_err("%s: %s slice count %d is not %u%s\n",
820 name, prefix, slices, expected, suffix);
821
822 pr_info("RPCS=0x%x; %u%sx%u%s\n",
823 rpcs, slices,
824 (rpcs & GEN8_RPCS_S_CNT_ENABLE) ? "*" : "",
825 (rpcs & GEN8_RPCS_SS_CNT_MASK) >> GEN8_RPCS_SS_CNT_SHIFT,
826 (rpcs & GEN8_RPCS_SS_CNT_ENABLE) ? "*" : "");
827
828 return -EINVAL;
829 }
830
831 static int
832 __sseu_finish(struct drm_i915_private *i915,
833 const char *name,
834 unsigned int flags,
835 struct i915_gem_context *ctx,
836 struct i915_gem_context *kctx,
837 struct intel_engine_cs *engine,
838 struct drm_i915_gem_object *obj,
839 unsigned int expected,
840 struct igt_spinner *spin)
841 {
842 unsigned int slices =
843 hweight32(intel_device_default_sseu(i915).slice_mask);
844 u32 rpcs = 0;
845 int ret = 0;
846
847 if (flags & TEST_RESET) {
848 ret = i915_reset_engine(engine, "sseu");
849 if (ret)
850 goto out;
851 }
852
853 ret = __read_slice_count(i915, ctx, engine, obj,
854 flags & TEST_RESET ? NULL : spin, &rpcs);
855 ret = __check_rpcs(name, rpcs, ret, expected, "Context", "!");
856 if (ret)
857 goto out;
858
859 ret = __read_slice_count(i915, kctx, engine, obj, NULL, &rpcs);
860 ret = __check_rpcs(name, rpcs, ret, slices, "Kernel context", "!");
861
862 out:
863 if (spin)
864 igt_spinner_end(spin);
865
866 if ((flags & TEST_IDLE) && ret == 0) {
867 ret = i915_gem_wait_for_idle(i915,
868 I915_WAIT_LOCKED,
869 MAX_SCHEDULE_TIMEOUT);
870 if (ret)
871 return ret;
872
873 ret = __read_slice_count(i915, ctx, engine, obj, NULL, &rpcs);
874 ret = __check_rpcs(name, rpcs, ret, expected,
875 "Context", " after idle!");
876 }
877
878 return ret;
879 }
880
881 static int
882 __sseu_test(struct drm_i915_private *i915,
883 const char *name,
884 unsigned int flags,
885 struct i915_gem_context *ctx,
886 struct intel_engine_cs *engine,
887 struct drm_i915_gem_object *obj,
888 struct intel_sseu sseu)
889 {
890 struct igt_spinner *spin = NULL;
891 struct i915_gem_context *kctx;
892 int ret;
893
894 kctx = kernel_context(i915);
895 if (IS_ERR(kctx))
896 return PTR_ERR(kctx);
897
898 ret = __sseu_prepare(i915, name, flags, ctx, engine, &spin);
899 if (ret)
900 goto out;
901
902 ret = __i915_gem_context_reconfigure_sseu(ctx, engine, sseu);
903 if (ret)
904 goto out;
905
906 ret = __sseu_finish(i915, name, flags, ctx, kctx, engine, obj,
907 hweight32(sseu.slice_mask), spin);
908
909 out:
910 if (spin) {
911 igt_spinner_end(spin);
912 igt_spinner_fini(spin);
913 kfree(spin);
914 }
915
916 kernel_context_close(kctx);
917
918 return ret;
919 }
920
921 static int
922 __igt_ctx_sseu(struct drm_i915_private *i915,
923 const char *name,
924 unsigned int flags)
925 {
926 struct intel_sseu default_sseu = intel_device_default_sseu(i915);
927 struct intel_engine_cs *engine = i915->engine[RCS];
928 struct drm_i915_gem_object *obj;
929 struct i915_gem_context *ctx;
930 struct intel_sseu pg_sseu;
931 intel_wakeref_t wakeref;
932 struct drm_file *file;
933 int ret;
934
935 if (INTEL_GEN(i915) < 9)
936 return 0;
937
938 if (!RUNTIME_INFO(i915)->sseu.has_slice_pg)
939 return 0;
940
941 if (hweight32(default_sseu.slice_mask) < 2)
942 return 0;
943
944 /*
945 * Gen11 VME friendly power-gated configuration with half enabled
946 * sub-slices.
947 */
948 pg_sseu = default_sseu;
949 pg_sseu.slice_mask = 1;
950 pg_sseu.subslice_mask =
951 ~(~0 << (hweight32(default_sseu.subslice_mask) / 2));
952
953 pr_info("SSEU subtest '%s', flags=%x, def_slices=%u, pg_slices=%u\n",
954 name, flags, hweight32(default_sseu.slice_mask),
955 hweight32(pg_sseu.slice_mask));
956
957 file = mock_file(i915);
958 if (IS_ERR(file))
959 return PTR_ERR(file);
960
961 if (flags & TEST_RESET)
962 igt_global_reset_lock(i915);
963
964 mutex_lock(&i915->drm.struct_mutex);
965
966 ctx = i915_gem_create_context(i915, file->driver_priv);
967 if (IS_ERR(ctx)) {
968 ret = PTR_ERR(ctx);
969 goto out_unlock;
970 }
971
972 obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
973 if (IS_ERR(obj)) {
974 ret = PTR_ERR(obj);
975 goto out_unlock;
976 }
977
978 wakeref = intel_runtime_pm_get(i915);
979
980 /* First set the default mask. */
981 ret = __sseu_test(i915, name, flags, ctx, engine, obj, default_sseu);
982 if (ret)
983 goto out_fail;
984
985 /* Then set a power-gated configuration. */
986 ret = __sseu_test(i915, name, flags, ctx, engine, obj, pg_sseu);
987 if (ret)
988 goto out_fail;
989
990 /* Back to defaults. */
991 ret = __sseu_test(i915, name, flags, ctx, engine, obj, default_sseu);
992 if (ret)
993 goto out_fail;
994
995 /* One last power-gated configuration for the road. */
996 ret = __sseu_test(i915, name, flags, ctx, engine, obj, pg_sseu);
997 if (ret)
998 goto out_fail;
999
1000 out_fail:
1001 if (igt_flush_test(i915, I915_WAIT_LOCKED))
1002 ret = -EIO;
1003
1004 i915_gem_object_put(obj);
1005
1006 intel_runtime_pm_put(i915, wakeref);
1007
1008 out_unlock:
1009 mutex_unlock(&i915->drm.struct_mutex);
1010
1011 if (flags & TEST_RESET)
1012 igt_global_reset_unlock(i915);
1013
1014 mock_file_free(i915, file);
1015
1016 if (ret)
1017 pr_err("%s: Failed with %d!\n", name, ret);
1018
1019 return ret;
1020 }
1021
1022 static int igt_ctx_sseu(void *arg)
1023 {
1024 struct {
1025 const char *name;
1026 unsigned int flags;
1027 } *phase, phases[] = {
1028 { .name = "basic", .flags = 0 },
1029 { .name = "idle", .flags = TEST_IDLE },
1030 { .name = "busy", .flags = TEST_BUSY },
1031 { .name = "busy-reset", .flags = TEST_BUSY | TEST_RESET },
1032 { .name = "busy-idle", .flags = TEST_BUSY | TEST_IDLE },
1033 { .name = "reset-idle", .flags = TEST_RESET | TEST_IDLE },
1034 };
1035 unsigned int i;
1036 int ret = 0;
1037
1038 for (i = 0, phase = phases; ret == 0 && i < ARRAY_SIZE(phases);
1039 i++, phase++)
1040 ret = __igt_ctx_sseu(arg, phase->name, phase->flags);
1041
1042 return ret;
1043 }
1044
1045 static int igt_ctx_readonly(void *arg)
1046 {
1047 struct drm_i915_private *i915 = arg;
1048 struct drm_i915_gem_object *obj = NULL;
1049 struct i915_gem_context *ctx;
1050 struct i915_hw_ppgtt *ppgtt;
1051 unsigned long ndwords, dw;
1052 struct igt_live_test t;
1053 struct drm_file *file;
1054 I915_RND_STATE(prng);
1055 IGT_TIMEOUT(end_time);
1056 LIST_HEAD(objects);
1057 int err = -ENODEV;
1058
1059 /*
1060 * Create a few read-only objects (with the occasional writable object)
1061 * and try to write into these object checking that the GPU discards
1062 * any write to a read-only object.
1063 */
1064
1065 file = mock_file(i915);
1066 if (IS_ERR(file))
1067 return PTR_ERR(file);
1068
1069 mutex_lock(&i915->drm.struct_mutex);
1070
1071 err = igt_live_test_begin(&t, i915, __func__, "");
1072 if (err)
1073 goto out_unlock;
1074
1075 ctx = i915_gem_create_context(i915, file->driver_priv);
1076 if (IS_ERR(ctx)) {
1077 err = PTR_ERR(ctx);
1078 goto out_unlock;
1079 }
1080
1081 ppgtt = ctx->ppgtt ?: i915->mm.aliasing_ppgtt;
1082 if (!ppgtt || !ppgtt->vm.has_read_only) {
1083 err = 0;
1084 goto out_unlock;
1085 }
1086
1087 ndwords = 0;
1088 dw = 0;
1089 while (!time_after(jiffies, end_time)) {
1090 struct intel_engine_cs *engine;
1091 unsigned int id;
1092
1093 for_each_engine(engine, i915, id) {
1094 intel_wakeref_t wakeref;
1095
1096 if (!intel_engine_can_store_dword(engine))
1097 continue;
1098
1099 if (!obj) {
1100 obj = create_test_object(ctx, file, &objects);
1101 if (IS_ERR(obj)) {
1102 err = PTR_ERR(obj);
1103 goto out_unlock;
1104 }
1105
1106 if (prandom_u32_state(&prng) & 1)
1107 i915_gem_object_set_readonly(obj);
1108 }
1109
1110 err = 0;
1111 with_intel_runtime_pm(i915, wakeref)
1112 err = gpu_fill(obj, ctx, engine, dw);
1113 if (err) {
1114 pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
1115 ndwords, dw, max_dwords(obj),
1116 engine->name, ctx->hw_id,
1117 yesno(!!ctx->ppgtt), err);
1118 goto out_unlock;
1119 }
1120
1121 if (++dw == max_dwords(obj)) {
1122 obj = NULL;
1123 dw = 0;
1124 }
1125 ndwords++;
1126 }
1127 }
1128 pr_info("Submitted %lu dwords (across %u engines)\n",
1129 ndwords, RUNTIME_INFO(i915)->num_rings);
1130
1131 dw = 0;
1132 list_for_each_entry(obj, &objects, st_link) {
1133 unsigned int rem =
1134 min_t(unsigned int, ndwords - dw, max_dwords(obj));
1135 unsigned int num_writes;
1136
1137 num_writes = rem;
1138 if (i915_gem_object_is_readonly(obj))
1139 num_writes = 0;
1140
1141 err = cpu_check(obj, num_writes);
1142 if (err)
1143 break;
1144
1145 dw += rem;
1146 }
1147
1148 out_unlock:
1149 if (igt_live_test_end(&t))
1150 err = -EIO;
1151 mutex_unlock(&i915->drm.struct_mutex);
1152
1153 mock_file_free(i915, file);
1154 return err;
1155 }
1156
1157 static int check_scratch(struct i915_gem_context *ctx, u64 offset)
1158 {
1159 struct drm_mm_node *node =
1160 __drm_mm_interval_first(&ctx->ppgtt->vm.mm,
1161 offset, offset + sizeof(u32) - 1);
1162 if (!node || node->start > offset)
1163 return 0;
1164
1165 GEM_BUG_ON(offset >= node->start + node->size);
1166
1167 pr_err("Target offset 0x%08x_%08x overlaps with a node in the mm!\n",
1168 upper_32_bits(offset), lower_32_bits(offset));
1169 return -EINVAL;
1170 }
1171
1172 static int write_to_scratch(struct i915_gem_context *ctx,
1173 struct intel_engine_cs *engine,
1174 u64 offset, u32 value)
1175 {
1176 struct drm_i915_private *i915 = ctx->i915;
1177 struct drm_i915_gem_object *obj;
1178 struct i915_request *rq;
1179 struct i915_vma *vma;
1180 u32 *cmd;
1181 int err;
1182
1183 GEM_BUG_ON(offset < I915_GTT_PAGE_SIZE);
1184
1185 obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
1186 if (IS_ERR(obj))
1187 return PTR_ERR(obj);
1188
1189 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB);
1190 if (IS_ERR(cmd)) {
1191 err = PTR_ERR(cmd);
1192 goto err;
1193 }
1194
1195 *cmd++ = MI_STORE_DWORD_IMM_GEN4;
1196 if (INTEL_GEN(i915) >= 8) {
1197 *cmd++ = lower_32_bits(offset);
1198 *cmd++ = upper_32_bits(offset);
1199 } else {
1200 *cmd++ = 0;
1201 *cmd++ = offset;
1202 }
1203 *cmd++ = value;
1204 *cmd = MI_BATCH_BUFFER_END;
1205 i915_gem_object_unpin_map(obj);
1206
1207 err = i915_gem_object_set_to_gtt_domain(obj, false);
1208 if (err)
1209 goto err;
1210
1211 vma = i915_vma_instance(obj, &ctx->ppgtt->vm, NULL);
1212 if (IS_ERR(vma)) {
1213 err = PTR_ERR(vma);
1214 goto err;
1215 }
1216
1217 err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED);
1218 if (err)
1219 goto err;
1220
1221 err = check_scratch(ctx, offset);
1222 if (err)
1223 goto err_unpin;
1224
1225 rq = i915_request_alloc(engine, ctx);
1226 if (IS_ERR(rq)) {
1227 err = PTR_ERR(rq);
1228 goto err_unpin;
1229 }
1230
1231 err = engine->emit_bb_start(rq, vma->node.start, vma->node.size, 0);
1232 if (err)
1233 goto err_request;
1234
1235 err = i915_vma_move_to_active(vma, rq, 0);
1236 if (err)
1237 goto skip_request;
1238
1239 i915_gem_object_set_active_reference(obj);
1240 i915_vma_unpin(vma);
1241 i915_vma_close(vma);
1242
1243 i915_request_add(rq);
1244
1245 return 0;
1246
1247 skip_request:
1248 i915_request_skip(rq, err);
1249 err_request:
1250 i915_request_add(rq);
1251 err_unpin:
1252 i915_vma_unpin(vma);
1253 err:
1254 i915_gem_object_put(obj);
1255 return err;
1256 }
1257
1258 static int read_from_scratch(struct i915_gem_context *ctx,
1259 struct intel_engine_cs *engine,
1260 u64 offset, u32 *value)
1261 {
1262 struct drm_i915_private *i915 = ctx->i915;
1263 struct drm_i915_gem_object *obj;
1264 const u32 RCS_GPR0 = 0x2600; /* not all engines have their own GPR! */
1265 const u32 result = 0x100;
1266 struct i915_request *rq;
1267 struct i915_vma *vma;
1268 u32 *cmd;
1269 int err;
1270
1271 GEM_BUG_ON(offset < I915_GTT_PAGE_SIZE);
1272
1273 obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
1274 if (IS_ERR(obj))
1275 return PTR_ERR(obj);
1276
1277 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB);
1278 if (IS_ERR(cmd)) {
1279 err = PTR_ERR(cmd);
1280 goto err;
1281 }
1282
1283 memset(cmd, POISON_INUSE, PAGE_SIZE);
1284 if (INTEL_GEN(i915) >= 8) {
1285 *cmd++ = MI_LOAD_REGISTER_MEM_GEN8;
1286 *cmd++ = RCS_GPR0;
1287 *cmd++ = lower_32_bits(offset);
1288 *cmd++ = upper_32_bits(offset);
1289 *cmd++ = MI_STORE_REGISTER_MEM_GEN8;
1290 *cmd++ = RCS_GPR0;
1291 *cmd++ = result;
1292 *cmd++ = 0;
1293 } else {
1294 *cmd++ = MI_LOAD_REGISTER_MEM;
1295 *cmd++ = RCS_GPR0;
1296 *cmd++ = offset;
1297 *cmd++ = MI_STORE_REGISTER_MEM;
1298 *cmd++ = RCS_GPR0;
1299 *cmd++ = result;
1300 }
1301 *cmd = MI_BATCH_BUFFER_END;
1302 i915_gem_object_unpin_map(obj);
1303
1304 err = i915_gem_object_set_to_gtt_domain(obj, false);
1305 if (err)
1306 goto err;
1307
1308 vma = i915_vma_instance(obj, &ctx->ppgtt->vm, NULL);
1309 if (IS_ERR(vma)) {
1310 err = PTR_ERR(vma);
1311 goto err;
1312 }
1313
1314 err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED);
1315 if (err)
1316 goto err;
1317
1318 err = check_scratch(ctx, offset);
1319 if (err)
1320 goto err_unpin;
1321
1322 rq = i915_request_alloc(engine, ctx);
1323 if (IS_ERR(rq)) {
1324 err = PTR_ERR(rq);
1325 goto err_unpin;
1326 }
1327
1328 err = engine->emit_bb_start(rq, vma->node.start, vma->node.size, 0);
1329 if (err)
1330 goto err_request;
1331
1332 err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
1333 if (err)
1334 goto skip_request;
1335
1336 i915_vma_unpin(vma);
1337 i915_vma_close(vma);
1338
1339 i915_request_add(rq);
1340
1341 err = i915_gem_object_set_to_cpu_domain(obj, false);
1342 if (err)
1343 goto err;
1344
1345 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB);
1346 if (IS_ERR(cmd)) {
1347 err = PTR_ERR(cmd);
1348 goto err;
1349 }
1350
1351 *value = cmd[result / sizeof(*cmd)];
1352 i915_gem_object_unpin_map(obj);
1353 i915_gem_object_put(obj);
1354
1355 return 0;
1356
1357 skip_request:
1358 i915_request_skip(rq, err);
1359 err_request:
1360 i915_request_add(rq);
1361 err_unpin:
1362 i915_vma_unpin(vma);
1363 err:
1364 i915_gem_object_put(obj);
1365 return err;
1366 }
1367
1368 static int igt_vm_isolation(void *arg)
1369 {
1370 struct drm_i915_private *i915 = arg;
1371 struct i915_gem_context *ctx_a, *ctx_b;
1372 struct intel_engine_cs *engine;
1373 intel_wakeref_t wakeref;
1374 struct igt_live_test t;
1375 struct drm_file *file;
1376 I915_RND_STATE(prng);
1377 unsigned long count;
1378 unsigned int id;
1379 u64 vm_total;
1380 int err;
1381
1382 if (INTEL_GEN(i915) < 7)
1383 return 0;
1384
1385 /*
1386 * The simple goal here is that a write into one context is not
1387 * observed in a second (separate page tables and scratch).
1388 */
1389
1390 file = mock_file(i915);
1391 if (IS_ERR(file))
1392 return PTR_ERR(file);
1393
1394 mutex_lock(&i915->drm.struct_mutex);
1395
1396 err = igt_live_test_begin(&t, i915, __func__, "");
1397 if (err)
1398 goto out_unlock;
1399
1400 ctx_a = i915_gem_create_context(i915, file->driver_priv);
1401 if (IS_ERR(ctx_a)) {
1402 err = PTR_ERR(ctx_a);
1403 goto out_unlock;
1404 }
1405
1406 ctx_b = i915_gem_create_context(i915, file->driver_priv);
1407 if (IS_ERR(ctx_b)) {
1408 err = PTR_ERR(ctx_b);
1409 goto out_unlock;
1410 }
1411
1412 /* We can only test vm isolation, if the vm are distinct */
1413 if (ctx_a->ppgtt == ctx_b->ppgtt)
1414 goto out_unlock;
1415
1416 vm_total = ctx_a->ppgtt->vm.total;
1417 GEM_BUG_ON(ctx_b->ppgtt->vm.total != vm_total);
1418 vm_total -= I915_GTT_PAGE_SIZE;
1419
1420 wakeref = intel_runtime_pm_get(i915);
1421
1422 count = 0;
1423 for_each_engine(engine, i915, id) {
1424 IGT_TIMEOUT(end_time);
1425 unsigned long this = 0;
1426
1427 if (!intel_engine_can_store_dword(engine))
1428 continue;
1429
1430 while (!__igt_timeout(end_time, NULL)) {
1431 u32 value = 0xc5c5c5c5;
1432 u64 offset;
1433
1434 div64_u64_rem(i915_prandom_u64_state(&prng),
1435 vm_total, &offset);
1436 offset &= ~sizeof(u32);
1437 offset += I915_GTT_PAGE_SIZE;
1438
1439 err = write_to_scratch(ctx_a, engine,
1440 offset, 0xdeadbeef);
1441 if (err == 0)
1442 err = read_from_scratch(ctx_b, engine,
1443 offset, &value);
1444 if (err)
1445 goto out_rpm;
1446
1447 if (value) {
1448 pr_err("%s: Read %08x from scratch (offset 0x%08x_%08x), after %lu reads!\n",
1449 engine->name, value,
1450 upper_32_bits(offset),
1451 lower_32_bits(offset),
1452 this);
1453 err = -EINVAL;
1454 goto out_rpm;
1455 }
1456
1457 this++;
1458 }
1459 count += this;
1460 }
1461 pr_info("Checked %lu scratch offsets across %d engines\n",
1462 count, RUNTIME_INFO(i915)->num_rings);
1463
1464 out_rpm:
1465 intel_runtime_pm_put(i915, wakeref);
1466 out_unlock:
1467 if (igt_live_test_end(&t))
1468 err = -EIO;
1469 mutex_unlock(&i915->drm.struct_mutex);
1470
1471 mock_file_free(i915, file);
1472 return err;
1473 }
1474
1475 static __maybe_unused const char *
1476 __engine_name(struct drm_i915_private *i915, unsigned int engines)
1477 {
1478 struct intel_engine_cs *engine;
1479 unsigned int tmp;
1480
1481 if (engines == ALL_ENGINES)
1482 return "all";
1483
1484 for_each_engine_masked(engine, i915, engines, tmp)
1485 return engine->name;
1486
1487 return "none";
1488 }
1489
1490 static int __igt_switch_to_kernel_context(struct drm_i915_private *i915,
1491 struct i915_gem_context *ctx,
1492 unsigned int engines)
1493 {
1494 struct intel_engine_cs *engine;
1495 unsigned int tmp;
1496 int err;
1497
1498 GEM_TRACE("Testing %s\n", __engine_name(i915, engines));
1499 for_each_engine_masked(engine, i915, engines, tmp) {
1500 struct i915_request *rq;
1501
1502 rq = i915_request_alloc(engine, ctx);
1503 if (IS_ERR(rq))
1504 return PTR_ERR(rq);
1505
1506 i915_request_add(rq);
1507 }
1508
1509 err = i915_gem_switch_to_kernel_context(i915);
1510 if (err)
1511 return err;
1512
1513 for_each_engine_masked(engine, i915, engines, tmp) {
1514 if (!engine_has_kernel_context_barrier(engine)) {
1515 pr_err("kernel context not last on engine %s!\n",
1516 engine->name);
1517 return -EINVAL;
1518 }
1519 }
1520
1521 err = i915_gem_wait_for_idle(i915,
1522 I915_WAIT_LOCKED,
1523 MAX_SCHEDULE_TIMEOUT);
1524 if (err)
1525 return err;
1526
1527 GEM_BUG_ON(i915->gt.active_requests);
1528 for_each_engine_masked(engine, i915, engines, tmp) {
1529 if (engine->last_retired_context->gem_context != i915->kernel_context) {
1530 pr_err("engine %s not idling in kernel context!\n",
1531 engine->name);
1532 return -EINVAL;
1533 }
1534 }
1535
1536 err = i915_gem_switch_to_kernel_context(i915);
1537 if (err)
1538 return err;
1539
1540 if (i915->gt.active_requests) {
1541 pr_err("switch-to-kernel-context emitted %d requests even though it should already be idling in the kernel context\n",
1542 i915->gt.active_requests);
1543 return -EINVAL;
1544 }
1545
1546 for_each_engine_masked(engine, i915, engines, tmp) {
1547 if (!intel_engine_has_kernel_context(engine)) {
1548 pr_err("kernel context not last on engine %s!\n",
1549 engine->name);
1550 return -EINVAL;
1551 }
1552 }
1553
1554 return 0;
1555 }
1556
1557 static int igt_switch_to_kernel_context(void *arg)
1558 {
1559 struct drm_i915_private *i915 = arg;
1560 struct intel_engine_cs *engine;
1561 struct i915_gem_context *ctx;
1562 enum intel_engine_id id;
1563 intel_wakeref_t wakeref;
1564 int err;
1565
1566 /*
1567 * A core premise of switching to the kernel context is that
1568 * if an engine is already idling in the kernel context, we
1569 * do not emit another request and wake it up. The other being
1570 * that we do indeed end up idling in the kernel context.
1571 */
1572
1573 mutex_lock(&i915->drm.struct_mutex);
1574 wakeref = intel_runtime_pm_get(i915);
1575
1576 ctx = kernel_context(i915);
1577 if (IS_ERR(ctx)) {
1578 mutex_unlock(&i915->drm.struct_mutex);
1579 return PTR_ERR(ctx);
1580 }
1581
1582 /* First check idling each individual engine */
1583 for_each_engine(engine, i915, id) {
1584 err = __igt_switch_to_kernel_context(i915, ctx, BIT(id));
1585 if (err)
1586 goto out_unlock;
1587 }
1588
1589 /* Now en masse */
1590 err = __igt_switch_to_kernel_context(i915, ctx, ALL_ENGINES);
1591 if (err)
1592 goto out_unlock;
1593
1594 out_unlock:
1595 GEM_TRACE_DUMP_ON(err);
1596 if (igt_flush_test(i915, I915_WAIT_LOCKED))
1597 err = -EIO;
1598
1599 intel_runtime_pm_put(i915, wakeref);
1600 mutex_unlock(&i915->drm.struct_mutex);
1601
1602 kernel_context_close(ctx);
1603 return err;
1604 }
1605
1606 int i915_gem_context_mock_selftests(void)
1607 {
1608 static const struct i915_subtest tests[] = {
1609 SUBTEST(igt_switch_to_kernel_context),
1610 };
1611 struct drm_i915_private *i915;
1612 int err;
1613
1614 i915 = mock_gem_device();
1615 if (!i915)
1616 return -ENOMEM;
1617
1618 err = i915_subtests(tests, i915);
1619
1620 drm_dev_put(&i915->drm);
1621 return err;
1622 }
1623
1624 int i915_gem_context_live_selftests(struct drm_i915_private *dev_priv)
1625 {
1626 static const struct i915_subtest tests[] = {
1627 SUBTEST(igt_switch_to_kernel_context),
1628 SUBTEST(live_nop_switch),
1629 SUBTEST(igt_ctx_exec),
1630 SUBTEST(igt_ctx_readonly),
1631 SUBTEST(igt_ctx_sseu),
1632 SUBTEST(igt_vm_isolation),
1633 };
1634
1635 if (i915_terminally_wedged(&dev_priv->gpu_error))
1636 return 0;
1637
1638 return i915_subtests(tests, dev_priv);
1639 }