Merge branch '2019-02-01-master-imports'
[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         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);