2 * Copyright © 2017 Intel Corporation
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:
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
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
25 #include <linux/prime_numbers.h>
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"
36 #include "mock_gem_device.h"
37 #include "huge_gem_object.h"
39 #define DW_PER_PAGE (PAGE_SIZE / sizeof(u32))
41 static int live_nop_switch(void *arg
)
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
;
55 * Create as many contexts as we can feasibly get away with
56 * and check we can switch between them rapidly.
58 * Serves as very simple stress test for submission and HW switching
62 if (!DRIVER_CAPS(i915
)->has_logical_contexts
)
65 file
= mock_file(i915
);
69 mutex_lock(&i915
->drm
.struct_mutex
);
70 wakeref
= intel_runtime_pm_get(i915
);
72 ctx
= kcalloc(nctx
, sizeof(*ctx
), GFP_KERNEL
);
78 for (n
= 0; n
< nctx
; n
++) {
79 ctx
[n
] = i915_gem_create_context(i915
, file
->driver_priv
);
81 err
= PTR_ERR(ctx
[n
]);
86 for_each_engine(engine
, i915
, id
) {
87 struct i915_request
*rq
;
88 unsigned long end_time
, prime
;
89 ktime_t times
[2] = {};
91 times
[0] = ktime_get_raw();
92 for (n
= 0; n
< nctx
; n
++) {
93 rq
= i915_request_alloc(engine
, ctx
[n
]);
100 if (i915_request_wait(rq
,
103 pr_err("Failed to populated %d contexts\n", nctx
);
104 i915_gem_set_wedged(i915
);
109 times
[1] = ktime_get_raw();
111 pr_info("Populated %d contexts on %s in %lluns\n",
112 nctx
, engine
->name
, ktime_to_ns(times
[1] - times
[0]));
114 err
= igt_live_test_begin(&t
, i915
, __func__
, engine
->name
);
118 end_time
= jiffies
+ i915_selftest
.timeout_jiffies
;
119 for_each_prime_number_from(prime
, 2, 8192) {
120 times
[1] = ktime_get_raw();
122 for (n
= 0; n
< prime
; n
++) {
123 rq
= i915_request_alloc(engine
, ctx
[n
% nctx
]);
130 * This space is left intentionally blank.
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
143 i915_request_add(rq
);
145 if (i915_request_wait(rq
,
148 pr_err("Switching between %ld contexts timed out\n",
150 i915_gem_set_wedged(i915
);
154 times
[1] = ktime_sub(ktime_get_raw(), times
[1]);
158 if (__igt_timeout(end_time
, NULL
))
162 err
= igt_live_test_end(&t
);
166 pr_info("Switch latencies on %s: 1 = %lluns, %lu = %lluns\n",
168 ktime_to_ns(times
[0]),
169 prime
- 1, div64_u64(ktime_to_ns(times
[1]), prime
- 1));
173 intel_runtime_pm_put(i915
, wakeref
);
174 mutex_unlock(&i915
->drm
.struct_mutex
);
175 mock_file_free(i915
, file
);
179 static struct i915_vma
*
180 gpu_fill_dw(struct i915_vma
*vma
, u64 offset
, unsigned long count
, u32 value
)
182 struct drm_i915_gem_object
*obj
;
183 const int gen
= INTEL_GEN(vma
->vm
->i915
);
184 unsigned long n
, size
;
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
);
192 return ERR_CAST(obj
);
194 cmd
= i915_gem_object_pin_map(obj
, I915_MAP_WB
);
200 GEM_BUG_ON(offset
+ (count
- 1) * PAGE_SIZE
> vma
->node
.size
);
201 offset
+= vma
->node
.start
;
203 for (n
= 0; n
< count
; n
++) {
205 *cmd
++ = MI_STORE_DWORD_IMM_GEN4
;
206 *cmd
++ = lower_32_bits(offset
);
207 *cmd
++ = upper_32_bits(offset
);
209 } else if (gen
>= 4) {
210 *cmd
++ = MI_STORE_DWORD_IMM_GEN4
|
211 (gen
< 6 ? MI_USE_GGTT
: 0);
216 *cmd
++ = MI_STORE_DWORD_IMM
| MI_MEM_VIRTUAL
;
222 *cmd
= MI_BATCH_BUFFER_END
;
223 i915_gem_object_unpin_map(obj
);
225 err
= i915_gem_object_set_to_gtt_domain(obj
, false);
229 vma
= i915_vma_instance(obj
, vma
->vm
, NULL
);
235 err
= i915_vma_pin(vma
, 0, 0, PIN_USER
);
242 i915_gem_object_put(obj
);
246 static unsigned long real_page_count(struct drm_i915_gem_object
*obj
)
248 return huge_gem_object_phys_size(obj
) >> PAGE_SHIFT
;
251 static unsigned long fake_page_count(struct drm_i915_gem_object
*obj
)
253 return huge_gem_object_dma_size(obj
) >> PAGE_SHIFT
;
256 static int gpu_fill(struct drm_i915_gem_object
*obj
,
257 struct i915_gem_context
*ctx
,
258 struct intel_engine_cs
*engine
,
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
;
270 GEM_BUG_ON(obj
->base
.size
> vm
->total
);
271 GEM_BUG_ON(!intel_engine_can_store_dword(engine
));
273 vma
= i915_vma_instance(obj
, vm
, NULL
);
277 err
= i915_gem_object_set_to_gtt_domain(obj
, false);
281 err
= i915_vma_pin(vma
, 0, 0, PIN_HIGH
| PIN_USER
);
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
292 batch
= gpu_fill_dw(vma
,
293 (dw
* real_page_count(obj
)) << PAGE_SHIFT
|
295 real_page_count(obj
),
298 err
= PTR_ERR(batch
);
302 rq
= i915_request_alloc(engine
, ctx
);
309 if (INTEL_GEN(vm
->i915
) <= 5)
310 flags
|= I915_DISPATCH_SECURE
;
312 err
= engine
->emit_bb_start(rq
,
313 batch
->node
.start
, batch
->node
.size
,
318 err
= i915_vma_move_to_active(batch
, rq
, 0);
322 err
= i915_vma_move_to_active(vma
, rq
, EXEC_OBJECT_WRITE
);
326 i915_gem_object_set_active_reference(batch
->obj
);
327 i915_vma_unpin(batch
);
328 i915_vma_close(batch
);
332 i915_request_add(rq
);
337 i915_request_skip(rq
, err
);
339 i915_request_add(rq
);
341 i915_vma_unpin(batch
);
348 static int cpu_fill(struct drm_i915_gem_object
*obj
, u32 value
)
350 const bool has_llc
= HAS_LLC(to_i915(obj
->base
.dev
));
351 unsigned int n
, m
, need_flush
;
354 err
= i915_gem_obj_prepare_shmem_write(obj
, &need_flush
);
358 for (n
= 0; n
< real_page_count(obj
); n
++) {
361 map
= kmap_atomic(i915_gem_object_get_page(obj
, n
));
362 for (m
= 0; m
< DW_PER_PAGE
; m
++)
365 drm_clflush_virt_range(map
, PAGE_SIZE
);
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;
375 static int cpu_check(struct drm_i915_gem_object
*obj
, unsigned int max
)
377 unsigned int n
, m
, needs_flush
;
380 err
= i915_gem_obj_prepare_shmem_read(obj
, &needs_flush
);
384 for (n
= 0; n
< real_page_count(obj
); n
++) {
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
);
391 for (m
= 0; m
< max
; m
++) {
393 pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",
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
);
415 i915_gem_obj_finish_shmem_access(obj
);
419 static int file_add_object(struct drm_file
*file
,
420 struct drm_i915_gem_object
*obj
)
424 GEM_BUG_ON(obj
->base
.handle_count
);
426 /* tie the object to the drm_file for easy reaping */
427 err
= idr_alloc(&file
->object_idr
, &obj
->base
, 1, 0, GFP_KERNEL
);
431 i915_gem_object_get(obj
);
432 obj
->base
.handle_count
++;
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
)
441 struct drm_i915_gem_object
*obj
;
442 struct i915_address_space
*vm
=
443 ctx
->ppgtt
? &ctx
->ppgtt
->vm
: &ctx
->i915
->ggtt
.vm
;
447 size
= min(vm
->total
/ 2, 1024ull * DW_PER_PAGE
* PAGE_SIZE
);
448 size
= round_down(size
, DW_PER_PAGE
* PAGE_SIZE
);
450 obj
= huge_gem_object(ctx
->i915
, DW_PER_PAGE
* PAGE_SIZE
, size
);
454 err
= file_add_object(file
, obj
);
455 i915_gem_object_put(obj
);
459 err
= cpu_fill(obj
, STACK_MAGIC
);
461 pr_err("Failed to fill object with cpu, err=%d\n",
466 list_add_tail(&obj
->st_link
, objects
);
470 static unsigned long max_dwords(struct drm_i915_gem_object
*obj
)
472 unsigned long npages
= fake_page_count(obj
);
474 GEM_BUG_ON(!IS_ALIGNED(npages
, DW_PER_PAGE
));
475 return npages
/ DW_PER_PAGE
;
478 static int igt_ctx_exec(void *arg
)
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
);
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.
495 if (!DRIVER_CAPS(i915
)->has_logical_contexts
)
498 file
= mock_file(i915
);
500 return PTR_ERR(file
);
502 mutex_lock(&i915
->drm
.struct_mutex
);
504 err
= igt_live_test_begin(&t
, i915
, __func__
, "");
511 while (!time_after(jiffies
, end_time
)) {
512 struct intel_engine_cs
*engine
;
513 struct i915_gem_context
*ctx
;
516 ctx
= i915_gem_create_context(i915
, file
->driver_priv
);
522 for_each_engine(engine
, i915
, id
) {
523 intel_wakeref_t wakeref
;
525 if (!engine
->context_size
)
526 continue; /* No logical context support in HW */
528 if (!intel_engine_can_store_dword(engine
))
532 obj
= create_test_object(ctx
, file
, &objects
);
540 with_intel_runtime_pm(i915
, wakeref
)
541 err
= gpu_fill(obj
, ctx
, engine
, dw
);
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
);
550 if (++dw
== max_dwords(obj
)) {
558 pr_info("Submitted %lu contexts (across %u engines), filling %lu dwords\n",
559 ncontexts
, RUNTIME_INFO(i915
)->num_rings
, ndwords
);
562 list_for_each_entry(obj
, &objects
, st_link
) {
564 min_t(unsigned int, ndwords
- dw
, max_dwords(obj
));
566 err
= cpu_check(obj
, rem
);
574 if (igt_live_test_end(&t
))
576 mutex_unlock(&i915
->drm
.struct_mutex
);
578 mock_file_free(i915
, file
);
582 static struct i915_vma
*rpcs_query_batch(struct i915_vma
*vma
)
584 struct drm_i915_gem_object
*obj
;
588 if (INTEL_GEN(vma
->vm
->i915
) < 8)
589 return ERR_PTR(-EINVAL
);
591 obj
= i915_gem_object_create_internal(vma
->vm
->i915
, PAGE_SIZE
);
593 return ERR_CAST(obj
);
595 cmd
= i915_gem_object_pin_map(obj
, I915_MAP_WB
);
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
;
607 i915_gem_object_unpin_map(obj
);
609 err
= i915_gem_object_set_to_gtt_domain(obj
, false);
613 vma
= i915_vma_instance(obj
, vma
->vm
, NULL
);
619 err
= i915_vma_pin(vma
, 0, 0, PIN_USER
);
626 i915_gem_object_put(obj
);
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
)
636 struct i915_request
*rq
;
637 struct i915_vma
*batch
;
638 struct i915_vma
*vma
;
641 GEM_BUG_ON(!intel_engine_can_store_dword(engine
));
643 vma
= i915_vma_instance(obj
, &ctx
->ppgtt
->vm
, NULL
);
647 err
= i915_gem_object_set_to_gtt_domain(obj
, false);
651 err
= i915_vma_pin(vma
, 0, 0, PIN_USER
);
655 batch
= rpcs_query_batch(vma
);
657 err
= PTR_ERR(batch
);
661 rq
= i915_request_alloc(engine
, ctx
);
667 err
= engine
->emit_bb_start(rq
, batch
->node
.start
, batch
->node
.size
, 0);
671 err
= i915_vma_move_to_active(batch
, rq
, 0);
675 err
= i915_vma_move_to_active(vma
, rq
, EXEC_OBJECT_WRITE
);
679 i915_gem_object_set_active_reference(batch
->obj
);
680 i915_vma_unpin(batch
);
681 i915_vma_close(batch
);
685 *rq_out
= i915_request_get(rq
);
687 i915_request_add(rq
);
692 i915_request_skip(rq
, err
);
694 i915_request_add(rq
);
696 i915_vma_unpin(batch
);
703 #define TEST_IDLE BIT(0)
704 #define TEST_BUSY BIT(1)
705 #define TEST_RESET BIT(2)
708 __sseu_prepare(struct drm_i915_private
*i915
,
711 struct i915_gem_context
*ctx
,
712 struct intel_engine_cs
*engine
,
713 struct igt_spinner
**spin_out
)
717 if (flags
& (TEST_BUSY
| TEST_RESET
)) {
718 struct igt_spinner
*spin
;
719 struct i915_request
*rq
;
721 spin
= kzalloc(sizeof(*spin
), GFP_KERNEL
);
727 ret
= igt_spinner_init(spin
, i915
);
731 rq
= igt_spinner_create_request(spin
, ctx
, engine
, MI_NOOP
);
734 igt_spinner_fini(spin
);
739 i915_request_add(rq
);
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
);
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
,
765 struct i915_request
*rq
= NULL
;
771 ret
= emit_rpcs_query(obj
, ctx
, engine
, &rq
);
776 igt_spinner_end(spin
);
778 ret
= i915_request_wait(rq
, I915_WAIT_LOCKED
, MAX_SCHEDULE_TIMEOUT
);
779 i915_request_put(rq
);
783 buf
= i915_gem_object_pin_map(obj
, I915_MAP_WB
);
789 if (INTEL_GEN(i915
) >= 11) {
790 s_mask
= GEN11_RPCS_S_CNT_MASK
;
791 s_shift
= GEN11_RPCS_S_CNT_SHIFT
;
793 s_mask
= GEN8_RPCS_S_CNT_MASK
;
794 s_shift
= GEN8_RPCS_S_CNT_SHIFT
;
798 cnt
= (val
& s_mask
) >> s_shift
;
801 i915_gem_object_unpin_map(obj
);
807 __check_rpcs(const char *name
, u32 rpcs
, int slices
, unsigned int expected
,
808 const char *prefix
, const char *suffix
)
810 if (slices
== expected
)
814 pr_err("%s: %s read slice count failed with %d%s\n",
815 name
, prefix
, slices
, suffix
);
819 pr_err("%s: %s slice count %d is not %u%s\n",
820 name
, prefix
, slices
, expected
, suffix
);
822 pr_info("RPCS=0x%x; %u%sx%u%s\n",
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
) ? "*" : "");
832 __sseu_finish(struct drm_i915_private
*i915
,
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
)
842 unsigned int slices
=
843 hweight32(intel_device_default_sseu(i915
).slice_mask
);
847 if (flags
& TEST_RESET
) {
848 ret
= i915_reset_engine(engine
, "sseu");
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", "!");
859 ret
= __read_slice_count(i915
, kctx
, engine
, obj
, NULL
, &rpcs
);
860 ret
= __check_rpcs(name
, rpcs
, ret
, slices
, "Kernel context", "!");
864 igt_spinner_end(spin
);
866 if ((flags
& TEST_IDLE
) && ret
== 0) {
867 ret
= i915_gem_wait_for_idle(i915
,
869 MAX_SCHEDULE_TIMEOUT
);
873 ret
= __read_slice_count(i915
, ctx
, engine
, obj
, NULL
, &rpcs
);
874 ret
= __check_rpcs(name
, rpcs
, ret
, expected
,
875 "Context", " after idle!");
882 __sseu_test(struct drm_i915_private
*i915
,
885 struct i915_gem_context
*ctx
,
886 struct intel_engine_cs
*engine
,
887 struct drm_i915_gem_object
*obj
,
888 struct intel_sseu sseu
)
890 struct igt_spinner
*spin
= NULL
;
891 struct i915_gem_context
*kctx
;
894 kctx
= kernel_context(i915
);
896 return PTR_ERR(kctx
);
898 ret
= __sseu_prepare(i915
, name
, flags
, ctx
, engine
, &spin
);
902 ret
= __i915_gem_context_reconfigure_sseu(ctx
, engine
, sseu
);
906 ret
= __sseu_finish(i915
, name
, flags
, ctx
, kctx
, engine
, obj
,
907 hweight32(sseu
.slice_mask
), spin
);
911 igt_spinner_end(spin
);
912 igt_spinner_fini(spin
);
916 kernel_context_close(kctx
);
922 __igt_ctx_sseu(struct drm_i915_private
*i915
,
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
;
935 if (INTEL_GEN(i915
) < 9)
938 if (!RUNTIME_INFO(i915
)->sseu
.has_slice_pg
)
941 if (hweight32(default_sseu
.slice_mask
) < 2)
945 * Gen11 VME friendly power-gated configuration with half enabled
948 pg_sseu
= default_sseu
;
949 pg_sseu
.slice_mask
= 1;
950 pg_sseu
.subslice_mask
=
951 ~(~0 << (hweight32(default_sseu
.subslice_mask
) / 2));
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
));
957 file
= mock_file(i915
);
959 return PTR_ERR(file
);
961 if (flags
& TEST_RESET
)
962 igt_global_reset_lock(i915
);
964 mutex_lock(&i915
->drm
.struct_mutex
);
966 ctx
= i915_gem_create_context(i915
, file
->driver_priv
);
972 obj
= i915_gem_object_create_internal(i915
, PAGE_SIZE
);
978 wakeref
= intel_runtime_pm_get(i915
);
980 /* First set the default mask. */
981 ret
= __sseu_test(i915
, name
, flags
, ctx
, engine
, obj
, default_sseu
);
985 /* Then set a power-gated configuration. */
986 ret
= __sseu_test(i915
, name
, flags
, ctx
, engine
, obj
, pg_sseu
);
990 /* Back to defaults. */
991 ret
= __sseu_test(i915
, name
, flags
, ctx
, engine
, obj
, default_sseu
);
995 /* One last power-gated configuration for the road. */
996 ret
= __sseu_test(i915
, name
, flags
, ctx
, engine
, obj
, pg_sseu
);
1001 if (igt_flush_test(i915
, I915_WAIT_LOCKED
))
1004 i915_gem_object_put(obj
);
1006 intel_runtime_pm_put(i915
, wakeref
);
1009 mutex_unlock(&i915
->drm
.struct_mutex
);
1011 if (flags
& TEST_RESET
)
1012 igt_global_reset_unlock(i915
);
1014 mock_file_free(i915
, file
);
1017 pr_err("%s: Failed with %d!\n", name
, ret
);
1022 static int igt_ctx_sseu(void *arg
)
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
},
1038 for (i
= 0, phase
= phases
; ret
== 0 && i
< ARRAY_SIZE(phases
);
1040 ret
= __igt_ctx_sseu(arg
, phase
->name
, phase
->flags
);
1045 static int igt_ctx_readonly(void *arg
)
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
);
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.
1065 file
= mock_file(i915
);
1067 return PTR_ERR(file
);
1069 mutex_lock(&i915
->drm
.struct_mutex
);
1071 err
= igt_live_test_begin(&t
, i915
, __func__
, "");
1075 ctx
= i915_gem_create_context(i915
, file
->driver_priv
);
1081 ppgtt
= ctx
->ppgtt
?: i915
->mm
.aliasing_ppgtt
;
1082 if (!ppgtt
|| !ppgtt
->vm
.has_read_only
) {
1089 while (!time_after(jiffies
, end_time
)) {
1090 struct intel_engine_cs
*engine
;
1093 for_each_engine(engine
, i915
, id
) {
1094 intel_wakeref_t wakeref
;
1096 if (!intel_engine_can_store_dword(engine
))
1100 obj
= create_test_object(ctx
, file
, &objects
);
1106 if (prandom_u32_state(&prng
) & 1)
1107 i915_gem_object_set_readonly(obj
);
1111 with_intel_runtime_pm(i915
, wakeref
)
1112 err
= gpu_fill(obj
, ctx
, engine
, dw
);
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
);
1121 if (++dw
== max_dwords(obj
)) {
1128 pr_info("Submitted %lu dwords (across %u engines)\n",
1129 ndwords
, RUNTIME_INFO(i915
)->num_rings
);
1132 list_for_each_entry(obj
, &objects
, st_link
) {
1134 min_t(unsigned int, ndwords
- dw
, max_dwords(obj
));
1135 unsigned int num_writes
;
1138 if (i915_gem_object_is_readonly(obj
))
1141 err
= cpu_check(obj
, num_writes
);
1149 if (igt_live_test_end(&t
))
1151 mutex_unlock(&i915
->drm
.struct_mutex
);
1153 mock_file_free(i915
, file
);
1157 static int check_scratch(struct i915_gem_context
*ctx
, u64 offset
)
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
)
1165 GEM_BUG_ON(offset
>= node
->start
+ node
->size
);
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
));
1172 static int write_to_scratch(struct i915_gem_context
*ctx
,
1173 struct intel_engine_cs
*engine
,
1174 u64 offset
, u32 value
)
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
;
1183 GEM_BUG_ON(offset
< I915_GTT_PAGE_SIZE
);
1185 obj
= i915_gem_object_create_internal(i915
, PAGE_SIZE
);
1187 return PTR_ERR(obj
);
1189 cmd
= i915_gem_object_pin_map(obj
, I915_MAP_WB
);
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
);
1204 *cmd
= MI_BATCH_BUFFER_END
;
1205 i915_gem_object_unpin_map(obj
);
1207 err
= i915_gem_object_set_to_gtt_domain(obj
, false);
1211 vma
= i915_vma_instance(obj
, &ctx
->ppgtt
->vm
, NULL
);
1217 err
= i915_vma_pin(vma
, 0, 0, PIN_USER
| PIN_OFFSET_FIXED
);
1221 err
= check_scratch(ctx
, offset
);
1225 rq
= i915_request_alloc(engine
, ctx
);
1231 err
= engine
->emit_bb_start(rq
, vma
->node
.start
, vma
->node
.size
, 0);
1235 err
= i915_vma_move_to_active(vma
, rq
, 0);
1239 i915_gem_object_set_active_reference(obj
);
1240 i915_vma_unpin(vma
);
1241 i915_vma_close(vma
);
1243 i915_request_add(rq
);
1248 i915_request_skip(rq
, err
);
1250 i915_request_add(rq
);
1252 i915_vma_unpin(vma
);
1254 i915_gem_object_put(obj
);
1258 static int read_from_scratch(struct i915_gem_context
*ctx
,
1259 struct intel_engine_cs
*engine
,
1260 u64 offset
, u32
*value
)
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
;
1271 GEM_BUG_ON(offset
< I915_GTT_PAGE_SIZE
);
1273 obj
= i915_gem_object_create_internal(i915
, PAGE_SIZE
);
1275 return PTR_ERR(obj
);
1277 cmd
= i915_gem_object_pin_map(obj
, I915_MAP_WB
);
1283 memset(cmd
, POISON_INUSE
, PAGE_SIZE
);
1284 if (INTEL_GEN(i915
) >= 8) {
1285 *cmd
++ = MI_LOAD_REGISTER_MEM_GEN8
;
1287 *cmd
++ = lower_32_bits(offset
);
1288 *cmd
++ = upper_32_bits(offset
);
1289 *cmd
++ = MI_STORE_REGISTER_MEM_GEN8
;
1294 *cmd
++ = MI_LOAD_REGISTER_MEM
;
1297 *cmd
++ = MI_STORE_REGISTER_MEM
;
1301 *cmd
= MI_BATCH_BUFFER_END
;
1302 i915_gem_object_unpin_map(obj
);
1304 err
= i915_gem_object_set_to_gtt_domain(obj
, false);
1308 vma
= i915_vma_instance(obj
, &ctx
->ppgtt
->vm
, NULL
);
1314 err
= i915_vma_pin(vma
, 0, 0, PIN_USER
| PIN_OFFSET_FIXED
);
1318 err
= check_scratch(ctx
, offset
);
1322 rq
= i915_request_alloc(engine
, ctx
);
1328 err
= engine
->emit_bb_start(rq
, vma
->node
.start
, vma
->node
.size
, 0);
1332 err
= i915_vma_move_to_active(vma
, rq
, EXEC_OBJECT_WRITE
);
1336 i915_vma_unpin(vma
);
1337 i915_vma_close(vma
);
1339 i915_request_add(rq
);
1341 err
= i915_gem_object_set_to_cpu_domain(obj
, false);
1345 cmd
= i915_gem_object_pin_map(obj
, I915_MAP_WB
);
1351 *value
= cmd
[result
/ sizeof(*cmd
)];
1352 i915_gem_object_unpin_map(obj
);
1353 i915_gem_object_put(obj
);
1358 i915_request_skip(rq
, err
);
1360 i915_request_add(rq
);
1362 i915_vma_unpin(vma
);
1364 i915_gem_object_put(obj
);
1368 static int igt_vm_isolation(void *arg
)
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
;
1382 if (INTEL_GEN(i915
) < 7)
1386 * The simple goal here is that a write into one context is not
1387 * observed in a second (separate page tables and scratch).
1390 file
= mock_file(i915
);
1392 return PTR_ERR(file
);
1394 mutex_lock(&i915
->drm
.struct_mutex
);
1396 err
= igt_live_test_begin(&t
, i915
, __func__
, "");
1400 ctx_a
= i915_gem_create_context(i915
, file
->driver_priv
);
1401 if (IS_ERR(ctx_a
)) {
1402 err
= PTR_ERR(ctx_a
);
1406 ctx_b
= i915_gem_create_context(i915
, file
->driver_priv
);
1407 if (IS_ERR(ctx_b
)) {
1408 err
= PTR_ERR(ctx_b
);
1412 /* We can only test vm isolation, if the vm are distinct */
1413 if (ctx_a
->ppgtt
== ctx_b
->ppgtt
)
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
;
1420 wakeref
= intel_runtime_pm_get(i915
);
1423 for_each_engine(engine
, i915
, id
) {
1424 IGT_TIMEOUT(end_time
);
1425 unsigned long this = 0;
1427 if (!intel_engine_can_store_dword(engine
))
1430 while (!__igt_timeout(end_time
, NULL
)) {
1431 u32 value
= 0xc5c5c5c5;
1434 div64_u64_rem(i915_prandom_u64_state(&prng
),
1436 offset
&= ~sizeof(u32
);
1437 offset
+= I915_GTT_PAGE_SIZE
;
1439 err
= write_to_scratch(ctx_a
, engine
,
1440 offset
, 0xdeadbeef);
1442 err
= read_from_scratch(ctx_b
, engine
,
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
),
1461 pr_info("Checked %lu scratch offsets across %d engines\n",
1462 count
, RUNTIME_INFO(i915
)->num_rings
);
1465 intel_runtime_pm_put(i915
, wakeref
);
1467 if (igt_live_test_end(&t
))
1469 mutex_unlock(&i915
->drm
.struct_mutex
);
1471 mock_file_free(i915
, file
);
1475 static __maybe_unused
const char *
1476 __engine_name(struct drm_i915_private
*i915
, unsigned int engines
)
1478 struct intel_engine_cs
*engine
;
1481 if (engines
== ALL_ENGINES
)
1484 for_each_engine_masked(engine
, i915
, engines
, tmp
)
1485 return engine
->name
;
1490 static int __igt_switch_to_kernel_context(struct drm_i915_private
*i915
,
1491 struct i915_gem_context
*ctx
,
1492 unsigned int engines
)
1494 struct intel_engine_cs
*engine
;
1498 GEM_TRACE("Testing %s\n", __engine_name(i915
, engines
));
1499 for_each_engine_masked(engine
, i915
, engines
, tmp
) {
1500 struct i915_request
*rq
;
1502 rq
= i915_request_alloc(engine
, ctx
);
1506 i915_request_add(rq
);
1509 err
= i915_gem_switch_to_kernel_context(i915
);
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",
1521 err
= i915_gem_wait_for_idle(i915
,
1523 MAX_SCHEDULE_TIMEOUT
);
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",
1536 err
= i915_gem_switch_to_kernel_context(i915
);
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
);
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",
1557 static int igt_switch_to_kernel_context(void *arg
)
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
;
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.
1573 mutex_lock(&i915
->drm
.struct_mutex
);
1574 wakeref
= intel_runtime_pm_get(i915
);
1576 ctx
= kernel_context(i915
);
1578 mutex_unlock(&i915
->drm
.struct_mutex
);
1579 return PTR_ERR(ctx
);
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
));
1590 err
= __igt_switch_to_kernel_context(i915
, ctx
, ALL_ENGINES
);
1595 GEM_TRACE_DUMP_ON(err
);
1596 if (igt_flush_test(i915
, I915_WAIT_LOCKED
))
1599 intel_runtime_pm_put(i915
, wakeref
);
1600 mutex_unlock(&i915
->drm
.struct_mutex
);
1602 kernel_context_close(ctx
);
1606 int i915_gem_context_mock_selftests(void)
1608 static const struct i915_subtest tests
[] = {
1609 SUBTEST(igt_switch_to_kernel_context
),
1611 struct drm_i915_private
*i915
;
1614 i915
= mock_gem_device();
1618 err
= i915_subtests(tests
, i915
);
1620 drm_dev_put(&i915
->drm
);
1624 int i915_gem_context_live_selftests(struct drm_i915_private
*dev_priv
)
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
),
1635 if (i915_terminally_wedged(&dev_priv
->gpu_error
))
1638 return i915_subtests(tests
, dev_priv
);