1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2018 Simon Goldschmidt
4 */
5
6 #include <common.h>
7 #include <lmb.h>
8 #include <dm/test.h>
9 #include <test/ut.h>
10
check_lmb(struct unit_test_state * uts,struct lmb * lmb,phys_addr_t ram_base,phys_size_t ram_size,unsigned long num_reserved,phys_addr_t base1,phys_size_t size1,phys_addr_t base2,phys_size_t size2,phys_addr_t base3,phys_size_t size3)11 static int check_lmb(struct unit_test_state *uts, struct lmb *lmb,
12 phys_addr_t ram_base, phys_size_t ram_size,
13 unsigned long num_reserved,
14 phys_addr_t base1, phys_size_t size1,
15 phys_addr_t base2, phys_size_t size2,
16 phys_addr_t base3, phys_size_t size3)
17 {
18 if (ram_size) {
19 ut_asserteq(lmb->memory.cnt, 1);
20 ut_asserteq(lmb->memory.region[0].base, ram_base);
21 ut_asserteq(lmb->memory.region[0].size, ram_size);
22 }
23
24 ut_asserteq(lmb->reserved.cnt, num_reserved);
25 if (num_reserved > 0) {
26 ut_asserteq(lmb->reserved.region[0].base, base1);
27 ut_asserteq(lmb->reserved.region[0].size, size1);
28 }
29 if (num_reserved > 1) {
30 ut_asserteq(lmb->reserved.region[1].base, base2);
31 ut_asserteq(lmb->reserved.region[1].size, size2);
32 }
33 if (num_reserved > 2) {
34 ut_asserteq(lmb->reserved.region[2].base, base3);
35 ut_asserteq(lmb->reserved.region[2].size, size3);
36 }
37 return 0;
38 }
39
40 #define ASSERT_LMB(lmb, ram_base, ram_size, num_reserved, base1, size1, \
41 base2, size2, base3, size3) \
42 ut_assert(!check_lmb(uts, lmb, ram_base, ram_size, \
43 num_reserved, base1, size1, base2, size2, base3, \
44 size3))
45
46 /*
47 * Test helper function that reserves 64 KiB somewhere in the simulated RAM and
48 * then does some alloc + free tests.
49 */
test_multi_alloc(struct unit_test_state * uts,const phys_addr_t ram,const phys_size_t ram_size,const phys_addr_t ram0,const phys_size_t ram0_size,const phys_addr_t alloc_64k_addr)50 static int test_multi_alloc(struct unit_test_state *uts, const phys_addr_t ram,
51 const phys_size_t ram_size, const phys_addr_t ram0,
52 const phys_size_t ram0_size,
53 const phys_addr_t alloc_64k_addr)
54 {
55 const phys_addr_t ram_end = ram + ram_size;
56 const phys_addr_t alloc_64k_end = alloc_64k_addr + 0x10000;
57
58 struct lmb lmb;
59 long ret;
60 phys_addr_t a, a2, b, b2, c, d;
61
62 /* check for overflow */
63 ut_assert(ram_end == 0 || ram_end > ram);
64 ut_assert(alloc_64k_end > alloc_64k_addr);
65 /* check input addresses + size */
66 ut_assert(alloc_64k_addr >= ram + 8);
67 ut_assert(alloc_64k_end <= ram_end - 8);
68
69 lmb_init(&lmb);
70
71 if (ram0_size) {
72 ret = lmb_add(&lmb, ram0, ram0_size);
73 ut_asserteq(ret, 0);
74 }
75
76 ret = lmb_add(&lmb, ram, ram_size);
77 ut_asserteq(ret, 0);
78
79 if (ram0_size) {
80 ut_asserteq(lmb.memory.cnt, 2);
81 ut_asserteq(lmb.memory.region[0].base, ram0);
82 ut_asserteq(lmb.memory.region[0].size, ram0_size);
83 ut_asserteq(lmb.memory.region[1].base, ram);
84 ut_asserteq(lmb.memory.region[1].size, ram_size);
85 } else {
86 ut_asserteq(lmb.memory.cnt, 1);
87 ut_asserteq(lmb.memory.region[0].base, ram);
88 ut_asserteq(lmb.memory.region[0].size, ram_size);
89 }
90
91 /* reserve 64KiB somewhere */
92 ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000);
93 ut_asserteq(ret, 0);
94 ASSERT_LMB(&lmb, 0, 0, 1, alloc_64k_addr, 0x10000,
95 0, 0, 0, 0);
96
97 /* allocate somewhere, should be at the end of RAM */
98 a = lmb_alloc(&lmb, 4, 1);
99 ut_asserteq(a, ram_end - 4);
100 ASSERT_LMB(&lmb, 0, 0, 2, alloc_64k_addr, 0x10000,
101 ram_end - 4, 4, 0, 0);
102 /* alloc below end of reserved region -> below reserved region */
103 b = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
104 ut_asserteq(b, alloc_64k_addr - 4);
105 ASSERT_LMB(&lmb, 0, 0, 2,
106 alloc_64k_addr - 4, 0x10000 + 4, ram_end - 4, 4, 0, 0);
107
108 /* 2nd time */
109 c = lmb_alloc(&lmb, 4, 1);
110 ut_asserteq(c, ram_end - 8);
111 ASSERT_LMB(&lmb, 0, 0, 2,
112 alloc_64k_addr - 4, 0x10000 + 4, ram_end - 8, 8, 0, 0);
113 d = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
114 ut_asserteq(d, alloc_64k_addr - 8);
115 ASSERT_LMB(&lmb, 0, 0, 2,
116 alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 8, 0, 0);
117
118 ret = lmb_free(&lmb, a, 4);
119 ut_asserteq(ret, 0);
120 ASSERT_LMB(&lmb, 0, 0, 2,
121 alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
122 /* allocate again to ensure we get the same address */
123 a2 = lmb_alloc(&lmb, 4, 1);
124 ut_asserteq(a, a2);
125 ASSERT_LMB(&lmb, 0, 0, 2,
126 alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 8, 0, 0);
127 ret = lmb_free(&lmb, a2, 4);
128 ut_asserteq(ret, 0);
129 ASSERT_LMB(&lmb, 0, 0, 2,
130 alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
131
132 ret = lmb_free(&lmb, b, 4);
133 ut_asserteq(ret, 0);
134 ASSERT_LMB(&lmb, 0, 0, 3,
135 alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000,
136 ram_end - 8, 4);
137 /* allocate again to ensure we get the same address */
138 b2 = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
139 ut_asserteq(b, b2);
140 ASSERT_LMB(&lmb, 0, 0, 2,
141 alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
142 ret = lmb_free(&lmb, b2, 4);
143 ut_asserteq(ret, 0);
144 ASSERT_LMB(&lmb, 0, 0, 3,
145 alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000,
146 ram_end - 8, 4);
147
148 ret = lmb_free(&lmb, c, 4);
149 ut_asserteq(ret, 0);
150 ASSERT_LMB(&lmb, 0, 0, 2,
151 alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000, 0, 0);
152 ret = lmb_free(&lmb, d, 4);
153 ut_asserteq(ret, 0);
154 ASSERT_LMB(&lmb, 0, 0, 1, alloc_64k_addr, 0x10000,
155 0, 0, 0, 0);
156
157 if (ram0_size) {
158 ut_asserteq(lmb.memory.cnt, 2);
159 ut_asserteq(lmb.memory.region[0].base, ram0);
160 ut_asserteq(lmb.memory.region[0].size, ram0_size);
161 ut_asserteq(lmb.memory.region[1].base, ram);
162 ut_asserteq(lmb.memory.region[1].size, ram_size);
163 } else {
164 ut_asserteq(lmb.memory.cnt, 1);
165 ut_asserteq(lmb.memory.region[0].base, ram);
166 ut_asserteq(lmb.memory.region[0].size, ram_size);
167 }
168
169 return 0;
170 }
171
test_multi_alloc_512mb(struct unit_test_state * uts,const phys_addr_t ram)172 static int test_multi_alloc_512mb(struct unit_test_state *uts,
173 const phys_addr_t ram)
174 {
175 return test_multi_alloc(uts, ram, 0x20000000, 0, 0, ram + 0x10000000);
176 }
177
test_multi_alloc_512mb_x2(struct unit_test_state * uts,const phys_addr_t ram,const phys_addr_t ram0)178 static int test_multi_alloc_512mb_x2(struct unit_test_state *uts,
179 const phys_addr_t ram,
180 const phys_addr_t ram0)
181 {
182 return test_multi_alloc(uts, ram, 0x20000000, ram0, 0x20000000,
183 ram + 0x10000000);
184 }
185
186 /* Create a memory region with one reserved region and allocate */
lib_test_lmb_simple(struct unit_test_state * uts)187 static int lib_test_lmb_simple(struct unit_test_state *uts)
188 {
189 int ret;
190
191 /* simulate 512 MiB RAM beginning at 1GiB */
192 ret = test_multi_alloc_512mb(uts, 0x40000000);
193 if (ret)
194 return ret;
195
196 /* simulate 512 MiB RAM beginning at 1.5GiB */
197 return test_multi_alloc_512mb(uts, 0xE0000000);
198 }
199
200 DM_TEST(lib_test_lmb_simple, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
201
202 /* Create two memory regions with one reserved region and allocate */
lib_test_lmb_simple_x2(struct unit_test_state * uts)203 static int lib_test_lmb_simple_x2(struct unit_test_state *uts)
204 {
205 int ret;
206
207 /* simulate 512 MiB RAM beginning at 2GiB and 1 GiB */
208 ret = test_multi_alloc_512mb_x2(uts, 0x80000000, 0x40000000);
209 if (ret)
210 return ret;
211
212 /* simulate 512 MiB RAM beginning at 3.5GiB and 1 GiB */
213 return test_multi_alloc_512mb_x2(uts, 0xE0000000, 0x40000000);
214 }
215
216 DM_TEST(lib_test_lmb_simple_x2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
217
218 /* Simulate 512 MiB RAM, allocate some blocks that fit/don't fit */
test_bigblock(struct unit_test_state * uts,const phys_addr_t ram)219 static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram)
220 {
221 const phys_size_t ram_size = 0x20000000;
222 const phys_size_t big_block_size = 0x10000000;
223 const phys_addr_t ram_end = ram + ram_size;
224 const phys_addr_t alloc_64k_addr = ram + 0x10000000;
225 struct lmb lmb;
226 long ret;
227 phys_addr_t a, b;
228
229 /* check for overflow */
230 ut_assert(ram_end == 0 || ram_end > ram);
231
232 lmb_init(&lmb);
233
234 ret = lmb_add(&lmb, ram, ram_size);
235 ut_asserteq(ret, 0);
236
237 /* reserve 64KiB in the middle of RAM */
238 ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000);
239 ut_asserteq(ret, 0);
240 ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
241 0, 0, 0, 0);
242
243 /* allocate a big block, should be below reserved */
244 a = lmb_alloc(&lmb, big_block_size, 1);
245 ut_asserteq(a, ram);
246 ASSERT_LMB(&lmb, ram, ram_size, 1, a,
247 big_block_size + 0x10000, 0, 0, 0, 0);
248 /* allocate 2nd big block */
249 /* This should fail, printing an error */
250 b = lmb_alloc(&lmb, big_block_size, 1);
251 ut_asserteq(b, 0);
252 ASSERT_LMB(&lmb, ram, ram_size, 1, a,
253 big_block_size + 0x10000, 0, 0, 0, 0);
254
255 ret = lmb_free(&lmb, a, big_block_size);
256 ut_asserteq(ret, 0);
257 ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
258 0, 0, 0, 0);
259
260 /* allocate too big block */
261 /* This should fail, printing an error */
262 a = lmb_alloc(&lmb, ram_size, 1);
263 ut_asserteq(a, 0);
264 ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
265 0, 0, 0, 0);
266
267 return 0;
268 }
269
lib_test_lmb_big(struct unit_test_state * uts)270 static int lib_test_lmb_big(struct unit_test_state *uts)
271 {
272 int ret;
273
274 /* simulate 512 MiB RAM beginning at 1GiB */
275 ret = test_bigblock(uts, 0x40000000);
276 if (ret)
277 return ret;
278
279 /* simulate 512 MiB RAM beginning at 1.5GiB */
280 return test_bigblock(uts, 0xE0000000);
281 }
282
283 DM_TEST(lib_test_lmb_big, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
284
285 /* Simulate 512 MiB RAM, allocate a block without previous reservation */
test_noreserved(struct unit_test_state * uts,const phys_addr_t ram,const phys_addr_t alloc_size,const ulong align)286 static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram,
287 const phys_addr_t alloc_size, const ulong align)
288 {
289 const phys_size_t ram_size = 0x20000000;
290 const phys_addr_t ram_end = ram + ram_size;
291 struct lmb lmb;
292 long ret;
293 phys_addr_t a, b;
294 const phys_addr_t alloc_size_aligned = (alloc_size + align - 1) &
295 ~(align - 1);
296
297 /* check for overflow */
298 ut_assert(ram_end == 0 || ram_end > ram);
299
300 lmb_init(&lmb);
301
302 ret = lmb_add(&lmb, ram, ram_size);
303 ut_asserteq(ret, 0);
304 ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
305
306 /* allocate a block */
307 a = lmb_alloc(&lmb, alloc_size, align);
308 ut_assert(a != 0);
309 ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
310 alloc_size, 0, 0, 0, 0);
311 /* allocate another block */
312 b = lmb_alloc(&lmb, alloc_size, align);
313 ut_assert(b != 0);
314 if (alloc_size == alloc_size_aligned) {
315 ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size -
316 (alloc_size_aligned * 2), alloc_size * 2, 0, 0, 0,
317 0);
318 } else {
319 ASSERT_LMB(&lmb, ram, ram_size, 2, ram + ram_size -
320 (alloc_size_aligned * 2), alloc_size, ram + ram_size
321 - alloc_size_aligned, alloc_size, 0, 0);
322 }
323 /* and free them */
324 ret = lmb_free(&lmb, b, alloc_size);
325 ut_asserteq(ret, 0);
326 ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
327 alloc_size, 0, 0, 0, 0);
328 ret = lmb_free(&lmb, a, alloc_size);
329 ut_asserteq(ret, 0);
330 ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
331
332 /* allocate a block with base*/
333 b = lmb_alloc_base(&lmb, alloc_size, align, ram_end);
334 ut_assert(a == b);
335 ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
336 alloc_size, 0, 0, 0, 0);
337 /* and free it */
338 ret = lmb_free(&lmb, b, alloc_size);
339 ut_asserteq(ret, 0);
340 ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
341
342 return 0;
343 }
344
lib_test_lmb_noreserved(struct unit_test_state * uts)345 static int lib_test_lmb_noreserved(struct unit_test_state *uts)
346 {
347 int ret;
348
349 /* simulate 512 MiB RAM beginning at 1GiB */
350 ret = test_noreserved(uts, 0x40000000, 4, 1);
351 if (ret)
352 return ret;
353
354 /* simulate 512 MiB RAM beginning at 1.5GiB */
355 return test_noreserved(uts, 0xE0000000, 4, 1);
356 }
357
358 DM_TEST(lib_test_lmb_noreserved, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
359
lib_test_lmb_unaligned_size(struct unit_test_state * uts)360 static int lib_test_lmb_unaligned_size(struct unit_test_state *uts)
361 {
362 int ret;
363
364 /* simulate 512 MiB RAM beginning at 1GiB */
365 ret = test_noreserved(uts, 0x40000000, 5, 8);
366 if (ret)
367 return ret;
368
369 /* simulate 512 MiB RAM beginning at 1.5GiB */
370 return test_noreserved(uts, 0xE0000000, 5, 8);
371 }
372
373 DM_TEST(lib_test_lmb_unaligned_size, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
374 /*
375 * Simulate a RAM that starts at 0 and allocate down to address 0, which must
376 * fail as '0' means failure for the lmb_alloc functions.
377 */
lib_test_lmb_at_0(struct unit_test_state * uts)378 static int lib_test_lmb_at_0(struct unit_test_state *uts)
379 {
380 const phys_addr_t ram = 0;
381 const phys_size_t ram_size = 0x20000000;
382 struct lmb lmb;
383 long ret;
384 phys_addr_t a, b;
385
386 lmb_init(&lmb);
387
388 ret = lmb_add(&lmb, ram, ram_size);
389 ut_asserteq(ret, 0);
390
391 /* allocate nearly everything */
392 a = lmb_alloc(&lmb, ram_size - 4, 1);
393 ut_asserteq(a, ram + 4);
394 ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
395 0, 0, 0, 0);
396 /* allocate the rest */
397 /* This should fail as the allocated address would be 0 */
398 b = lmb_alloc(&lmb, 4, 1);
399 ut_asserteq(b, 0);
400 /* check that this was an error by checking lmb */
401 ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
402 0, 0, 0, 0);
403 /* check that this was an error by freeing b */
404 ret = lmb_free(&lmb, b, 4);
405 ut_asserteq(ret, -1);
406 ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
407 0, 0, 0, 0);
408
409 ret = lmb_free(&lmb, a, ram_size - 4);
410 ut_asserteq(ret, 0);
411 ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
412
413 return 0;
414 }
415
416 DM_TEST(lib_test_lmb_at_0, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
417
418 /* Check that calling lmb_reserve with overlapping regions fails. */
lib_test_lmb_overlapping_reserve(struct unit_test_state * uts)419 static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
420 {
421 const phys_addr_t ram = 0x40000000;
422 const phys_size_t ram_size = 0x20000000;
423 struct lmb lmb;
424 long ret;
425
426 lmb_init(&lmb);
427
428 ret = lmb_add(&lmb, ram, ram_size);
429 ut_asserteq(ret, 0);
430
431 ret = lmb_reserve(&lmb, 0x40010000, 0x10000);
432 ut_asserteq(ret, 0);
433 ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000,
434 0, 0, 0, 0);
435 /* allocate overlapping region should fail */
436 ret = lmb_reserve(&lmb, 0x40011000, 0x10000);
437 ut_asserteq(ret, -1);
438 ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000,
439 0, 0, 0, 0);
440 /* allocate 3nd region */
441 ret = lmb_reserve(&lmb, 0x40030000, 0x10000);
442 ut_asserteq(ret, 0);
443 ASSERT_LMB(&lmb, ram, ram_size, 2, 0x40010000, 0x10000,
444 0x40030000, 0x10000, 0, 0);
445 /* allocate 2nd region */
446 ret = lmb_reserve(&lmb, 0x40020000, 0x10000);
447 ut_assert(ret >= 0);
448 ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x30000,
449 0, 0, 0, 0);
450
451 return 0;
452 }
453
454 DM_TEST(lib_test_lmb_overlapping_reserve,
455 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
456
457 /*
458 * Simulate 512 MiB RAM, reserve 3 blocks, allocate addresses in between.
459 * Expect addresses outside the memory range to fail.
460 */
test_alloc_addr(struct unit_test_state * uts,const phys_addr_t ram)461 static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram)
462 {
463 const phys_size_t ram_size = 0x20000000;
464 const phys_addr_t ram_end = ram + ram_size;
465 const phys_size_t alloc_addr_a = ram + 0x8000000;
466 const phys_size_t alloc_addr_b = ram + 0x8000000 * 2;
467 const phys_size_t alloc_addr_c = ram + 0x8000000 * 3;
468 struct lmb lmb;
469 long ret;
470 phys_addr_t a, b, c, d, e;
471
472 /* check for overflow */
473 ut_assert(ram_end == 0 || ram_end > ram);
474
475 lmb_init(&lmb);
476
477 ret = lmb_add(&lmb, ram, ram_size);
478 ut_asserteq(ret, 0);
479
480 /* reserve 3 blocks */
481 ret = lmb_reserve(&lmb, alloc_addr_a, 0x10000);
482 ut_asserteq(ret, 0);
483 ret = lmb_reserve(&lmb, alloc_addr_b, 0x10000);
484 ut_asserteq(ret, 0);
485 ret = lmb_reserve(&lmb, alloc_addr_c, 0x10000);
486 ut_asserteq(ret, 0);
487 ASSERT_LMB(&lmb, ram, ram_size, 3, alloc_addr_a, 0x10000,
488 alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
489
490 /* allocate blocks */
491 a = lmb_alloc_addr(&lmb, ram, alloc_addr_a - ram);
492 ut_asserteq(a, ram);
493 ASSERT_LMB(&lmb, ram, ram_size, 3, ram, 0x8010000,
494 alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
495 b = lmb_alloc_addr(&lmb, alloc_addr_a + 0x10000,
496 alloc_addr_b - alloc_addr_a - 0x10000);
497 ut_asserteq(b, alloc_addr_a + 0x10000);
498 ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x10010000,
499 alloc_addr_c, 0x10000, 0, 0);
500 c = lmb_alloc_addr(&lmb, alloc_addr_b + 0x10000,
501 alloc_addr_c - alloc_addr_b - 0x10000);
502 ut_asserteq(c, alloc_addr_b + 0x10000);
503 ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
504 0, 0, 0, 0);
505 d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000,
506 ram_end - alloc_addr_c - 0x10000);
507 ut_asserteq(d, alloc_addr_c + 0x10000);
508 ASSERT_LMB(&lmb, ram, ram_size, 1, ram, ram_size,
509 0, 0, 0, 0);
510
511 /* allocating anything else should fail */
512 e = lmb_alloc(&lmb, 1, 1);
513 ut_asserteq(e, 0);
514 ASSERT_LMB(&lmb, ram, ram_size, 1, ram, ram_size,
515 0, 0, 0, 0);
516
517 ret = lmb_free(&lmb, d, ram_end - alloc_addr_c - 0x10000);
518 ut_asserteq(ret, 0);
519
520 /* allocate at 3 points in free range */
521
522 d = lmb_alloc_addr(&lmb, ram_end - 4, 4);
523 ut_asserteq(d, ram_end - 4);
524 ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000,
525 d, 4, 0, 0);
526 ret = lmb_free(&lmb, d, 4);
527 ut_asserteq(ret, 0);
528 ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
529 0, 0, 0, 0);
530
531 d = lmb_alloc_addr(&lmb, ram_end - 128, 4);
532 ut_asserteq(d, ram_end - 128);
533 ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000,
534 d, 4, 0, 0);
535 ret = lmb_free(&lmb, d, 4);
536 ut_asserteq(ret, 0);
537 ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
538 0, 0, 0, 0);
539
540 d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000, 4);
541 ut_asserteq(d, alloc_addr_c + 0x10000);
542 ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010004,
543 0, 0, 0, 0);
544 ret = lmb_free(&lmb, d, 4);
545 ut_asserteq(ret, 0);
546 ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
547 0, 0, 0, 0);
548
549 /* allocate at the bottom */
550 ret = lmb_free(&lmb, a, alloc_addr_a - ram);
551 ut_asserteq(ret, 0);
552 ASSERT_LMB(&lmb, ram, ram_size, 1, ram + 0x8000000, 0x10010000,
553 0, 0, 0, 0);
554 d = lmb_alloc_addr(&lmb, ram, 4);
555 ut_asserteq(d, ram);
556 ASSERT_LMB(&lmb, ram, ram_size, 2, d, 4,
557 ram + 0x8000000, 0x10010000, 0, 0);
558
559 /* check that allocating outside memory fails */
560 if (ram_end != 0) {
561 ret = lmb_alloc_addr(&lmb, ram_end, 1);
562 ut_asserteq(ret, 0);
563 }
564 if (ram != 0) {
565 ret = lmb_alloc_addr(&lmb, ram - 1, 1);
566 ut_asserteq(ret, 0);
567 }
568
569 return 0;
570 }
571
lib_test_lmb_alloc_addr(struct unit_test_state * uts)572 static int lib_test_lmb_alloc_addr(struct unit_test_state *uts)
573 {
574 int ret;
575
576 /* simulate 512 MiB RAM beginning at 1GiB */
577 ret = test_alloc_addr(uts, 0x40000000);
578 if (ret)
579 return ret;
580
581 /* simulate 512 MiB RAM beginning at 1.5GiB */
582 return test_alloc_addr(uts, 0xE0000000);
583 }
584
585 DM_TEST(lib_test_lmb_alloc_addr, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
586
587 /* Simulate 512 MiB RAM, reserve 3 blocks, check addresses in between */
test_get_unreserved_size(struct unit_test_state * uts,const phys_addr_t ram)588 static int test_get_unreserved_size(struct unit_test_state *uts,
589 const phys_addr_t ram)
590 {
591 const phys_size_t ram_size = 0x20000000;
592 const phys_addr_t ram_end = ram + ram_size;
593 const phys_size_t alloc_addr_a = ram + 0x8000000;
594 const phys_size_t alloc_addr_b = ram + 0x8000000 * 2;
595 const phys_size_t alloc_addr_c = ram + 0x8000000 * 3;
596 struct lmb lmb;
597 long ret;
598 phys_size_t s;
599
600 /* check for overflow */
601 ut_assert(ram_end == 0 || ram_end > ram);
602
603 lmb_init(&lmb);
604
605 ret = lmb_add(&lmb, ram, ram_size);
606 ut_asserteq(ret, 0);
607
608 /* reserve 3 blocks */
609 ret = lmb_reserve(&lmb, alloc_addr_a, 0x10000);
610 ut_asserteq(ret, 0);
611 ret = lmb_reserve(&lmb, alloc_addr_b, 0x10000);
612 ut_asserteq(ret, 0);
613 ret = lmb_reserve(&lmb, alloc_addr_c, 0x10000);
614 ut_asserteq(ret, 0);
615 ASSERT_LMB(&lmb, ram, ram_size, 3, alloc_addr_a, 0x10000,
616 alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
617
618 /* check addresses in between blocks */
619 s = lmb_get_free_size(&lmb, ram);
620 ut_asserteq(s, alloc_addr_a - ram);
621 s = lmb_get_free_size(&lmb, ram + 0x10000);
622 ut_asserteq(s, alloc_addr_a - ram - 0x10000);
623 s = lmb_get_free_size(&lmb, alloc_addr_a - 4);
624 ut_asserteq(s, 4);
625
626 s = lmb_get_free_size(&lmb, alloc_addr_a + 0x10000);
627 ut_asserteq(s, alloc_addr_b - alloc_addr_a - 0x10000);
628 s = lmb_get_free_size(&lmb, alloc_addr_a + 0x20000);
629 ut_asserteq(s, alloc_addr_b - alloc_addr_a - 0x20000);
630 s = lmb_get_free_size(&lmb, alloc_addr_b - 4);
631 ut_asserteq(s, 4);
632
633 s = lmb_get_free_size(&lmb, alloc_addr_c + 0x10000);
634 ut_asserteq(s, ram_end - alloc_addr_c - 0x10000);
635 s = lmb_get_free_size(&lmb, alloc_addr_c + 0x20000);
636 ut_asserteq(s, ram_end - alloc_addr_c - 0x20000);
637 s = lmb_get_free_size(&lmb, ram_end - 4);
638 ut_asserteq(s, 4);
639
640 return 0;
641 }
642
lib_test_lmb_get_free_size(struct unit_test_state * uts)643 static int lib_test_lmb_get_free_size(struct unit_test_state *uts)
644 {
645 int ret;
646
647 /* simulate 512 MiB RAM beginning at 1GiB */
648 ret = test_get_unreserved_size(uts, 0x40000000);
649 if (ret)
650 return ret;
651
652 /* simulate 512 MiB RAM beginning at 1.5GiB */
653 return test_get_unreserved_size(uts, 0xE0000000);
654 }
655
656 DM_TEST(lib_test_lmb_get_free_size,
657 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
658