lmb.c 19 KB

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