mblock_v2.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein is
  5. * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
  6. * the prior written permission of MediaTek inc. and/or its licensors, any
  7. * reproduction, modification, use or disclosure of MediaTek Software, and
  8. * information contained herein, in whole or in part, shall be strictly
  9. * prohibited.
  10. *
  11. * MediaTek Inc. (C) 2016. All rights reserved.
  12. *
  13. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  14. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  15. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
  16. * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
  17. * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  19. * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
  20. * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
  21. * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
  22. * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
  23. * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
  24. * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
  25. * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
  26. * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  27. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
  28. * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
  29. * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
  30. * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
  31. * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  32. *
  33. * The following software/firmware and/or related documentation ("MediaTek
  34. * Software") have been modified by MediaTek Inc. All revisions are subject to
  35. * any receiver's applicable license agreements with MediaTek Inc.
  36. */
  37. /*
  38. * setup block correctly, we should hander both 4GB mode and
  39. * non-4GB mode.
  40. */
  41. #include "mblock.h"
  42. #include "platform.h"
  43. #include "dram_buffer.h"
  44. //#define dprintf print
  45. #define dprintf(fmt, args...) do{}while(0)
  46. #define bootarg g_dram_buf->bootarg
  47. void setup_mblock_info(mblock_info_t *mblock_info, dram_info_t *orig_dram_info,
  48. mem_desc_t *lca_reserved_mem)
  49. {
  50. int i;
  51. u64 max_dram_size = -1; /* MAX value */
  52. u64 size = 0;
  53. u64 total_dram_size = 0;
  54. memset(mblock_info, 0, sizeof(mblock_info_t));
  55. for (i = 0; i < orig_dram_info->rank_num; i++) {
  56. total_dram_size +=
  57. orig_dram_info->rank_info[i].size;
  58. }
  59. mblock_info->mblock_magic = MBLOCK_MAGIC;
  60. mblock_info->mblock_version = MBLOCK_VERSION;
  61. #ifdef CUSTOM_CONFIG_MAX_DRAM_SIZE
  62. max_dram_size = CUSTOM_CONFIG_MAX_DRAM_SIZE;
  63. print("CUSTOM_CONFIG_MAX_DRAM_SIZE: 0x%llx\n", max_dram_size);
  64. #endif
  65. lca_reserved_mem->start = lca_reserved_mem->size = 0;
  66. /*
  67. * non-4GB mode case
  68. */
  69. /* we do some DRAM size fixup here base on orig_dram_info */
  70. for (i = 0; i < orig_dram_info->rank_num; i++) {
  71. size += orig_dram_info->rank_info[i].size;
  72. mblock_info->mblock[i].start =
  73. orig_dram_info->rank_info[i].start;
  74. mblock_info->mblock[i].rank = i; /* setup rank */
  75. if (size <= max_dram_size) {
  76. mblock_info->mblock[i].size =
  77. orig_dram_info->rank_info[i].size;
  78. } else {
  79. /* max dram size reached */
  80. size -= orig_dram_info->rank_info[i].size;
  81. mblock_info->mblock[i].size =
  82. max_dram_size - size;
  83. /* get lca_reserved_mem info */
  84. lca_reserved_mem->start = mblock_info->mblock[i].start
  85. + mblock_info->mblock[i].size;
  86. if (mblock_info->mblock[i].size) {
  87. mblock_info->mblock_num++;
  88. }
  89. break;
  90. }
  91. if (mblock_info->mblock[i].size) {
  92. mblock_info->mblock_num++;
  93. }
  94. }
  95. print("total_dram_size: 0x%llx, max_dram_size: 0x%llx\n",
  96. total_dram_size, max_dram_size);
  97. print("dump mblock info \n");
  98. for (i = 0;i < mblock_info->mblock_num;i++)
  99. print("mblock[i] start=%llx size=%llx\n", i,
  100. mblock_info->mblock[i].start, mblock_info->mblock[i].size);
  101. if (total_dram_size > max_dram_size) {
  102. /* add left unused memory to lca_reserved memory */
  103. lca_reserved_mem->size = total_dram_size - max_dram_size;
  104. print("lca_reserved_mem start: 0x%llx, size: 0x%llx\n",
  105. lca_reserved_mem->start,
  106. lca_reserved_mem->size);
  107. }
  108. /*
  109. * TBD
  110. * for 4GB mode, we fixup the start address of every mblock
  111. */
  112. }
  113. /*
  114. * reserve a memory from mblock
  115. * @mblock_info: address of mblock_info
  116. * @reserved_size: size of memory
  117. * @align: alignment
  118. * @limit: address limit. Must higher than return address + reserved_size
  119. * @mapping: describe kernel mapping mechanism , 1:map or 0:no-map
  120. * @name: assign a dedicated name for this memory area
  121. * It returns as high address as possible.
  122. */
  123. u64 mblock_reserve_ext(mblock_info_t *mblock_info, u64 reserved_size, u64 align, u64 limit,
  124. u32 mapping,char *name)
  125. {
  126. unsigned int i;
  127. int target = -1;
  128. u64 start, end, sz, max_addr = 0;
  129. u64 reserved_addr = 0;
  130. mblock_t mblock;
  131. if (mblock_info->mblock_num >= (MBLOCK_NUM_MAX - 1)
  132. || mblock_info->reserved_num >= (MBLOCK_RESERVED_NUM_MAX - 1) ||
  133. (mapping >> 1) ||
  134. (name)?(strlen(name) >= MBLOCK_RESERVED_NAME_SIZE - 1):true) {
  135. /* the mblock[] is full */
  136. printf("mblock_reserve_ext failed");
  137. printf("mblock_num or reserved_num is full");
  138. printf("rmblock_num=%d, reserved_num=%d mapping=%d name=%s\n",
  139. mblock_info->mblock_num,
  140. mblock_info->reserved_num, mapping, name);
  141. goto mblock_error;
  142. }
  143. if (!align)
  144. align = 0x1000;
  145. /* must be at least 4k aligned */
  146. if (align & (0x1000 - 1))
  147. align &= ~(0x1000 - 1);
  148. for (i = 0; i < mblock_info->mblock_num; i++) {
  149. start = mblock_info->mblock[i].start;
  150. sz = mblock_info->mblock[i].size;
  151. end = limit < (start + sz) ? limit : (start + sz);
  152. if( reserved_size > sz || limit <= start || end <= start) {
  153. dprintf("skip this mblock start=%llx sz=%llx limit=%llx end=%llx\n",
  154. start, sz, limit, end);
  155. continue;
  156. }
  157. reserved_addr = (end - reserved_size);
  158. reserved_addr &= ~(align - 1);
  159. dprintf("mblock[%d].start: 0x%llx, sz: 0x%llx, limit: 0x%llx, "
  160. "max_addr: 0x%llx, target: %d, reserved_addr: 0x%llx,"
  161. "reserved_size: 0x%llx\n",
  162. i, start, sz, limit, max_addr,
  163. target, reserved_addr, reserved_size);
  164. dprintf("mblock_reserve dbg[%d]: %d, %d, %d, %d\n",
  165. i, (reserved_addr + reserved_size <= start + sz),
  166. (reserved_addr >= start),
  167. (start + sz > max_addr),
  168. (reserved_addr + reserved_size <= limit));
  169. if ((reserved_addr + reserved_size <= start + sz) &&
  170. (reserved_addr >= start) &&
  171. (start + sz > max_addr) &&
  172. (reserved_addr + reserved_size <= limit)) {
  173. max_addr = start + sz;
  174. target = i;
  175. }
  176. }
  177. if (target < 0) {
  178. goto mblock_error;
  179. }
  180. /* update variable reference to correct target info*/
  181. start = mblock_info->mblock[target].start;
  182. sz = mblock_info->mblock[target].size;
  183. end = limit < (start + sz)? limit: (start + sz);
  184. reserved_addr = (end - reserved_size);
  185. reserved_addr &= ~(align - 1);
  186. /* store reserved_t info */
  187. /* dprintf(CRITICAL,"mblock_info->reserved_num=%d\n",mblock_info->reserved_num); */
  188. /*sanity check , reserved_num of array must be empty */
  189. if (mblock_info->reserved[mblock_info->reserved_num].start) {
  190. printf("mblock_reserve error , resreved slot already exist\
  191. start=0x%llx size=0x%llx\n", mblock_info->reserved[mblock_info->reserved_num].start
  192. , mblock_info->reserved[mblock_info->reserved_num].size);
  193. goto mblock_error;
  194. }
  195. mblock_info->reserved[mblock_info->reserved_num].start = reserved_addr;
  196. mblock_info->reserved[mblock_info->reserved_num].size = reserved_size;
  197. mblock_info->reserved[mblock_info->reserved_num].mapping = mapping;
  198. memcpy(&mblock_info->reserved[mblock_info->reserved_num].name, name, MBLOCK_RESERVED_NAME_SIZE);
  199. mblock_info->reserved_num++;
  200. /* split mblock if necessary */
  201. if (reserved_addr == start) {
  202. /*
  203. * only needs to fixup target mblock
  204. * [reserved_addr, reserved_size](reserved) +
  205. * [reserved_addr + reserved_size, sz - reserved_size]
  206. */
  207. mblock_info->mblock[target].start = reserved_addr + reserved_size;
  208. mblock_info->mblock[target].size -= reserved_size;
  209. } else if ((reserved_addr + reserved_size) == (start + sz)) {
  210. /*
  211. * only needs to fixup target mblock
  212. * [start, reserved_addr - start] +
  213. * [reserved_addr, reserved_size](reserved)
  214. */
  215. mblock_info->mblock[target].size = reserved_addr - start;
  216. } else {
  217. /*
  218. * fixup target mblock and create a new mblock
  219. * [start, reserved_addr - start] +
  220. * [reserved_addr, reserved_size](reserved) +
  221. * [reserved_addr + reserved_size, start + sz - reserved_addr - reserved_size]
  222. */
  223. /* fixup original mblock */
  224. mblock_info->mblock[target].size = reserved_addr - start;
  225. /* new mblock */
  226. mblock.rank = mblock_info->mblock[target].rank;
  227. mblock.start = reserved_addr + reserved_size;
  228. mblock.size = start + sz - (reserved_addr + reserved_size);
  229. /* insert the new node, keep the list sorted */
  230. memmove(&mblock_info->mblock[target + 2],
  231. &mblock_info->mblock[target + 1],
  232. sizeof(mblock_t) *
  233. (mblock_info->mblock_num - target - 1));
  234. mblock_info->mblock[target + 1] = mblock;
  235. mblock_info->mblock_num += 1;
  236. dprintf( "mblock[%d]: %llx, %llx from mblock\n"
  237. "mblock[%d]: %llx, %llx from mblock\n",
  238. target,
  239. mblock_info->mblock[target].start,
  240. mblock_info->mblock[target].size,
  241. target + 1,
  242. mblock_info->mblock[target + 1].start,
  243. mblock_info->mblock[target + 1].size);
  244. }
  245. print("mblock_reserve: %llx - %llx from mblock %d\n",
  246. reserved_addr, reserved_addr + reserved_size,
  247. target);
  248. /* print debug info */
  249. for (i = 0; i < mblock_info->mblock_num; i++) {
  250. start = mblock_info->mblock[i].start;
  251. sz = mblock_info->mblock[i].size;
  252. dprintf("mblock_reserve[%d].start: 0x%llx, sz: 0x%llx\n",
  253. i, start, sz);
  254. }
  255. for (i = 0; i < mblock_info->reserved_num; i++) {
  256. start = mblock_info->reserved[i].start;
  257. sz = mblock_info->reserved[i].size;
  258. dprintf("mblock_reserve-R[%d].start: 0x%llx, sz: 0x%llx map:%d name:%s\n",
  259. i, start, sz, mblock_info->reserved[i].mapping, mblock_info->reserved[i].name);
  260. }
  261. return reserved_addr;
  262. mblock_error:
  263. print("mblock_reserve_ext failed\n");
  264. return 0;
  265. }
  266. void mblock_set_mem_tag(unsigned int ** ptr)
  267. {
  268. int i;
  269. boot_tag *tags = (boot_tag *)*ptr;
  270. memset(tags,0,sizeof(boot_tag));
  271. tags->hdr.size = boot_tag_size(boot_tag_mem);
  272. tags->hdr.tag = BOOT_TAG_MEM;
  273. tags->u.mem.dram_rank_num = bootarg.orig_dram_info.rank_num;
  274. for (i = 0; i < 4 ; i++) {
  275. bootarg.dram_rank_size[i] = bootarg.mblock_info.mblock[i].size;
  276. }
  277. for(i=0;i<4;i++){
  278. tags->u.mem.dram_rank_size[i] = bootarg.dram_rank_size[i];
  279. }
  280. tags->u.mem.mblock_info.mblock_num = bootarg.mblock_info.mblock_num;
  281. for(i=0;i<tags->u.mem.mblock_info.mblock_num;i++) {
  282. tags->u.mem.mblock_info.mblock[i].start = bootarg.mblock_info.mblock[i].start;
  283. tags->u.mem.mblock_info.mblock[i].size = bootarg.mblock_info.mblock[i].size;
  284. tags->u.mem.mblock_info.mblock[i].rank = bootarg.mblock_info.mblock[i].rank;
  285. }
  286. #if defined(CFG_MBLOCK_LIB) && (MBLOCK_EXPAND(CFG_MBLOCK_LIB) == MBLOCK_EXPAND(2))
  287. tags->u.mem.mblock_info.mblock_magic = MBLOCK_MAGIC;
  288. tags->u.mem.mblock_info.mblock_version = MBLOCK_VERSION;
  289. tags->u.mem.mblock_info.reserved_num = bootarg.mblock_info.reserved_num;
  290. for(i=0;i<tags->u.mem.mblock_info.reserved_num;i++) {
  291. tags->u.mem.mblock_info.reserved[i].start = bootarg.mblock_info.reserved[i].start;
  292. tags->u.mem.mblock_info.reserved[i].size = bootarg.mblock_info.reserved[i].size;
  293. tags->u.mem.mblock_info.reserved[i].mapping= bootarg.mblock_info.reserved[i].mapping;
  294. memcpy(&tags->u.mem.mblock_info.reserved[i].name, &bootarg.mblock_info.reserved[i].name, MBLOCK_RESERVED_NAME_SIZE);
  295. }
  296. #endif
  297. tags->u.mem.orig_dram_info.rank_num = bootarg.orig_dram_info.rank_num;
  298. for(i=0;i<4;i++) {
  299. tags->u.mem.orig_dram_info.rank_info[i].start = bootarg.orig_dram_info.rank_info[i].start; // 64
  300. tags->u.mem.orig_dram_info.rank_info[i].size = bootarg.orig_dram_info.rank_info[i].size; // 64
  301. }
  302. tags->u.mem.lca_reserved_mem.start= bootarg.lca_reserved_mem.start;
  303. tags->u.mem.lca_reserved_mem.size = bootarg.lca_reserved_mem.size;
  304. tags->u.mem.tee_reserved_mem.start= bootarg.tee_reserved_mem.start;
  305. tags->u.mem.tee_reserved_mem.size = bootarg.tee_reserved_mem.size;
  306. *ptr += tags->hdr.size;
  307. }
  308. /*
  309. * mblock_create - create mblock started at addr or merge with existing mblock
  310. *
  311. * @mblock_info: mblock information
  312. * @orig_dram_info: original dram information
  313. * @addr: start address of a mblock, must be 4k align
  314. * @size: size of the given block, must be 4K align
  315. * return 0 on success, otherwise 1
  316. */
  317. int mblock_create(mblock_info_t *mblock_info, dram_info_t *orig_dram_info
  318. , u64 addr, u64 size)
  319. {
  320. int err = -1;
  321. unsigned int i, valid, target, map;
  322. u64 start, sz;
  323. mblock_t mblock;
  324. reserved_t reserved;
  325. mblock_t *mblock_candidate_left = NULL, *mblock_candidate_right = NULL;
  326. /* check size, addr valid and align with 4K*/
  327. if (!size || size&(0x1000 - 1) || addr&(0x1000 - 1)) {
  328. pal_log_debug("mblock_create size invalid size=%llx\n", size);
  329. goto error;
  330. }
  331. /* for lca check*/
  332. if (bootarg.lca_reserved_mem.start && bootarg.lca_reserved_mem.size) {
  333. if ((addr >= bootarg.lca_reserved_mem.start && addr < bootarg.lca_reserved_mem.start \
  334. + bootarg.lca_reserved_mem.size) || \
  335. (addr + size > bootarg.lca_reserved_mem.start \
  336. && (addr + size) < bootarg.lca_reserved_mem.start + bootarg.lca_reserved_mem.size)) {
  337. pal_log_debug("mblock_create ERROR , overlap with LCA addr and size invalid addr = %llx size=%llx\n", addr, size);
  338. goto error;
  339. }
  340. }
  341. /* for tee check*/
  342. if (bootarg.tee_reserved_mem.start && bootarg.tee_reserved_mem.size) {
  343. if ((addr >= bootarg.tee_reserved_mem.start && addr < bootarg.tee_reserved_mem.start \
  344. + bootarg.tee_reserved_mem.size) || \
  345. (addr + size > bootarg.tee_reserved_mem.start \
  346. && (addr + size) < bootarg.tee_reserved_mem.start + bootarg.tee_reserved_mem.size)) {
  347. pal_log_debug("mblock_create ERROR , overlap with tee addr and size invalid addr = %llx size=%llx\n", addr, size);
  348. goto error;
  349. }
  350. }
  351. /*it's not allow to create mblock which is cross rank
  352. * and mblock should not exceed rank size */
  353. for (i = 0, valid = 0; i < orig_dram_info->rank_num; i++) {
  354. start = orig_dram_info->rank_info[i].start;
  355. sz = orig_dram_info->rank_info[i].size;
  356. if (addr >= start && addr < start + sz && addr + size <= start + sz) {
  357. valid = 1;
  358. break;
  359. }
  360. }
  361. if (!valid) {
  362. pal_log_debug("mblock_create addr \
  363. and size invalid addr=%llx size=%llx\n", addr, size);
  364. goto error;
  365. }
  366. /* check every mblock the addr and size should not be within any existing mblock */
  367. for (i = 0; i < mblock_info->mblock_num; i++) {
  368. start = mblock_info->mblock[i].start;
  369. sz = mblock_info->mblock[i].size;
  370. /*addr should start from reserved memory space and addr + size should not overlap with mblock
  371. * when addr is smaller than start*/
  372. if (((addr >= start) && (addr < start + sz)) || (addr < start && addr + size > start)) {
  373. pal_log_debug("mblock_create error: addr %llx overlap with mblock %llx, size: %llx\n",
  374. addr, start, sz);
  375. goto error;
  376. }
  377. }
  378. /* check if reserved record contain this one , it must exist */
  379. for (i = 0, valid = 0; i < mblock_info->reserved_num; i++) {
  380. start = mblock_info->reserved[i].start;
  381. sz = mblock_info->reserved[i].size;
  382. /* pal_log_info("mblock_create start=0x%llx sz=0x%llx addr=0x%lx size=0x%llx\n",
  383. start, sz, addr, size);
  384. */
  385. if (addr >= start && ((addr + size) <= (start + sz))) {
  386. valid = 1;
  387. target = i;
  388. break;
  389. }
  390. }
  391. if (!valid) {
  392. pal_log_debug("mblock_create error: not exist in reserved record\n addr=0x%llx size=0x%llx\n",
  393. addr, size);
  394. goto error;
  395. }
  396. /* dealling with 4 case */
  397. /* 1. create whole reserved record means destroy it and shit rest record*/
  398. /* 2. create from the left most side to the middle of record*/
  399. /* 3. create from the right most side to the middle of record*/
  400. /* 4. create from the middle of record, and then divide it*/
  401. start = mblock_info->reserved[target].start;
  402. sz = mblock_info->reserved[target].size;
  403. if (addr == start && size == sz) {
  404. /* destroy current record first */
  405. memset(&mblock_info->reserved[i], 0, sizeof(reserved_t));
  406. /* more than one record exist , we need to shift record */
  407. /* we no need to shift record once it's the last one */
  408. if (mblock_info->reserved_num > 1 && target != mblock_info->reserved_num - 1) {
  409. memmove(&mblock_info->reserved[target], &mblock_info->reserved[target + 1]\
  410. , sizeof(reserved_t) * ((mblock_info->reserved_num - 1) - target));
  411. /* after memmove, we must clean the last one */
  412. memset(&mblock_info->reserved[mblock_info->reserved_num - 1], 0, sizeof(reserved_t));
  413. }
  414. mblock_info->reserved_num--;
  415. } else if (addr == start || (addr + size == start + sz)) {
  416. /*Now we deal with lef and right most case*/
  417. /* we just shrink the record */
  418. if (addr == start) {
  419. mblock_info->reserved[target].start = start + size;
  420. mblock_info->reserved[target].size = sz - size;
  421. } else {/* (addr + size == start + sz)*/
  422. mblock_info->reserved[target].size = sz - size;
  423. }
  424. } else {/* this is middle case we need to divide it*/
  425. /* shrink original one and create new one after */
  426. if (mblock_info->reserved_num >= MBLOCK_RESERVED_NUM_MAX) {
  427. pal_log_debug("mblock_create error: can not split , reserved_num reach the max\n");
  428. goto error;
  429. }
  430. reserved.start = addr + size;
  431. reserved.size = (start + sz) - (addr + size);
  432. /* clone from original one*/
  433. reserved.mapping = mblock_info->reserved[target].mapping;
  434. memcpy(&reserved.name, &mblock_info->reserved[target].name, MBLOCK_RESERVED_NAME_SIZE);
  435. /* check if this target is last one or not */
  436. /* target start from 0 , reserved_num start from 1 */
  437. if (target != mblock_info->reserved_num - 1) {
  438. for (i = 0; i < (mblock_info->reserved_num - target - 1); i++) {
  439. mblock_info->reserved[mblock_info->reserved_num - i] = \
  440. mblock_info->reserved[mblock_info->reserved_num - i - 1];
  441. }
  442. mblock_info->reserved[target+1] = reserved;
  443. } else {/*target is the last one */
  444. mblock_info->reserved[mblock_info->reserved_num] = reserved;
  445. }
  446. /* shrink original target size at last step */
  447. mblock_info->reserved[target].size = addr - start;
  448. mblock_info->reserved_num++;
  449. }
  450. /*
  451. * ok, the mblock is valid let's create the mblock
  452. * and try to merge it with the same bank and choose the bigger size one
  453. */
  454. /* setup a new mblock */
  455. mblock.start = addr;
  456. mblock.size = size;
  457. pal_log_debug("mblock_create mblock start %llx size: %llx\n",
  458. mblock.start, mblock.size);
  459. /* setup rank */
  460. for (i = 0; i < orig_dram_info->rank_num; i++) {
  461. start = orig_dram_info->rank_info[i].start;
  462. sz = orig_dram_info->rank_info[i].size;
  463. if ((mblock.start >= start) && ((mblock.start + mblock.size) <= (start + sz))) {
  464. mblock.rank = i;
  465. break;
  466. }
  467. }
  468. if (i >= orig_dram_info->rank_num) {
  469. pal_log_debug("mblock_create error: mblock not in orig_dram_info: %llx, size(%llx)\n",
  470. mblock.start, mblock.size);
  471. goto error;
  472. }
  473. /* put the mblock back to mblock_info */
  474. for (i = 0; i < mblock_info->mblock_num; i++) {
  475. start = mblock_info->mblock[i].start;
  476. sz = mblock_info->mblock[i].size;
  477. if (mblock.rank == mblock_info->mblock[i].rank) {
  478. if (mblock.start + mblock.size == start) {
  479. /*
  480. * the new mblock could be merged to this mblock
  481. */
  482. mblock_candidate_right = &mblock_info->mblock[i];
  483. } else if (start + sz == mblock.start) {
  484. /*
  485. * the new mblock can be merged to this mblock
  486. */
  487. mblock_candidate_left = &mblock_info->mblock[i];
  488. }
  489. }
  490. }
  491. /*we can merge either left or right , choose the bigger one */
  492. if (mblock_candidate_right && mblock_candidate_left) {
  493. if (mblock_candidate_right->size >= mblock_candidate_left->size) {
  494. pal_log_debug("mblock_candidate_right->size = %llx \
  495. mblock_candidate_left->size = %llx \n", mblock_candidate_right->size, mblock_candidate_left->size);
  496. mblock_candidate_right->start = mblock.start;
  497. mblock_candidate_right->size += mblock.size;
  498. } else { /*left bigger*/
  499. pal_log_debug("mblock_candidate_right->size = %llx \
  500. mblock_candidate_left->size = %llx \n", mblock_candidate_right->size, mblock_candidate_left->size);
  501. mblock_candidate_left->size += mblock.size;
  502. }
  503. /* destroy block */
  504. mblock.size = 0;
  505. } else {
  506. if (mblock_candidate_right) {
  507. mblock_candidate_right->start = mblock.start;
  508. mblock_candidate_right->size += mblock.size;
  509. /* destroy block */
  510. mblock.size = 0;
  511. }
  512. if (mblock_candidate_left) {
  513. mblock_candidate_left->size += mblock.size;
  514. /* destroy block */
  515. mblock.size = 0;
  516. }
  517. }
  518. /*
  519. * mblock cannot be merge into mblock_info, insert it into mblock_info
  520. */
  521. if (mblock.size) {
  522. for (i = 0; i < mblock_info->mblock_num; i++) {
  523. if (mblock.start < mblock_info->mblock[i].start)
  524. break;
  525. }
  526. /* insert the new node, keep the list sorted */
  527. if (i != mblock_info->mblock_num) {
  528. memmove(&mblock_info->mblock[i + 1],
  529. &mblock_info->mblock[i],
  530. sizeof(mblock_t) *
  531. (mblock_info->mblock_num - i));
  532. }
  533. mblock_info->mblock[i] = mblock;
  534. mblock_info->mblock_num += 1;
  535. pal_log_debug("create mblock[%d]: %llx, %llx\n",
  536. i,
  537. mblock_info->mblock[i].start,
  538. mblock_info->mblock[i].size);
  539. }
  540. /* print debug info */
  541. for (i = 0; i < mblock_info->mblock_num; i++) {
  542. start = mblock_info->mblock[i].start;
  543. sz = mblock_info->mblock[i].size;
  544. pal_log_debug("mblock-create-debug[%d].start: 0x%llx, sz: 0x%llx\n",
  545. i, start, sz);
  546. }
  547. /* print debug info */
  548. for (i = 0; i < mblock_info->reserved_num; i++) {
  549. start = mblock_info->reserved[i].start;
  550. sz = mblock_info->reserved[i].size;
  551. map = mblock_info->reserved[i].mapping;
  552. pal_log_debug("mblock-create-debug-R[%d].start: 0x%llx, sz: 0x%llx map: %d name: %s\n",
  553. i, start, sz, map, mblock_info->reserved[i].name);
  554. }
  555. return 0;
  556. error:
  557. pal_log_info("mblock_create failed\n");
  558. return err;
  559. }
  560. void mblock_dump_mem_tag(unsigned int *ptr)
  561. {
  562. boot_tag * tags = (boot_tag *)ptr;
  563. int i;
  564. printf("MEM_NUM: %d\n", tags->u.mem.dram_rank_num);
  565. for (i = 0; i < tags->u.mem.dram_rank_num; i++)
  566. print("MEM_SIZE: 0x%x\n", tags->u.mem.dram_rank_size[i]);
  567. printf("mblock num: 0x%x\n", tags->u.mem.mblock_info.mblock_num);
  568. for(i=0;i<tags->u.mem.mblock_info.mblock_num;i++) {
  569. printf("mblock start: 0x%llx\n", tags->u.mem.mblock_info.mblock[i].start);
  570. printf("mblock size: 0x%llx\n", tags->u.mem.mblock_info.mblock[i].size);
  571. printf("mblock rank: 0x%x\n", tags->u.mem.mblock_info.mblock[i].rank);
  572. }
  573. #if defined(CFG_MBLOCK_LIB) && (MBLOCK_EXPAND(CFG_MBLOCK_LIB) == MBLOCK_EXPAND(2))
  574. printf("magic=0x%lx version=0x%lx reserve num: 0x%x\n", \
  575. tags->u.mem.mblock_info.mblock_magic, \
  576. tags->u.mem.mblock_info.mblock_version,\
  577. tags->u.mem.mblock_info.reserved_num);\
  578. for(i=0;i<tags->u.mem.mblock_info.reserved_num;i++) {
  579. printf("mblock start: 0x%llx\n", tags->u.mem.mblock_info.reserved[i].start);
  580. printf("mblock size: 0x%llx\n", tags->u.mem.mblock_info.reserved[i].size);
  581. printf("mblock mapping: 0x%x\n", tags->u.mem.mblock_info.reserved[i].mapping);
  582. printf("mblock name: %s\n", tags->u.mem.mblock_info.reserved[i].name);
  583. }
  584. #endif
  585. printf("orig_dram num: 0x%x\n", tags->u.mem.orig_dram_info.rank_num);
  586. for(i=0;i<4;i++) {
  587. printf("orig_dram start: 0x%llx\n", tags->u.mem.orig_dram_info.rank_info[i].start);
  588. printf("orig_dram size: 0x%llx\n", tags->u.mem.orig_dram_info.rank_info[i].size);
  589. }
  590. printf("lca start: 0x%llx\n", tags->u.mem.lca_reserved_mem.start);
  591. printf("lca size: 0x%llx\n", tags->u.mem.lca_reserved_mem.size);
  592. printf("tee start: 0x%llx\n", tags->u.mem.tee_reserved_mem.start);
  593. printf("tee size: 0x%llx\n", tags->u.mem.tee_reserved_mem.size);
  594. }