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