1 // SPDX-License-Identifier: GPL-2.0+
3 * Procedures for maintaining information about logical memory blocks.
5 * Peter Bergner, IBM Corp. June 2001.
6 * Copyright (C) 2001 Peter Bergner.
10 #include <efi_loader.h>
18 #include <asm/global_data.h>
19 #include <asm/sections.h>
20 #include <linux/kernel.h>
21 #include <linux/sizes.h>
23 DECLARE_GLOBAL_DATA_PTR;
25 #define LMB_ALLOC_ANYWHERE 0
26 #define LMB_ALIST_INITIAL_SIZE 4
28 static struct lmb lmb;
30 static void lmb_print_region_flags(enum lmb_flags flags)
33 const char *flag_str[] = { "none", "no-map", "no-overwrite" };
36 bitpos = flags ? fls(flags) - 1 : 0;
37 printf("%s", flag_str[bitpos]);
38 flags &= ~(1ull << bitpos);
39 puts(flags ? ", " : "\n");
43 static void lmb_dump_region(struct alist *lmb_rgn_lst, char *name)
45 struct lmb_region *rgn = lmb_rgn_lst->data;
46 unsigned long long base, size, end;
50 printf(" %s.count = 0x%x\n", name, lmb_rgn_lst->count);
52 for (i = 0; i < lmb_rgn_lst->count; i++) {
55 end = base + size - 1;
58 printf(" %s[%d]\t[0x%llx-0x%llx], 0x%08llx bytes flags: ",
59 name, i, base, end, size);
60 lmb_print_region_flags(flags);
64 void lmb_dump_all_force(void)
66 printf("lmb_dump_all:\n");
67 lmb_dump_region(&lmb.free_mem, "memory");
68 lmb_dump_region(&lmb.used_mem, "reserved");
71 void lmb_dump_all(void)
78 static long lmb_addrs_overlap(phys_addr_t base1, phys_size_t size1,
79 phys_addr_t base2, phys_size_t size2)
81 const phys_addr_t base1_end = base1 + size1 - 1;
82 const phys_addr_t base2_end = base2 + size2 - 1;
84 return ((base1 <= base2_end) && (base2 <= base1_end));
87 static long lmb_addrs_adjacent(phys_addr_t base1, phys_size_t size1,
88 phys_addr_t base2, phys_size_t size2)
90 if (base2 == base1 + size1)
92 else if (base1 == base2 + size2)
98 static long lmb_regions_overlap(struct alist *lmb_rgn_lst, unsigned long r1,
101 struct lmb_region *rgn = lmb_rgn_lst->data;
103 phys_addr_t base1 = rgn[r1].base;
104 phys_size_t size1 = rgn[r1].size;
105 phys_addr_t base2 = rgn[r2].base;
106 phys_size_t size2 = rgn[r2].size;
108 return lmb_addrs_overlap(base1, size1, base2, size2);
111 static long lmb_regions_adjacent(struct alist *lmb_rgn_lst, unsigned long r1,
114 struct lmb_region *rgn = lmb_rgn_lst->data;
116 phys_addr_t base1 = rgn[r1].base;
117 phys_size_t size1 = rgn[r1].size;
118 phys_addr_t base2 = rgn[r2].base;
119 phys_size_t size2 = rgn[r2].size;
120 return lmb_addrs_adjacent(base1, size1, base2, size2);
123 static void lmb_remove_region(struct alist *lmb_rgn_lst, unsigned long r)
126 struct lmb_region *rgn = lmb_rgn_lst->data;
128 for (i = r; i < lmb_rgn_lst->count - 1; i++) {
129 rgn[i].base = rgn[i + 1].base;
130 rgn[i].size = rgn[i + 1].size;
131 rgn[i].flags = rgn[i + 1].flags;
133 lmb_rgn_lst->count--;
136 /* Assumption: base addr of region 1 < base addr of region 2 */
137 static void lmb_coalesce_regions(struct alist *lmb_rgn_lst, unsigned long r1,
140 struct lmb_region *rgn = lmb_rgn_lst->data;
142 rgn[r1].size += rgn[r2].size;
143 lmb_remove_region(lmb_rgn_lst, r2);
146 /*Assumption : base addr of region 1 < base addr of region 2*/
147 static void lmb_fix_over_lap_regions(struct alist *lmb_rgn_lst,
148 unsigned long r1, unsigned long r2)
150 struct lmb_region *rgn = lmb_rgn_lst->data;
152 phys_addr_t base1 = rgn[r1].base;
153 phys_size_t size1 = rgn[r1].size;
154 phys_addr_t base2 = rgn[r2].base;
155 phys_size_t size2 = rgn[r2].size;
157 if (base1 + size1 > base2 + size2) {
158 printf("This will not be a case any time\n");
161 rgn[r1].size = base2 + size2 - base1;
162 lmb_remove_region(lmb_rgn_lst, r2);
166 * efi_lmb_reserve() - add reservations for EFI memory
168 * Add reservations for all EFI memory areas that are not
169 * EFI_CONVENTIONAL_MEMORY.
171 * Return: 0 on success, 1 on failure
173 static __maybe_unused int efi_lmb_reserve(void)
175 struct efi_mem_desc *memmap = NULL, *map;
176 efi_uintn_t i, map_size = 0;
179 ret = efi_get_memory_map_alloc(&map_size, &memmap);
180 if (ret != EFI_SUCCESS)
183 for (i = 0, map = memmap; i < map_size / sizeof(*map); ++map, ++i) {
184 if (map->type != EFI_CONVENTIONAL_MEMORY) {
185 lmb_reserve_flags(map_to_sysmem((void *)(uintptr_t)
186 map->physical_start),
187 map->num_pages * EFI_PAGE_SIZE,
188 map->type == EFI_RESERVED_MEMORY_TYPE
189 ? LMB_NOMAP : LMB_NONE);
192 efi_free_pool(memmap);
197 static void lmb_reserve_uboot_region(void)
201 phys_addr_t rsv_start;
203 rsv_start = gd->start_addr_sp - CONFIG_STACK_SIZE;
207 * Reserve memory from aligned address below the bottom of U-Boot stack
208 * until end of RAM area to prevent LMB from overwriting that memory.
210 debug("## Current stack ends at 0x%08lx ", (ulong)rsv_start);
212 /* adjust sp by 16K to be safe */
214 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
215 if (!gd->bd->bi_dram[bank].size ||
216 rsv_start < gd->bd->bi_dram[bank].start)
218 /* Watch out for RAM at end of address space! */
219 bank_end = gd->bd->bi_dram[bank].start +
220 gd->bd->bi_dram[bank].size - 1;
221 if (rsv_start > bank_end)
226 lmb_reserve_flags(rsv_start, bank_end - rsv_start + 1,
229 if (gd->flags & GD_FLG_SKIP_RELOC)
230 lmb_reserve_flags((phys_addr_t)(uintptr_t)_start,
231 gd->mon_len, LMB_NOOVERWRITE);
237 static void lmb_reserve_common(void *fdt_blob)
239 lmb_reserve_uboot_region();
241 if (CONFIG_IS_ENABLED(OF_LIBFDT) && fdt_blob)
242 boot_fdt_add_mem_rsv_regions(fdt_blob);
244 if (CONFIG_IS_ENABLED(EFI_LOADER))
248 static __maybe_unused void lmb_reserve_common_spl(void)
250 phys_addr_t rsv_start;
251 phys_size_t rsv_size;
254 * Assume a SPL stack of 16KB. This must be
255 * more than enough for the SPL stage.
257 if (IS_ENABLED(CONFIG_SPL_STACK_R_ADDR)) {
258 rsv_start = gd->start_addr_sp - 16384;
260 lmb_reserve_flags(rsv_start, rsv_size, LMB_NOOVERWRITE);
263 if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS)) {
264 /* Reserve the bss region */
265 rsv_start = (phys_addr_t)(uintptr_t)__bss_start;
266 rsv_size = (phys_addr_t)(uintptr_t)__bss_end -
267 (phys_addr_t)(uintptr_t)__bss_start;
268 lmb_reserve_flags(rsv_start, rsv_size, LMB_NOOVERWRITE);
273 * lmb_add_memory() - Add memory range for LMB allocations
275 * Add the entire available memory range to the pool of memory that
276 * can be used by the LMB module for allocations.
280 void lmb_add_memory(void)
285 u64 ram_top = gd->ram_top;
286 struct bd_info *bd = gd->bd;
288 /* Assume a 4GB ram_top if not defined */
290 ram_top = 0x100000000ULL;
292 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
293 size = bd->bi_dram[i].size;
295 if (bd->bi_dram[i].start > ram_top)
298 rgn_top = bd->bi_dram[i].start +
301 if (rgn_top > ram_top)
302 size -= rgn_top - ram_top;
304 lmb_add(bd->bi_dram[i].start, size);
309 static long lmb_resize_regions(struct alist *lmb_rgn_lst,
310 unsigned long idx_start,
311 phys_addr_t base, phys_size_t size)
314 unsigned long rgn_cnt, idx, idx_end;
315 phys_addr_t rgnbase, rgnend;
316 phys_addr_t mergebase, mergeend;
317 struct lmb_region *rgn = lmb_rgn_lst->data;
324 * First thing to do is to identify how many regions
325 * the requested region overlaps.
326 * If the flags match, combine all these overlapping
327 * regions into a single region, and remove the merged
330 while (idx <= lmb_rgn_lst->count - 1) {
331 rgnbase = rgn[idx].base;
332 rgnsize = rgn[idx].size;
334 if (lmb_addrs_overlap(base, size, rgnbase,
336 if (rgn[idx].flags != LMB_NONE)
344 /* The merged region's base and size */
345 rgnbase = rgn[idx_start].base;
346 mergebase = min(base, rgnbase);
347 rgnend = rgn[idx_end].base + rgn[idx_end].size;
348 mergeend = max(rgnend, (base + size));
350 rgn[idx_start].base = mergebase;
351 rgn[idx_start].size = mergeend - mergebase;
353 /* Now remove the merged regions */
355 lmb_remove_region(lmb_rgn_lst, idx_start + 1);
361 * lmb_add_region_flags() - Add an lmb region to the given list
362 * @lmb_rgn_lst: LMB list to which region is to be added(free/used)
363 * @base: Start address of the region
364 * @size: Size of the region to be added
365 * @flags: Attributes of the LMB region
367 * Add a region of memory to the list. If the region does not exist, add
368 * it to the list. Depending on the attributes of the region to be added,
369 * the function might resize an already existing region or coalesce two
373 * Returns: 0 if the region addition successful, -1 on failure
375 static long lmb_add_region_flags(struct alist *lmb_rgn_lst, phys_addr_t base,
376 phys_size_t size, enum lmb_flags flags)
378 unsigned long coalesced = 0;
380 struct lmb_region *rgn = lmb_rgn_lst->data;
382 if (alist_err(lmb_rgn_lst))
385 /* First try and coalesce this LMB with another. */
386 for (i = 0; i < lmb_rgn_lst->count; i++) {
387 phys_addr_t rgnbase = rgn[i].base;
388 phys_size_t rgnsize = rgn[i].size;
389 phys_size_t rgnflags = rgn[i].flags;
390 phys_addr_t end = base + size - 1;
391 phys_addr_t rgnend = rgnbase + rgnsize - 1;
392 if (rgnbase <= base && end <= rgnend) {
393 if (flags == rgnflags)
394 /* Already have this region, so we're done */
397 return -1; /* regions with new flags */
400 ret = lmb_addrs_adjacent(base, size, rgnbase, rgnsize);
402 if (flags != rgnflags)
408 } else if (ret < 0) {
409 if (flags != rgnflags)
414 } else if (lmb_addrs_overlap(base, size, rgnbase, rgnsize)) {
415 if (flags == LMB_NONE) {
416 ret = lmb_resize_regions(lmb_rgn_lst, i, base,
429 if (lmb_rgn_lst->count && i < lmb_rgn_lst->count - 1) {
430 rgn = lmb_rgn_lst->data;
431 if (rgn[i].flags == rgn[i + 1].flags) {
432 if (lmb_regions_adjacent(lmb_rgn_lst, i, i + 1)) {
433 lmb_coalesce_regions(lmb_rgn_lst, i, i + 1);
435 } else if (lmb_regions_overlap(lmb_rgn_lst, i, i + 1)) {
436 /* fix overlapping area */
437 lmb_fix_over_lap_regions(lmb_rgn_lst, i, i + 1);
446 if (alist_full(lmb_rgn_lst) &&
447 !alist_expand_by(lmb_rgn_lst, lmb_rgn_lst->alloc))
449 rgn = lmb_rgn_lst->data;
451 /* Couldn't coalesce the LMB, so add it to the sorted table. */
452 for (i = lmb_rgn_lst->count; i >= 0; i--) {
453 if (i && base < rgn[i - 1].base) {
458 rgn[i].flags = flags;
463 lmb_rgn_lst->count++;
468 static long lmb_add_region(struct alist *lmb_rgn_lst, phys_addr_t base,
471 return lmb_add_region_flags(lmb_rgn_lst, base, size, LMB_NONE);
474 /* This routine may be called with relocation disabled. */
475 long lmb_add(phys_addr_t base, phys_size_t size)
477 struct alist *lmb_rgn_lst = &lmb.free_mem;
479 return lmb_add_region(lmb_rgn_lst, base, size);
482 long lmb_free(phys_addr_t base, phys_size_t size)
484 struct lmb_region *rgn;
485 struct alist *lmb_rgn_lst = &lmb.used_mem;
486 phys_addr_t rgnbegin, rgnend;
487 phys_addr_t end = base + size - 1;
490 rgnbegin = rgnend = 0; /* supress gcc warnings */
491 rgn = lmb_rgn_lst->data;
492 /* Find the region where (base, size) belongs to */
493 for (i = 0; i < lmb_rgn_lst->count; i++) {
494 rgnbegin = rgn[i].base;
495 rgnend = rgnbegin + rgn[i].size - 1;
497 if ((rgnbegin <= base) && (end <= rgnend))
501 /* Didn't find the region */
502 if (i == lmb_rgn_lst->count)
505 /* Check to see if we are removing entire region */
506 if ((rgnbegin == base) && (rgnend == end)) {
507 lmb_remove_region(lmb_rgn_lst, i);
511 /* Check to see if region is matching at the front */
512 if (rgnbegin == base) {
513 rgn[i].base = end + 1;
518 /* Check to see if the region is matching at the end */
525 * We need to split the entry - adjust the current one to the
526 * beginging of the hole and add the region after hole.
528 rgn[i].size = base - rgn[i].base;
529 return lmb_add_region_flags(lmb_rgn_lst, end + 1, rgnend - end,
533 long lmb_reserve_flags(phys_addr_t base, phys_size_t size, enum lmb_flags flags)
535 struct alist *lmb_rgn_lst = &lmb.used_mem;
537 return lmb_add_region_flags(lmb_rgn_lst, base, size, flags);
540 long lmb_reserve(phys_addr_t base, phys_size_t size)
542 return lmb_reserve_flags(base, size, LMB_NONE);
545 static long lmb_overlaps_region(struct alist *lmb_rgn_lst, phys_addr_t base,
549 struct lmb_region *rgn = lmb_rgn_lst->data;
551 for (i = 0; i < lmb_rgn_lst->count; i++) {
552 phys_addr_t rgnbase = rgn[i].base;
553 phys_size_t rgnsize = rgn[i].size;
554 if (lmb_addrs_overlap(base, size, rgnbase, rgnsize))
558 return (i < lmb_rgn_lst->count) ? i : -1;
561 static phys_addr_t lmb_align_down(phys_addr_t addr, phys_size_t size)
563 return addr & ~(size - 1);
566 static phys_addr_t __lmb_alloc_base(phys_size_t size, ulong align,
567 phys_addr_t max_addr, enum lmb_flags flags)
570 phys_addr_t base = 0;
571 phys_addr_t res_base;
572 struct lmb_region *lmb_used = lmb.used_mem.data;
573 struct lmb_region *lmb_memory = lmb.free_mem.data;
575 for (i = lmb.free_mem.count - 1; i >= 0; i--) {
576 phys_addr_t lmbbase = lmb_memory[i].base;
577 phys_size_t lmbsize = lmb_memory[i].size;
581 if (max_addr == LMB_ALLOC_ANYWHERE)
582 base = lmb_align_down(lmbbase + lmbsize - size, align);
583 else if (lmbbase < max_addr) {
584 base = lmbbase + lmbsize;
587 base = min(base, max_addr);
588 base = lmb_align_down(base - size, align);
592 while (base && lmbbase <= base) {
593 rgn = lmb_overlaps_region(&lmb.used_mem, base, size);
595 /* This area isn't reserved, take it */
596 if (lmb_add_region_flags(&lmb.used_mem, base,
602 res_base = lmb_used[rgn].base;
605 base = lmb_align_down(res_base - size, align);
611 phys_addr_t lmb_alloc(phys_size_t size, ulong align)
613 return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
616 phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr)
620 alloc = __lmb_alloc_base(size, align, max_addr, LMB_NONE);
623 printf("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n",
624 (ulong)size, (ulong)max_addr);
629 static phys_addr_t __lmb_alloc_addr(phys_addr_t base, phys_size_t size,
630 enum lmb_flags flags)
633 struct lmb_region *lmb_memory = lmb.free_mem.data;
635 /* Check if the requested address is in one of the memory regions */
636 rgn = lmb_overlaps_region(&lmb.free_mem, base, size);
639 * Check if the requested end address is in the same memory
642 if (lmb_addrs_overlap(lmb_memory[rgn].base,
643 lmb_memory[rgn].size,
644 base + size - 1, 1)) {
645 /* ok, reserve the memory */
646 if (lmb_reserve_flags(base, size, flags) >= 0)
655 * Try to allocate a specific address range: must be in defined memory but not
658 phys_addr_t lmb_alloc_addr(phys_addr_t base, phys_size_t size)
660 return __lmb_alloc_addr(base, size, LMB_NONE);
663 /* Return number of bytes from a given address that are free */
664 phys_size_t lmb_get_free_size(phys_addr_t addr)
668 struct lmb_region *lmb_used = lmb.used_mem.data;
669 struct lmb_region *lmb_memory = lmb.free_mem.data;
671 /* check if the requested address is in the memory regions */
672 rgn = lmb_overlaps_region(&lmb.free_mem, addr, 1);
674 for (i = 0; i < lmb.used_mem.count; i++) {
675 if (addr < lmb_used[i].base) {
676 /* first reserved range > requested address */
677 return lmb_used[i].base - addr;
679 if (lmb_used[i].base +
680 lmb_used[i].size > addr) {
681 /* requested addr is in this reserved range */
685 /* if we come here: no reserved ranges above requested addr */
686 return lmb_memory[lmb.free_mem.count - 1].base +
687 lmb_memory[lmb.free_mem.count - 1].size - addr;
692 int lmb_is_reserved_flags(phys_addr_t addr, int flags)
695 struct lmb_region *lmb_used = lmb.used_mem.data;
697 for (i = 0; i < lmb.used_mem.count; i++) {
698 phys_addr_t upper = lmb_used[i].base +
699 lmb_used[i].size - 1;
700 if (addr >= lmb_used[i].base && addr <= upper)
701 return (lmb_used[i].flags & flags) == flags;
706 static int lmb_setup(void)
710 ret = alist_init(&lmb.free_mem, sizeof(struct lmb_region),
711 (uint)LMB_ALIST_INITIAL_SIZE);
713 log_debug("Unable to initialise the list for LMB free memory\n");
717 ret = alist_init(&lmb.used_mem, sizeof(struct lmb_region),
718 (uint)LMB_ALIST_INITIAL_SIZE);
720 log_debug("Unable to initialise the list for LMB used memory\n");
728 * lmb_init() - Initialise the LMB module
730 * Initialise the LMB lists needed for keeping the memory map. There
731 * are two lists, in form of alloced list data structure. One for the
732 * available memory, and one for the used memory. Initialise the two
733 * lists as part of board init. Add memory to the available memory
734 * list and reserve common areas by adding them to the used memory
737 * Return: 0 on success, -ve on error
745 log_info("Unable to init LMB\n");
751 /* Reserve the U-Boot image region once U-Boot has relocated */
752 if (xpl_phase() == PHASE_SPL)
753 lmb_reserve_common_spl();
754 else if (xpl_phase() == PHASE_BOARD_R)
755 lmb_reserve_common((void *)gd->fdt_blob);
760 #if CONFIG_IS_ENABLED(UNIT_TEST)
761 struct lmb *lmb_get(void)
766 int lmb_push(struct lmb *store)
778 void lmb_pop(struct lmb *store)
780 alist_uninit(&lmb.free_mem);
781 alist_uninit(&lmb.used_mem);
784 #endif /* UNIT_TEST */