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