[RFC 1/1] lib: lmb: add lmb_get_reservable_size, fix ramfs
Tomas Alvarez Vanoli
tomas.alvarez-vanoli at hitachienergy.com
Tue Aug 5 11:40:12 CEST 2025
Our implementation of the ramfs kernel memory calculation relied on the
fact that the lmb library was working with local copies of the lmb
table.
This was updated in u-boot 2025, now the lmb library uses a static table
shared globally. The function that we were using to calculate how much
ram to give to the kernel checks the free size, which does not include
memory that was allocated but not reserved. For example, when we load
the bootfs with tftp, that memory is allocated by the tftp code. This
memory will be overwritten if some other command wants to use it, but it
will not show as free.
This commit introduces the function "lmb_get_reservable_size", which is
exactly like "lmb_get_free_size" except it also considers memory with
flags set to 0 as free.
Signed-off-by: Tomas Alvarez Vanoli <tomas.alvarez-vanoli at hitachienergy.com>
---
board/keymile/common/common.c | 10 ++++++++--
include/lmb.h | 1 +
lib/lmb.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/board/keymile/common/common.c b/board/keymile/common/common.c
index 9b1068376b3..46e04a25abd 100644
--- a/board/keymile/common/common.c
+++ b/board/keymile/common/common.c
@@ -40,7 +40,6 @@ static int do_calc_ramfs_addr(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_FAILURE;
}
- // "Allocate" space for the rootfs (it's only on our local lmb struct)
phys_addr_t addr = lmb_alloc(size, SZ_16K);
if (addr == 0) {
@@ -49,12 +48,19 @@ static int do_calc_ramfs_addr(struct cmd_tbl *cmdtp, int flag, int argc,
}
// calculate how much ram we can give the kernel
- phys_size_t free = lmb_get_free_size(CFG_SYS_SDRAM_BASE) & ~(SZ_16K - 1);
+ phys_size_t free = lmb_get_reservable_size(CFG_SYS_SDRAM_BASE) & ~(SZ_16K - 1);
if (free <= 0) {
printf("%s: failed to calculate free memory for kernel\n", __func__);
return CMD_RET_FAILURE;
}
+ /* We dont reserve the memory for the rootfs, because tftp needs to write it.
+ * because of that, we check here if the kernel memory overlaps it or not.
+ */
+ if (CFG_SYS_SDRAM_BASE + free > addr) {
+ free = (addr - CFG_SYS_SDRAM_BASE) & ~(SZ_16K - 1);
+ }
+
char envval[20];
sprintf(envval, "%pa", &addr);
env_set("rootfsaddr", envval);
diff --git a/include/lmb.h b/include/lmb.h
index 606a92cca48..74513c38369 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -106,6 +106,7 @@ long lmb_reserve(phys_addr_t base, phys_size_t size, u32 flags);
phys_addr_t lmb_alloc(phys_size_t size, ulong align);
phys_size_t lmb_get_free_size(phys_addr_t addr);
+phys_size_t lmb_get_reservable_size(phys_addr_t addr);
/**
* lmb_alloc_base() - Allocate specified memory region with specified
diff --git a/lib/lmb.c b/lib/lmb.c
index bf11405fa57..4537f582a5d 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -802,6 +802,37 @@ phys_size_t lmb_get_free_size(phys_addr_t addr)
return 0;
}
+/* Return number of bytes from a given address that are free or have no flags */
+phys_size_t lmb_get_reservable_size(phys_addr_t addr)
+{
+ int i;
+ long rgn;
+ struct lmb_region *lmb_used = lmb.used_mem.data;
+ struct lmb_region *lmb_memory = lmb.available_mem.data;
+
+ /* check if the requested address is in the memory regions */
+ rgn = lmb_overlaps_region(&lmb.available_mem, addr, 1);
+ if (rgn >= 0) {
+ for (i = 0; i < lmb.used_mem.count; i++) {
+ if (!lmb_used[i].flags)
+ continue;
+ if (addr < lmb_used[i].base) {
+ /* first reserved range > requested address */
+ return lmb_used[i].base - addr;
+ }
+ if (lmb_used[i].base +
+ lmb_used[i].size > addr) {
+ /* requested addr is in this reserved range */
+ return 0;
+ }
+ }
+ /* if we come here: no reserved ranges above requested addr */
+ return lmb_memory[lmb.available_mem.count - 1].base +
+ lmb_memory[lmb.available_mem.count - 1].size - addr;
+ }
+ return 0;
+}
+
int lmb_is_reserved_flags(phys_addr_t addr, int flags)
{
int i;
--
2.43.0
More information about the U-Boot
mailing list