xref: /linux/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c (revision f5bd7da05a5988506dedcb3e67aecb3a13a4cdf0)
1 // SPDX-License-Identifier: GPL-2.0 AND MIT
2 /*
3  * Copyright © 2024 Intel Corporation
4  */
5 
6 #include <kunit/static_stub.h>
7 #include <kunit/test.h>
8 #include <kunit/test-bug.h>
9 
10 #include "xe_device.h"
11 #include "xe_ggtt.h"
12 #include "xe_guc_ct.h"
13 #include "xe_kunit_helpers.h"
14 #include "xe_pci_test.h"
15 
16 #define DUT_GGTT_START		SZ_1M
17 #define DUT_GGTT_SIZE		SZ_2M
18 
19 static struct xe_bo *replacement_xe_managed_bo_create_pin_map(struct xe_device *xe,
20 							      struct xe_tile *tile,
21 							      size_t size, u32 flags)
22 {
23 	struct kunit *test = kunit_get_current_test();
24 	struct xe_bo *bo;
25 	void *buf;
26 
27 	bo = drmm_kzalloc(&xe->drm, sizeof(*bo), GFP_KERNEL);
28 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo);
29 
30 	buf = drmm_kzalloc(&xe->drm, size, GFP_KERNEL);
31 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
32 
33 	bo->tile = tile;
34 	bo->ttm.bdev = &xe->ttm;
35 	bo->ttm.base.size = size;
36 	iosys_map_set_vaddr(&bo->vmap, buf);
37 
38 	if (flags & XE_BO_FLAG_GGTT) {
39 		struct xe_ggtt *ggtt = tile->mem.ggtt;
40 
41 		bo->ggtt_node[tile->id] = xe_ggtt_insert_node(ggtt, xe_bo_size(bo), SZ_4K);
42 		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo->ggtt_node[tile->id]);
43 	}
44 
45 	return bo;
46 }
47 
48 static int guc_buf_test_init(struct kunit *test)
49 {
50 	struct xe_pci_fake_data fake = {
51 		.sriov_mode = XE_SRIOV_MODE_PF,
52 		.platform = XE_TIGERLAKE, /* some random platform */
53 		.subplatform = XE_SUBPLATFORM_NONE,
54 	};
55 	struct xe_ggtt *ggtt;
56 	struct xe_guc *guc;
57 
58 	test->priv = &fake;
59 	xe_kunit_helper_xe_device_test_init(test);
60 
61 	ggtt = xe_device_get_root_tile(test->priv)->mem.ggtt;
62 	guc = &xe_device_get_gt(test->priv, 0)->uc.guc;
63 
64 	KUNIT_ASSERT_EQ(test, 0,
65 			xe_ggtt_init_kunit(ggtt, DUT_GGTT_START,
66 					   DUT_GGTT_SIZE));
67 
68 	kunit_activate_static_stub(test, xe_managed_bo_create_pin_map,
69 				   replacement_xe_managed_bo_create_pin_map);
70 
71 	KUNIT_ASSERT_EQ(test, 0, xe_guc_buf_cache_init(&guc->buf));
72 
73 	test->priv = &guc->buf;
74 	return 0;
75 }
76 
77 static void test_smallest(struct kunit *test)
78 {
79 	struct xe_guc_buf_cache *cache = test->priv;
80 	struct xe_guc_buf buf;
81 
82 	buf = xe_guc_buf_reserve(cache, 1);
83 	KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf));
84 	KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf));
85 	KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf));
86 	KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf));
87 	KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf));
88 	xe_guc_buf_release(buf);
89 }
90 
91 static void test_largest(struct kunit *test)
92 {
93 	struct xe_guc_buf_cache *cache = test->priv;
94 	struct xe_guc_buf buf;
95 
96 	buf = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache));
97 	KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf));
98 	KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf));
99 	KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf));
100 	KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf));
101 	KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf));
102 	xe_guc_buf_release(buf);
103 }
104 
105 static void test_granular(struct kunit *test)
106 {
107 	struct xe_guc_buf_cache *cache = test->priv;
108 	struct xe_guc_buf *bufs;
109 	int n, dwords;
110 
111 	dwords = xe_guc_buf_cache_dwords(cache);
112 	bufs = kunit_kcalloc(test, dwords, sizeof(*bufs), GFP_KERNEL);
113 	KUNIT_EXPECT_NOT_NULL(test, bufs);
114 
115 	for (n = 0; n < dwords; n++)
116 		bufs[n] = xe_guc_buf_reserve(cache, 1);
117 
118 	for (n = 0; n < dwords; n++)
119 		KUNIT_EXPECT_TRUE_MSG(test, xe_guc_buf_is_valid(bufs[n]), "n=%d", n);
120 
121 	for (n = 0; n < dwords; n++)
122 		xe_guc_buf_release(bufs[n]);
123 }
124 
125 static void test_unique(struct kunit *test)
126 {
127 	struct xe_guc_buf_cache *cache = test->priv;
128 	struct xe_guc_buf *bufs;
129 	int n, m, dwords;
130 
131 	dwords = xe_guc_buf_cache_dwords(cache);
132 	bufs = kunit_kcalloc(test, dwords, sizeof(*bufs), GFP_KERNEL);
133 	KUNIT_EXPECT_NOT_NULL(test, bufs);
134 
135 	for (n = 0; n < dwords; n++)
136 		bufs[n] = xe_guc_buf_reserve(cache, 1);
137 
138 	for (n = 0; n < dwords; n++) {
139 		for (m = n + 1; m < dwords; m++) {
140 			KUNIT_EXPECT_PTR_NE_MSG(test, xe_guc_buf_cpu_ptr(bufs[n]),
141 						xe_guc_buf_cpu_ptr(bufs[m]), "n=%d, m=%d", n, m);
142 			KUNIT_ASSERT_NE_MSG(test, xe_guc_buf_gpu_addr(bufs[n]),
143 					    xe_guc_buf_gpu_addr(bufs[m]), "n=%d, m=%d", n, m);
144 		}
145 	}
146 
147 	for (n = 0; n < dwords; n++)
148 		xe_guc_buf_release(bufs[n]);
149 }
150 
151 static void test_overlap(struct kunit *test)
152 {
153 	struct xe_guc_buf_cache *cache = test->priv;
154 	struct xe_guc_buf b1, b2;
155 	u32 dwords = xe_guc_buf_cache_dwords(cache) / 2;
156 	u32 bytes = dwords * sizeof(u32);
157 	void *p1, *p2;
158 	u64 a1, a2;
159 
160 	b1 = xe_guc_buf_reserve(cache, dwords);
161 	b2 = xe_guc_buf_reserve(cache, dwords);
162 
163 	p1 = xe_guc_buf_cpu_ptr(b1);
164 	p2 = xe_guc_buf_cpu_ptr(b2);
165 
166 	a1 = xe_guc_buf_gpu_addr(b1);
167 	a2 = xe_guc_buf_gpu_addr(b2);
168 
169 	KUNIT_EXPECT_PTR_NE(test, p1, p2);
170 	if (p1 < p2)
171 		KUNIT_EXPECT_LT(test, (uintptr_t)(p1 + bytes - 1), (uintptr_t)p2);
172 	else
173 		KUNIT_EXPECT_LT(test, (uintptr_t)(p2 + bytes - 1), (uintptr_t)p1);
174 
175 	KUNIT_EXPECT_NE(test, a1, a2);
176 	if (a1 < a2)
177 		KUNIT_EXPECT_LT(test, a1 + bytes - 1, a2);
178 	else
179 		KUNIT_EXPECT_LT(test, a2 + bytes - 1, a1);
180 
181 	xe_guc_buf_release(b1);
182 	xe_guc_buf_release(b2);
183 }
184 
185 static void test_reusable(struct kunit *test)
186 {
187 	struct xe_guc_buf_cache *cache = test->priv;
188 	struct xe_guc_buf b1, b2;
189 	void *p1;
190 	u64 a1;
191 
192 	b1 = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache));
193 	KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(b1));
194 	KUNIT_EXPECT_NOT_NULL(test, p1 = xe_guc_buf_cpu_ptr(b1));
195 	KUNIT_EXPECT_NE(test, 0, a1 = xe_guc_buf_gpu_addr(b1));
196 	xe_guc_buf_release(b1);
197 
198 	b2 = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache));
199 	KUNIT_EXPECT_PTR_EQ(test, p1, xe_guc_buf_cpu_ptr(b2));
200 	KUNIT_EXPECT_EQ(test, a1, xe_guc_buf_gpu_addr(b2));
201 	xe_guc_buf_release(b2);
202 }
203 
204 static void test_too_big(struct kunit *test)
205 {
206 	struct xe_guc_buf_cache *cache = test->priv;
207 	struct xe_guc_buf buf;
208 
209 	buf = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache) + 1);
210 	KUNIT_EXPECT_FALSE(test, xe_guc_buf_is_valid(buf));
211 	xe_guc_buf_release(buf); /* shouldn't crash */
212 }
213 
214 static void test_flush(struct kunit *test)
215 {
216 	struct xe_guc_buf_cache *cache = test->priv;
217 	struct xe_guc_buf buf;
218 	const u32 dwords = xe_guc_buf_cache_dwords(cache);
219 	const u32 bytes = dwords * sizeof(u32);
220 	u32 *s, *p, *d;
221 	int n;
222 
223 	KUNIT_ASSERT_NOT_NULL(test, s = kunit_kcalloc(test, dwords, sizeof(u32), GFP_KERNEL));
224 	KUNIT_ASSERT_NOT_NULL(test, d = kunit_kcalloc(test, dwords, sizeof(u32), GFP_KERNEL));
225 
226 	for (n = 0; n < dwords; n++)
227 		s[n] = n;
228 
229 	buf = xe_guc_buf_reserve(cache, dwords);
230 	KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf));
231 	KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf));
232 	KUNIT_EXPECT_PTR_NE(test, p, s);
233 	KUNIT_EXPECT_PTR_NE(test, p, d);
234 
235 	memcpy(p, s, bytes);
236 	KUNIT_EXPECT_NE(test, 0, xe_guc_buf_flush(buf));
237 
238 	iosys_map_memcpy_from(d, &cache->sam->bo->vmap, 0, bytes);
239 	KUNIT_EXPECT_MEMEQ(test, s, d, bytes);
240 
241 	xe_guc_buf_release(buf);
242 }
243 
244 static void test_lookup(struct kunit *test)
245 {
246 	struct xe_guc_buf_cache *cache = test->priv;
247 	struct xe_guc_buf buf;
248 	u32 dwords;
249 	u64 addr;
250 	u32 *p;
251 	int n;
252 
253 	dwords = xe_guc_buf_cache_dwords(cache);
254 	buf = xe_guc_buf_reserve(cache, dwords);
255 	KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf));
256 	KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf));
257 	KUNIT_ASSERT_NE(test, 0, addr = xe_guc_buf_gpu_addr(buf));
258 
259 	KUNIT_EXPECT_EQ(test, 0, xe_guc_cache_gpu_addr_from_ptr(cache, p - 1, sizeof(u32)));
260 	KUNIT_EXPECT_EQ(test, 0, xe_guc_cache_gpu_addr_from_ptr(cache, p + dwords, sizeof(u32)));
261 
262 	for (n = 0; n < dwords; n++)
263 		KUNIT_EXPECT_EQ_MSG(test, xe_guc_cache_gpu_addr_from_ptr(cache, p + n, sizeof(u32)),
264 				    addr + n * sizeof(u32), "n=%d", n);
265 
266 	xe_guc_buf_release(buf);
267 }
268 
269 static void test_data(struct kunit *test)
270 {
271 	static const u32 data[] = { 1, 2, 3, 4, 5, 6 };
272 	struct xe_guc_buf_cache *cache = test->priv;
273 	struct xe_guc_buf buf;
274 	void *p;
275 
276 	buf = xe_guc_buf_from_data(cache, data, sizeof(data));
277 	KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf));
278 	KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf));
279 	KUNIT_EXPECT_MEMEQ(test, p, data, sizeof(data));
280 
281 	xe_guc_buf_release(buf);
282 }
283 
284 static void test_class(struct kunit *test)
285 {
286 	struct xe_guc_buf_cache *cache = test->priv;
287 	u32 dwords = xe_guc_buf_cache_dwords(cache);
288 
289 	{
290 		CLASS(xe_guc_buf, buf)(cache, dwords);
291 		KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf));
292 		KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf));
293 		KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf));
294 		KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf));
295 		KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf));
296 	}
297 
298 	{
299 		CLASS(xe_guc_buf, buf)(cache, dwords);
300 		KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf));
301 		KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf));
302 		KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf));
303 		KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf));
304 		KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf));
305 	}
306 }
307 
308 static struct kunit_case guc_buf_test_cases[] = {
309 	KUNIT_CASE(test_smallest),
310 	KUNIT_CASE(test_largest),
311 	KUNIT_CASE(test_granular),
312 	KUNIT_CASE(test_unique),
313 	KUNIT_CASE(test_overlap),
314 	KUNIT_CASE(test_reusable),
315 	KUNIT_CASE(test_too_big),
316 	KUNIT_CASE(test_flush),
317 	KUNIT_CASE(test_lookup),
318 	KUNIT_CASE(test_data),
319 	KUNIT_CASE(test_class),
320 	{}
321 };
322 
323 static struct kunit_suite guc_buf_suite = {
324 	.name = "guc_buf",
325 	.test_cases = guc_buf_test_cases,
326 	.init = guc_buf_test_init,
327 };
328 
329 kunit_test_suites(&guc_buf_suite);
330