xref: /openbmc/u-boot/test/lib/lmb.c (revision 872cfa20)
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 
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  */
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 
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 
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 */
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 */
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 */
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 
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 */
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 
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 
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  */
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. */
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  */
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 
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 */
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 
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