drm/i915/gem: Support discontiguous lmem object maps
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / selftests / intel_memory_region.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2019 Intel Corporation
4  */
5
6 #include <linux/prime_numbers.h>
7
8 #include "../i915_selftest.h"
9
10 #include "mock_drm.h"
11 #include "mock_gem_device.h"
12 #include "mock_region.h"
13
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"
24
25 static void close_objects(struct intel_memory_region *mem,
26                           struct list_head *objects)
27 {
28         struct drm_i915_private *i915 = mem->i915;
29         struct drm_i915_gem_object *obj, *on;
30
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);
38         }
39
40         cond_resched();
41
42         i915_gem_drain_freed_objects(i915);
43 }
44
45 static int igt_mock_fill(void *arg)
46 {
47         struct intel_memory_region *mem = arg;
48         resource_size_t total = resource_size(&mem->region);
49         resource_size_t page_size;
50         resource_size_t rem;
51         unsigned long max_pages;
52         unsigned long page_num;
53         LIST_HEAD(objects);
54         int err = 0;
55
56         page_size = mem->mm.chunk_size;
57         max_pages = div64_u64(total, page_size);
58         rem = total;
59
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;
63
64                 obj = i915_gem_object_create_region(mem, size, 0);
65                 if (IS_ERR(obj)) {
66                         err = PTR_ERR(obj);
67                         break;
68                 }
69
70                 err = i915_gem_object_pin_pages(obj);
71                 if (err) {
72                         i915_gem_object_put(obj);
73                         break;
74                 }
75
76                 list_add(&obj->st_link, &objects);
77                 rem -= size;
78         }
79
80         if (err == -ENOMEM)
81                 err = 0;
82         if (err == -ENXIO) {
83                 if (page_num * page_size <= rem) {
84                         pr_err("%s failed, space still left in region\n",
85                                __func__);
86                         err = -EINVAL;
87                 } else {
88                         err = 0;
89                 }
90         }
91
92         close_objects(mem, &objects);
93
94         return err;
95 }
96
97 static struct drm_i915_gem_object *
98 igt_object_create(struct intel_memory_region *mem,
99                   struct list_head *objects,
100                   u64 size,
101                   unsigned int flags)
102 {
103         struct drm_i915_gem_object *obj;
104         int err;
105
106         obj = i915_gem_object_create_region(mem, size, flags);
107         if (IS_ERR(obj))
108                 return obj;
109
110         err = i915_gem_object_pin_pages(obj);
111         if (err)
112                 goto put;
113
114         list_add(&obj->st_link, objects);
115         return obj;
116
117 put:
118         i915_gem_object_put(obj);
119         return ERR_PTR(err);
120 }
121
122 static void igt_object_release(struct drm_i915_gem_object *obj)
123 {
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);
128 }
129
130 static int igt_mock_contiguous(void *arg)
131 {
132         struct intel_memory_region *mem = arg;
133         struct drm_i915_gem_object *obj;
134         unsigned long n_objects;
135         LIST_HEAD(objects);
136         LIST_HEAD(holes);
137         I915_RND_STATE(prng);
138         resource_size_t total;
139         resource_size_t min;
140         u64 target;
141         int err = 0;
142
143         total = resource_size(&mem->region);
144
145         /* Min size */
146         obj = igt_object_create(mem, &objects, mem->mm.chunk_size,
147                                 I915_BO_ALLOC_CONTIGUOUS);
148         if (IS_ERR(obj))
149                 return PTR_ERR(obj);
150
151         if (obj->mm.pages->nents != 1) {
152                 pr_err("%s min object spans multiple sg entries\n", __func__);
153                 err = -EINVAL;
154                 goto err_close_objects;
155         }
156
157         igt_object_release(obj);
158
159         /* Max size */
160         obj = igt_object_create(mem, &objects, total, I915_BO_ALLOC_CONTIGUOUS);
161         if (IS_ERR(obj))
162                 return PTR_ERR(obj);
163
164         if (obj->mm.pages->nents != 1) {
165                 pr_err("%s max object spans multiple sg entries\n", __func__);
166                 err = -EINVAL;
167                 goto err_close_objects;
168         }
169
170         igt_object_release(obj);
171
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);
177
178         obj = igt_object_create(mem, &objects, target,
179                                 I915_BO_ALLOC_CONTIGUOUS);
180         if (IS_ERR(obj))
181                 return PTR_ERR(obj);
182
183         if (obj->base.size != target) {
184                 pr_err("%s obj->base.size(%zx) != target(%llx)\n", __func__,
185                        obj->base.size, target);
186                 err = -EINVAL;
187                 goto err_close_objects;
188         }
189
190         if (obj->mm.pages->nents != 1) {
191                 pr_err("%s object spans multiple sg entries\n", __func__);
192                 err = -EINVAL;
193                 goto err_close_objects;
194         }
195
196         igt_object_release(obj);
197
198         /*
199          * Try to fragment the address space, such that half of it is free, but
200          * the max contiguous block size is SZ_64K.
201          */
202
203         target = SZ_64K;
204         n_objects = div64_u64(total, target);
205
206         while (n_objects--) {
207                 struct list_head *list;
208
209                 if (n_objects % 2)
210                         list = &holes;
211                 else
212                         list = &objects;
213
214                 obj = igt_object_create(mem, list, target,
215                                         I915_BO_ALLOC_CONTIGUOUS);
216                 if (IS_ERR(obj)) {
217                         err = PTR_ERR(obj);
218                         goto err_close_objects;
219                 }
220         }
221
222         close_objects(mem, &holes);
223
224         min = target;
225         target = total >> 1;
226
227         /* Make sure we can still allocate all the fragmented space */
228         obj = igt_object_create(mem, &objects, target, 0);
229         if (IS_ERR(obj)) {
230                 err = PTR_ERR(obj);
231                 goto err_close_objects;
232         }
233
234         igt_object_release(obj);
235
236         /*
237          * Even though we have enough free space, we don't have a big enough
238          * contiguous block. Make sure that holds true.
239          */
240
241         do {
242                 bool should_fail = target > min;
243
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",
248                                __func__, target);
249                         err = -EINVAL;
250                         goto err_close_objects;
251                 }
252
253                 target >>= 1;
254         } while (target >= mem->mm.chunk_size);
255
256 err_close_objects:
257         list_splice_tail(&holes, &objects);
258         close_objects(mem, &objects);
259         return err;
260 }
261
262 static int igt_gpu_write_dw(struct intel_context *ce,
263                             struct i915_vma *vma,
264                             u32 dword,
265                             u32 value)
266 {
267         return igt_gpu_fill_dw(ce, vma, dword * sizeof(u32),
268                                vma->size >> PAGE_SHIFT, value);
269 }
270
271 static int igt_cpu_check(struct drm_i915_gem_object *obj, u32 dword, u32 val)
272 {
273         unsigned long n = obj->base.size >> PAGE_SHIFT;
274         u32 *ptr;
275         int err;
276
277         err = i915_gem_object_wait(obj, 0, MAX_SCHEDULE_TIMEOUT);
278         if (err)
279                 return err;
280
281         ptr = i915_gem_object_pin_map(obj, I915_MAP_WC);
282         if (IS_ERR(ptr))
283                 return PTR_ERR(ptr);
284
285         ptr += dword;
286         while (n--) {
287                 if (*ptr != val) {
288                         pr_err("base[%u]=%08x, val=%08x\n",
289                                dword, *ptr, val);
290                         err = -EINVAL;
291                         break;
292                 }
293
294                 ptr += PAGE_SIZE / sizeof(*ptr);
295         }
296
297         i915_gem_object_unpin_map(obj);
298         return err;
299 }
300
301 static int igt_gpu_write(struct i915_gem_context *ctx,
302                          struct drm_i915_gem_object *obj)
303 {
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);
310         unsigned int count;
311         struct i915_vma *vma;
312         int *order;
313         int i, n;
314         int err = 0;
315
316         GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
317
318         n = 0;
319         count = 0;
320         for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
321                 count++;
322                 if (!intel_engine_can_store_dword(ce->engine))
323                         continue;
324
325                 vm = ce->vm;
326                 n++;
327         }
328         i915_gem_context_unlock_engines(ctx);
329         if (!n)
330                 return 0;
331
332         order = i915_random_order(count * count, &prng);
333         if (!order)
334                 return -ENOMEM;
335
336         vma = i915_vma_instance(obj, vm, NULL);
337         if (IS_ERR(vma)) {
338                 err = PTR_ERR(vma);
339                 goto out_free;
340         }
341
342         err = i915_vma_pin(vma, 0, 0, PIN_USER);
343         if (err)
344                 goto out_free;
345
346         i = 0;
347         engines = i915_gem_context_lock_engines(ctx);
348         do {
349                 u32 rng = prandom_u32_state(&prng);
350                 u32 dword = offset_in_page(rng) / 4;
351
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))
355                         continue;
356
357                 err = igt_gpu_write_dw(ce, vma, dword, rng);
358                 if (err)
359                         break;
360
361                 err = igt_cpu_check(obj, dword, rng);
362                 if (err)
363                         break;
364         } while (!__igt_timeout(end_time, NULL));
365         i915_gem_context_unlock_engines(ctx);
366
367 out_free:
368         kfree(order);
369
370         if (err == -ENOMEM)
371                 err = 0;
372
373         return err;
374 }
375
376 static int igt_lmem_create(void *arg)
377 {
378         struct drm_i915_private *i915 = arg;
379         struct drm_i915_gem_object *obj;
380         int err = 0;
381
382         obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
383         if (IS_ERR(obj))
384                 return PTR_ERR(obj);
385
386         err = i915_gem_object_pin_pages(obj);
387         if (err)
388                 goto out_put;
389
390         i915_gem_object_unpin_pages(obj);
391 out_put:
392         i915_gem_object_put(obj);
393
394         return err;
395 }
396
397 static int igt_lmem_write_gpu(void *arg)
398 {
399         struct drm_i915_private *i915 = arg;
400         struct drm_i915_gem_object *obj;
401         struct i915_gem_context *ctx;
402         struct file *file;
403         I915_RND_STATE(prng);
404         u32 sz;
405         int err;
406
407         file = mock_file(i915);
408         if (IS_ERR(file))
409                 return PTR_ERR(file);
410
411         ctx = live_context(i915, file);
412         if (IS_ERR(ctx)) {
413                 err = PTR_ERR(ctx);
414                 goto out_file;
415         }
416
417         sz = round_up(prandom_u32_state(&prng) % SZ_32M, PAGE_SIZE);
418
419         obj = i915_gem_object_create_lmem(i915, sz, 0);
420         if (IS_ERR(obj)) {
421                 err = PTR_ERR(obj);
422                 goto out_file;
423         }
424
425         err = i915_gem_object_pin_pages(obj);
426         if (err)
427                 goto out_put;
428
429         err = igt_gpu_write(ctx, obj);
430         if (err)
431                 pr_err("igt_gpu_write failed(%d)\n", err);
432
433         i915_gem_object_unpin_pages(obj);
434 out_put:
435         i915_gem_object_put(obj);
436 out_file:
437         fput(file);
438         return err;
439 }
440
441 static struct intel_engine_cs *
442 random_engine_class(struct drm_i915_private *i915,
443                     unsigned int class,
444                     struct rnd_state *prng)
445 {
446         struct intel_engine_cs *engine;
447         unsigned int count;
448
449         count = 0;
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))
454                 count++;
455
456         count = i915_prandom_u32_max_state(count, prng);
457         return intel_engine_lookup_user(i915, class, count);
458 }
459
460 static int igt_lmem_write_cpu(void *arg)
461 {
462         struct drm_i915_private *i915 = arg;
463         struct drm_i915_gem_object *obj;
464         I915_RND_STATE(prng);
465         IGT_TIMEOUT(end_time);
466         u32 bytes[] = {
467                 0, /* rng placeholder */
468                 sizeof(u32),
469                 sizeof(u64),
470                 64, /* cl */
471                 PAGE_SIZE,
472                 PAGE_SIZE - sizeof(u32),
473                 PAGE_SIZE - sizeof(u64),
474                 PAGE_SIZE - 64,
475         };
476         struct intel_engine_cs *engine;
477         u32 *vaddr;
478         u32 sz;
479         u32 i;
480         int *order;
481         int count;
482         int err;
483
484         engine = random_engine_class(i915, I915_ENGINE_CLASS_COPY, &prng);
485         if (!engine)
486                 return 0;
487
488         pr_info("%s: using %s\n", __func__, engine->name);
489
490         sz = round_up(prandom_u32_state(&prng) % SZ_32M, PAGE_SIZE);
491         sz = max_t(u32, 2 * PAGE_SIZE, sz);
492
493         obj = i915_gem_object_create_lmem(i915, sz, I915_BO_ALLOC_CONTIGUOUS);
494         if (IS_ERR(obj))
495                 return PTR_ERR(obj);
496
497         vaddr = i915_gem_object_pin_map(obj, I915_MAP_WC);
498         if (IS_ERR(vaddr)) {
499                 err = PTR_ERR(vaddr);
500                 goto out_put;
501         }
502
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);
507         if (err)
508                 goto out_unpin;
509
510         i915_gem_object_lock(obj);
511         err = i915_gem_object_set_to_wc_domain(obj, true);
512         i915_gem_object_unlock(obj);
513         if (err)
514                 goto out_unpin;
515
516         count = ARRAY_SIZE(bytes);
517         order = i915_random_order(count * count, &prng);
518         if (!order) {
519                 err = -ENOMEM;
520                 goto out_unpin;
521         }
522
523         /* We want to throw in a random width/align */
524         bytes[0] = igt_random_offset(&prng, 0, PAGE_SIZE, sizeof(u32),
525                                      sizeof(u32));
526
527         i = 0;
528         do {
529                 u32 offset;
530                 u32 align;
531                 u32 dword;
532                 u32 size;
533                 u32 val;
534
535                 size = bytes[order[i] % count];
536                 i = (i + 1) % (count * count);
537
538                 align = bytes[order[i] % count];
539                 i = (i + 1) % (count * count);
540
541                 align = max_t(u32, sizeof(u32), rounddown_pow_of_two(align));
542
543                 offset = igt_random_offset(&prng, 0, obj->base.size,
544                                            size, align);
545
546                 val = prandom_u32_state(&prng);
547                 memset32(vaddr + offset / sizeof(u32), val ^ 0xdeadbeaf,
548                          size / sizeof(u32));
549
550                 /*
551                  * Sample random dw -- don't waste precious time reading every
552                  * single dw.
553                  */
554                 dword = igt_random_offset(&prng, offset,
555                                           offset + size,
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);
562                         err = -EINVAL;
563                         break;
564                 }
565         } while (!__igt_timeout(end_time, NULL));
566
567 out_unpin:
568         i915_gem_object_unpin_map(obj);
569 out_put:
570         i915_gem_object_put(obj);
571
572         return err;
573 }
574
575 int intel_memory_region_mock_selftests(void)
576 {
577         static const struct i915_subtest tests[] = {
578                 SUBTEST(igt_mock_fill),
579                 SUBTEST(igt_mock_contiguous),
580         };
581         struct intel_memory_region *mem;
582         struct drm_i915_private *i915;
583         int err;
584
585         i915 = mock_gem_device();
586         if (!i915)
587                 return -ENOMEM;
588
589         mem = mock_region_create(i915, 0, SZ_2G, I915_GTT_PAGE_SIZE_4K, 0);
590         if (IS_ERR(mem)) {
591                 pr_err("failed to create memory region\n");
592                 err = PTR_ERR(mem);
593                 goto out_unref;
594         }
595
596         err = i915_subtests(tests, mem);
597
598         intel_memory_region_put(mem);
599 out_unref:
600         drm_dev_put(&i915->drm);
601         return err;
602 }
603
604 int intel_memory_region_live_selftests(struct drm_i915_private *i915)
605 {
606         static const struct i915_subtest tests[] = {
607                 SUBTEST(igt_lmem_create),
608                 SUBTEST(igt_lmem_write_cpu),
609                 SUBTEST(igt_lmem_write_gpu),
610         };
611
612         if (!HAS_LMEM(i915)) {
613                 pr_info("device lacks LMEM support, skipping\n");
614                 return 0;
615         }
616
617         if (intel_gt_is_wedged(&i915->gt))
618                 return 0;
619
620         return i915_live_subtests(tests, i915);
621 }