1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2018 Simon Goldschmidt
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)
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);
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);
27 if (num_reserved > 1) {
28 ut_asserteq(lmb->reserved.region[1].base, base2);
29 ut_asserteq(lmb->reserved.region[1].size, size2);
31 if (num_reserved > 2) {
32 ut_asserteq(lmb->reserved.region[2].base, base3);
33 ut_asserteq(lmb->reserved.region[2].size, size3);
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, \
45 * Test helper function that reserves 64 KiB somewhere in the simulated RAM and
46 * then does some alloc + free tests.
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)
52 const phys_addr_t ram_end = ram + ram_size;
53 const phys_addr_t alloc_64k_end = alloc_64k_addr + 0x10000;
57 phys_addr_t a, a2, b, b2, c, d;
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);
68 ret = lmb_add(&lmb, ram, ram_size);
71 /* reserve 64KiB somewhere */
72 ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000);
74 ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
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);
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);
98 ret = lmb_free(&lmb, a, 4);
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);
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);
109 ASSERT_LMB(&lmb, ram, ram_size, 2,
110 alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
112 ret = lmb_free(&lmb, b, 4);
114 ASSERT_LMB(&lmb, ram, ram_size, 3,
115 alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000,
117 /* allocate again to ensure we get the same address */
118 b2 = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
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);
124 ASSERT_LMB(&lmb, ram, ram_size, 3,
125 alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000,
128 ret = lmb_free(&lmb, c, 4);
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);
134 ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
140 static int test_multi_alloc_512mb(struct unit_test_state *uts,
141 const phys_addr_t ram)
143 return test_multi_alloc(uts, ram, 0x20000000, ram + 0x10000000);
146 /* Create a memory region with one reserved region and allocate */
147 static int lib_test_lmb_simple(struct unit_test_state *uts)
151 /* simulate 512 MiB RAM beginning at 1GiB */
152 ret = test_multi_alloc_512mb(uts, 0x40000000);
156 /* simulate 512 MiB RAM beginning at 1.5GiB */
157 return test_multi_alloc_512mb(uts, 0xE0000000);
160 DM_TEST(lib_test_lmb_simple, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
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)
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;
173 /* check for overflow */
174 ut_assert(ram_end == 0 || ram_end > ram);
178 ret = lmb_add(&lmb, ram, ram_size);
181 /* reserve 64KiB in the middle of RAM */
182 ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000);
184 ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
187 /* allocate a big block, should be below reserved */
188 a = lmb_alloc(&lmb, big_block_size, 1);
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);
196 ASSERT_LMB(&lmb, ram, ram_size, 1, a,
197 big_block_size + 0x10000, 0, 0, 0, 0);
199 ret = lmb_free(&lmb, a, big_block_size);
201 ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
204 /* allocate too big block */
205 /* This should fail, printing an error */
206 a = lmb_alloc(&lmb, ram_size, 1);
208 ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
214 static int lib_test_lmb_big(struct unit_test_state *uts)
218 /* simulate 512 MiB RAM beginning at 1GiB */
219 ret = test_bigblock(uts, 0x40000000);
223 /* simulate 512 MiB RAM beginning at 1.5GiB */
224 return test_bigblock(uts, 0xE0000000);
227 DM_TEST(lib_test_lmb_big, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
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)
233 const phys_size_t ram_size = 0x20000000;
234 const phys_addr_t ram_end = ram + ram_size;
238 const phys_addr_t alloc_size_aligned = (alloc_size + align - 1) &
241 /* check for overflow */
242 ut_assert(ram_end == 0 || ram_end > ram);
246 ret = lmb_add(&lmb, ram, ram_size);
248 ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
250 /* allocate a block */
251 a = lmb_alloc(&lmb, alloc_size, align);
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);
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,
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);
268 ret = lmb_free(&lmb, b, alloc_size);
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);
274 ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
276 /* allocate a block with base*/
277 b = lmb_alloc_base(&lmb, alloc_size, align, ram_end);
279 ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
280 alloc_size, 0, 0, 0, 0);
282 ret = lmb_free(&lmb, b, alloc_size);
284 ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
289 static int lib_test_lmb_noreserved(struct unit_test_state *uts)
293 /* simulate 512 MiB RAM beginning at 1GiB */
294 ret = test_noreserved(uts, 0x40000000, 4, 1);
298 /* simulate 512 MiB RAM beginning at 1.5GiB */
299 return test_noreserved(uts, 0xE0000000, 4, 1);
302 DM_TEST(lib_test_lmb_noreserved, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
304 static int lib_test_lmb_unaligned_size(struct unit_test_state *uts)
308 /* simulate 512 MiB RAM beginning at 1GiB */
309 ret = test_noreserved(uts, 0x40000000, 5, 8);
313 /* simulate 512 MiB RAM beginning at 1.5GiB */
314 return test_noreserved(uts, 0xE0000000, 5, 8);
317 DM_TEST(lib_test_lmb_unaligned_size, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
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.
322 static int lib_test_lmb_at_0(struct unit_test_state *uts)
324 const phys_addr_t ram = 0;
325 const phys_size_t ram_size = 0x20000000;
332 ret = lmb_add(&lmb, ram, ram_size);
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,
340 /* allocate the rest */
341 /* This should fail as the allocated address would be 0 */
342 b = lmb_alloc(&lmb, 4, 1);
344 /* check that this was an error by checking lmb */
345 ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
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,
353 ret = lmb_free(&lmb, a, ram_size - 4);
355 ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
360 DM_TEST(lib_test_lmb_at_0, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
362 /* Check that calling lmb_reserve with overlapping regions fails. */
363 static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
365 const phys_addr_t ram = 0x40000000;
366 const phys_size_t ram_size = 0x20000000;
372 ret = lmb_add(&lmb, ram, ram_size);
375 ret = lmb_reserve(&lmb, 0x40010000, 0x10000);
377 ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000,
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,
384 /* allocate 3nd region */
385 ret = lmb_reserve(&lmb, 0x40030000, 0x10000);
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);
392 ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x30000,
398 DM_TEST(lib_test_lmb_overlapping_reserve,
399 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);