Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
41static 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
172out_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
179static struct i915_vma *
180gpu_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
241err:
242 i915_gem_object_put(obj);
243 return ERR_PTR(err);
244}
245
246static unsigned long real_page_count(struct drm_i915_gem_object *obj)
247{
248 return huge_gem_object_phys_size(obj) >> PAGE_SHIFT;
249}
250
251static unsigned long fake_page_count(struct drm_i915_gem_object *obj)
252{
253 return huge_gem_object_dma_size(obj) >> PAGE_SHIFT;
254}
255
256static 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
336skip_request:
337 i915_request_skip(rq, err);
338err_request:
339 i915_request_add(rq);
340err_batch:
341 i915_vma_unpin(batch);
342 i915_vma_put(batch);
343err_vma:
344 i915_vma_unpin(vma);
345 return err;
346}
347
348static 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
375static 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
409out_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
419static 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
436static struct drm_i915_gem_object *
437create_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
470static 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
478static 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
573out_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
582static 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
625err:
626 i915_gem_object_put(obj);
627 return ERR_PTR(err);
628}
629
630static int
631emit_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
691skip_request:
692 i915_request_skip(rq, err);
693err_request:
694 i915_request_add(rq);
695err_batch:
696 i915_vma_unpin(batch);
697err_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
707static 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)
714{
715 struct i915_request *rq;
716 int ret;
717
718 *spin = NULL;
719 if (!(flags & (TEST_BUSY | TEST_RESET)))
720 return 0;
721
722 *spin = kzalloc(sizeof(**spin), GFP_KERNEL);
723 if (!*spin)
724 return -ENOMEM;
725
726 ret = igt_spinner_init(*spin, i915);
727 if (ret)
728 goto err_free;
729
730 rq = igt_spinner_create_request(*spin, ctx, engine, MI_NOOP);
731 if (IS_ERR(rq)) {
732 ret = PTR_ERR(rq);
733 goto err_fini;
734 }
735
736 i915_request_add(rq);
737
738 if (!igt_wait_for_spinner(*spin, rq)) {
739 pr_err("%s: Spinner failed to start!\n", name);
740 ret = -ETIMEDOUT;
741 goto err_end;
742 }
743
744 return 0;
745
746err_end:
747 igt_spinner_end(*spin);
748err_fini:
749 igt_spinner_fini(*spin);
750err_free:
751 kfree(fetch_and_zero(spin));
752 return ret;
753}
754
755static int
756__read_slice_count(struct drm_i915_private *i915,
757 struct i915_gem_context *ctx,
758 struct intel_engine_cs *engine,
759 struct drm_i915_gem_object *obj,
760 struct igt_spinner *spin,
761 u32 *rpcs)
762{
763 struct i915_request *rq = NULL;
764 u32 s_mask, s_shift;
765 unsigned int cnt;
766 u32 *buf, val;
767 long ret;
768
769 ret = emit_rpcs_query(obj, ctx, engine, &rq);
770 if (ret)
771 return ret;
772
773 if (spin)
774 igt_spinner_end(spin);
775
776 ret = i915_request_wait(rq, I915_WAIT_LOCKED, MAX_SCHEDULE_TIMEOUT);
777 i915_request_put(rq);
778 if (ret < 0)
779 return ret;
780
781 buf = i915_gem_object_pin_map(obj, I915_MAP_WB);
782 if (IS_ERR(buf)) {
783 ret = PTR_ERR(buf);
784 return ret;
785 }
786
787 if (INTEL_GEN(i915) >= 11) {
788 s_mask = GEN11_RPCS_S_CNT_MASK;
789 s_shift = GEN11_RPCS_S_CNT_SHIFT;
790 } else {
791 s_mask = GEN8_RPCS_S_CNT_MASK;
792 s_shift = GEN8_RPCS_S_CNT_SHIFT;
793 }
794
795 val = *buf;
796 cnt = (val & s_mask) >> s_shift;
797 *rpcs = val;
798
799 i915_gem_object_unpin_map(obj);
800
801 return cnt;
802}
803
804static int
805__check_rpcs(const char *name, u32 rpcs, int slices, unsigned int expected,
806 const char *prefix, const char *suffix)
807{
808 if (slices == expected)
809 return 0;
810
811 if (slices < 0) {
812 pr_err("%s: %s read slice count failed with %d%s\n",
813 name, prefix, slices, suffix);
814 return slices;
815 }
816
817 pr_err("%s: %s slice count %d is not %u%s\n",
818 name, prefix, slices, expected, suffix);
819
820 pr_info("RPCS=0x%x; %u%sx%u%s\n",
821 rpcs, slices,
822 (rpcs & GEN8_RPCS_S_CNT_ENABLE) ? "*" : "",
823 (rpcs & GEN8_RPCS_SS_CNT_MASK) >> GEN8_RPCS_SS_CNT_SHIFT,
824 (rpcs & GEN8_RPCS_SS_CNT_ENABLE) ? "*" : "");
825
826 return -EINVAL;
827}
828
829static int
830__sseu_finish(struct drm_i915_private *i915,
831 const char *name,
832 unsigned int flags,
833 struct i915_gem_context *ctx,
834 struct i915_gem_context *kctx,
835 struct intel_engine_cs *engine,
836 struct drm_i915_gem_object *obj,
837 unsigned int expected,
838 struct igt_spinner *spin)
839{
840 unsigned int slices =
841 hweight32(intel_device_default_sseu(i915).slice_mask);
842 u32 rpcs = 0;
843 int ret = 0;
844
845 if (flags & TEST_RESET) {
846 ret = i915_reset_engine(engine, "sseu");
847 if (ret)
848 goto out;
849 }
850
851 ret = __read_slice_count(i915, ctx, engine, obj,
852 flags & TEST_RESET ? NULL : spin, &rpcs);
853 ret = __check_rpcs(name, rpcs, ret, expected, "Context", "!");
854 if (ret)
855 goto out;
856
857 ret = __read_slice_count(i915, kctx, engine, obj, NULL, &rpcs);
858 ret = __check_rpcs(name, rpcs, ret, slices, "Kernel context", "!");
859
860out:
861 if (spin)
862 igt_spinner_end(spin);
863
864 if ((flags & TEST_IDLE) && ret == 0) {
865 ret = i915_gem_wait_for_idle(i915,
866 I915_WAIT_LOCKED,
867 MAX_SCHEDULE_TIMEOUT);
868 if (ret)
869 return ret;
870
871 ret = __read_slice_count(i915, ctx, engine, obj, NULL, &rpcs);
872 ret = __check_rpcs(name, rpcs, ret, expected,
873 "Context", " after idle!");
874 }
875
876 return ret;
877}
878
879static int
880__sseu_test(struct drm_i915_private *i915,
881 const char *name,
882 unsigned int flags,
883 struct i915_gem_context *ctx,
884 struct intel_engine_cs *engine,
885 struct drm_i915_gem_object *obj,
886 struct intel_sseu sseu)
887{
888 struct igt_spinner *spin = NULL;
889 struct i915_gem_context *kctx;
890 int ret;
891
892 kctx = kernel_context(i915);
893 if (IS_ERR(kctx))
894 return PTR_ERR(kctx);
895
896 ret = __sseu_prepare(i915, name, flags, ctx, engine, &spin);
897 if (ret)
898 goto out_context;
899
900 ret = __i915_gem_context_reconfigure_sseu(ctx, engine, sseu);
901 if (ret)
902 goto out_spin;
903
904 ret = __sseu_finish(i915, name, flags, ctx, kctx, engine, obj,
905 hweight32(sseu.slice_mask), spin);
906
907out_spin:
908 if (spin) {
909 igt_spinner_end(spin);
910 igt_spinner_fini(spin);
911 kfree(spin);
912 }
913
914out_context:
915 kernel_context_close(kctx);
916
917 return ret;
918}
919
920static int
921__igt_ctx_sseu(struct drm_i915_private *i915,
922 const char *name,
923 unsigned int flags)
924{
925 struct intel_sseu default_sseu = intel_device_default_sseu(i915);
926 struct intel_engine_cs *engine = i915->engine[RCS];
927 struct drm_i915_gem_object *obj;
928 struct i915_gem_context *ctx;
929 struct intel_sseu pg_sseu;
930 intel_wakeref_t wakeref;
931 struct drm_file *file;
932 int ret;
933
934 if (INTEL_GEN(i915) < 9)
935 return 0;
936
937 if (!RUNTIME_INFO(i915)->sseu.has_slice_pg)
938 return 0;
939
940 if (hweight32(default_sseu.slice_mask) < 2)
941 return 0;
942
943 /*
944 * Gen11 VME friendly power-gated configuration with half enabled
945 * sub-slices.
946 */
947 pg_sseu = default_sseu;
948 pg_sseu.slice_mask = 1;
949 pg_sseu.subslice_mask =
950 ~(~0 << (hweight32(default_sseu.subslice_mask) / 2));
951
952 pr_info("SSEU subtest '%s', flags=%x, def_slices=%u, pg_slices=%u\n",
953 name, flags, hweight32(default_sseu.slice_mask),
954 hweight32(pg_sseu.slice_mask));
955
956 file = mock_file(i915);
957 if (IS_ERR(file))
958 return PTR_ERR(file);
959
960 if (flags & TEST_RESET)
961 igt_global_reset_lock(i915);
962
963 mutex_lock(&i915->drm.struct_mutex);
964
965 ctx = i915_gem_create_context(i915, file->driver_priv);
966 if (IS_ERR(ctx)) {
967 ret = PTR_ERR(ctx);
968 goto out_unlock;
969 }
970
971 obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
972 if (IS_ERR(obj)) {
973 ret = PTR_ERR(obj);
974 goto out_unlock;
975 }
976
977 wakeref = intel_runtime_pm_get(i915);
978
979 /* First set the default mask. */
980 ret = __sseu_test(i915, name, flags, ctx, engine, obj, default_sseu);
981 if (ret)
982 goto out_fail;
983
984 /* Then set a power-gated configuration. */
985 ret = __sseu_test(i915, name, flags, ctx, engine, obj, pg_sseu);
986 if (ret)
987 goto out_fail;
988
989 /* Back to defaults. */
990 ret = __sseu_test(i915, name, flags, ctx, engine, obj, default_sseu);
991 if (ret)
992 goto out_fail;
993
994 /* One last power-gated configuration for the road. */
995 ret = __sseu_test(i915, name, flags, ctx, engine, obj, pg_sseu);
996 if (ret)
997 goto out_fail;
998
999out_fail:
1000 if (igt_flush_test(i915, I915_WAIT_LOCKED))
1001 ret = -EIO;
1002
1003 i915_gem_object_put(obj);
1004
1005 intel_runtime_pm_put(i915, wakeref);
1006
1007out_unlock:
1008 mutex_unlock(&i915->drm.struct_mutex);
1009
1010 if (flags & TEST_RESET)
1011 igt_global_reset_unlock(i915);
1012
1013 mock_file_free(i915, file);
1014
1015 if (ret)
1016 pr_err("%s: Failed with %d!\n", name, ret);
1017
1018 return ret;
1019}
1020
1021static int igt_ctx_sseu(void *arg)
1022{
1023 struct {
1024 const char *name;
1025 unsigned int flags;
1026 } *phase, phases[] = {
1027 { .name = "basic", .flags = 0 },
1028 { .name = "idle", .flags = TEST_IDLE },
1029 { .name = "busy", .flags = TEST_BUSY },
1030 { .name = "busy-reset", .flags = TEST_BUSY | TEST_RESET },
1031 { .name = "busy-idle", .flags = TEST_BUSY | TEST_IDLE },
1032 { .name = "reset-idle", .flags = TEST_RESET | TEST_IDLE },
1033 };
1034 unsigned int i;
1035 int ret = 0;
1036
1037 for (i = 0, phase = phases; ret == 0 && i < ARRAY_SIZE(phases);
1038 i++, phase++)
1039 ret = __igt_ctx_sseu(arg, phase->name, phase->flags);
1040
1041 return ret;
1042}
1043
1044static int igt_ctx_readonly(void *arg)
1045{
1046 struct drm_i915_private *i915 = arg;
1047 struct drm_i915_gem_object *obj = NULL;
1048 struct i915_gem_context *ctx;
1049 struct i915_hw_ppgtt *ppgtt;
1050 unsigned long ndwords, dw;
1051 struct igt_live_test t;
1052 struct drm_file *file;
1053 I915_RND_STATE(prng);
1054 IGT_TIMEOUT(end_time);
1055 LIST_HEAD(objects);
1056 int err = -ENODEV;
1057
1058 /*
1059 * Create a few read-only objects (with the occasional writable object)
1060 * and try to write into these object checking that the GPU discards
1061 * any write to a read-only object.
1062 */
1063
1064 file = mock_file(i915);
1065 if (IS_ERR(file))
1066 return PTR_ERR(file);
1067
1068 mutex_lock(&i915->drm.struct_mutex);
1069
1070 err = igt_live_test_begin(&t, i915, __func__, "");
1071 if (err)
1072 goto out_unlock;
1073
1074 ctx = i915_gem_create_context(i915, file->driver_priv);
1075 if (IS_ERR(ctx)) {
1076 err = PTR_ERR(ctx);
1077 goto out_unlock;
1078 }
1079
1080 ppgtt = ctx->ppgtt ?: i915->mm.aliasing_ppgtt;
1081 if (!ppgtt || !ppgtt->vm.has_read_only) {
1082 err = 0;
1083 goto out_unlock;
1084 }
1085
1086 ndwords = 0;
1087 dw = 0;
1088 while (!time_after(jiffies, end_time)) {
1089 struct intel_engine_cs *engine;
1090 unsigned int id;
1091
1092 for_each_engine(engine, i915, id) {
1093 intel_wakeref_t wakeref;
1094
1095 if (!intel_engine_can_store_dword(engine))
1096 continue;
1097
1098 if (!obj) {
1099 obj = create_test_object(ctx, file, &objects);
1100 if (IS_ERR(obj)) {
1101 err = PTR_ERR(obj);
1102 goto out_unlock;
1103 }
1104
1105 if (prandom_u32_state(&prng) & 1)
1106 i915_gem_object_set_readonly(obj);
1107 }
1108
1109 err = 0;
1110 with_intel_runtime_pm(i915, wakeref)
1111 err = gpu_fill(obj, ctx, engine, dw);
1112 if (err) {
1113 pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
1114 ndwords, dw, max_dwords(obj),
1115 engine->name, ctx->hw_id,
1116 yesno(!!ctx->ppgtt), err);
1117 goto out_unlock;
1118 }
1119
1120 if (++dw == max_dwords(obj)) {
1121 obj = NULL;
1122 dw = 0;
1123 }
1124 ndwords++;
1125 }
1126 }
1127 pr_info("Submitted %lu dwords (across %u engines)\n",
1128 ndwords, RUNTIME_INFO(i915)->num_rings);
1129
1130 dw = 0;
1131 list_for_each_entry(obj, &objects, st_link) {
1132 unsigned int rem =
1133 min_t(unsigned int, ndwords - dw, max_dwords(obj));
1134 unsigned int num_writes;
1135
1136 num_writes = rem;
1137 if (i915_gem_object_is_readonly(obj))
1138 num_writes = 0;
1139
1140 err = cpu_check(obj, num_writes);
1141 if (err)
1142 break;
1143
1144 dw += rem;
1145 }
1146
1147out_unlock:
1148 if (igt_live_test_end(&t))
1149 err = -EIO;
1150 mutex_unlock(&i915->drm.struct_mutex);
1151
1152 mock_file_free(i915, file);
1153 return err;
1154}
1155
1156static int check_scratch(struct i915_gem_context *ctx, u64 offset)
1157{
1158 struct drm_mm_node *node =
1159 __drm_mm_interval_first(&ctx->ppgtt->vm.mm,
1160 offset, offset + sizeof(u32) - 1);
1161 if (!node || node->start > offset)
1162 return 0;
1163
1164 GEM_BUG_ON(offset >= node->start + node->size);
1165
1166 pr_err("Target offset 0x%08x_%08x overlaps with a node in the mm!\n",
1167 upper_32_bits(offset), lower_32_bits(offset));
1168 return -EINVAL;
1169}
1170
1171static int write_to_scratch(struct i915_gem_context *ctx,
1172 struct intel_engine_cs *engine,
1173 u64 offset, u32 value)
1174{
1175 struct drm_i915_private *i915 = ctx->i915;
1176 struct drm_i915_gem_object *obj;
1177 struct i915_request *rq;
1178 struct i915_vma *vma;
1179 u32 *cmd;
1180 int err;
1181
1182 GEM_BUG_ON(offset < I915_GTT_PAGE_SIZE);
1183
1184 obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
1185 if (IS_ERR(obj))
1186 return PTR_ERR(obj);
1187
1188 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB);
1189 if (IS_ERR(cmd)) {
1190 err = PTR_ERR(cmd);
1191 goto err;
1192 }
1193
1194 *cmd++ = MI_STORE_DWORD_IMM_GEN4;
1195 if (INTEL_GEN(i915) >= 8) {
1196 *cmd++ = lower_32_bits(offset);
1197 *cmd++ = upper_32_bits(offset);
1198 } else {
1199 *cmd++ = 0;
1200 *cmd++ = offset;
1201 }
1202 *cmd++ = value;
1203 *cmd = MI_BATCH_BUFFER_END;
1204 i915_gem_object_unpin_map(obj);
1205
1206 err = i915_gem_object_set_to_gtt_domain(obj, false);
1207 if (err)
1208 goto err;
1209
1210 vma = i915_vma_instance(obj, &ctx->ppgtt->vm, NULL);
1211 if (IS_ERR(vma)) {
1212 err = PTR_ERR(vma);
1213 goto err;
1214 }
1215
1216 err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED);
1217 if (err)
1218 goto err;
1219
1220 err = check_scratch(ctx, offset);
1221 if (err)
1222 goto err_unpin;
1223
1224 rq = i915_request_alloc(engine, ctx);
1225 if (IS_ERR(rq)) {
1226 err = PTR_ERR(rq);
1227 goto err_unpin;
1228 }
1229
1230 err = engine->emit_bb_start(rq, vma->node.start, vma->node.size, 0);
1231 if (err)
1232 goto err_request;
1233
1234 err = i915_vma_move_to_active(vma, rq, 0);
1235 if (err)
1236 goto skip_request;
1237
1238 i915_gem_object_set_active_reference(obj);
1239 i915_vma_unpin(vma);
1240 i915_vma_close(vma);
1241
1242 i915_request_add(rq);
1243
1244 return 0;
1245
1246skip_request:
1247 i915_request_skip(rq, err);
1248err_request:
1249 i915_request_add(rq);
1250err_unpin:
1251 i915_vma_unpin(vma);
1252err:
1253 i915_gem_object_put(obj);
1254 return err;
1255}
1256
1257static int read_from_scratch(struct i915_gem_context *ctx,
1258 struct intel_engine_cs *engine,
1259 u64 offset, u32 *value)
1260{
1261 struct drm_i915_private *i915 = ctx->i915;
1262 struct drm_i915_gem_object *obj;
1263 const u32 RCS_GPR0 = 0x2600; /* not all engines have their own GPR! */
1264 const u32 result = 0x100;
1265 struct i915_request *rq;
1266 struct i915_vma *vma;
1267 u32 *cmd;
1268 int err;
1269
1270 GEM_BUG_ON(offset < I915_GTT_PAGE_SIZE);
1271
1272 obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
1273 if (IS_ERR(obj))
1274 return PTR_ERR(obj);
1275
1276 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB);
1277 if (IS_ERR(cmd)) {
1278 err = PTR_ERR(cmd);
1279 goto err;
1280 }
1281
1282 memset(cmd, POISON_INUSE, PAGE_SIZE);
1283 if (INTEL_GEN(i915) >= 8) {
1284 *cmd++ = MI_LOAD_REGISTER_MEM_GEN8;
1285 *cmd++ = RCS_GPR0;
1286 *cmd++ = lower_32_bits(offset);
1287 *cmd++ = upper_32_bits(offset);
1288 *cmd++ = MI_STORE_REGISTER_MEM_GEN8;
1289 *cmd++ = RCS_GPR0;
1290 *cmd++ = result;
1291 *cmd++ = 0;
1292 } else {
1293 *cmd++ = MI_LOAD_REGISTER_MEM;
1294 *cmd++ = RCS_GPR0;
1295 *cmd++ = offset;
1296 *cmd++ = MI_STORE_REGISTER_MEM;
1297 *cmd++ = RCS_GPR0;
1298 *cmd++ = result;
1299 }
1300 *cmd = MI_BATCH_BUFFER_END;
1301 i915_gem_object_unpin_map(obj);
1302
1303 err = i915_gem_object_set_to_gtt_domain(obj, false);
1304 if (err)
1305 goto err;
1306
1307 vma = i915_vma_instance(obj, &ctx->ppgtt->vm, NULL);
1308 if (IS_ERR(vma)) {
1309 err = PTR_ERR(vma);
1310 goto err;
1311 }
1312
1313 err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED);
1314 if (err)
1315 goto err;
1316
1317 err = check_scratch(ctx, offset);
1318 if (err)
1319 goto err_unpin;
1320
1321 rq = i915_request_alloc(engine, ctx);
1322 if (IS_ERR(rq)) {
1323 err = PTR_ERR(rq);
1324 goto err_unpin;
1325 }
1326
1327 err = engine->emit_bb_start(rq, vma->node.start, vma->node.size, 0);
1328 if (err)
1329 goto err_request;
1330
1331 err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
1332 if (err)
1333 goto skip_request;
1334
1335 i915_vma_unpin(vma);
1336 i915_vma_close(vma);
1337
1338 i915_request_add(rq);
1339
1340 err = i915_gem_object_set_to_cpu_domain(obj, false);
1341 if (err)
1342 goto err;
1343
1344 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB);
1345 if (IS_ERR(cmd)) {
1346 err = PTR_ERR(cmd);
1347 goto err;
1348 }
1349
1350 *value = cmd[result / sizeof(*cmd)];
1351 i915_gem_object_unpin_map(obj);
1352 i915_gem_object_put(obj);
1353
1354 return 0;
1355
1356skip_request:
1357 i915_request_skip(rq, err);
1358err_request:
1359 i915_request_add(rq);
1360err_unpin:
1361 i915_vma_unpin(vma);
1362err:
1363 i915_gem_object_put(obj);
1364 return err;
1365}
1366
1367static int igt_vm_isolation(void *arg)
1368{
1369 struct drm_i915_private *i915 = arg;
1370 struct i915_gem_context *ctx_a, *ctx_b;
1371 struct intel_engine_cs *engine;
1372 intel_wakeref_t wakeref;
1373 struct igt_live_test t;
1374 struct drm_file *file;
1375 I915_RND_STATE(prng);
1376 unsigned long count;
1377 unsigned int id;
1378 u64 vm_total;
1379 int err;
1380
1381 if (INTEL_GEN(i915) < 7)
1382 return 0;
1383
1384 /*
1385 * The simple goal here is that a write into one context is not
1386 * observed in a second (separate page tables and scratch).
1387 */
1388
1389 file = mock_file(i915);
1390 if (IS_ERR(file))
1391 return PTR_ERR(file);
1392
1393 mutex_lock(&i915->drm.struct_mutex);
1394
1395 err = igt_live_test_begin(&t, i915, __func__, "");
1396 if (err)
1397 goto out_unlock;
1398
1399 ctx_a = i915_gem_create_context(i915, file->driver_priv);
1400 if (IS_ERR(ctx_a)) {
1401 err = PTR_ERR(ctx_a);
1402 goto out_unlock;
1403 }
1404
1405 ctx_b = i915_gem_create_context(i915, file->driver_priv);
1406 if (IS_ERR(ctx_b)) {
1407 err = PTR_ERR(ctx_b);
1408 goto out_unlock;
1409 }
1410
1411 /* We can only test vm isolation, if the vm are distinct */
1412 if (ctx_a->ppgtt == ctx_b->ppgtt)
1413 goto out_unlock;
1414
1415 vm_total = ctx_a->ppgtt->vm.total;
1416 GEM_BUG_ON(ctx_b->ppgtt->vm.total != vm_total);
1417 vm_total -= I915_GTT_PAGE_SIZE;
1418
1419 wakeref = intel_runtime_pm_get(i915);
1420
1421 count = 0;
1422 for_each_engine(engine, i915, id) {
1423 IGT_TIMEOUT(end_time);
1424 unsigned long this = 0;
1425
1426 if (!intel_engine_can_store_dword(engine))
1427 continue;
1428
1429 while (!__igt_timeout(end_time, NULL)) {
1430 u32 value = 0xc5c5c5c5;
1431 u64 offset;
1432
1433 div64_u64_rem(i915_prandom_u64_state(&prng),
1434 vm_total, &offset);
1435 offset &= ~sizeof(u32);
1436 offset += I915_GTT_PAGE_SIZE;
1437
1438 err = write_to_scratch(ctx_a, engine,
1439 offset, 0xdeadbeef);
1440 if (err == 0)
1441 err = read_from_scratch(ctx_b, engine,
1442 offset, &value);
1443 if (err)
1444 goto out_rpm;
1445
1446 if (value) {
1447 pr_err("%s: Read %08x from scratch (offset 0x%08x_%08x), after %lu reads!\n",
1448 engine->name, value,
1449 upper_32_bits(offset),
1450 lower_32_bits(offset),
1451 this);
1452 err = -EINVAL;
1453 goto out_rpm;
1454 }
1455
1456 this++;
1457 }
1458 count += this;
1459 }
1460 pr_info("Checked %lu scratch offsets across %d engines\n",
1461 count, RUNTIME_INFO(i915)->num_rings);
1462
1463out_rpm:
1464 intel_runtime_pm_put(i915, wakeref);
1465out_unlock:
1466 if (igt_live_test_end(&t))
1467 err = -EIO;
1468 mutex_unlock(&i915->drm.struct_mutex);
1469
1470 mock_file_free(i915, file);
1471 return err;
1472}
1473
1474static __maybe_unused const char *
1475__engine_name(struct drm_i915_private *i915, unsigned int engines)
1476{
1477 struct intel_engine_cs *engine;
1478 unsigned int tmp;
1479
1480 if (engines == ALL_ENGINES)
1481 return "all";
1482
1483 for_each_engine_masked(engine, i915, engines, tmp)
1484 return engine->name;
1485
1486 return "none";
1487}
1488
1489static int __igt_switch_to_kernel_context(struct drm_i915_private *i915,
1490 struct i915_gem_context *ctx,
1491 unsigned int engines)
1492{
1493 struct intel_engine_cs *engine;
1494 unsigned int tmp;
1495 int err;
1496
1497 GEM_TRACE("Testing %s\n", __engine_name(i915, engines));
1498 for_each_engine_masked(engine, i915, engines, tmp) {
1499 struct i915_request *rq;
1500
1501 rq = i915_request_alloc(engine, ctx);
1502 if (IS_ERR(rq))
1503 return PTR_ERR(rq);
1504
1505 i915_request_add(rq);
1506 }
1507
1508 err = i915_gem_switch_to_kernel_context(i915);
1509 if (err)
1510 return err;
1511
1512 for_each_engine_masked(engine, i915, engines, tmp) {
1513 if (!engine_has_kernel_context_barrier(engine)) {
1514 pr_err("kernel context not last on engine %s!\n",
1515 engine->name);
1516 return -EINVAL;
1517 }
1518 }
1519
1520 err = i915_gem_wait_for_idle(i915,
1521 I915_WAIT_LOCKED,
1522 MAX_SCHEDULE_TIMEOUT);
1523 if (err)
1524 return err;
1525
1526 GEM_BUG_ON(i915->gt.active_requests);
1527 for_each_engine_masked(engine, i915, engines, tmp) {
1528 if (engine->last_retired_context->gem_context != i915->kernel_context) {
1529 pr_err("engine %s not idling in kernel context!\n",
1530 engine->name);
1531 return -EINVAL;
1532 }
1533 }
1534
1535 err = i915_gem_switch_to_kernel_context(i915);
1536 if (err)
1537 return err;
1538
1539 if (i915->gt.active_requests) {
1540 pr_err("switch-to-kernel-context emitted %d requests even though it should already be idling in the kernel context\n",
1541 i915->gt.active_requests);
1542 return -EINVAL;
1543 }
1544
1545 for_each_engine_masked(engine, i915, engines, tmp) {
1546 if (!intel_engine_has_kernel_context(engine)) {
1547 pr_err("kernel context not last on engine %s!\n",
1548 engine->name);
1549 return -EINVAL;
1550 }
1551 }
1552
1553 return 0;
1554}
1555
1556static int igt_switch_to_kernel_context(void *arg)
1557{
1558 struct drm_i915_private *i915 = arg;
1559 struct intel_engine_cs *engine;
1560 struct i915_gem_context *ctx;
1561 enum intel_engine_id id;
1562 intel_wakeref_t wakeref;
1563 int err;
1564
1565 /*
1566 * A core premise of switching to the kernel context is that
1567 * if an engine is already idling in the kernel context, we
1568 * do not emit another request and wake it up. The other being
1569 * that we do indeed end up idling in the kernel context.
1570 */
1571
1572 mutex_lock(&i915->drm.struct_mutex);
1573 wakeref = intel_runtime_pm_get(i915);
1574
1575 ctx = kernel_context(i915);
1576 if (IS_ERR(ctx)) {
1577 mutex_unlock(&i915->drm.struct_mutex);
1578 return PTR_ERR(ctx);
1579 }
1580
1581 /* First check idling each individual engine */
1582 for_each_engine(engine, i915, id) {
1583 err = __igt_switch_to_kernel_context(i915, ctx, BIT(id));
1584 if (err)
1585 goto out_unlock;
1586 }
1587
1588 /* Now en masse */
1589 err = __igt_switch_to_kernel_context(i915, ctx, ALL_ENGINES);
1590 if (err)
1591 goto out_unlock;
1592
1593out_unlock:
1594 GEM_TRACE_DUMP_ON(err);
1595 if (igt_flush_test(i915, I915_WAIT_LOCKED))
1596 err = -EIO;
1597
1598 intel_runtime_pm_put(i915, wakeref);
1599 mutex_unlock(&i915->drm.struct_mutex);
1600
1601 kernel_context_close(ctx);
1602 return err;
1603}
1604
1605int i915_gem_context_mock_selftests(void)
1606{
1607 static const struct i915_subtest tests[] = {
1608 SUBTEST(igt_switch_to_kernel_context),
1609 };
1610 struct drm_i915_private *i915;
1611 int err;
1612
1613 i915 = mock_gem_device();
1614 if (!i915)
1615 return -ENOMEM;
1616
1617 err = i915_subtests(tests, i915);
1618
1619 drm_dev_put(&i915->drm);
1620 return err;
1621}
1622
1623int i915_gem_context_live_selftests(struct drm_i915_private *dev_priv)
1624{
1625 static const struct i915_subtest tests[] = {
1626 SUBTEST(igt_switch_to_kernel_context),
1627 SUBTEST(live_nop_switch),
1628 SUBTEST(igt_ctx_exec),
1629 SUBTEST(igt_ctx_readonly),
1630 SUBTEST(igt_ctx_sseu),
1631 SUBTEST(igt_vm_isolation),
1632 };
1633
1634 if (i915_terminally_wedged(&dev_priv->gpu_error))
1635 return 0;
1636
1637 return i915_subtests(tests, dev_priv);
1638}