Skip to content

Commit 4f869f1

Browse files
committed
drm/i915/lmem: support optional CPU clearing for special internal use
For some internal device local-memory objects it would be useful to have an option to CPU clear the pages upon gathering the backing store. Note that this might be before the blitter is useable, which is the case for some internal GuC objects. Signed-off-by: Matthew Auld <[email protected]> Cc: Joonas Lahtinen <[email protected]> Cc: Thomas Hellström <[email protected]> Cc: Daniele Ceraolo Spurio <[email protected]> Cc: Lionel Landwerlin <[email protected]> Cc: Jon Bloomfield <[email protected]> Cc: Jordan Justen <[email protected]> Cc: Daniel Vetter <[email protected]> Cc: Kenneth Graunke <[email protected]> Cc: Jason Ekstrand <[email protected]> Cc: Dave Airlie <[email protected]> Cc: [email protected] Cc: [email protected] Acked-by: Kenneth Graunke <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 2459e56 commit 4f869f1

File tree

3 files changed

+113
-4
lines changed

3 files changed

+113
-4
lines changed

drivers/gpu/drm/i915/gem/i915_gem_object_types.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,13 @@ struct drm_i915_gem_object {
172172
#define I915_BO_ALLOC_CONTIGUOUS BIT(0)
173173
#define I915_BO_ALLOC_VOLATILE BIT(1)
174174
#define I915_BO_ALLOC_STRUCT_PAGE BIT(2)
175+
#define I915_BO_ALLOC_CPU_CLEAR BIT(3)
175176
#define I915_BO_ALLOC_FLAGS (I915_BO_ALLOC_CONTIGUOUS | \
176177
I915_BO_ALLOC_VOLATILE | \
177-
I915_BO_ALLOC_STRUCT_PAGE)
178-
#define I915_BO_READONLY BIT(3)
179-
#define I915_TILING_QUIRK_BIT 4 /* unknown swizzling; do not release! */
178+
I915_BO_ALLOC_STRUCT_PAGE | \
179+
I915_BO_ALLOC_CPU_CLEAR)
180+
#define I915_BO_READONLY BIT(4)
181+
#define I915_TILING_QUIRK_BIT 5 /* unknown swizzling; do not release! */
180182

181183
/*
182184
* Is the object to be mapped as read-only to the GPU

drivers/gpu/drm/i915/gem/i915_gem_region.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,28 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj)
9595
sg_mark_end(sg);
9696
i915_sg_trim(st);
9797

98+
/* Intended for kernel internal use only */
99+
if (obj->flags & I915_BO_ALLOC_CPU_CLEAR) {
100+
struct scatterlist *sg;
101+
unsigned long i;
102+
103+
for_each_sg(st->sgl, sg, st->nents, i) {
104+
unsigned int length;
105+
void __iomem *vaddr;
106+
dma_addr_t daddr;
107+
108+
daddr = sg_dma_address(sg);
109+
daddr -= mem->region.start;
110+
length = sg_dma_len(sg);
111+
112+
vaddr = io_mapping_map_wc(&mem->iomap, daddr, length);
113+
memset64((void __force *)vaddr, 0, length / sizeof(u64));
114+
io_mapping_unmap(vaddr);
115+
}
116+
117+
wmb();
118+
}
119+
98120
__i915_gem_object_set_pages(obj, st, sg_page_sizes);
99121

100122
return 0;

drivers/gpu/drm/i915/selftests/intel_memory_region.c

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ static int igt_cpu_check(struct drm_i915_gem_object *obj, u32 dword, u32 val)
513513
if (err)
514514
return err;
515515

516-
ptr = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WC);
516+
ptr = i915_gem_object_pin_map(obj, I915_MAP_WC);
517517
if (IS_ERR(ptr))
518518
return PTR_ERR(ptr);
519519

@@ -593,7 +593,9 @@ static int igt_gpu_write(struct i915_gem_context *ctx,
593593
if (err)
594594
break;
595595

596+
i915_gem_object_lock(obj, NULL);
596597
err = igt_cpu_check(obj, dword, rng);
598+
i915_gem_object_unlock(obj);
597599
if (err)
598600
break;
599601
} while (!__igt_timeout(end_time, NULL));
@@ -629,6 +631,88 @@ static int igt_lmem_create(void *arg)
629631
return err;
630632
}
631633

634+
static int igt_lmem_create_cleared_cpu(void *arg)
635+
{
636+
struct drm_i915_private *i915 = arg;
637+
I915_RND_STATE(prng);
638+
IGT_TIMEOUT(end_time);
639+
u32 size, i;
640+
int err;
641+
642+
i915_gem_drain_freed_objects(i915);
643+
644+
size = max_t(u32, PAGE_SIZE, i915_prandom_u32_max_state(SZ_32M, &prng));
645+
size = round_up(size, PAGE_SIZE);
646+
i = 0;
647+
648+
do {
649+
struct drm_i915_gem_object *obj;
650+
unsigned int flags;
651+
u32 dword, val;
652+
void *vaddr;
653+
654+
/*
655+
* Alternate between cleared and uncleared allocations, while
656+
* also dirtying the pages each time to check that the pages are
657+
* always cleared if requested, since we should get some overlap
658+
* of the underlying pages, if not all, since we are the only
659+
* user.
660+
*/
661+
662+
flags = I915_BO_ALLOC_CPU_CLEAR;
663+
if (i & 1)
664+
flags = 0;
665+
666+
obj = i915_gem_object_create_lmem(i915, size, flags);
667+
if (IS_ERR(obj))
668+
return PTR_ERR(obj);
669+
670+
i915_gem_object_lock(obj, NULL);
671+
err = i915_gem_object_pin_pages(obj);
672+
if (err)
673+
goto out_put;
674+
675+
dword = i915_prandom_u32_max_state(PAGE_SIZE / sizeof(u32),
676+
&prng);
677+
678+
if (flags & I915_BO_ALLOC_CPU_CLEAR) {
679+
err = igt_cpu_check(obj, dword, 0);
680+
if (err) {
681+
pr_err("%s failed with size=%u, flags=%u\n",
682+
__func__, size, flags);
683+
goto out_unpin;
684+
}
685+
}
686+
687+
vaddr = i915_gem_object_pin_map(obj, I915_MAP_WC);
688+
if (IS_ERR(vaddr)) {
689+
err = PTR_ERR(vaddr);
690+
goto out_unpin;
691+
}
692+
693+
val = prandom_u32_state(&prng);
694+
695+
memset32(vaddr, val, obj->base.size / sizeof(u32));
696+
697+
i915_gem_object_flush_map(obj);
698+
i915_gem_object_unpin_map(obj);
699+
out_unpin:
700+
i915_gem_object_unpin_pages(obj);
701+
__i915_gem_object_put_pages(obj);
702+
out_put:
703+
i915_gem_object_unlock(obj);
704+
i915_gem_object_put(obj);
705+
706+
if (err)
707+
break;
708+
++i;
709+
} while (!__igt_timeout(end_time, NULL));
710+
711+
pr_info("%s completed (%u) iterations\n", __func__, i);
712+
713+
return err;
714+
}
715+
632716
static int igt_lmem_write_gpu(void *arg)
633717
{
634718
struct drm_i915_private *i915 = arg;
@@ -1043,6 +1127,7 @@ int intel_memory_region_live_selftests(struct drm_i915_private *i915)
10431127
{
10441128
static const struct i915_subtest tests[] = {
10451129
SUBTEST(igt_lmem_create),
1130+
SUBTEST(igt_lmem_create_cleared_cpu),
10461131
SUBTEST(igt_lmem_write_cpu),
10471132
SUBTEST(igt_lmem_write_gpu),
10481133
};

0 commit comments

Comments
 (0)