1 // SPDX-License-Identifier: MIT
3 * Copyright © 2019 Intel Corporation
6 #include <linux/prime_numbers.h>
8 #include "../i915_selftest.h"
11 #include "mock_gem_device.h"
12 #include "mock_region.h"
14 #include "gem/i915_gem_context.h"
15 #include "gem/i915_gem_lmem.h"
16 #include "gem/i915_gem_region.h"
17 #include "gem/i915_gem_object_blt.h"
18 #include "gem/selftests/igt_gem_utils.h"
19 #include "gem/selftests/mock_context.h"
20 #include "gt/intel_engine_user.h"
21 #include "gt/intel_gt.h"
22 #include "selftests/igt_flush_test.h"
23 #include "selftests/i915_random.h"
25 static void close_objects(struct intel_memory_region
*mem
,
26 struct list_head
*objects
)
28 struct drm_i915_private
*i915
= mem
->i915
;
29 struct drm_i915_gem_object
*obj
, *on
;
31 list_for_each_entry_safe(obj
, on
, objects
, st_link
) {
32 if (i915_gem_object_has_pinned_pages(obj
))
33 i915_gem_object_unpin_pages(obj
);
34 /* No polluting the memory region between tests */
35 __i915_gem_object_put_pages(obj
);
36 list_del(&obj
->st_link
);
37 i915_gem_object_put(obj
);
42 i915_gem_drain_freed_objects(i915
);
45 static int igt_mock_fill(void *arg
)
47 struct intel_memory_region
*mem
= arg
;
48 resource_size_t total
= resource_size(&mem
->region
);
49 resource_size_t page_size
;
51 unsigned long max_pages
;
52 unsigned long page_num
;
56 page_size
= mem
->mm
.chunk_size
;
57 max_pages
= div64_u64(total
, page_size
);
60 for_each_prime_number_from(page_num
, 1, max_pages
) {
61 resource_size_t size
= page_num
* page_size
;
62 struct drm_i915_gem_object
*obj
;
64 obj
= i915_gem_object_create_region(mem
, size
, 0);
70 err
= i915_gem_object_pin_pages(obj
);
72 i915_gem_object_put(obj
);
76 list_add(&obj
->st_link
, &objects
);
83 if (page_num
* page_size
<= rem
) {
84 pr_err("%s failed, space still left in region\n",
92 close_objects(mem
, &objects
);
97 static struct drm_i915_gem_object
*
98 igt_object_create(struct intel_memory_region
*mem
,
99 struct list_head
*objects
,
103 struct drm_i915_gem_object
*obj
;
106 obj
= i915_gem_object_create_region(mem
, size
, flags
);
110 err
= i915_gem_object_pin_pages(obj
);
114 list_add(&obj
->st_link
, objects
);
118 i915_gem_object_put(obj
);
122 static void igt_object_release(struct drm_i915_gem_object
*obj
)
124 i915_gem_object_unpin_pages(obj
);
125 __i915_gem_object_put_pages(obj
);
126 list_del(&obj
->st_link
);
127 i915_gem_object_put(obj
);
130 static int igt_mock_contiguous(void *arg
)
132 struct intel_memory_region
*mem
= arg
;
133 struct drm_i915_gem_object
*obj
;
134 unsigned long n_objects
;
137 I915_RND_STATE(prng
);
138 resource_size_t total
;
143 total
= resource_size(&mem
->region
);
146 obj
= igt_object_create(mem
, &objects
, mem
->mm
.chunk_size
,
147 I915_BO_ALLOC_CONTIGUOUS
);
151 if (obj
->mm
.pages
->nents
!= 1) {
152 pr_err("%s min object spans multiple sg entries\n", __func__
);
154 goto err_close_objects
;
157 igt_object_release(obj
);
160 obj
= igt_object_create(mem
, &objects
, total
, I915_BO_ALLOC_CONTIGUOUS
);
164 if (obj
->mm
.pages
->nents
!= 1) {
165 pr_err("%s max object spans multiple sg entries\n", __func__
);
167 goto err_close_objects
;
170 igt_object_release(obj
);
172 /* Internal fragmentation should not bleed into the object size */
173 target
= i915_prandom_u64_state(&prng
);
174 div64_u64_rem(target
, total
, &target
);
175 target
= round_up(target
, PAGE_SIZE
);
176 target
= max_t(u64
, PAGE_SIZE
, target
);
178 obj
= igt_object_create(mem
, &objects
, target
,
179 I915_BO_ALLOC_CONTIGUOUS
);
183 if (obj
->base
.size
!= target
) {
184 pr_err("%s obj->base.size(%zx) != target(%llx)\n", __func__
,
185 obj
->base
.size
, target
);
187 goto err_close_objects
;
190 if (obj
->mm
.pages
->nents
!= 1) {
191 pr_err("%s object spans multiple sg entries\n", __func__
);
193 goto err_close_objects
;
196 igt_object_release(obj
);
199 * Try to fragment the address space, such that half of it is free, but
200 * the max contiguous block size is SZ_64K.
204 n_objects
= div64_u64(total
, target
);
206 while (n_objects
--) {
207 struct list_head
*list
;
214 obj
= igt_object_create(mem
, list
, target
,
215 I915_BO_ALLOC_CONTIGUOUS
);
218 goto err_close_objects
;
222 close_objects(mem
, &holes
);
227 /* Make sure we can still allocate all the fragmented space */
228 obj
= igt_object_create(mem
, &objects
, target
, 0);
231 goto err_close_objects
;
234 igt_object_release(obj
);
237 * Even though we have enough free space, we don't have a big enough
238 * contiguous block. Make sure that holds true.
242 bool should_fail
= target
> min
;
244 obj
= igt_object_create(mem
, &objects
, target
,
245 I915_BO_ALLOC_CONTIGUOUS
);
246 if (should_fail
!= IS_ERR(obj
)) {
247 pr_err("%s target allocation(%llx) mismatch\n",
250 goto err_close_objects
;
254 } while (target
>= mem
->mm
.chunk_size
);
257 list_splice_tail(&holes
, &objects
);
258 close_objects(mem
, &objects
);
262 static int igt_gpu_write_dw(struct intel_context
*ce
,
263 struct i915_vma
*vma
,
267 return igt_gpu_fill_dw(ce
, vma
, dword
* sizeof(u32
),
268 vma
->size
>> PAGE_SHIFT
, value
);
271 static int igt_cpu_check(struct drm_i915_gem_object
*obj
, u32 dword
, u32 val
)
273 unsigned long n
= obj
->base
.size
>> PAGE_SHIFT
;
277 err
= i915_gem_object_wait(obj
, 0, MAX_SCHEDULE_TIMEOUT
);
281 ptr
= i915_gem_object_pin_map(obj
, I915_MAP_WC
);
288 pr_err("base[%u]=%08x, val=%08x\n",
294 ptr
+= PAGE_SIZE
/ sizeof(*ptr
);
297 i915_gem_object_unpin_map(obj
);
301 static int igt_gpu_write(struct i915_gem_context
*ctx
,
302 struct drm_i915_gem_object
*obj
)
304 struct i915_gem_engines
*engines
;
305 struct i915_gem_engines_iter it
;
306 struct i915_address_space
*vm
;
307 struct intel_context
*ce
;
308 I915_RND_STATE(prng
);
309 IGT_TIMEOUT(end_time
);
311 struct i915_vma
*vma
;
316 GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj
));
320 for_each_gem_engine(ce
, i915_gem_context_lock_engines(ctx
), it
) {
322 if (!intel_engine_can_store_dword(ce
->engine
))
328 i915_gem_context_unlock_engines(ctx
);
332 order
= i915_random_order(count
* count
, &prng
);
336 vma
= i915_vma_instance(obj
, vm
, NULL
);
342 err
= i915_vma_pin(vma
, 0, 0, PIN_USER
);
347 engines
= i915_gem_context_lock_engines(ctx
);
349 u32 rng
= prandom_u32_state(&prng
);
350 u32 dword
= offset_in_page(rng
) / 4;
352 ce
= engines
->engines
[order
[i
] % engines
->num_engines
];
353 i
= (i
+ 1) % (count
* count
);
354 if (!ce
|| !intel_engine_can_store_dword(ce
->engine
))
357 err
= igt_gpu_write_dw(ce
, vma
, dword
, rng
);
361 err
= igt_cpu_check(obj
, dword
, rng
);
364 } while (!__igt_timeout(end_time
, NULL
));
365 i915_gem_context_unlock_engines(ctx
);
376 static int igt_lmem_create(void *arg
)
378 struct drm_i915_private
*i915
= arg
;
379 struct drm_i915_gem_object
*obj
;
382 obj
= i915_gem_object_create_lmem(i915
, PAGE_SIZE
, 0);
386 err
= i915_gem_object_pin_pages(obj
);
390 i915_gem_object_unpin_pages(obj
);
392 i915_gem_object_put(obj
);
397 static int igt_lmem_write_gpu(void *arg
)
399 struct drm_i915_private
*i915
= arg
;
400 struct drm_i915_gem_object
*obj
;
401 struct i915_gem_context
*ctx
;
403 I915_RND_STATE(prng
);
407 file
= mock_file(i915
);
409 return PTR_ERR(file
);
411 ctx
= live_context(i915
, file
);
417 sz
= round_up(prandom_u32_state(&prng
) % SZ_32M
, PAGE_SIZE
);
419 obj
= i915_gem_object_create_lmem(i915
, sz
, 0);
425 err
= i915_gem_object_pin_pages(obj
);
429 err
= igt_gpu_write(ctx
, obj
);
431 pr_err("igt_gpu_write failed(%d)\n", err
);
433 i915_gem_object_unpin_pages(obj
);
435 i915_gem_object_put(obj
);
441 static struct intel_engine_cs
*
442 random_engine_class(struct drm_i915_private
*i915
,
444 struct rnd_state
*prng
)
446 struct intel_engine_cs
*engine
;
450 for (engine
= intel_engine_lookup_user(i915
, class, 0);
451 engine
&& engine
->uabi_class
== class;
452 engine
= rb_entry_safe(rb_next(&engine
->uabi_node
),
453 typeof(*engine
), uabi_node
))
456 count
= i915_prandom_u32_max_state(count
, prng
);
457 return intel_engine_lookup_user(i915
, class, count
);
460 static int igt_lmem_write_cpu(void *arg
)
462 struct drm_i915_private
*i915
= arg
;
463 struct drm_i915_gem_object
*obj
;
464 I915_RND_STATE(prng
);
465 IGT_TIMEOUT(end_time
);
467 0, /* rng placeholder */
472 PAGE_SIZE
- sizeof(u32
),
473 PAGE_SIZE
- sizeof(u64
),
476 struct intel_engine_cs
*engine
;
484 engine
= random_engine_class(i915
, I915_ENGINE_CLASS_COPY
, &prng
);
488 pr_info("%s: using %s\n", __func__
, engine
->name
);
490 sz
= round_up(prandom_u32_state(&prng
) % SZ_32M
, PAGE_SIZE
);
491 sz
= max_t(u32
, 2 * PAGE_SIZE
, sz
);
493 obj
= i915_gem_object_create_lmem(i915
, sz
, I915_BO_ALLOC_CONTIGUOUS
);
497 vaddr
= i915_gem_object_pin_map(obj
, I915_MAP_WC
);
499 err
= PTR_ERR(vaddr
);
503 /* Put the pages into a known state -- from the gpu for added fun */
504 intel_engine_pm_get(engine
);
505 err
= i915_gem_object_fill_blt(obj
, engine
->kernel_context
, 0xdeadbeaf);
506 intel_engine_pm_put(engine
);
510 i915_gem_object_lock(obj
);
511 err
= i915_gem_object_set_to_wc_domain(obj
, true);
512 i915_gem_object_unlock(obj
);
516 count
= ARRAY_SIZE(bytes
);
517 order
= i915_random_order(count
* count
, &prng
);
523 /* We want to throw in a random width/align */
524 bytes
[0] = igt_random_offset(&prng
, 0, PAGE_SIZE
, sizeof(u32
),
535 size
= bytes
[order
[i
] % count
];
536 i
= (i
+ 1) % (count
* count
);
538 align
= bytes
[order
[i
] % count
];
539 i
= (i
+ 1) % (count
* count
);
541 align
= max_t(u32
, sizeof(u32
), rounddown_pow_of_two(align
));
543 offset
= igt_random_offset(&prng
, 0, obj
->base
.size
,
546 val
= prandom_u32_state(&prng
);
547 memset32(vaddr
+ offset
/ sizeof(u32
), val
^ 0xdeadbeaf,
551 * Sample random dw -- don't waste precious time reading every
554 dword
= igt_random_offset(&prng
, offset
,
556 sizeof(u32
), sizeof(u32
));
557 dword
/= sizeof(u32
);
558 if (vaddr
[dword
] != (val
^ 0xdeadbeaf)) {
559 pr_err("%s vaddr[%u]=%u, val=%u, size=%u, align=%u, offset=%u\n",
560 __func__
, dword
, vaddr
[dword
], val
^ 0xdeadbeaf,
561 size
, align
, offset
);
565 } while (!__igt_timeout(end_time
, NULL
));
568 i915_gem_object_unpin_map(obj
);
570 i915_gem_object_put(obj
);
575 int intel_memory_region_mock_selftests(void)
577 static const struct i915_subtest tests
[] = {
578 SUBTEST(igt_mock_fill
),
579 SUBTEST(igt_mock_contiguous
),
581 struct intel_memory_region
*mem
;
582 struct drm_i915_private
*i915
;
585 i915
= mock_gem_device();
589 mem
= mock_region_create(i915
, 0, SZ_2G
, I915_GTT_PAGE_SIZE_4K
, 0);
591 pr_err("failed to create memory region\n");
596 err
= i915_subtests(tests
, mem
);
598 intel_memory_region_put(mem
);
600 drm_dev_put(&i915
->drm
);
604 int intel_memory_region_live_selftests(struct drm_i915_private
*i915
)
606 static const struct i915_subtest tests
[] = {
607 SUBTEST(igt_lmem_create
),
608 SUBTEST(igt_lmem_write_cpu
),
609 SUBTEST(igt_lmem_write_gpu
),
612 if (!HAS_LMEM(i915
)) {
613 pr_info("device lacks LMEM support, skipping\n");
617 if (intel_gt_is_wedged(&i915
->gt
))
620 return i915_live_subtests(tests
, i915
);