Merge tag 'u-boot-imx-20190129' of git://git.denx.de/u-boot-imx
[platform/kernel/u-boot.git] / test / lib / lmb.c
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);