[RFC PATCH v2 48/48] temp: mx6sabresd: bump up the size limit of the board

2024-07-04 Thread Sughosh Ganu
With the changes to add notifications for any changes to the LMB map,
the size of the image exceeds the limit set. Bump up the image size
limit for now to get the platform to build.

This is not for committing.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: None

 configs/mx6sabresd_defconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configs/mx6sabresd_defconfig b/configs/mx6sabresd_defconfig
index 868f6b1551..7308ae2ec6 100644
--- a/configs/mx6sabresd_defconfig
+++ b/configs/mx6sabresd_defconfig
@@ -23,7 +23,7 @@ CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_PCI=y
 CONFIG_LTO=y
 CONFIG_HAS_BOARD_SIZE_LIMIT=y
-CONFIG_BOARD_SIZE_LIMIT=715766
+CONFIG_BOARD_SIZE_LIMIT=718108
 CONFIG_FIT=y
 CONFIG_SPL_FIT_PRINT=y
 CONFIG_SPL_LOAD_FIT=y
-- 
2.34.1



[RFC PATCH v2 47/48] test: event: update the expected event dump output

2024-07-04 Thread Sughosh Ganu
With the addition of two events for notification of any changes to
memory that is occupied and is free, the output of the event_dump.py
script has changed. Update the expected event log to incorporate this
change.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Remove the line for EFI mem map update.

 test/py/tests/test_event_dump.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py
index e282c67335..3537f0383c 100644
--- a/test/py/tests/test_event_dump.py
+++ b/test/py/tests/test_event_dump.py
@@ -19,6 +19,7 @@ def test_event_dump(u_boot_console):
 EVT_FT_FIXUP  bootmeth_vbe_ft_fixup   .*boot/vbe_request.c:.*
 EVT_FT_FIXUP  bootmeth_vbe_simple_ft_fixup.*boot/vbe_simple_os.c:.*
 EVT_LAST_STAGE_INIT   install_smbios_table
.*lib/efi_loader/efi_smbios.c:.*
+EVT_LMB_MAP_UPDATElmb_mem_map_update_sync 
.*lib/efi_loader/efi_memory.c:.*
 EVT_MISC_INIT_F   sandbox_early_getopt_check  
.*arch/sandbox/cpu/start.c:.*
 EVT_TEST  h_adder_simple  .*test/common/event.c:'''
 assert re.match(expect, out, re.MULTILINE) is not None
-- 
2.34.1



[RFC PATCH v2 46/48] lmb: mark the EFI runtime memory regions as reserved

2024-07-04 Thread Sughosh Ganu
Mark the EFI runtime memory region as reserved memory during board
init so that it does not get allocated by the LMB module on subsequent
memory requests.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 lib/lmb.c | 41 -
 1 file changed, 20 insertions(+), 21 deletions(-)

diff --git a/lib/lmb.c b/lib/lmb.c
index 387ec2ac65..6018f1de31 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -212,33 +213,31 @@ void arch_lmb_reserve_generic(ulong sp, ulong end, ulong 
align)
 /**
  * efi_lmb_reserve() - add reservations for EFI memory
  *
- * Add reservations for all EFI memory areas that are not
- * EFI_CONVENTIONAL_MEMORY.
+ * Add reservations for EFI runtime services memory
  *
- * Return: 0 on success, 1 on failure
+ * Return: None
  */
-static __maybe_unused int efi_lmb_reserve(void)
+static __maybe_unused void efi_lmb_reserve(void)
 {
-   struct efi_mem_desc *memmap = NULL, *map;
-   efi_uintn_t i, map_size = 0;
-   efi_status_t ret;
+   phys_addr_t runtime_start, runtime_end;
+   unsigned long runtime_mask = EFI_PAGE_MASK;
 
-   ret = efi_get_memory_map_alloc(_size, );
-   if (ret != EFI_SUCCESS)
-   return 1;
+#if defined(__aarch64__)
+   /*
+* Runtime Services must be 64KiB aligned according to the
+* "AArch64 Platforms" section in the UEFI spec (2.7+).
+*/
 
-   for (i = 0, map = memmap; i < map_size / sizeof(*map); ++map, ++i) {
-   if (map->type != EFI_CONVENTIONAL_MEMORY) {
-   lmb_reserve_flags(map_to_sysmem((void *)(uintptr_t)
-   map->physical_start),
- map->num_pages * EFI_PAGE_SIZE,
- map->type == EFI_RESERVED_MEMORY_TYPE
- ? LMB_NOMAP : LMB_NONE);
-   }
-   }
-   efi_free_pool(memmap);
+   runtime_mask = SZ_64K - 1;
+#endif
 
-   return 0;
+   /* Reserve the EFI runtime services memory */
+   runtime_start = (uintptr_t)__efi_runtime_start & ~runtime_mask;
+   runtime_end = (uintptr_t)__efi_runtime_stop;
+   runtime_end = (runtime_end + runtime_mask) & ~runtime_mask;
+
+   lmb_reserve_flags(runtime_start, runtime_end - runtime_start,
+ LMB_NOOVERWRITE | LMB_NONOTIFY);
 }
 
 static void lmb_reserve_common(void *fdt_blob)
-- 
2.34.1



[RFC PATCH v2 45/48] efi_memory: do not add RAM memory to the memory map

2024-07-04 Thread Sughosh Ganu
The EFI_CONVENTIONAL_MEMORY type, which is the usable RAM memory is
now being managed by the LMB module. Remove the addition of this
memory type to the EFI memory map. This memory now gets added to the
EFI memory map as part of the LMB memory map update event handler.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 include/efi_loader.h| 12 +++---
 lib/efi_loader/efi_memory.c | 75 +++--
 2 files changed, 12 insertions(+), 75 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 6c993e1a69..e5090afe2a 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -795,9 +795,6 @@ efi_status_t efi_get_memory_map(efi_uintn_t 
*memory_map_size,
uint32_t *descriptor_version);
 /* Adds a range into the EFI memory map */
 efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type);
-/* Adds a conventional range into the EFI memory map */
-efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
-u64 ram_top);
 
 /* Called by board init to initialize the EFI drivers */
 efi_status_t efi_driver_init(void);
@@ -1183,9 +1180,14 @@ efi_status_t efi_console_get_u16_string
 efi_status_t efi_disk_get_device_name(const efi_handle_t handle, char *buf, 
int size);
 
 /**
- * efi_add_known_memory() - add memory banks to EFI memory map
+ * efi_add_known_memory() - add memory types to the EFI memory map
  *
- * This weak function may be overridden for specific architectures.
+ * This function is to be used to adding different memory types other
+ * than EFI_CONVENTIONAL_MEMORY to the EFI memory map. The conventional
+ * memory is handled by the LMB module, and gets added to the memory
+ * map through the LMB module.
+ *
+ * This function may be overridden for specific architectures.
  */
 void efi_add_known_memory(void);
 
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index bd12504f72..3ceb670e79 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -793,82 +793,17 @@ efi_status_t efi_get_memory_map_alloc(efi_uintn_t 
*map_size,
 }
 
 /**
- * efi_add_conventional_memory_map() - add a RAM memory area to the map
+ * efi_add_known_memory() - add memory types to the EFI memory map
  *
- * @ram_start: start address of a RAM memory area
- * @ram_end:   end address of a RAM memory area
- * @ram_top:   max address to be used as conventional memory
- * Return: status code
- */
-efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
-u64 ram_top)
-{
-   u64 pages;
-
-   /* Remove partial pages */
-   ram_end &= ~EFI_PAGE_MASK;
-   ram_start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
-
-   if (ram_end <= ram_start) {
-   /* Invalid mapping */
-   return EFI_INVALID_PARAMETER;
-   }
-
-   pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT;
-
-   efi_add_memory_map_pg(ram_start, pages,
- EFI_CONVENTIONAL_MEMORY, false);
-
-   /*
-* Boards may indicate to the U-Boot memory core that they
-* can not support memory above ram_top. Let's honor this
-* in the efi_loader subsystem too by declaring any memory
-* above ram_top as "already occupied by firmware".
-*/
-   if (ram_top < ram_start) {
-   /* ram_top is before this region, reserve all */
-   efi_add_memory_map_pg(ram_start, pages,
- EFI_BOOT_SERVICES_DATA, true);
-   } else if (ram_top < ram_end) {
-   /* ram_top is inside this region, reserve parts */
-   pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT;
-
-   efi_add_memory_map_pg(ram_top, pages,
- EFI_BOOT_SERVICES_DATA, true);
-   }
-
-   return EFI_SUCCESS;
-}
-
-/**
- * efi_add_known_memory() - add memory banks to map
+ * This function is to be used to adding different memory types other
+ * than EFI_CONVENTIONAL_MEMORY to the EFI memory map. The conventional
+ * memory is handled by the LMB module, and gets added to the memory
+ * map through the LMB module.
  *
  * This function may be overridden for specific architectures.
  */
 __weak void efi_add_known_memory(void)
 {
-   u64 ram_top = gd->ram_top & ~EFI_PAGE_MASK;
-   int i;
-
-   /*
-* ram_top is just outside mapped memory. So use an offset of one for
-* mapping the sandbox address.
-*/
-   ram_top = (uintptr_t)map_sysmem(ram_top - 1, 0) + 1;
-
-   /* Fix for 32bit targets with ram_top at 4G */
-   if (!ram_top)
-   ram_top = 0x1ULL;
-
-   /* Add RAM */
-   for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-   u64 ram_end, ram_start;
-
-   ra

[RFC PATCH v2 44/48] x86: e820: use the lmb API for adding RAM memory

2024-07-04 Thread Sughosh Ganu
The EFI_CONVENTIONAL_MEMORY type is now being managed through the LMB
module. Add a separate function, lmb_add_memory() to add the RAM
memory to the LMB memory map. The efi_add_known_memory() function is
now used for adding any other memory type to the EFI memory map.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 arch/x86/lib/e820.c | 47 ++---
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/arch/x86/lib/e820.c b/arch/x86/lib/e820.c
index 122b4f7ca0..8b3ce8c6ec 100644
--- a/arch/x86/lib/e820.c
+++ b/arch/x86/lib/e820.c
@@ -4,6 +4,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 
@@ -41,15 +42,11 @@ void efi_add_known_memory(void)
 {
struct e820_entry e820[E820MAX];
unsigned int i, num;
-   u64 start, ram_top;
+   u64 start;
int type;
 
num = install_e820_map(ARRAY_SIZE(e820), e820);
 
-   ram_top = (u64)gd->ram_top & ~EFI_PAGE_MASK;
-   if (!ram_top)
-   ram_top = 0x1ULL;
-
for (i = 0; i < num; ++i) {
start = e820[i].addr;
 
@@ -72,13 +69,41 @@ void efi_add_known_memory(void)
break;
}
 
-   if (type == EFI_CONVENTIONAL_MEMORY) {
-   efi_add_conventional_memory_map(start,
-   start + e820[i].size,
-   ram_top);
-   } else {
+   if (type != EFI_CONVENTIONAL_MEMORY)
efi_add_memory_map(start, e820[i].size, type);
-   }
}
 }
 #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
+
+#if CONFIG_IS_ENABLED(LMB)
+void lmb_add_memory(void)
+{
+   struct e820_entry e820[E820MAX];
+   unsigned int i, num;
+   u64 ram_top;
+
+   num = install_e820_map(ARRAY_SIZE(e820), e820);
+
+   ram_top = (u64)gd->ram_top & ~EFI_PAGE_MASK;
+   if (!ram_top)
+   ram_top = 0x1ULL;
+
+   for (i = 0; i < num; ++i) {
+   if (e820[i].type == E820_RAM) {
+   u64 start, size, rgn_top;
+
+   start = e820[i].addr;
+   size = e820[i].size;
+   rgn_top = start + size;
+
+   if (start > ram_top)
+   continue;
+
+   if (rgn_top > ram_top)
+   size -= rgn_top - ram_top;
+
+   lmb_add(start, size);
+   }
+   }
+}
+#endif /* CONFIG_IS_ENABLED(LMB) */
-- 
2.34.1



[RFC PATCH v2 43/48] layerscape: use the lmb API's to add RAM memory

2024-07-04 Thread Sughosh Ganu
The EFI memory allocations are now being done through the LMB module,
and hence the memory map is maintained by the LMB module. Use the
lmb_add_memory() API function to add the usable RAM memory to the
LMB's memory map.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c 
b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index d2dbfdd08a..dacb95f1a8 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1525,8 +1526,8 @@ int dram_init_banksize(void)
return 0;
 }
 
-#if CONFIG_IS_ENABLED(EFI_LOADER)
-void efi_add_known_memory(void)
+#if CONFIG_IS_ENABLED(LMB)
+void lmb_add_memory(void)
 {
int i;
phys_addr_t ram_start;
@@ -1548,8 +1549,7 @@ void efi_add_known_memory(void)
gd->arch.resv_ram < ram_start + ram_size)
ram_size = gd->arch.resv_ram - ram_start;
 #endif
-   efi_add_memory_map(ram_start, ram_size,
-  EFI_CONVENTIONAL_MEMORY);
+   lmb_add(ram_start, ram_size);
}
 }
 #endif
-- 
2.34.1



[RFC PATCH v2 42/48] ti: k3: remove efi_add_known_memory() function definition

2024-07-04 Thread Sughosh Ganu
The efi_add_known_memory() function for the TI K3 platforms is adding
the EFI_CONVENTIONAL_MEMORY type. This memory is now being handled
through the LMB module -- the lmb_add_memory() adds this memory to the
memory map. Remove the definition of the now superfluous
efi_add_known_memory() function.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 arch/arm/mach-k3/common.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index eaa7d36176..a5c0170cd2 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -310,14 +310,3 @@ void setup_qos(void)
writel(qos_data[i].val, (uintptr_t)qos_data[i].reg);
 }
 #endif
-
-void efi_add_known_memory(void)
-{
-   if (IS_ENABLED(CONFIG_EFI_LOADER))
-   /*
-* Memory over ram_top can be used by various firmware
-* Declare to EFI only memory area below ram_top
-*/
-   efi_add_memory_map(gd->ram_base, gd->ram_top - gd->ram_base,
-  EFI_CONVENTIONAL_MEMORY);
-}
-- 
2.34.1



[RFC PATCH v2 41/48] efi_memory: add an event handler to update memory map

2024-07-04 Thread Sughosh Ganu
There are events that would be used to notify other interested modules
of any changes in available and occupied memory. This would happen
when a module allocates or reserves memory, or frees up memory. These
changes in memory map should be notified to other interested modules
so that the allocated memory does not get overwritten. Add an event
handler in the EFI memory module to update the EFI memory map
accordingly when such changes happen. As a consequence, any subsequent
memory request would honour the updated memory map and only available
memory would be allocated from.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Handle the addition of memory to the LMB memory map.
* Pass the overlap_only_ram parameter to the efi_add_memory_map_pg()
  based on the type of operation.

 lib/efi_loader/Kconfig  |  1 +
 lib/efi_loader/efi_memory.c | 34 ++
 2 files changed, 35 insertions(+)

diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index bdf5732974..2d90bcef2f 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -16,6 +16,7 @@ config EFI_LOADER
select CHARSET
# We need to send DM events, dynamically, in the EFI block driver
select DM_EVENT
+   select EVENT
select EVENT_DYNAMIC
select LIB_UUID
select LMB
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 5691b5da03..bd12504f72 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -45,6 +45,10 @@ static LIST_HEAD(efi_mem);
 void *efi_bounce_buffer;
 #endif
 
+#define MAP_OP_RESERVE (u8)0x1
+#define MAP_OP_FREE(u8)0x2
+#define MAP_OP_ADD (u8)0x3
+
 /**
  * struct efi_pool_allocation - memory block allocated from pool
  *
@@ -928,3 +932,33 @@ int efi_memory_init(void)
 
return 0;
 }
+
+#if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
+static int lmb_mem_map_update_sync(void *ctx, struct event *event)
+{
+   u8 op;
+   u64 addr;
+   u64 pages;
+   efi_status_t status;
+   struct event_lmb_map_update *lmb_map = >data.lmb_map;
+
+   addr = (uintptr_t)map_sysmem(lmb_map->base, 0);
+   pages = efi_size_in_pages(lmb_map->size + (addr & EFI_PAGE_MASK));
+   op = lmb_map->op;
+   addr &= ~EFI_PAGE_MASK;
+
+   if (op != MAP_OP_RESERVE && op != MAP_OP_FREE && op != MAP_OP_ADD) {
+   log_debug("Invalid map update op received (%d)\n", op);
+   return -1;
+   }
+
+   status = efi_add_memory_map_pg(addr, pages,
+  op == MAP_OP_RESERVE ?
+  EFI_BOOT_SERVICES_DATA :
+  EFI_CONVENTIONAL_MEMORY,
+  op == MAP_OP_RESERVE ? true : false);
+
+   return status == EFI_SUCCESS ? 0 : -1;
+}
+EVENT_SPY_FULL(EVT_LMB_MAP_UPDATE, lmb_mem_map_update_sync);
+#endif /* MEM_MAP_UPDATE_NOTIFY */
-- 
2.34.1



[RFC PATCH v2 40/48] lmb: notify of any changes to the LMB memory map

2024-07-04 Thread Sughosh Ganu
In U-Boot, LMB and EFI are two primary modules who provide memory
allocation and reservation API's. Both these modules operate with the
same regions of memory for allocations. Use the LMB memory map update
event to notify other interested listeners about a change in it's
memory map. This can then be used by the other module to keep track of
available and used memory.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Notify addition of memory to the LMB memory map.
* Add a function lmb_notify() to check if notification has to be sent.

 lib/lmb.c | 61 ---
 1 file changed, 58 insertions(+), 3 deletions(-)

diff --git a/lib/lmb.c b/lib/lmb.c
index d2edb3525a..387ec2ac65 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -21,12 +22,36 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define MAP_OP_RESERVE (u8)0x1
+#define MAP_OP_FREE(u8)0x2
+#define MAP_OP_ADD (u8)0x3
+
 #define LMB_ALLOC_ANYWHERE 0
 #define LMB_ALIST_INITIAL_SIZE 4
 
 struct alist lmb_free_mem;
 struct alist lmb_used_mem;
 
+extern bool is_addr_in_ram(uintptr_t addr);
+
+static bool lmb_notify(enum lmb_flags flags)
+{
+   return !(flags & LMB_NONOTIFY);
+}
+
+static void lmb_map_update_notify(phys_addr_t addr, phys_size_t size,
+ u8 op)
+{
+   struct event_lmb_map_update lmb_map = {0};
+
+   lmb_map.base = addr;
+   lmb_map.size = size;
+   lmb_map.op = op;
+
+   if (is_addr_in_ram((uintptr_t)addr))
+   event_notify(EVT_LMB_MAP_UPDATE, _map, sizeof(lmb_map));
+}
+
 static void lmb_dump_region(struct alist *lmb_rgn_lst, char *name)
 {
struct lmb_region *rgn = lmb_rgn_lst->data;
@@ -463,9 +488,17 @@ static long lmb_add_region(struct alist *lmb_rgn_lst, 
phys_addr_t base,
 /* This routine may be called with relocation disabled. */
 long lmb_add(phys_addr_t base, phys_size_t size)
 {
+   long ret;
struct alist *lmb_rgn_lst = _free_mem;
 
-   return lmb_add_region(lmb_rgn_lst, base, size);
+   ret = lmb_add_region(lmb_rgn_lst, base, size);
+   if (ret)
+   return ret;
+
+   if (CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY))
+   lmb_map_update_notify(base, size, MAP_OP_ADD);
+
+   return 0;
 }
 
 static long __lmb_free(phys_addr_t base, phys_size_t size)
@@ -521,7 +554,16 @@ static long __lmb_free(phys_addr_t base, phys_size_t size)
 
 long lmb_free(phys_addr_t base, phys_size_t size)
 {
-   return __lmb_free(base, size);
+   long ret;
+
+   ret = __lmb_free(base, size);
+   if (ret < 0)
+   return ret;
+
+   if (CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY))
+   lmb_map_update_notify(base, size, MAP_OP_FREE);
+
+   return 0;
 }
 
 long lmb_free_flags(phys_addr_t base, phys_size_t size,
@@ -532,9 +574,17 @@ long lmb_free_flags(phys_addr_t base, phys_size_t size,
 
 long lmb_reserve_flags(phys_addr_t base, phys_size_t size, enum lmb_flags 
flags)
 {
+   long ret = 0;
struct alist *lmb_rgn_lst = _used_mem;
 
-   return lmb_add_region_flags(lmb_rgn_lst, base, size, flags);
+   ret = lmb_add_region_flags(lmb_rgn_lst, base, size, flags);
+   if (ret < 0)
+   return -1;
+
+   if (CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY) && lmb_notify(flags))
+   lmb_map_update_notify(base, size, MAP_OP_RESERVE);
+
+   return ret;
 }
 
 long lmb_reserve(phys_addr_t base, phys_size_t size)
@@ -596,6 +646,11 @@ static phys_addr_t __lmb_alloc_base(phys_size_t size, 
ulong align,
if (lmb_add_region_flags(_used_mem, base,
   size, flags) < 0)
return 0;
+
+   if (CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY) &&
+   lmb_notify(flags))
+   lmb_map_update_notify(base, size,
+ MAP_OP_RESERVE);
return base;
}
 
-- 
2.34.1



[RFC PATCH v2 39/48] add a function to check if an address is in RAM memory

2024-07-04 Thread Sughosh Ganu
Add a function to check if a given address falls within the RAM
address used by U-Boot. This will be used to notify other modules if
the address gets allocated, so as to not get re-allocated by some
other module.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Have a common weak function for all platforms, sandbox included.

 common/board_r.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index 1a5bb98218..427688168c 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -72,6 +72,11 @@ DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
 
+__weak bool __maybe_unused is_addr_in_ram(uintptr_t addr)
+{
+   return addr >= gd->ram_base && addr <= gd->ram_top;
+}
+
 __weak int board_flash_wp_on(void)
 {
/*
-- 
2.34.1



[RFC PATCH v2 38/48] lib: Kconfig: add a config symbol for getting lmb memory map updates

2024-07-04 Thread Sughosh Ganu
Add a Kconfig symbol to enable getting updates on any memory map
changes that might be done by the LMB module. This notification
mechanism can then be used to have a synchronous view of allocated and
free memory.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Change the description to highlight only LMB notifications.
* Add a separate line for dependencies.

 lib/Kconfig | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/lib/Kconfig b/lib/Kconfig
index 7eea517b3b..b422183a0f 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -74,6 +74,16 @@ config HAVE_PRIVATE_LIBGCC
 config LIB_UUID
bool
 
+config MEM_MAP_UPDATE_NOTIFY
+   bool "Get notified of any changes to the LMB memory map"
+   depends on EVENT && LMB && EFI_LOADER
+   default y
+   help
+ Enable this option to get notification on any changes to the
+ memory that is allocated or freed by the LMB module. This will
+ allow different modules that allocate memory or maintain a memory
+ map to have a synchronous view of available and allocated memory.
+
 config RANDOM_UUID
bool "GPT Random UUID generation"
select LIB_UUID
-- 
2.34.1



[RFC PATCH v2 37/48] event: add event to notify lmb memory map changes

2024-07-04 Thread Sughosh Ganu
Add an event which would be used for notifying changes in the
LMB modules' memory map. This is to be used for having a
synchronous view of the memory that is currently in use, and that is
available for allocations.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Remove the event for EFI notifications.

 common/event.c  |  2 ++
 include/event.h | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/common/event.c b/common/event.c
index dda569d447..fc8002603c 100644
--- a/common/event.c
+++ b/common/event.c
@@ -48,6 +48,8 @@ const char *const type_name[] = {
 
/* main loop events */
"main_loop",
+
+   "lmb_map_update",
 };
 
 _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
diff --git a/include/event.h b/include/event.h
index fb353ad623..fce7e96170 100644
--- a/include/event.h
+++ b/include/event.h
@@ -153,6 +153,14 @@ enum event_t {
 */
EVT_MAIN_LOOP,
 
+   /**
+* @EVT_LMB_MAP_UPDATE:
+* This event is triggered on an update to the LMB reserved memory
+* region. This can be used to notify about any LMB memory allocation
+* or freeing of memory having occurred.
+*/
+   EVT_LMB_MAP_UPDATE,
+
/**
 * @EVT_COUNT:
 * This constants holds the maximum event number + 1 and is used when
@@ -203,6 +211,12 @@ union event_data {
oftree tree;
struct bootm_headers *images;
} ft_fixup;
+
+   struct event_lmb_map_update {
+   u64 base;
+   u64 size;
+   u8 op;
+   } lmb_map;
 };
 
 /**
-- 
2.34.1



[RFC PATCH v2 36/48] efi: memory: use the lmb API's for allocating and freeing memory

2024-07-04 Thread Sughosh Ganu
Use the LMB API's for allocating and freeing up memory. With this, the
LMB module becomes the common backend for managing non U-Boot image
memory that might be requested by other modules.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 lib/efi_loader/Kconfig  |  1 +
 lib/efi_loader/efi_memory.c | 78 +++--
 2 files changed, 23 insertions(+), 56 deletions(-)

diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index ee71f41714..bdf5732974 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -18,6 +18,7 @@ config EFI_LOADER
select DM_EVENT
select EVENT_DYNAMIC
select LIB_UUID
+   select LMB
imply PARTITION_UUIDS
select REGEX
imply FAT
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 12cf23fa3f..5691b5da03 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -9,12 +9,14 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -435,55 +437,6 @@ static efi_status_t efi_check_allocated(u64 addr, bool 
must_be_allocated)
return EFI_NOT_FOUND;
 }
 
-/**
- * efi_find_free_memory() - find free memory pages
- *
- * @len:   size of memory area needed
- * @max_addr:  highest address to allocate
- * Return: pointer to free memory area or 0
- */
-static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr)
-{
-   struct list_head *lhandle;
-
-   /*
-* Prealign input max address, so we simplify our matching
-* logic below and can just reuse it as return pointer.
-*/
-   max_addr &= ~EFI_PAGE_MASK;
-
-   list_for_each(lhandle, _mem) {
-   struct efi_mem_list *lmem = list_entry(lhandle,
-   struct efi_mem_list, link);
-   struct efi_mem_desc *desc = >desc;
-   uint64_t desc_len = desc->num_pages << EFI_PAGE_SHIFT;
-   uint64_t desc_end = desc->physical_start + desc_len;
-   uint64_t curmax = min(max_addr, desc_end);
-   uint64_t ret = curmax - len;
-
-   /* We only take memory from free RAM */
-   if (desc->type != EFI_CONVENTIONAL_MEMORY)
-   continue;
-
-   /* Out of bounds for max_addr */
-   if ((ret + len) > max_addr)
-   continue;
-
-   /* Out of bounds for upper map limit */
-   if ((ret + len) > desc_end)
-   continue;
-
-   /* Out of bounds for lower map limit */
-   if (ret < desc->physical_start)
-   continue;
-
-   /* Return the highest address in this map within bounds */
-   return ret;
-   }
-
-   return 0;
-}
-
 /**
  * efi_allocate_pages - allocate memory pages
  *
@@ -498,6 +451,7 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
efi_uintn_t pages, uint64_t *memory)
 {
u64 len;
+   uint flags;
efi_status_t ret;
uint64_t addr;
 
@@ -513,33 +467,35 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type 
type,
(len >> EFI_PAGE_SHIFT) != (u64)pages)
return EFI_OUT_OF_RESOURCES;
 
+   flags = LMB_NOOVERWRITE | LMB_NONOTIFY;
switch (type) {
case EFI_ALLOCATE_ANY_PAGES:
/* Any page */
-   addr = efi_find_free_memory(len, -1ULL);
+   addr = (u64)lmb_alloc_flags(len, EFI_PAGE_SIZE, flags);
if (!addr)
return EFI_OUT_OF_RESOURCES;
break;
case EFI_ALLOCATE_MAX_ADDRESS:
/* Max address */
-   addr = efi_find_free_memory(len, *memory);
+   addr = (u64)lmb_alloc_base_flags(len, EFI_PAGE_SIZE, *memory,
+flags);
if (!addr)
return EFI_OUT_OF_RESOURCES;
break;
case EFI_ALLOCATE_ADDRESS:
if (*memory & EFI_PAGE_MASK)
return EFI_NOT_FOUND;
-   /* Exact address, reserve it. The addr is already in *memory. */
-   ret = efi_check_allocated(*memory, false);
-   if (ret != EFI_SUCCESS)
-   return EFI_NOT_FOUND;
-   addr = *memory;
+
+   addr = (u64)lmb_alloc_addr_flags(*memory, len, flags);
+   if (!addr)
+   return EFI_OUT_OF_RESOURCES;
break;
default:
/* UEFI doesn't specify other allocation types */
return EFI_INVALID_PARAMETER;
}
 
+   addr = (u64)(uintptr_t)map_sysmem(addr, 0);
/* Reserve that map in our memory maps */
ret = efi_add_memory_map_pg(addr

[RFC PATCH v2 35/48] lmb: add a flag to allow suppressing memory map change notification

2024-07-04 Thread Sughosh Ganu
Add a flag LMB_NONOTIFY that can be passed to the LMB API's for
reserving memory. This will then result in no notification being sent
from the LMB module for the changes to the LMB's memory map.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 include/lmb.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/lmb.h b/include/lmb.h
index afab04426d..dbf3e9e30f 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -24,6 +24,7 @@ enum lmb_flags {
LMB_NONE= BIT(0),
LMB_NOMAP   = BIT(1),
LMB_NOOVERWRITE = BIT(2),
+   LMB_NONOTIFY= BIT(3),
 };
 
 /**
-- 
2.34.1



[RFC PATCH v2 34/48] lmb: add versions of the lmb API with flags

2024-07-04 Thread Sughosh Ganu
The LMB module is to be used as a backend for allocating and freeing
up memory requested from other modules like EFI. These memory requests
are different from the typical LMB reservations in that memory
required by the EFI module cannot be overwritten, or re-requested. Add
versions of the LMB API functions with flags for allocating and
freeing up memory. The caller can then use these API's for specifying
the type of memory that is required. For now, these functions will be
used by the EFI memory module.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 include/lmb.h |  6 ++
 lib/lmb.c | 39 ++-
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/include/lmb.h b/include/lmb.h
index d9d5e3f3cb..afab04426d 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -74,8 +74,13 @@ long lmb_reserve(phys_addr_t base, phys_size_t size);
 long lmb_reserve_flags(phys_addr_t base, phys_size_t size,
   enum lmb_flags flags);
 phys_addr_t lmb_alloc(phys_size_t size, ulong align);
+phys_addr_t lmb_alloc_flags(phys_size_t size, ulong align, uint flags);
 phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t 
max_addr);
+phys_addr_t lmb_alloc_base_flags(phys_size_t size, ulong align,
+phys_addr_t max_addr, uint flags);
 phys_addr_t lmb_alloc_addr(phys_addr_t base, phys_size_t size);
+phys_addr_t lmb_alloc_addr_flags(phys_addr_t base, phys_size_t size,
+uint flags);
 phys_size_t lmb_get_free_size(phys_addr_t addr);
 
 /**
@@ -91,6 +96,7 @@ phys_size_t lmb_get_free_size(phys_addr_t addr);
 int lmb_is_reserved_flags(phys_addr_t addr, int flags);
 
 long lmb_free(phys_addr_t base, phys_size_t size);
+long lmb_free_flags(phys_addr_t base, phys_size_t size, uint flags);
 
 void lmb_dump_all(void);
 void lmb_dump_all_force(void);
diff --git a/lib/lmb.c b/lib/lmb.c
index 4480710d73..d2edb3525a 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -468,7 +468,7 @@ long lmb_add(phys_addr_t base, phys_size_t size)
return lmb_add_region(lmb_rgn_lst, base, size);
 }
 
-long lmb_free(phys_addr_t base, phys_size_t size)
+static long __lmb_free(phys_addr_t base, phys_size_t size)
 {
struct lmb_region *rgn;
struct alist *lmb_rgn_lst = _used_mem;
@@ -519,6 +519,17 @@ long lmb_free(phys_addr_t base, phys_size_t size)
rgn[i].flags);
 }
 
+long lmb_free(phys_addr_t base, phys_size_t size)
+{
+   return __lmb_free(base, size);
+}
+
+long lmb_free_flags(phys_addr_t base, phys_size_t size,
+   __always_unused uint flags)
+{
+   return __lmb_free(base, size);
+}
+
 long lmb_reserve_flags(phys_addr_t base, phys_size_t size, enum lmb_flags 
flags)
 {
struct alist *lmb_rgn_lst = _used_mem;
@@ -602,6 +613,12 @@ phys_addr_t lmb_alloc(phys_size_t size, ulong align)
return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
 }
 
+phys_addr_t lmb_alloc_flags(phys_size_t size, ulong align, uint flags)
+{
+   return __lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE,
+   flags);
+}
+
 phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr)
 {
phys_addr_t alloc;
@@ -615,6 +632,20 @@ phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, 
phys_addr_t max_addr)
return alloc;
 }
 
+phys_addr_t lmb_alloc_base_flags(phys_size_t size, ulong align,
+phys_addr_t max_addr, uint flags)
+{
+   phys_addr_t alloc;
+
+   alloc = __lmb_alloc_base(size, align, max_addr, flags);
+
+   if (alloc == 0)
+   printf("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n",
+  (ulong)size, (ulong)max_addr);
+
+   return alloc;
+}
+
 static phys_addr_t __lmb_alloc_addr(phys_addr_t base, phys_size_t size,
enum lmb_flags flags)
 {
@@ -649,6 +680,12 @@ phys_addr_t lmb_alloc_addr(phys_addr_t base, phys_size_t 
size)
return __lmb_alloc_addr(base, size, LMB_NONE);
 }
 
+phys_addr_t lmb_alloc_addr_flags(phys_addr_t base, phys_size_t size,
+uint flags)
+{
+   return __lmb_alloc_addr(base, size, flags);
+}
+
 /* Return number of bytes from a given address that are free */
 phys_size_t lmb_get_free_size(phys_addr_t addr)
 {
-- 
2.34.1



[RFC PATCH v2 33/48] test: bdinfo: dump the global LMB memory map

2024-07-04 Thread Sughosh Ganu
The LMB code has been changed to make the memory reservations
persistent and global. Make corresponding change the the
lmb_test_dump_all() function to print the global LMB available and
used memory.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Corresponding changes needed to work with alist based lmb lists.

 test/cmd/bdinfo.c | 28 
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c
index 1cd81a195b..3184aaf629 100644
--- a/test/cmd/bdinfo.c
+++ b/test/cmd/bdinfo.c
@@ -5,6 +5,7 @@
  * Copyright 2023 Marek Vasut 
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -21,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -99,19 +101,20 @@ static int test_video_info(struct unit_test_state *uts)
 }
 
 static int lmb_test_dump_region(struct unit_test_state *uts,
-   struct lmb_region *rgn, char *name)
+   struct alist *lmb_rgn_lst, char *name)
 {
+   struct lmb_region *rgn = lmb_rgn_lst->data;
unsigned long long base, size, end;
enum lmb_flags flags;
int i;
 
-   ut_assert_nextline(" %s.cnt = 0x%lx / max = 0x%lx", name, rgn->cnt, 
rgn->max);
+   ut_assert_nextline(" %s.count = 0x%hx", name, lmb_rgn_lst->count);
 
-   for (i = 0; i < rgn->cnt; i++) {
-   base = rgn->region[i].base;
-   size = rgn->region[i].size;
+   for (i = 0; i < lmb_rgn_lst->count; i++) {
+   base = rgn[i].base;
+   size = rgn[i].size;
end = base + size - 1;
-   flags = rgn->region[i].flags;
+   flags = rgn[i].flags;
 
if (!IS_ENABLED(CONFIG_SANDBOX) && i == 3) {
ut_assert_nextlinen(" %s[%d]\t[", name, i);
@@ -124,11 +127,14 @@ static int lmb_test_dump_region(struct unit_test_state 
*uts,
return 0;
 }
 
-static int lmb_test_dump_all(struct unit_test_state *uts, struct lmb *lmb)
+static int lmb_test_dump_all(struct unit_test_state *uts)
 {
+   extern struct alist lmb_free_mem;
+   extern struct alist lmb_used_mem;
+
ut_assert_nextline("lmb_dump_all:");
-   ut_assertok(lmb_test_dump_region(uts, >memory, "memory"));
-   ut_assertok(lmb_test_dump_region(uts, >reserved, "reserved"));
+   ut_assertok(lmb_test_dump_region(uts, _free_mem, "memory"));
+   ut_assertok(lmb_test_dump_region(uts, _used_mem, "reserved"));
 
return 0;
 }
@@ -190,9 +196,7 @@ static int bdinfo_test_all(struct unit_test_state *uts)
 #endif
 
if (IS_ENABLED(CONFIG_LMB) && gd->fdt_blob) {
-   struct lmb lmb;
-
-   ut_assertok(lmb_test_dump_all(uts, ));
+   ut_assertok(lmb_test_dump_all(uts));
if (IS_ENABLED(CONFIG_OF_REAL))
ut_assert_nextline("devicetree  = %s", 
fdtdec_get_srcname());
}
-- 
2.34.1



[RFC PATCH v2 32/48] test: lmb: invoke the LMB unit tests from a separate script

2024-07-04 Thread Sughosh Ganu
With the LMB tests moved under a separate class of unit tests, invoke
these from a separate script which would allow for a system reset once
the tests have been run. This enables clearing up the LMB memory map
after having run the tests.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 test/py/tests/test_lmb.py | 24 
 1 file changed, 24 insertions(+)
 create mode 100644 test/py/tests/test_lmb.py

diff --git a/test/py/tests/test_lmb.py b/test/py/tests/test_lmb.py
new file mode 100644
index 00..b6f9ff9c6a
--- /dev/null
+++ b/test/py/tests/test_lmb.py
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2024 Linaro Ltd
+#
+# Run the LMB tests
+
+import pytest
+
+base_script = '''
+ut lmb -f
+'''
+
+@pytest.mark.boardspec('sandbox')
+def test_lmb(u_boot_console):
+cons = u_boot_console
+cmd = base_script
+
+with cons.log.section('LMB Unit Test'):
+output = cons.run_command_list(cmd.splitlines())
+
+assert 'Failures: 0' in output[-1]
+
+# Restart so that the LMB memory map starts with
+# a clean slate for the next set of tests.
+u_boot_console.restart_uboot()
-- 
2.34.1



[RFC PATCH v2 31/48] test: lmb: add a separate class of unit tests for lmb

2024-07-04 Thread Sughosh Ganu
Add the LMB unit tests under a separate class of tests. The LMB tests
involve changing the LMB's memory map. With the memory map now
persistent and global, running these tests has a side effect and
impact any subsequent tests. Run these tests separately so that the
system can be reset on completion of these tests.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 include/test/suites.h|  1 +
 test/Kconfig |  9 ++
 test/Makefile|  1 +
 test/cmd_ut.c|  7 +
 test/lib/Makefile|  1 -
 test/{lib/lmb.c => lmb_ut.c} | 53 ++--
 6 files changed, 50 insertions(+), 22 deletions(-)
 rename test/{lib/lmb.c => lmb_ut.c} (93%)

diff --git a/include/test/suites.h b/include/test/suites.h
index 365d5f20df..5ef164a956 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -45,6 +45,7 @@ int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char 
*const argv[]);
 int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_hush(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ut_lmb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_mbr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
diff --git a/test/Kconfig b/test/Kconfig
index e2ec0994a2..49c24722dc 100644
--- a/test/Kconfig
+++ b/test/Kconfig
@@ -79,6 +79,15 @@ config UT_COMPRESSION
  Enables tests for compression and decompression routines for simple
  sanity and for buffer overflow conditions.
 
+config UT_LMB
+   bool "Unit tests for LMB functions"
+   depends on !SPL && UNIT_TEST
+   default y
+   help
+ Enables the 'ut lmb' commands which tests the lmb functions
+ responsible for reserving memory for loading images into
+ memory.
+
 config UT_LOG
bool "Unit tests for logging functions"
depends on UNIT_TEST
diff --git a/test/Makefile b/test/Makefile
index ed312cd0a4..e9bdd14eba 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_$(SPL_)CMDLINE) += command_ut.o
 obj-$(CONFIG_$(SPL_)UT_COMPRESSION) += compression.o
 obj-y += dm/
 obj-$(CONFIG_FUZZ) += fuzz/
+obj-$(CONFIG_UT_LMB) += lmb_ut.o
 ifndef CONFIG_SANDBOX_VPL
 obj-$(CONFIG_UNIT_TEST) += lib/
 endif
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 4e4aa8f1cb..60ff872723 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -78,6 +78,7 @@ static struct cmd_tbl cmd_ut_sub[] = {
 #ifdef CONFIG_CONSOLE_TRUETYPE
U_BOOT_CMD_MKENT(font, CONFIG_SYS_MAXARGS, 1, do_ut_font, "", ""),
 #endif
+
 #ifdef CONFIG_UT_OPTEE
U_BOOT_CMD_MKENT(optee, CONFIG_SYS_MAXARGS, 1, do_ut_optee, "", ""),
 #endif
@@ -87,6 +88,9 @@ static struct cmd_tbl cmd_ut_sub[] = {
 #ifdef CONFIG_UT_LIB
U_BOOT_CMD_MKENT(lib, CONFIG_SYS_MAXARGS, 1, do_ut_lib, "", ""),
 #endif
+#ifdef CONFIG_UT_LMB
+   U_BOOT_CMD_MKENT(lmb, CONFIG_SYS_MAXARGS, 1, do_ut_lmb, "", ""),
+#endif
 #ifdef CONFIG_UT_LOG
U_BOOT_CMD_MKENT(log, CONFIG_SYS_MAXARGS, 1, do_ut_log, "", ""),
 #endif
@@ -228,6 +232,9 @@ U_BOOT_LONGHELP(ut,
 #ifdef CONFIG_UT_LIB
"\nlib - library functions"
 #endif
+#ifdef CONFIG_UT_LMB
+   "\nlmb - lmb functions"
+#endif
 #ifdef CONFIG_UT_LOG
"\nlog - logging functions"
 #endif
diff --git a/test/lib/Makefile b/test/lib/Makefile
index 70f14c46b1..ecb96dc1d7 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_EFI_LOADER) += efi_device_path.o
 obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
 obj-y += hexdump.o
 obj-$(CONFIG_SANDBOX) += kconfig.o
-obj-y += lmb.o
 obj-y += longjmp.o
 obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
 obj-$(CONFIG_SSCANF) += sscanf.o
diff --git a/test/lib/lmb.c b/test/lmb_ut.c
similarity index 93%
rename from test/lib/lmb.c
rename to test/lmb_ut.c
index 878aacee8d..a304e9317e 100644
--- a/test/lib/lmb.c
+++ b/test/lmb_ut.c
@@ -9,10 +9,13 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 
+
+#define LMB_TEST(_name, _flags)UNIT_TEST(_name, _flags, lmb_test)
+
 static inline bool lmb_is_nomap(struct lmb_region *m)
 {
return m->flags & LMB_NOMAP;
@@ -200,7 +203,7 @@ static int test_multi_alloc_512mb_x2(struct unit_test_state 
*uts,
 }
 
 /* Create a memory region with one reserved region and allocate */
-static int lib_test_lmb_simple_norun(struct unit_test_state *uts)
+static int lmb_test_lmb_simple_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -212,10 +215,10 @@ stat

[RFC PATCH v2 30/48] test: lmb: run lmb tests only manually

2024-07-04 Thread Sughosh Ganu
The LMB code has been changed so that the memory reservations and
allocations are now persistent and global. With this change, the
design of the LMB tests needs to be changed accordingly. Mark the LMB
tests to be run only manually. The tests won't be run as part of the
unit test suite, but would be invoked through a separate test, and
thus would not interfere with the running of the rest of the tests.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: None

 test/lib/lmb.c | 41 -
 1 file changed, 20 insertions(+), 21 deletions(-)

diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 50f32793bc..878aacee8d 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -200,7 +200,7 @@ static int test_multi_alloc_512mb_x2(struct unit_test_state 
*uts,
 }
 
 /* Create a memory region with one reserved region and allocate */
-static int lib_test_lmb_simple(struct unit_test_state *uts)
+static int lib_test_lmb_simple_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -212,10 +212,10 @@ static int lib_test_lmb_simple(struct unit_test_state 
*uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_multi_alloc_512mb(uts, 0xE000);
 }
-LIB_TEST(lib_test_lmb_simple, 0);
+LIB_TEST(lib_test_lmb_simple_norun, UT_TESTF_MANUAL);
 
 /* Create two memory regions with one reserved region and allocate */
-static int lib_test_lmb_simple_x2(struct unit_test_state *uts)
+static int lib_test_lmb_simple_x2_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -227,7 +227,7 @@ static int lib_test_lmb_simple_x2(struct unit_test_state 
*uts)
/* simulate 512 MiB RAM beginning at 3.5GiB and 1 GiB */
return test_multi_alloc_512mb_x2(uts, 0xE000, 0x4000);
 }
-LIB_TEST(lib_test_lmb_simple_x2, 0);
+LIB_TEST(lib_test_lmb_simple_x2_norun, UT_TESTF_MANUAL);
 
 /* Simulate 512 MiB RAM, allocate some blocks that fit/don't fit */
 static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram)
@@ -286,7 +286,7 @@ static int test_bigblock(struct unit_test_state *uts, const 
phys_addr_t ram)
return 0;
 }
 
-static int lib_test_lmb_big(struct unit_test_state *uts)
+static int lib_test_lmb_big_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -298,7 +298,7 @@ static int lib_test_lmb_big(struct unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_bigblock(uts, 0xE000);
 }
-LIB_TEST(lib_test_lmb_big, 0);
+LIB_TEST(lib_test_lmb_big_norun, UT_TESTF_MANUAL);
 
 /* Simulate 512 MiB RAM, allocate a block without previous reservation */
 static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram,
@@ -368,7 +368,7 @@ static int test_noreserved(struct unit_test_state *uts, 
const phys_addr_t ram,
return 0;
 }
 
-static int lib_test_lmb_noreserved(struct unit_test_state *uts)
+static int lib_test_lmb_noreserved_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -380,10 +380,9 @@ static int lib_test_lmb_noreserved(struct unit_test_state 
*uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_noreserved(uts, 0xE000, 4, 1);
 }
+LIB_TEST(lib_test_lmb_noreserved_norun, UT_TESTF_MANUAL);
 
-LIB_TEST(lib_test_lmb_noreserved, 0);
-
-static int lib_test_lmb_unaligned_size(struct unit_test_state *uts)
+static int lib_test_lmb_unaligned_size_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -395,13 +394,13 @@ static int lib_test_lmb_unaligned_size(struct 
unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_noreserved(uts, 0xE000, 5, 8);
 }
-LIB_TEST(lib_test_lmb_unaligned_size, 0);
+LIB_TEST(lib_test_lmb_unaligned_size_norun, UT_TESTF_MANUAL);
 
 /*
  * Simulate a RAM that starts at 0 and allocate down to address 0, which must
  * fail as '0' means failure for the lmb_alloc functions.
  */
-static int lib_test_lmb_at_0(struct unit_test_state *uts)
+static int lib_test_lmb_at_0_norun(struct unit_test_state *uts)
 {
const phys_addr_t ram = 0;
const phys_size_t ram_size = 0x2000;
@@ -443,10 +442,10 @@ static int lib_test_lmb_at_0(struct unit_test_state *uts)
 
return 0;
 }
-LIB_TEST(lib_test_lmb_at_0, 0);
+LIB_TEST(lib_test_lmb_at_0_norun, UT_TESTF_MANUAL);
 
 /* Check that calling lmb_reserve with overlapping regions fails. */
-static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
+static int lib_test_lmb_overlapping_reserve_norun(struct unit_test_state *uts)
 {
const phys_addr_t ram = 0x4000;
const phys_size_t ram_size = 0x2000;
@@ -497,7 +496,7 @@ static int lib_test_lmb_overlapping_reserve(struct 
unit_test_state *uts)
 
return 0;
 }
-LIB_TEST(lib_test_lmb_overlapping_reserve, 0);
+LIB_TEST(lib_test_lmb_overlapping_reserve_norun, UT_TESTF_MANUAL);
 
 /*
  * Simulate 512 MiB RAM, reserve 3 blocks, allocate addresses in between.
@@ -619,7 +618,7 @@ static int test_alloc_addr(struct unit_test_state

[RFC PATCH v2 29/48] test: lmb: tweak the tests for the persistent lmb memory map

2024-07-04 Thread Sughosh Ganu
The LMB memory maps are now persistent, with alloced lists being used
to keep track of the available and free memory. Make corresponding
changes in the test functions so that the list information can be
accessed by the tests for checking against expected values. Also
introduce functions to initialise and cleanup the lists. These
functions will be invoked from every test to start the memory map from
a clean slate.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Make changes to the lmb_init() function for working with alist based
  lmb lists.
* Add a lmb_uninit() function to clear out the lists.

 include/lmb.h  |   7 ++
 lib/lmb.c  |  32 ++
 test/lib/lmb.c | 292 ++---
 3 files changed, 219 insertions(+), 112 deletions(-)

diff --git a/include/lmb.h b/include/lmb.h
index cc4cf9f3c8..d9d5e3f3cb 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -13,6 +13,8 @@
  * Copyright (C) 2001 Peter Bergner, IBM Corp.
  */
 
+struct alist;
+
 /**
  * enum lmb_flags - definition of memory region attributes
  * @LMB_NONE: no special request
@@ -110,6 +112,11 @@ void arch_lmb_reserve_generic(ulong sp, ulong end, ulong 
align);
  */
 int lmb_mem_regions_init(void);
 
+#if CONFIG_IS_ENABLED(UT_LMB)
+int lmb_init(struct alist **mem_lst, struct alist **used_lst);
+void lmb_uninit(struct alist *mem_lst, struct alist *used_lst);
+#endif /* UT_LMB */
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_LMB_H */
diff --git a/lib/lmb.c b/lib/lmb.c
index 7cb97e2d42..4480710d73 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -763,3 +763,35 @@ int initr_lmb(void)
 
return ret;
 }
+
+#if CONFIG_IS_ENABLED(UT_LMB)
+int lmb_init(struct alist **mem_lst, struct alist **used_lst)
+{
+   bool ret;
+
+   ret = alist_init(_free_mem, sizeof(struct lmb_region),
+(uint)LMB_ALIST_INITIAL_SIZE);
+   if (!ret) {
+   log_debug("Unable to initialise the list for LMB free 
memory\n");
+   return -1;
+   }
+
+   ret = alist_init(_used_mem, sizeof(struct lmb_region),
+(uint)LMB_ALIST_INITIAL_SIZE);
+   if (!ret) {
+   log_debug("Unable to initialise the list for LMB used 
memory\n");
+   return -1;
+   }
+
+   *mem_lst = _free_mem;
+   *used_lst = _used_mem;
+
+   return 0;
+}
+
+void lmb_uninit(struct alist *mem_lst, struct alist *used_lst)
+{
+   alist_uninit(mem_lst);
+   alist_uninit(used_lst);
+}
+#endif /* UT_LMB */
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index a3a7ad904c..50f32793bc 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -3,6 +3,7 @@
  * (C) Copyright 2018 Simon Goldschmidt
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -12,52 +13,51 @@
 #include 
 #include 
 
-extern struct lmb lmb;
-
-static inline bool lmb_is_nomap(struct lmb_property *m)
+static inline bool lmb_is_nomap(struct lmb_region *m)
 {
return m->flags & LMB_NOMAP;
 }
 
-static int check_lmb(struct unit_test_state *uts, struct lmb *lmb,
-phys_addr_t ram_base, phys_size_t ram_size,
-unsigned long num_reserved,
+static int check_lmb(struct unit_test_state *uts, struct alist *mem_lst,
+struct alist *used_lst, phys_addr_t ram_base,
+phys_size_t ram_size, unsigned long num_reserved,
 phys_addr_t base1, phys_size_t size1,
 phys_addr_t base2, phys_size_t size2,
 phys_addr_t base3, phys_size_t size3)
 {
+   struct lmb_region *mem, *used;
+
+   mem = mem_lst->data;
+   used = used_lst->data;
+
if (ram_size) {
-   ut_asserteq(lmb->memory.cnt, 1);
-   ut_asserteq(lmb->memory.region[0].base, ram_base);
-   ut_asserteq(lmb->memory.region[0].size, ram_size);
+   ut_asserteq(mem_lst->count, 1);
+   ut_asserteq(mem[0].base, ram_base);
+   ut_asserteq(mem[0].size, ram_size);
}
 
-   ut_asserteq(lmb->reserved.cnt, num_reserved);
+   ut_asserteq(used_lst->count, num_reserved);
if (num_reserved > 0) {
-   ut_asserteq(lmb->reserved.region[0].base, base1);
-   ut_asserteq(lmb->reserved.region[0].size, size1);
+   ut_asserteq(used[0].base, base1);
+   ut_asserteq(used[0].size, size1);
}
if (num_reserved > 1) {
-   ut_asserteq(lmb->reserved.region[1].base, base2);
-   ut_asserteq(lmb->reserved.region[1].size, size2);
+   ut_asserteq(used[1].base, base2);
+   ut_asserteq(used[1].size, size2);
}
if (num_reserved > 2) {
-   ut_asserteq(lmb->reserved.region[2].base, base3);
-   ut_asserteq(lmb->reserved.region[2].size, size3);
+   ut_asserteq(used[2].base, base3);
+   ut_asserteq(

[RFC PATCH v2 28/48] test: cedit: use allocated address for reading file

2024-07-04 Thread Sughosh Ganu
Instead of a randomly selected address, use an LMB allocated one for
reading the file into memory. With the LMB map now being persistent
and global, the address used for reading the file might be already
allocated as non-overwritable, resulting in a failure. Get a valid
address from LMB and then read the file to that address.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Free up the memory allocated once done with it.

 test/boot/cedit.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index fd19da0a0c..923ddd1481 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -61,7 +62,7 @@ static int cedit_fdt(struct unit_test_state *uts)
struct video_priv *vid_priv;
extern struct expo *cur_exp;
struct scene_obj_menu *menu;
-   ulong addr = 0x1000;
+   ulong addr;
struct ofprop prop;
struct scene *scn;
oftree tree;
@@ -86,6 +87,8 @@ static int cedit_fdt(struct unit_test_state *uts)
str = abuf_data(>buf);
strcpy(str, "my-machine");
 
+   addr = lmb_alloc(1024, 1024);
+   ut_asserteq(!!addr, !0);
ut_assertok(run_command("cedit write_fdt hostfs - settings.dtb", 0));
ut_assertok(run_commandf("load hostfs - %lx settings.dtb", addr));
ut_assert_nextlinen("1024 bytes read");
@@ -94,6 +97,7 @@ static int cedit_fdt(struct unit_test_state *uts)
tree = oftree_from_fdt(fdt);
node = ofnode_find_subnode(oftree_root(tree), CEDIT_NODE_NAME);
ut_assert(ofnode_valid(node));
+   lmb_free(addr, 1024);
 
ut_asserteq(ID_CPU_SPEED_2,
ofnode_read_u32_default(node, "cpu-speed", 0));
-- 
2.34.1



[RFC PATCH v2 27/48] zynq: lmb: do not add to lmb map before relocation

2024-07-04 Thread Sughosh Ganu
The LMB memory is typically not needed very early in the platform's
boot. Do not add memory to the LMB map before relocation. Reservation
of common areas and adding of memory is done after relocation.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: None

 board/xilinx/common/board.c | 31 ---
 1 file changed, 31 deletions(-)

diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index f04c92a70f..3440402ab4 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -12,7 +12,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -665,36 +664,6 @@ int embedded_dtb_select(void)
 }
 #endif
 
-#if IS_ENABLED(CONFIG_LMB)
-
-#ifndef MMU_SECTION_SIZE
-#define MMU_SECTION_SIZE(1 * 1024 * 1024)
-#endif
-
-phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
-{
-   phys_size_t size;
-   phys_addr_t reg;
-
-   if (!total_size)
-   return gd->ram_top;
-
-   if (!IS_ALIGNED((ulong)gd->fdt_blob, 0x8))
-   panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob);
-
-   /* found enough not-reserved memory to relocated U-Boot */
-   lmb_add(gd->ram_base, gd->ram_size);
-   boot_fdt_add_mem_rsv_regions((void *)gd->fdt_blob);
-   size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE);
-   reg = lmb_alloc(size, MMU_SECTION_SIZE);
-
-   if (!reg)
-   reg = gd->ram_top - size;
-
-   return reg + size;
-}
-#endif
-
 #ifdef CONFIG_OF_BOARD_SETUP
 #define MAX_RAND_SIZE 8
 int ft_board_setup(void *blob, struct bd_info *bd)
-- 
2.34.1



[RFC PATCH v2 26/48] sandbox: iommu: remove lmb allocation in the driver

2024-07-04 Thread Sughosh Ganu
The sandbox iommu driver uses the LMB module to allocate a particular
range of memory for the device virtual address(DVA). This used to work
earlier since the LMB memory map was caller specific and not
global. But with the change to make the LMB allocations global and
persistent, adding this memory range has other side effects. On the
other hand, the sandbox iommu test expects to see this particular
value of the DVA. Use the DVA address directly, instead of mapping it
in the LMB memory map, and then have it allocated.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: None

 drivers/iommu/sandbox_iommu.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/sandbox_iommu.c b/drivers/iommu/sandbox_iommu.c
index 5b4a6a8982..81f10e8433 100644
--- a/drivers/iommu/sandbox_iommu.c
+++ b/drivers/iommu/sandbox_iommu.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 
+#define DVA_ADDR   0x89abc000
 #define IOMMU_PAGE_SIZESZ_4K
 
 static dma_addr_t sandbox_iommu_map(struct udevice *dev, void *addr,
@@ -21,7 +22,7 @@ static dma_addr_t sandbox_iommu_map(struct udevice *dev, void 
*addr,
off = virt_to_phys(addr) - paddr;
psize = ALIGN(size + off, IOMMU_PAGE_SIZE);
 
-   dva = lmb_alloc(psize, IOMMU_PAGE_SIZE);
+   dva = (phys_addr_t)DVA_ADDR;
 
return dva + off;
 }
@@ -35,8 +36,6 @@ static void sandbox_iommu_unmap(struct udevice *dev, 
dma_addr_t addr,
dva = ALIGN_DOWN(addr, IOMMU_PAGE_SIZE);
psize = size + (addr - dva);
psize = ALIGN(psize, IOMMU_PAGE_SIZE);
-
-   lmb_free(dva, psize);
 }
 
 static struct iommu_ops sandbox_iommu_ops = {
@@ -46,8 +45,6 @@ static struct iommu_ops sandbox_iommu_ops = {
 
 static int sandbox_iommu_probe(struct udevice *dev)
 {
-   lmb_add(0x89abc000, SZ_16K);
-
return 0;
 }
 
-- 
2.34.1



[RFC PATCH v2 25/48] sandbox: spl: enable lmb in SPL

2024-07-04 Thread Sughosh Ganu
Enable the LMB module in the SPL stage. This will allow the LMB code
to be exercised and tested in the SPL stage.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 configs/sandbox_spl_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index f7b92dc844..31ccdbd502 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -249,6 +249,7 @@ CONFIG_ZSTD=y
 CONFIG_SPL_LZMA=y
 CONFIG_ERRNO_STR=y
 CONFIG_SPL_HEXDUMP=y
+CONFIG_SPL_LMB=y
 CONFIG_UNIT_TEST=y
 CONFIG_SPL_UNIT_TEST=y
 CONFIG_UT_TIME=y
-- 
2.34.1



[RFC PATCH v2 24/48] lmb: add a common implementation of arch_lmb_reserve()

2024-07-04 Thread Sughosh Ganu
Almost all of the current definitions of arch_lmb_reserve() are doing
the same thing. The only exception in a couple of cases is the
alignment parameter requirement. Have a generic weak implementation of
this function, keeping the highest value of alignment that is being
used(16K).

Also, instead of using the current value of stack pointer for starting
the reserved region, have a fixed value, considering the stack size
config value.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 arch/arc/lib/cache.c| 14 --
 arch/arm/lib/stack.c| 14 --
 arch/m68k/lib/bootm.c   | 17 -
 arch/microblaze/lib/bootm.c | 14 --
 arch/mips/lib/bootm.c   | 15 ---
 arch/nios2/lib/bootm.c  | 13 -
 arch/powerpc/lib/bootm.c| 13 +++--
 arch/riscv/lib/bootm.c  | 13 -
 arch/sh/lib/bootm.c | 13 -
 arch/x86/lib/bootm.c| 18 --
 arch/xtensa/lib/bootm.c | 13 -
 lib/lmb.c   |  6 +-
 12 files changed, 8 insertions(+), 155 deletions(-)

diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c
index 5151af917a..5169fc627f 100644
--- a/arch/arc/lib/cache.c
+++ b/arch/arc/lib/cache.c
@@ -10,7 +10,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -820,16 +819,3 @@ void sync_n_cleanup_cache_all(void)
 
__ic_entire_invalidate();
 }
-
-static ulong get_sp(void)
-{
-   ulong ret;
-
-   asm("mov %0, sp" : "=r"(ret) : );
-   return ret;
-}
-
-void arch_lmb_reserve(void)
-{
-   arch_lmb_reserve_generic(get_sp(), gd->ram_top, 4096);
-}
diff --git a/arch/arm/lib/stack.c b/arch/arm/lib/stack.c
index 87d5c962d7..2b21ec0734 100644
--- a/arch/arm/lib/stack.c
+++ b/arch/arm/lib/stack.c
@@ -11,7 +11,6 @@
  * Marius Groeger 
  */
 #include 
-#include 
 #include 
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -33,16 +32,3 @@ int arch_reserve_stacks(void)
 
return 0;
 }
-
-static ulong get_sp(void)
-{
-   ulong ret;
-
-   asm("mov %0, sp" : "=r"(ret) : );
-   return ret;
-}
-
-void arch_lmb_reserve(void)
-{
-   arch_lmb_reserve_generic(get_sp(), gd->ram_top, 16384);
-}
diff --git a/arch/m68k/lib/bootm.c b/arch/m68k/lib/bootm.c
index eb220d178d..06854e1442 100644
--- a/arch/m68k/lib/bootm.c
+++ b/arch/m68k/lib/bootm.c
@@ -9,7 +9,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -27,14 +26,8 @@ DECLARE_GLOBAL_DATA_PTR;
 #define LINUX_MAX_ENVS 256
 #define LINUX_MAX_ARGS 256
 
-static ulong get_sp (void);
 static void set_clocks_in_mhz (struct bd_info *kbd);
 
-void arch_lmb_reserve(void)
-{
-   arch_lmb_reserve_generic(get_sp(), gd->ram_top, 1024);
-}
-
 int do_bootm_linux(int flag, struct bootm_info *bmi)
 {
struct bootm_headers *images = bmi->images;
@@ -88,16 +81,6 @@ error:
return 1;
 }
 
-static ulong get_sp (void)
-{
-   ulong sp;
-
-   asm("movel %%a7, %%d0\n"
-   "movel %%d0, %0\n": "=d"(sp): :"%d0");
-
-   return sp;
-}
-
 static void set_clocks_in_mhz (struct bd_info *kbd)
 {
char *s;
diff --git a/arch/microblaze/lib/bootm.c b/arch/microblaze/lib/bootm.c
index ce96bca28f..4879a41aab 100644
--- a/arch/microblaze/lib/bootm.c
+++ b/arch/microblaze/lib/bootm.c
@@ -15,7 +15,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -24,19 +23,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static ulong get_sp(void)
-{
-   ulong ret;
-
-   asm("addik %0, r1, 0" : "=r"(ret) : );
-   return ret;
-}
-
-void arch_lmb_reserve(void)
-{
-   arch_lmb_reserve_generic(get_sp(), gd->ram_top, 4096);
-}
-
 static void boot_jump_linux(struct bootm_headers *images, int flag)
 {
void (*thekernel)(char *cmdline, ulong rd, ulong dt);
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 8fb3a3923f..8719510002 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -9,7 +9,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -28,20 +27,6 @@ static char **linux_env;
 static char *linux_env_p;
 static int linux_env_idx;
 
-static ulong arch_get_sp(void)
-{
-   ulong ret;
-
-   __asm__ __volatile__("move %0, $sp" : "=r"(ret) : );
-
-   return ret;
-}
-
-void arch_lmb_reserve(void)
-{
-   arch_lmb_reserve_generic(arch_get_sp(), gd->ram_top, 4096);
-}
-
 static void linux_cmdline_init(void)
 {
linux_argc = 1;
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
index d33d45d28f..71319839ba 100644
--- a/arch/nios2/lib/bootm.c
+++ b/arch/nios2/lib/bootm.c
@@ -64,16 +64,3 @@ int do_bootm_linux(int flag, struct bootm_info *bmi)
 
return 1;
 }
-
-static ulong get_sp(void)
-{
-   ulong ret;
-
-   asm("mov %0, sp" : "=

[RFC PATCH v2 23/48] lmb: use the BIT macro for lmb flags

2024-07-04 Thread Sughosh Ganu
Use the BIT macro for assigning values to the LMB flags instead of
assigning random values to them.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch based on review comment from Heinrich

 include/lmb.h | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/lmb.h b/include/lmb.h
index 02891a14be..cc4cf9f3c8 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -5,6 +5,7 @@
 
 #include 
 #include 
+#include 
 
 /*
  * Logical memory blocks.
@@ -18,9 +19,9 @@
  * @LMB_NOMAP: don't add to mmu configuration
  */
 enum lmb_flags {
-   LMB_NONE= 0x0,
-   LMB_NOMAP   = 0x4,
-   LMB_NOOVERWRITE = 0x8,
+   LMB_NONE= BIT(0),
+   LMB_NOMAP   = BIT(1),
+   LMB_NOOVERWRITE = BIT(2),
 };
 
 /**
-- 
2.34.1



[RFC PATCH v2 22/48] lmb: init: initialise the lmb data structures during board init

2024-07-04 Thread Sughosh Ganu
The memory map maintained by the LMB module is now persistent and
global. This memory map is being maintained through the alloced list
structure which can be extended at runtime -- there is one list for
the available memory, and one for the used memory. Allocate and
initialise these lists during the board init.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Initialise the lmb structures as part of board init.
* Initialise the lmb structure durint SPL init when enabled.

 common/board_r.c |  4 
 common/spl/spl.c |  4 
 include/lmb.h| 11 +++
 lib/lmb.c| 20 
 4 files changed, 39 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index c823cd262f..1a5bb98218 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -611,6 +612,9 @@ static init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_CLOCKS
set_cpu_clk_info, /* Setup clock information */
 #endif
+#if CONFIG_IS_ENABLED(LMB)
+   initr_lmb,
+#endif
 #ifdef CONFIG_EFI_LOADER
efi_memory_init,
 #endif
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 7794ddccad..633dbd1234 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -686,6 +686,10 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
SPL_SYS_MALLOC_SIZE);
gd->flags |= GD_FLG_FULL_MALLOC_INIT;
}
+
+   if (IS_ENABLED(CONFIG_SPL_LMB))
+   initr_lmb();
+
if (!(gd->flags & GD_FLG_SPL_INIT)) {
if (spl_init())
hang();
diff --git a/include/lmb.h b/include/lmb.h
index d0c094107c..02891a14be 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -36,6 +36,17 @@ struct lmb_region {
enum lmb_flags flags;
 };
 
+/**
+ * initr_lmb() - Initialise the LMB lists
+ *
+ * Initialise the LMB lists needed for keeping the memory map. There
+ * are two lists, in form of alloced list data structure. One for the
+ * available memory, and one for the used memory.
+ *
+ * Return: 0 on success, -ve on error
+ */
+int initr_lmb(void);
+
 /**
  * lmb_add_memory() - Add memory range for LMB allocations
  *
diff --git a/lib/lmb.c b/lib/lmb.c
index bf6254f4fc..1534380969 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -739,3 +739,23 @@ int lmb_mem_regions_init(void)
 
return 0;
 }
+
+/**
+ * initr_lmb() - Initialise the LMB lists
+ *
+ * Initialise the LMB lists needed for keeping the memory map. There
+ * are two lists, in form of alloced list data structure. One for the
+ * available memory, and one for the used memory.
+ *
+ * Return: 0 on success, -ve on error
+ */
+int initr_lmb(void)
+{
+   int ret;
+
+   ret = lmb_mem_regions_init();
+   if (ret)
+   printf("Unable to initialise the LMB data structures\n");
+
+   return ret;
+}
-- 
2.34.1



[RFC PATCH v2 21/48] lmb: remove lmb_init_and_reserve_range() function

2024-07-04 Thread Sughosh Ganu
With the move to make the LMB allocations persistent and the common
memory regions being reserved during board init, there is no need for
an explicit reservation of a memory range. Remove the
lmb_init_and_reserve_range() function.

Signed-off-by: Sughosh Ganu 
Reviewed-by: Ilias Apalodimas 
Reviewed-by: Tom Rini 
---
Changes since V1: None

 boot/bootm.c | 15 +--
 lib/lmb.c|  8 
 2 files changed, 1 insertion(+), 22 deletions(-)

diff --git a/boot/bootm.c b/boot/bootm.c
index 5ce84b73b5..d44fd2ed87 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -239,18 +239,7 @@ static int boot_get_kernel(const char *addr_fit, struct 
bootm_headers *images,
return 0;
 }
 
-#if CONFIG_IS_ENABLED(LMB)
-static void boot_start_lmb(void)
-{
-   phys_addr_t mem_start;
-   phys_size_t mem_size;
-
-   mem_start = env_get_bootm_low();
-   mem_size = env_get_bootm_size();
-
-   lmb_init_and_reserve_range(mem_start, mem_size, NULL);
-}
-#else
+#if !CONFIG_IS_ENABLED(LMB)
 #define lmb_reserve(base, size)
 static inline void boot_start_lmb(void) { }
 #endif
@@ -260,8 +249,6 @@ static int bootm_start(void)
memset((void *), 0, sizeof(images));
images.verify = env_get_yesno("verify");
 
-   boot_start_lmb();
-
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
images.state = BOOTM_STATE_START;
 
diff --git a/lib/lmb.c b/lib/lmb.c
index 456b64c00a..bf6254f4fc 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -268,14 +268,6 @@ __weak void lmb_add_memory(void)
}
 }
 
-/* Initialize the struct, add memory and call arch/board reserve functions */
-void lmb_init_and_reserve_range(phys_addr_t base, phys_size_t size,
-   void *fdt_blob)
-{
-   lmb_add(base, size);
-   lmb_reserve_common(fdt_blob);
-}
-
 static bool lmb_region_flags_match(struct lmb_region *rgn, unsigned long r1,
   enum lmb_flags flags)
 {
-- 
2.34.1



[RFC PATCH v2 20/48] lmb: reserve common areas during board init

2024-07-04 Thread Sughosh Ganu
The LMB module provides API's for allocating and reserving chunks of
memory which is then typically used for things like loading images for
booting. Reserve the portion of memory that is occupied by the U-Boot
image itself, and other parts of memory that might have been marked as
reserved in the board's DTB.

Mark these regions of memory with the LMB_NOOVERWRITE flag to indicate
that these regions cannot be re-requested or overwritten.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Mark the reserved regions as LMB_NOOVERWRITE.
* Call the lmb_reserve_common() function in U-Boot proper after
  relocation.

 lib/lmb.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/lib/lmb.c b/lib/lmb.c
index e1dde14a3c..456b64c00a 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -173,10 +174,11 @@ void arch_lmb_reserve_generic(ulong sp, ulong end, ulong 
align)
if (bank_end > end)
bank_end = end - 1;
 
-   lmb_reserve(sp, bank_end - sp + 1);
+   lmb_reserve_flags(sp, bank_end - sp + 1, LMB_NOOVERWRITE);
 
if (gd->flags & GD_FLG_SKIP_RELOC)
-   lmb_reserve((phys_addr_t)(uintptr_t)_start, 
gd->mon_len);
+   lmb_reserve_flags((phys_addr_t)(uintptr_t)_start,
+   gd->mon_len, LMB_NOOVERWRITE);
 
break;
}
@@ -739,5 +741,9 @@ int lmb_mem_regions_init(void)
 
lmb_add_memory();
 
+   /* Reserve the U-Boot image region once U-Boot has relocated */
+   if (spl_phase() == PHASE_BOARD_R)
+   lmb_reserve_common((void *)gd->fdt_blob);
+
return 0;
 }
-- 
2.34.1



[RFC PATCH v2 19/48] lmb: remove the lmb_init_and_reserve() function

2024-07-04 Thread Sughosh Ganu
With the changes to make the LMB reservations persistent, the common
memory regions are being added during board init. Remove the
now superfluous lmb_init_and_reserve() function.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Removed the replacement of lmb_init_and_reserve() with
  lmb_add_memory(), as memory gets added during board init.

 arch/arm/mach-apple/board.c  |  2 --
 arch/arm/mach-snapdragon/board.c |  2 --
 arch/arm/mach-stm32mp/stm32mp1/cpu.c |  3 ---
 cmd/bdinfo.c |  1 -
 cmd/load.c   |  2 --
 fs/fs.c  |  1 -
 lib/lmb.c| 13 -
 net/tftp.c   |  2 --
 net/wget.c   |  2 --
 test/cmd/bdinfo.c|  9 -
 10 files changed, 37 deletions(-)

diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c
index 213390d6e8..0b6d290b8a 100644
--- a/arch/arm/mach-apple/board.c
+++ b/arch/arm/mach-apple/board.c
@@ -775,8 +775,6 @@ int board_late_init(void)
 {
u32 status = 0;
 
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
-
/* somewhat based on the Linux Kernel boot requirements:
 * align by 2M and maximal FDT size 2M
 */
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index a63c8bec45..22a7d2a637 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -282,8 +282,6 @@ int board_late_init(void)
 {
u32 status = 0;
 
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
-
/* We need to be fairly conservative here as we support boards with 
just 1G of TOTAL RAM */
status |= env_set_hex("kernel_addr_r", addr_alloc(SZ_128M));
status |= env_set_hex("ramdisk_addr_r", addr_alloc(SZ_128M));
diff --git a/arch/arm/mach-stm32mp/stm32mp1/cpu.c 
b/arch/arm/mach-stm32mp/stm32mp1/cpu.c
index a913737342..64480da9f8 100644
--- a/arch/arm/mach-stm32mp/stm32mp1/cpu.c
+++ b/arch/arm/mach-stm32mp/stm32mp1/cpu.c
@@ -141,9 +141,6 @@ int mach_cpu_init(void)
 
 void enable_caches(void)
 {
-   /* parse device tree when data cache is still activated */
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
-
/* I-cache is already enabled in start.S: icache_enable() not needed */
 
/* deactivate the data cache, early enabled in arch_cpu_init() */
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index b31e0208df..3c40dee143 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -162,7 +162,6 @@ static int bdinfo_print_all(struct bd_info *bd)
bdinfo_print_num_l("multi_dtb_fit", (ulong)gd->multi_dtb_fit);
 #endif
if (IS_ENABLED(CONFIG_LMB) && gd->fdt_blob) {
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
lmb_dump_all_force();
if (IS_ENABLED(CONFIG_OF_REAL))
printf("devicetree  = %s\n", fdtdec_get_srcname());
diff --git a/cmd/load.c b/cmd/load.c
index b4e747f966..29cc98ff37 100644
--- a/cmd/load.c
+++ b/cmd/load.c
@@ -153,8 +153,6 @@ static ulong load_serial(long offset)
int line_count =  0;
long ret;
 
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
-
while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
type = srec_decode(record, , , binbuf);
 
diff --git a/fs/fs.c b/fs/fs.c
index 3fb00590be..4bc28d1dff 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -549,7 +549,6 @@ static int fs_read_lmb_check(const char *filename, ulong 
addr, loff_t offset,
if (len && len < read_len)
read_len = len;
 
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
lmb_dump_all();
 
if (lmb_alloc_addr(addr, read_len) == addr)
diff --git a/lib/lmb.c b/lib/lmb.c
index e4733b82ac..e1dde14a3c 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -226,19 +226,6 @@ static void lmb_reserve_common(void *fdt_blob)
efi_lmb_reserve();
 }
 
-/* Initialize the struct, add memory and call arch/board reserve functions */
-void lmb_init_and_reserve(struct bd_info *bd, void *fdt_blob)
-{
-   int i;
-
-   for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-   if (bd->bi_dram[i].size)
-   lmb_add(bd->bi_dram[i].start, bd->bi_dram[i].size);
-   }
-
-   lmb_reserve_common(fdt_blob);
-}
-
 /**
  * lmb_add_memory() - Add memory range for LMB allocations
  *
diff --git a/net/tftp.c b/net/tftp.c
index 5c75d9d04f..dfbc620c73 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -713,8 +713,6 @@ static int tftp_init_load_addr(void)
 #if CONFIG_IS_ENABLED(LMB)
phys_size_t max_size;
 
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
-
max_size = lmb_get_free_size(image_load_addr);
if (!max_size)
return -1;
diff --git a/

[RFC PATCH v2 18/48] lmb: introduce a function to add memory to the lmb memory map

2024-07-04 Thread Sughosh Ganu
Introduce a function lmb_add_memory() to add available memory to the
LMB memory map. Call this function during board init once the LMB data
structures have been initialised.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Add memory only till ram_top to the LMB memory map, instead of all
  enumerated memory.

 include/lmb.h | 11 +++
 lib/lmb.c | 42 ++
 2 files changed, 53 insertions(+)

diff --git a/include/lmb.h b/include/lmb.h
index 27cdb18c37..d0c094107c 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -36,6 +36,17 @@ struct lmb_region {
enum lmb_flags flags;
 };
 
+/**
+ * lmb_add_memory() - Add memory range for LMB allocations
+ *
+ * Add the entire available memory range to the pool of memory that
+ * can be used by the LMB module for allocations.
+ *
+ * Return: None
+ *
+ */
+void lmb_add_memory(void);
+
 long lmb_add(phys_addr_t base, phys_size_t size);
 long lmb_reserve(phys_addr_t base, phys_size_t size);
 /**
diff --git a/lib/lmb.c b/lib/lmb.c
index a46bc8a7a3..e4733b82ac 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -239,6 +239,46 @@ void lmb_init_and_reserve(struct bd_info *bd, void 
*fdt_blob)
lmb_reserve_common(fdt_blob);
 }
 
+/**
+ * lmb_add_memory() - Add memory range for LMB allocations
+ *
+ * Add the entire available memory range to the pool of memory that
+ * can be used by the LMB module for allocations.
+ *
+ * This can be overridden for specific boards/architectures.
+ *
+ * Return: None
+ *
+ */
+__weak void lmb_add_memory(void)
+{
+   int i;
+   phys_size_t size;
+   phys_addr_t rgn_top;
+   u64 ram_top = gd->ram_top;
+   struct bd_info *bd = gd->bd;
+
+   /* Assume a 4GB ram_top if not defined */
+   if (!ram_top)
+   ram_top = 0x1ULL;
+
+   for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+   size = bd->bi_dram[i].size;
+   if (size) {
+   if (bd->bi_dram[i].start > ram_top)
+   continue;
+
+   rgn_top = bd->bi_dram[i].start +
+   bd->bi_dram[i].size;
+
+   if (rgn_top > ram_top )
+   size -= rgn_top - ram_top;
+
+   lmb_add(bd->bi_dram[i].start, size);
+   }
+   }
+}
+
 /* Initialize the struct, add memory and call arch/board reserve functions */
 void lmb_init_and_reserve_range(phys_addr_t base, phys_size_t size,
void *fdt_blob)
@@ -710,5 +750,7 @@ int lmb_mem_regions_init(void)
return -1;
}
 
+   lmb_add_memory();
+
return 0;
 }
-- 
2.34.1



[RFC PATCH v2 17/48] lmb: allow lmb module to be used in SPL

2024-07-04 Thread Sughosh Ganu
With the introduction of separate config symbols for the SPL phase of
U-Boot, the condition checks need to be tweaked so that platforms that
enable the LMB module in SPL are also able to call the LMB API's. Use
the appropriate condition checks to achieve this.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 board/xilinx/common/board.c | 2 +-
 boot/bootm.c| 4 ++--
 boot/image-board.c  | 2 +-
 fs/fs.c | 4 ++--
 lib/Makefile| 2 +-
 net/tftp.c  | 6 +++---
 net/wget.c  | 4 ++--
 7 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 4056884400..f04c92a70f 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -665,7 +665,7 @@ int embedded_dtb_select(void)
 }
 #endif
 
-#if defined(CONFIG_LMB)
+#if IS_ENABLED(CONFIG_LMB)
 
 #ifndef MMU_SECTION_SIZE
 #define MMU_SECTION_SIZE(1 * 1024 * 1024)
diff --git a/boot/bootm.c b/boot/bootm.c
index 7b3fe551de..5ce84b73b5 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -239,7 +239,7 @@ static int boot_get_kernel(const char *addr_fit, struct 
bootm_headers *images,
return 0;
 }
 
-#ifdef CONFIG_LMB
+#if CONFIG_IS_ENABLED(LMB)
 static void boot_start_lmb(void)
 {
phys_addr_t mem_start;
@@ -1048,7 +1048,7 @@ int bootm_run_states(struct bootm_info *bmi, int states)
}
}
 #endif
-#if CONFIG_IS_ENABLED(OF_LIBFDT) && defined(CONFIG_LMB)
+#if CONFIG_IS_ENABLED(OF_LIBFDT) && CONFIG_IS_ENABLED(LMB)
if (!ret && (states & BOOTM_STATE_FDT)) {
boot_fdt_add_mem_rsv_regions(images->ft_addr);
ret = boot_relocate_fdt(>ft_addr, >ft_len);
diff --git a/boot/image-board.c b/boot/image-board.c
index 1f8c1ac69f..99ee7968ba 100644
--- a/boot/image-board.c
+++ b/boot/image-board.c
@@ -883,7 +883,7 @@ int image_setup_linux(struct bootm_headers *images)
int ret;
 
/* This function cannot be called without lmb support */
-   if (!IS_ENABLED(CONFIG_LMB))
+   if (!CONFIG_IS_ENABLED(LMB))
return -EFAULT;
if (CONFIG_IS_ENABLED(OF_LIBFDT))
boot_fdt_add_mem_rsv_regions(*of_flat_tree);
diff --git a/fs/fs.c b/fs/fs.c
index 2c835eef86..3fb00590be 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -526,7 +526,7 @@ int fs_size(const char *filename, loff_t *size)
return ret;
 }
 
-#ifdef CONFIG_LMB
+#if CONFIG_IS_ENABLED(LMB)
 /* Check if a file may be read to the given address */
 static int fs_read_lmb_check(const char *filename, ulong addr, loff_t offset,
 loff_t len, struct fstype_info *info)
@@ -567,7 +567,7 @@ static int _fs_read(const char *filename, ulong addr, 
loff_t offset, loff_t len,
void *buf;
int ret;
 
-#ifdef CONFIG_LMB
+#if CONFIG_IS_ENABLED(LMB)
if (do_lmb_check) {
ret = fs_read_lmb_check(filename, addr, offset, len, info);
if (ret)
diff --git a/lib/Makefile b/lib/Makefile
index 81b503ab52..398c11726e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -118,7 +118,7 @@ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdtdec.o 
fdtdec_common.o
 obj-y += hang.o
 obj-y += linux_compat.o
 obj-y += linux_string.o
-obj-$(CONFIG_LMB) += lmb.o
+obj-$(CONFIG_$(SPL_)LMB) += lmb.o
 obj-y += membuff.o
 obj-$(CONFIG_REGEX) += slre.o
 obj-y += string.o
diff --git a/net/tftp.c b/net/tftp.c
index 5e27fd4aa9..5c75d9d04f 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -82,7 +82,7 @@ static ulong  tftp_block_wrap;
 static ulong   tftp_block_wrap_offset;
 static int tftp_state;
 static ulong   tftp_load_addr;
-#ifdef CONFIG_LMB
+#if CONFIG_IS_ENABLED(LMB)
 static ulong   tftp_load_size;
 #endif
 #ifdef CONFIG_TFTP_TSIZE
@@ -160,7 +160,7 @@ static inline int store_block(int block, uchar *src, 
unsigned int len)
ulong store_addr = tftp_load_addr + offset;
void *ptr;
 
-#ifdef CONFIG_LMB
+#if CONFIG_IS_ENABLED(LMB)
ulong end_addr = tftp_load_addr + tftp_load_size;
 
if (!end_addr)
@@ -710,7 +710,7 @@ static void tftp_timeout_handler(void)
 /* Initialize tftp_load_addr and tftp_load_size from image_load_addr and lmb */
 static int tftp_init_load_addr(void)
 {
-#ifdef CONFIG_LMB
+#if CONFIG_IS_ENABLED(LMB)
phys_size_t max_size;
 
lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
diff --git a/net/wget.c b/net/wget.c
index 7cf809a8ef..b8ea43e7f0 100644
--- a/net/wget.c
+++ b/net/wget.c
@@ -98,7 +98,7 @@ static inline int store_block(uchar *src, unsigned int 
offset, unsigned int len)
ulong newsize = offset + len;
uchar *ptr;
 
-   if (IS_ENABLED(CONFIG_LMB)) {
+   if (CONFIG_IS_ENABLED(LMB)) {
ulong end_addr = image_load_addr + wget_load_size;
 
if (!end_addr)
@@ -496,7 +496,7 @@ void wget_start(void)
debug_cond(DEBUG_WGET,
 

[RFC PATCH v2 16/48] lmb: config: add lmb config symbols for SPL

2024-07-04 Thread Sughosh Ganu
Add separate config symbols for enabling the LMB module for the SPL
phase. The LMB module implementation now relies on alloced list data
structure which requires heap area to be present. Add specific config
symbol for the SPL phase of U-Boot so that this can be enabled on
platforms which support a heap in SPL.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 lib/Kconfig | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/lib/Kconfig b/lib/Kconfig
index 072ed0ecfa..7eea517b3b 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -1103,7 +1103,17 @@ config LMB
default y if ARC || ARM || M68K || MICROBLAZE || MIPS || \
 NIOS2 || PPC || RISCV || SANDBOX || SH || X86 || XTENSA
help
- Support the library logical memory blocks.
+ Support the library logical memory blocks. This will require
+ a malloc() implementation for defining the data structures
+ needed for maintaining the LMB memory map.
+
+config SPL_LMB
+   bool "Enable LMB module for SPL"
+   depends on SPL && SPL_FRAMEWORK && SPL_SYS_MALLOC
+   help
+ Enable support for Logical Memory Block library routines in
+ SPL. This will require a malloc() implementation for defining
+ the data structures needed for maintaining the LMB memory map.
 
 config PHANDLE_CHECK_SEQ
bool "Enable phandle check while getting sequence number"
-- 
2.34.1



[RFC PATCH v2 15/48] test: lmb: remove the test for max regions

2024-07-04 Thread Sughosh Ganu
The LMB memory map is now persistent and global, and the
CONFIG_LMB_USE_MAX_REGIONS config symbol has now been removed. Remove
the corresponding lmb test case.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 test/lib/lmb.c | 67 --
 1 file changed, 67 deletions(-)

diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 9f6b5633a7..a3a7ad904c 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -648,73 +648,6 @@ static int lib_test_lmb_get_free_size(struct 
unit_test_state *uts)
 }
 LIB_TEST(lib_test_lmb_get_free_size, 0);
 
-#ifdef CONFIG_LMB_USE_MAX_REGIONS
-static int lib_test_lmb_max_regions(struct unit_test_state *uts)
-{
-   const phys_addr_t ram = 0x;
-   /*
-* All of 32bit memory space will contain regions for this test, so
-* we need to scale ram_size (which in this case is the size of the lmb
-* region) to match.
-*/
-   const phys_size_t ram_size = ((0x >> CONFIG_LMB_MAX_REGIONS)
-   + 1) * CONFIG_LMB_MAX_REGIONS;
-   const phys_size_t blk_size = 0x1;
-   phys_addr_t offset;
-   int ret, i;
-
-   ut_asserteq(lmb.memory.cnt, 0);
-   ut_asserteq(lmb.memory.max, CONFIG_LMB_MAX_REGIONS);
-   ut_asserteq(lmb.reserved.cnt, 0);
-   ut_asserteq(lmb.reserved.max, CONFIG_LMB_MAX_REGIONS);
-
-   /*  Add CONFIG_LMB_MAX_REGIONS memory regions */
-   for (i = 0; i < CONFIG_LMB_MAX_REGIONS; i++) {
-   offset = ram + 2 * i * ram_size;
-   ret = lmb_add(offset, ram_size);
-   ut_asserteq(ret, 0);
-   }
-   ut_asserteq(lmb.memory.cnt, CONFIG_LMB_MAX_REGIONS);
-   ut_asserteq(lmb.reserved.cnt, 0);
-
-   /*  error for the (CONFIG_LMB_MAX_REGIONS + 1) memory regions */
-   offset = ram + 2 * (CONFIG_LMB_MAX_REGIONS + 1) * ram_size;
-   ret = lmb_add(offset, ram_size);
-   ut_asserteq(ret, -1);
-
-   ut_asserteq(lmb.memory.cnt, CONFIG_LMB_MAX_REGIONS);
-   ut_asserteq(lmb.reserved.cnt, 0);
-
-   /*  reserve CONFIG_LMB_MAX_REGIONS regions */
-   for (i = 0; i < CONFIG_LMB_MAX_REGIONS; i++) {
-   offset = ram + 2 * i * blk_size;
-   ret = lmb_reserve(offset, blk_size);
-   ut_asserteq(ret, 0);
-   }
-
-   ut_asserteq(lmb.memory.cnt, CONFIG_LMB_MAX_REGIONS);
-   ut_asserteq(lmb.reserved.cnt, CONFIG_LMB_MAX_REGIONS);
-
-   /*  error for the 9th reserved blocks */
-   offset = ram + 2 * (CONFIG_LMB_MAX_REGIONS + 1) * blk_size;
-   ret = lmb_reserve(offset, blk_size);
-   ut_asserteq(ret, -1);
-
-   ut_asserteq(lmb.memory.cnt, CONFIG_LMB_MAX_REGIONS);
-   ut_asserteq(lmb.reserved.cnt, CONFIG_LMB_MAX_REGIONS);
-
-   /*  check each regions */
-   for (i = 0; i < CONFIG_LMB_MAX_REGIONS; i++)
-   ut_asserteq(lmb.memory.region[i].base, ram + 2 * i * ram_size);
-
-   for (i = 0; i < CONFIG_LMB_MAX_REGIONS; i++)
-   ut_asserteq(lmb.reserved.region[i].base, ram + 2 * i * 
blk_size);
-
-   return 0;
-}
-LIB_TEST(lib_test_lmb_max_regions, 0);
-#endif
-
 static int lib_test_lmb_flags(struct unit_test_state *uts)
 {
const phys_addr_t ram = 0x4000;
-- 
2.34.1



[RFC PATCH v2 14/48] lmb: remove config symbols used for lmb region count

2024-07-04 Thread Sughosh Ganu
The LMB memory maps are now being maintained through a couple of
alloced lists, one for the available(added) memory, and one for the
used memory. These lists are not static arrays but can be extended at
runtime. Remove the config symbols which were being used to define the
size of these lists with the earlier implementation of static arrays.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 configs/a3y17lte_defconfig   |  1 -
 configs/a5y17lte_defconfig   |  1 -
 configs/a7y17lte_defconfig   |  1 -
 configs/apple_m1_defconfig   |  1 -
 configs/mt7981_emmc_rfb_defconfig|  1 -
 configs/mt7981_rfb_defconfig |  1 -
 configs/mt7981_sd_rfb_defconfig  |  1 -
 configs/mt7986_rfb_defconfig |  1 -
 configs/mt7986a_bpir3_emmc_defconfig |  1 -
 configs/mt7986a_bpir3_sd_defconfig   |  1 -
 configs/mt7988_rfb_defconfig |  1 -
 configs/mt7988_sd_rfb_defconfig  |  1 -
 configs/qcom_defconfig   |  1 -
 configs/stm32mp13_defconfig  |  3 ---
 configs/stm32mp15_basic_defconfig|  3 ---
 configs/stm32mp15_defconfig  |  3 ---
 configs/stm32mp15_trusted_defconfig  |  3 ---
 configs/stm32mp25_defconfig  |  3 ---
 configs/th1520_lpi4a_defconfig   |  1 -
 lib/Kconfig  | 34 
 20 files changed, 63 deletions(-)

diff --git a/configs/a3y17lte_defconfig b/configs/a3y17lte_defconfig
index 5c15d51fdc..b012b985a3 100644
--- a/configs/a3y17lte_defconfig
+++ b/configs/a3y17lte_defconfig
@@ -23,4 +23,3 @@ CONFIG_HUSH_PARSER=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_DM_I2C_GPIO=y
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/a5y17lte_defconfig b/configs/a5y17lte_defconfig
index 7c9b6b2511..25a7d5bc98 100644
--- a/configs/a5y17lte_defconfig
+++ b/configs/a5y17lte_defconfig
@@ -23,4 +23,3 @@ CONFIG_HUSH_PARSER=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_DM_I2C_GPIO=y
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/a7y17lte_defconfig b/configs/a7y17lte_defconfig
index c7297f7d75..c87379ab39 100644
--- a/configs/a7y17lte_defconfig
+++ b/configs/a7y17lte_defconfig
@@ -23,4 +23,3 @@ CONFIG_HUSH_PARSER=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_DM_I2C_GPIO=y
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig
index 20d2cff93f..dca6e0ca8b 100644
--- a/configs/apple_m1_defconfig
+++ b/configs/apple_m1_defconfig
@@ -26,4 +26,3 @@ CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_NO_FB_CLEAR=y
 CONFIG_VIDEO_SIMPLE=y
 # CONFIG_SMBIOS is not set
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/mt7981_emmc_rfb_defconfig 
b/configs/mt7981_emmc_rfb_defconfig
index 76ee2aa2d6..d3e833905f 100644
--- a/configs/mt7981_emmc_rfb_defconfig
+++ b/configs/mt7981_emmc_rfb_defconfig
@@ -62,4 +62,3 @@ CONFIG_MTK_SERIAL=y
 CONFIG_FAT_WRITE=y
 CONFIG_HEXDUMP=y
 # CONFIG_EFI_LOADER is not set
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/mt7981_rfb_defconfig b/configs/mt7981_rfb_defconfig
index 3989c79d2b..4bc2173f13 100644
--- a/configs/mt7981_rfb_defconfig
+++ b/configs/mt7981_rfb_defconfig
@@ -65,4 +65,3 @@ CONFIG_DM_SPI=y
 CONFIG_MTK_SPIM=y
 CONFIG_HEXDUMP=y
 # CONFIG_EFI_LOADER is not set
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/mt7981_sd_rfb_defconfig b/configs/mt7981_sd_rfb_defconfig
index 9b33245527..8721b4074a 100644
--- a/configs/mt7981_sd_rfb_defconfig
+++ b/configs/mt7981_sd_rfb_defconfig
@@ -62,4 +62,3 @@ CONFIG_MTK_SERIAL=y
 CONFIG_FAT_WRITE=y
 CONFIG_HEXDUMP=y
 # CONFIG_EFI_LOADER is not set
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/mt7986_rfb_defconfig b/configs/mt7986_rfb_defconfig
index 4d0cc85d0e..15c31de236 100644
--- a/configs/mt7986_rfb_defconfig
+++ b/configs/mt7986_rfb_defconfig
@@ -65,4 +65,3 @@ CONFIG_DM_SPI=y
 CONFIG_MTK_SPIM=y
 CONFIG_HEXDUMP=y
 # CONFIG_EFI_LOADER is not set
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/mt7986a_bpir3_emmc_defconfig 
b/configs/mt7986a_bpir3_emmc_defconfig
index 3c296ab803..56921f3605 100644
--- a/configs/mt7986a_bpir3_emmc_defconfig
+++ b/configs/mt7986a_bpir3_emmc_defconfig
@@ -62,4 +62,3 @@ CONFIG_MTK_SERIAL=y
 CONFIG_FAT_WRITE=y
 CONFIG_HEXDUMP=y
 # CONFIG_EFI_LOADER is not set
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/mt7986a_bpir3_sd_defconfig 
b/configs/mt7986a_bpir3_sd_defconfig
index f644070f4e..4ed06b72d5 100644
--- a/configs/mt7986a_bpir3_sd_defconfig
+++ b/configs/mt7986a_bpir3_sd_defconfig
@@ -62,4 +62,3 @@ CONFIG_MTK_SERIAL=y
 CONFIG_FAT_WRITE=y
 CONFIG_HEXDUMP=y
 # CONFIG_EFI_LOADER is not set
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/mt7988_rfb_defconfig b/configs/mt7988_rfb_defconfig
index d0ed2cc1c9..f7ceaceb30 100644
--- a/configs/mt7988_rfb_defconfig
+++ b/configs/mt7988_rfb_defconfig
@@ -81,4 +81,3 @@ CONFIG_MTK_SPIM=y
 CONFIG_LZO=y
 CONFIG_HEXDUMP=y
 # CONFIG_EFI_LOADER is not set
-CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/mt7988_sd_rfb_defconfig b/configs/mt7988_sd_rfb_defconfig
index 5631eaa338..808c8b9011 100644
--- a/configs

[RFC PATCH v2 13/48] lmb: make LMB memory map persistent and global

2024-07-04 Thread Sughosh Ganu
The current LMB API's for allocating and reserving memory use a
per-caller based memory view. Memory allocated by a caller can then be
overwritten by another caller. Make these allocations and reservations
persistent using the alloced list data structure.

Two alloced lists are declared -- one for the available(free) memory,
and one for the used memory. Once full, the list can then be extended
at runtime.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Use alloced list structure for the available and reserved memory
  lists instead of static arrays.
* Corresponding changes in the code made as a result of the above
  change.
* Rename the reserved memory list as 'used'.

 include/lmb.h |  77 +++
 lib/lmb.c | 346 ++
 2 files changed, 224 insertions(+), 199 deletions(-)

diff --git a/include/lmb.h b/include/lmb.h
index 99fcf5781f..27cdb18c37 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -24,78 +24,18 @@ enum lmb_flags {
 };
 
 /**
- * struct lmb_property - Description of one region.
+ * struct lmb_region - Description of one region.
  *
  * @base:  Base address of the region.
  * @size:  Size of the region
  * @flags: memory region attributes
  */
-struct lmb_property {
+struct lmb_region {
phys_addr_t base;
phys_size_t size;
enum lmb_flags flags;
 };
 
-/*
- * For regions size management, see LMB configuration in KConfig
- * all the #if test are done with CONFIG_LMB_USE_MAX_REGIONS (boolean)
- *
- * case 1. CONFIG_LMB_USE_MAX_REGIONS is defined (legacy mode)
- * => CONFIG_LMB_MAX_REGIONS is used to configure the region size,
- * directly in the array lmb_region.region[], with the same
- * configuration for memory and reserved regions.
- *
- * case 2. CONFIG_LMB_USE_MAX_REGIONS is not defined, the size of each
- * region is configurated *independently* with
- * => CONFIG_LMB_MEMORY_REGIONS: struct lmb.memory_regions
- * => CONFIG_LMB_RESERVED_REGIONS: struct lmb.reserved_regions
- * lmb_region.region is only a pointer to the correct buffer,
- * initialized in lmb_init(). This configuration is useful to manage
- * more reserved memory regions with CONFIG_LMB_RESERVED_REGIONS.
- */
-
-/**
- * struct lmb_region - Description of a set of region.
- *
- * @cnt: Number of regions.
- * @max: Size of the region array, max value of cnt.
- * @region: Array of the region properties
- */
-struct lmb_region {
-   unsigned long cnt;
-   unsigned long max;
-#if IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
-   struct lmb_property region[CONFIG_LMB_MAX_REGIONS];
-#else
-   struct lmb_property *region;
-#endif
-};
-
-/**
- * struct lmb - Logical memory block handle.
- *
- * Clients provide storage for Logical memory block (lmb) handles.
- * The content of the structure is managed by the lmb library.
- * A lmb struct is  initialized by lmb_init() functions.
- * The lmb struct is passed to all other lmb APIs.
- *
- * @memory: Description of memory regions.
- * @reserved: Description of reserved regions.
- * @memory_regions: Array of the memory regions (statically allocated)
- * @reserved_regions: Array of the reserved regions (statically allocated)
- */
-struct lmb {
-   struct lmb_region memory;
-   struct lmb_region reserved;
-#if !IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
-   struct lmb_property memory_regions[CONFIG_LMB_MEMORY_REGIONS];
-   struct lmb_property reserved_regions[CONFIG_LMB_RESERVED_REGIONS];
-#endif
-};
-
-void lmb_init_and_reserve(struct bd_info *bd, void *fdt_blob);
-void lmb_init_and_reserve_range(phys_addr_t base, phys_size_t size,
-   void *fdt_blob);
 long lmb_add(phys_addr_t base, phys_size_t size);
 long lmb_reserve(phys_addr_t base, phys_size_t size);
 /**
@@ -134,6 +74,19 @@ void board_lmb_reserve(void);
 void arch_lmb_reserve(void);
 void arch_lmb_reserve_generic(ulong sp, ulong end, ulong align);
 
+/**
+ * lmb_mem_regions_init() - Initialise the LMB memory
+ *
+ * Initialise the LMB subsystem related data structures. There are two
+ * alloced lists that are initialised, one for the free memory, and one
+ * for the used memory.
+ *
+ * Initialise the two lists as part of board init.
+ *
+ * Return: 0 if OK, -ve on failure.
+ */
+int lmb_mem_regions_init(void);
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_LMB_H */
diff --git a/lib/lmb.c b/lib/lmb.c
index 80945e3cae..a46bc8a7a3 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -6,6 +6,7 @@
  * Copyright (C) 2001 Peter Bergner.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -15,24 +16,30 @@
 
 #include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
 #define LMB_ALLOC_ANYWHERE 0
+#define LMB_ALIST_INITIAL_SIZE 4
 
-static void lmb_dump_region(struct lmb_region *rgn, char *name)
+struct alist lmb_free_mem;
+struct alist lmb_used_mem;
+
+static void lmb_dump_region(struct alist *lmb_rgn_lst, c

[RFC PATCH v2 12/48] lmb: allow for resizing lmb regions

2024-07-04 Thread Sughosh Ganu
Allow for resizing of LMB regions if the region attributes match. The
current code returns a failure status on detecting an overlapping
address. This worked up until now since the LMB calls were not
persistent and global -- the LMB memory map was specific and private
to a given caller of the LMB API's.

With the change in the LMB code to make the LMB reservations
persistent, there needs to be a check on whether the memory region can
be resized, and then do it if so. To distinguish between memory that
cannot be resized, add a new flag, LMB_NOOVERWRITE. Reserving a region
of memory with this attribute would indicate that the region cannot be
resized.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Do the check for the region flags in lmb_resize_regions() and
  lmb_merge_overlap_regions() to decide on merging the overlapping
  regions.

 include/lmb.h |   1 +
 lib/lmb.c | 116 --
 2 files changed, 103 insertions(+), 14 deletions(-)

diff --git a/include/lmb.h b/include/lmb.h
index 069c6af2a3..99fcf5781f 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -20,6 +20,7 @@
 enum lmb_flags {
LMB_NONE= 0x0,
LMB_NOMAP   = 0x4,
+   LMB_NOOVERWRITE = 0x8,
 };
 
 /**
diff --git a/lib/lmb.c b/lib/lmb.c
index 0d01e58a46..80945e3cae 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -230,12 +230,88 @@ void lmb_init_and_reserve_range(phys_addr_t base, 
phys_size_t size,
lmb_reserve_common(fdt_blob);
 }
 
+static bool lmb_region_flags_match(struct lmb_region *rgn, unsigned long r1,
+  enum lmb_flags flags)
+{
+   return rgn->region[r1].flags == flags;
+}
+
+static long lmb_merge_overlap_regions(struct lmb_region *rgn, unsigned long i,
+ phys_addr_t base, phys_size_t size,
+ enum lmb_flags flags)
+{
+   phys_size_t rgnsize;
+   unsigned long rgn_cnt, idx;
+   phys_addr_t rgnbase, rgnend;
+   phys_addr_t mergebase, mergeend;
+
+   rgn_cnt = 0;
+   idx = i;
+   /*
+* First thing to do is to identify how many regions does
+* the requested region overlap.
+* If the flags match, combine all these overlapping
+* regions into a single region, and remove the merged
+* regions.
+*/
+   while (idx < rgn->cnt - 1) {
+   rgnbase = rgn->region[idx].base;
+   rgnsize = rgn->region[idx].size;
+
+   if (lmb_addrs_overlap(base, size, rgnbase,
+ rgnsize)) {
+   if (!lmb_region_flags_match(rgn, idx, flags))
+   return -1;
+   rgn_cnt++;
+   idx++;
+   }
+   }
+
+   /* The merged region's base and size */
+   rgnbase = rgn->region[i].base;
+   mergebase = min(base, rgnbase);
+   rgnend = rgn->region[idx].base + rgn->region[idx].size;
+   mergeend = max(rgnend, (base + size));
+
+   rgn->region[i].base = mergebase;
+   rgn->region[i].size = mergeend - mergebase;
+
+   /* Now remove the merged regions */
+   while (--rgn_cnt)
+   lmb_remove_region(rgn, i + 1);
+
+   return 0;
+}
+
+static long lmb_resize_regions(struct lmb_region *rgn, unsigned long i,
+  phys_addr_t base, phys_size_t size,
+  enum lmb_flags flags)
+{
+   long ret = 0;
+   phys_addr_t rgnend;
+
+   if (i == rgn->cnt - 1 ||
+   base + size < rgn->region[i + 1].base) {
+   if (!lmb_region_flags_match(rgn, i, flags))
+   return -1;
+
+   rgnend = rgn->region[i].base + rgn->region[i].size;
+   rgn->region[i].base = min(base, rgn->region[i].base);
+   rgnend = max(base + size, rgnend);
+   rgn->region[i].size = rgnend - rgn->region[i].base;
+   } else {
+   ret = lmb_merge_overlap_regions(rgn, i, base, size, flags);
+   }
+
+   return ret;
+}
+
 /* This routine called with relocation disabled. */
 static long lmb_add_region_flags(struct lmb_region *rgn, phys_addr_t base,
 phys_size_t size, enum lmb_flags flags)
 {
unsigned long coalesced = 0;
-   long adjacent, i;
+   long ret, i;
 
if (rgn->cnt == 0) {
rgn->region[0].base = base;
@@ -260,23 +336,28 @@ static long lmb_add_region_flags(struct lmb_region *rgn, 
phys_addr_t base,
return -1; /* regions with new flags */
}
 
-   adjacent = lmb_addrs_adjacent(base, size, rgnbase, rgnsize);
-   if (adjacent > 0) {
+   ret = lmb_addrs_adjacent(base, size, rgnbase, rgnsize);
+   if (ret > 0) {
   

[RFC PATCH v2 11/48] lmb: pass a flag to image_setup_libfdt() for lmb reservations

2024-07-04 Thread Sughosh Ganu
The image_setup_libfdt() function optionally calls the LMB API to
reserve the region of memory occupied by the FDT blob. This was
earlier determined through the presence of the pointer to the lmb
structure, which is no longer present. Pass a flag to the
image_setup_libfdt() function to indicate if the region occupied by
the FDT blob is to be marked as reserved by the LMB module.

Signed-off-by: Sughosh Ganu 
---
Changes since V1:
* Use true/false identifiers for bool instead of 1/0
* Fix the argument passed to the function in arch/mips/lib/bootm.c

 arch/mips/lib/bootm.c | 2 +-
 boot/image-board.c| 2 +-
 boot/image-fdt.c  | 7 +++
 cmd/elf.c | 2 +-
 include/image.h   | 5 ++---
 lib/efi_loader/efi_dt_fixup.c | 2 +-
 lib/efi_loader/efi_helper.c   | 2 +-
 7 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 54d89e9cca..8fb3a3923f 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -247,7 +247,7 @@ static int boot_setup_fdt(struct bootm_headers *images)
images->initrd_start = virt_to_phys((void *)images->initrd_start);
images->initrd_end = virt_to_phys((void *)images->initrd_end);
 
-   return image_setup_libfdt(images, images->ft_addr, >lmb);
+   return image_setup_libfdt(images, images->ft_addr, true);
 }
 
 static void boot_prep_linux(struct bootm_headers *images)
diff --git a/boot/image-board.c b/boot/image-board.c
index e3cb418e3c..1f8c1ac69f 100644
--- a/boot/image-board.c
+++ b/boot/image-board.c
@@ -904,7 +904,7 @@ int image_setup_linux(struct bootm_headers *images)
}
 
if (CONFIG_IS_ENABLED(OF_LIBFDT) && of_size) {
-   ret = image_setup_libfdt(images, *of_flat_tree, lmb);
+   ret = image_setup_libfdt(images, *of_flat_tree, true);
if (ret)
return ret;
}
diff --git a/boot/image-fdt.c b/boot/image-fdt.c
index 943a3477a1..7c3d66bad7 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -566,8 +566,7 @@ __weak int arch_fixup_fdt(void *blob)
return 0;
 }
 
-int image_setup_libfdt(struct bootm_headers *images, void *blob,
-  struct lmb *lmb)
+int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb)
 {
ulong *initrd_start = >initrd_start;
ulong *initrd_end = >initrd_end;
@@ -667,7 +666,7 @@ int image_setup_libfdt(struct bootm_headers *images, void 
*blob,
}
 
/* Delete the old LMB reservation */
-   if (lmb)
+   if (CONFIG_IS_ENABLED(LMB) && lmb)
lmb_free(map_to_sysmem(blob), fdt_totalsize(blob));
 
ret = fdt_shrink_to_minimum(blob, 0);
@@ -676,7 +675,7 @@ int image_setup_libfdt(struct bootm_headers *images, void 
*blob,
of_size = ret;
 
/* Create a new LMB reservation */
-   if (lmb)
+   if (CONFIG_IS_ENABLED(LMB) && lmb)
lmb_reserve(map_to_sysmem(blob), of_size);
 
 #if defined(CONFIG_ARCH_KEYSTONE)
diff --git a/cmd/elf.c b/cmd/elf.c
index 32b7462f92..df53c5b0cb 100644
--- a/cmd/elf.c
+++ b/cmd/elf.c
@@ -68,7 +68,7 @@ int do_bootelf(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
log_debug("Setting up FDT at 0x%08lx ...\n", fdt_addr);
flush();
 
-   if (image_setup_libfdt(, (void *)fdt_addr, NULL))
+   if (image_setup_libfdt(, (void *)fdt_addr, false))
return 1;
}
 #endif
diff --git a/include/image.h b/include/image.h
index 8036eae15c..47fd80bef4 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1018,11 +1018,10 @@ int image_decomp(int comp, ulong load, ulong 
image_start, int type,
  *
  * @images:Images information
  * @blob:  FDT to update
- * @lmb:   Points to logical memory block structure
+ * @lmb:   Flag indicating use of lmb for reserving FDT memory region
  * Return: 0 if ok, <0 on failure
  */
-int image_setup_libfdt(struct bootm_headers *images, void *blob,
-  struct lmb *lmb);
+int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb);
 
 /**
  * Set up the FDT to use for booting a kernel
diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c
index 9886e6897c..9d017804ee 100644
--- a/lib/efi_loader/efi_dt_fixup.c
+++ b/lib/efi_loader/efi_dt_fixup.c
@@ -172,7 +172,7 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
}
 
fdt_set_totalsize(dtb, *buffer_size);
-   if (image_setup_libfdt(, dtb, NULL)) {
+   if (image_setup_libfdt(, dtb, false)) {
log_err("failed to process device tree\n");
ret = EFI_INVALID_PARAMETER;
goto out;
diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c
index

[RFC PATCH v2 10/48] lmb: remove local instances of the lmb structure variable

2024-07-04 Thread Sughosh Ganu
With the move of the LMB structure to a persistent state, there is no
need to declare the variable locally, and pass it as part of the LMB
API's. Remove all local variable instances and change the API's
correspondingly.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: None

 arch/arc/lib/cache.c |   4 +-
 arch/arm/lib/stack.c |   4 +-
 arch/arm/mach-apple/board.c  |  17 ++-
 arch/arm/mach-snapdragon/board.c |  17 ++-
 arch/arm/mach-stm32mp/dram_init.c|   7 +-
 arch/arm/mach-stm32mp/stm32mp1/cpu.c |   6 +-
 arch/m68k/lib/bootm.c|   7 +-
 arch/microblaze/lib/bootm.c  |   4 +-
 arch/mips/lib/bootm.c|   9 +-
 arch/nios2/lib/bootm.c   |   4 +-
 arch/powerpc/cpu/mpc85xx/mp.c|   4 +-
 arch/powerpc/include/asm/mp.h|   4 +-
 arch/powerpc/lib/bootm.c |  14 +-
 arch/riscv/lib/bootm.c   |   4 +-
 arch/sh/lib/bootm.c  |   4 +-
 arch/x86/lib/bootm.c |   4 +-
 arch/xtensa/lib/bootm.c  |   4 +-
 board/xilinx/common/board.c  |   7 +-
 boot/bootm.c |  26 ++--
 boot/bootm_os.c  |   5 +-
 boot/image-board.c   |  32 ++---
 boot/image-fdt.c |  29 ++---
 cmd/bdinfo.c |   6 +-
 cmd/booti.c  |   2 +-
 cmd/bootz.c  |   2 +-
 cmd/load.c   |   7 +-
 drivers/iommu/apple_dart.c   |   7 +-
 drivers/iommu/sandbox_iommu.c|  15 +--
 fs/fs.c  |   7 +-
 include/image.h  |  22 +---
 include/lmb.h|  39 +++---
 lib/lmb.c|  81 ++--
 net/tftp.c   |   5 +-
 net/wget.c   |   5 +-
 test/cmd/bdinfo.c|   2 +-
 test/lib/lmb.c   | 187 +--
 36 files changed, 270 insertions(+), 333 deletions(-)

diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c
index 22e748868a..5151af917a 100644
--- a/arch/arc/lib/cache.c
+++ b/arch/arc/lib/cache.c
@@ -829,7 +829,7 @@ static ulong get_sp(void)
return ret;
 }
 
-void arch_lmb_reserve(struct lmb *lmb)
+void arch_lmb_reserve(void)
 {
-   arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 4096);
+   arch_lmb_reserve_generic(get_sp(), gd->ram_top, 4096);
 }
diff --git a/arch/arm/lib/stack.c b/arch/arm/lib/stack.c
index ea1b937add..87d5c962d7 100644
--- a/arch/arm/lib/stack.c
+++ b/arch/arm/lib/stack.c
@@ -42,7 +42,7 @@ static ulong get_sp(void)
return ret;
 }
 
-void arch_lmb_reserve(struct lmb *lmb)
+void arch_lmb_reserve(void)
 {
-   arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 16384);
+   arch_lmb_reserve_generic(get_sp(), gd->ram_top, 16384);
 }
diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c
index 8bace3005e..213390d6e8 100644
--- a/arch/arm/mach-apple/board.c
+++ b/arch/arm/mach-apple/board.c
@@ -773,23 +773,22 @@ u64 get_page_table_size(void)
 
 int board_late_init(void)
 {
-   struct lmb lmb;
u32 status = 0;
 
-   lmb_init_and_reserve(, gd->bd, (void *)gd->fdt_blob);
+   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
 
/* somewhat based on the Linux Kernel boot requirements:
 * align by 2M and maximal FDT size 2M
 */
-   status |= env_set_hex("loadaddr", lmb_alloc(, SZ_1G, SZ_2M));
-   status |= env_set_hex("fdt_addr_r", lmb_alloc(, SZ_2M, SZ_2M));
-   status |= env_set_hex("kernel_addr_r", lmb_alloc(, SZ_128M, SZ_2M));
-   status |= env_set_hex("ramdisk_addr_r", lmb_alloc(, SZ_1G, SZ_2M));
+   status |= env_set_hex("loadaddr", lmb_alloc(SZ_1G, SZ_2M));
+   status |= env_set_hex("fdt_addr_r", lmb_alloc(SZ_2M, SZ_2M));
+   status |= env_set_hex("kernel_addr_r", lmb_alloc(SZ_128M, SZ_2M));
+   status |= env_set_hex("ramdisk_addr_r", lmb_alloc(SZ_1G, SZ_2M));
status |= env_set_hex("kernel_comp_addr_r",
- lmb_alloc(, KERNEL_COMP_SIZE, SZ_2M));
+ lmb_alloc(KERNEL_COMP_SIZE, SZ_2M));
status |= env_set_hex("kernel_comp_size", KERNEL_COMP_SIZE);
-   status |= env_set_hex("scriptaddr", lmb_alloc(, SZ_4M, SZ_2M));
-   status |= env_set_hex("pxefile_addr_r", lmb_alloc(, SZ_4M, SZ_2M));
+   status |= env_set_hex("scriptaddr", lmb_alloc(SZ_4M, SZ_2M));
+   status |= env_set_hex("pxefile_addr_r", lmb_alloc(SZ_4M, SZ_2M));
 
if (status)
log_warning("late_init: Failed to set run time variables\n");
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index b439a19ec7..a63c

[RFC PATCH v2 09/48] lmb: remove call to lmb_init()

2024-07-04 Thread Sughosh Ganu
The LMB module will be changed to have persistent and global memory
maps of available and used memory. With this change, there won't be
any need to explicitly initialise the LMB memory maps. Remove the call
to the lmb_init() function.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 arch/arm/mach-stm32mp/dram_init.c |  1 -
 board/xilinx/common/board.c   |  1 -
 drivers/iommu/apple_dart.c|  1 -
 drivers/iommu/sandbox_iommu.c |  1 -
 include/lmb.h |  1 -
 lib/lmb.c | 18 --
 test/lib/lmb.c| 18 --
 7 files changed, 41 deletions(-)

diff --git a/arch/arm/mach-stm32mp/dram_init.c 
b/arch/arm/mach-stm32mp/dram_init.c
index 6024959b97..a5437e4e55 100644
--- a/arch/arm/mach-stm32mp/dram_init.c
+++ b/arch/arm/mach-stm32mp/dram_init.c
@@ -59,7 +59,6 @@ phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
gd->ram_top = clamp_val(gd->ram_top, 0, SZ_4G - 1);
 
/* found enough not-reserved memory to relocated U-Boot */
-   lmb_init();
lmb_add(, gd->ram_base, gd->ram_top - gd->ram_base);
boot_fdt_add_mem_rsv_regions(, (void *)gd->fdt_blob);
/* add 8M for reserved memory for display, fdt, gd,... */
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 0b43407b9e..61dc37964d 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -684,7 +684,6 @@ phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob);
 
/* found enough not-reserved memory to relocated U-Boot */
-   lmb_init();
lmb_add(, gd->ram_base, gd->ram_size);
boot_fdt_add_mem_rsv_regions(, (void *)gd->fdt_blob);
size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE);
diff --git a/drivers/iommu/apple_dart.c b/drivers/iommu/apple_dart.c
index 9327dea1e3..3e59490973 100644
--- a/drivers/iommu/apple_dart.c
+++ b/drivers/iommu/apple_dart.c
@@ -213,7 +213,6 @@ static int apple_dart_probe(struct udevice *dev)
priv->dvabase = DART_PAGE_SIZE;
priv->dvaend = SZ_4G - DART_PAGE_SIZE;
 
-   lmb_init(>lmb);
lmb_add(>lmb, priv->dvabase, priv->dvaend - priv->dvabase);
 
/* Disable translations. */
diff --git a/drivers/iommu/sandbox_iommu.c b/drivers/iommu/sandbox_iommu.c
index e37976f86f..3184b3a64e 100644
--- a/drivers/iommu/sandbox_iommu.c
+++ b/drivers/iommu/sandbox_iommu.c
@@ -54,7 +54,6 @@ static int sandbox_iommu_probe(struct udevice *dev)
 {
struct sandbox_iommu_priv *priv = dev_get_priv(dev);
 
-   lmb_init(>lmb);
lmb_add(>lmb, 0x89abc000, SZ_16K);
 
return 0;
diff --git a/include/lmb.h b/include/lmb.h
index 7b87181b9e..20d6feebf5 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -92,7 +92,6 @@ struct lmb {
 #endif
 };
 
-void lmb_init(struct lmb *lmb);
 void lmb_init_and_reserve(struct lmb *lmb, struct bd_info *bd, void *fdt_blob);
 void lmb_init_and_reserve_range(struct lmb *lmb, phys_addr_t base,
phys_size_t size, void *fdt_blob);
diff --git a/lib/lmb.c b/lib/lmb.c
index 4d39c0d1f9..0141da9766 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -130,21 +130,6 @@ static void lmb_fix_over_lap_regions(struct lmb_region 
*rgn, unsigned long r1,
lmb_remove_region(rgn, r2);
 }
 
-void lmb_init(struct lmb *lmb)
-{
-#if IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
-   lmb->memory.max = CONFIG_LMB_MAX_REGIONS;
-   lmb->reserved.max = CONFIG_LMB_MAX_REGIONS;
-#else
-   lmb->memory.max = CONFIG_LMB_MEMORY_REGIONS;
-   lmb->reserved.max = CONFIG_LMB_RESERVED_REGIONS;
-   lmb->memory.region = lmb->memory_regions;
-   lmb->reserved.region = lmb->reserved_regions;
-#endif
-   lmb->memory.cnt = 0;
-   lmb->reserved.cnt = 0;
-}
-
 void arch_lmb_reserve_generic(struct lmb *lmb, ulong sp, ulong end, ulong 
align)
 {
ulong bank_end;
@@ -231,8 +216,6 @@ void lmb_init_and_reserve(struct lmb *lmb, struct bd_info 
*bd, void *fdt_blob)
 {
int i;
 
-   lmb_init(lmb);
-
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
if (bd->bi_dram[i].size) {
lmb_add(lmb, bd->bi_dram[i].start,
@@ -247,7 +230,6 @@ void lmb_init_and_reserve(struct lmb *lmb, struct bd_info 
*bd, void *fdt_blob)
 void lmb_init_and_reserve_range(struct lmb *lmb, phys_addr_t base,
phys_size_t size, void *fdt_blob)
 {
-   lmb_init(lmb);
lmb_add(lmb, base, size);
lmb_reserve_common(lmb, fdt_blob);
 }
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 4b5b6e5e20..74e74501cf 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -75,8 +75,6 @@ static int test_multi_alloc(struct unit_test_state *uts, 
const phys_addr_t ram,
ut_assert(alloc_64k_addr &

[RFC PATCH v2 08/48] lmb: staticize __lmb_alloc_base()

2024-07-04 Thread Sughosh Ganu
The __lmb_alloc_base() function is only called from within the lmb
module. Moreover, the lmb_alloc() and lmb_alloc_base() API's are good
enough for the allocation API calls. Make the __lmb_alloc_base()
function static.

Signed-off-by: Sughosh Ganu 
Reviewed-by: Ilias Apalodimas 
---
Changes since V1: None

 include/lmb.h |  2 --
 lib/lmb.c | 39 ---
 2 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/include/lmb.h b/include/lmb.h
index 6c50d93e83..7b87181b9e 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -112,8 +112,6 @@ long lmb_reserve_flags(struct lmb *lmb, phys_addr_t base,
 phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align);
 phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
   phys_addr_t max_addr);
-phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
-phys_addr_t max_addr);
 phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t 
size);
 phys_size_t lmb_get_free_size(struct lmb *lmb, phys_addr_t addr);
 
diff --git a/lib/lmb.c b/lib/lmb.c
index adc3abd5b4..4d39c0d1f9 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -435,30 +435,13 @@ static long lmb_overlaps_region(struct lmb_region *rgn, 
phys_addr_t base,
return (i < rgn->cnt) ? i : -1;
 }
 
-phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align)
-{
-   return lmb_alloc_base(lmb, size, align, LMB_ALLOC_ANYWHERE);
-}
-
-phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, 
phys_addr_t max_addr)
-{
-   phys_addr_t alloc;
-
-   alloc = __lmb_alloc_base(lmb, size, align, max_addr);
-
-   if (alloc == 0)
-   printf("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n",
-  (ulong)size, (ulong)max_addr);
-
-   return alloc;
-}
-
 static phys_addr_t lmb_align_down(phys_addr_t addr, phys_size_t size)
 {
return addr & ~(size - 1);
 }
 
-phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, 
phys_addr_t max_addr)
+static phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size,
+   ulong align, phys_addr_t max_addr)
 {
long i, rgn;
phys_addr_t base = 0;
@@ -499,6 +482,24 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t 
size, ulong align, phy
return 0;
 }
 
+phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align)
+{
+   return lmb_alloc_base(lmb, size, align, LMB_ALLOC_ANYWHERE);
+}
+
+phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, 
phys_addr_t max_addr)
+{
+   phys_addr_t alloc;
+
+   alloc = __lmb_alloc_base(lmb, size, align, max_addr);
+
+   if (alloc == 0)
+   printf("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n",
+  (ulong)size, (ulong)max_addr);
+
+   return alloc;
+}
+
 /*
  * Try to allocate a specific address range: must be in defined memory but not
  * reserved
-- 
2.34.1



[RFC PATCH v2 07/48] lmb: remove the unused lmb_is_reserved() function

2024-07-04 Thread Sughosh Ganu
The lmb_is_reserved() API is not used. There is another API,
lmb_is_reserved_flags() which can be used to check if a particular
memory region is reserved. Remove the unused API.

Signed-off-by: Sughosh Ganu 
Reviewed-by: Ilias Apalodimas 
---
Changes since V1: None

 include/lmb.h | 11 ---
 lib/lmb.c |  5 -
 2 files changed, 16 deletions(-)

diff --git a/include/lmb.h b/include/lmb.h
index 231b68b27d..6c50d93e83 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -117,17 +117,6 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t 
size, ulong align,
 phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t 
size);
 phys_size_t lmb_get_free_size(struct lmb *lmb, phys_addr_t addr);
 
-/**
- * lmb_is_reserved() - test if address is in reserved region
- *
- * The function checks if a reserved region comprising @addr exists.
- *
- * @lmb:   the logical memory block struct
- * @addr:  address to be tested
- * Return: 1 if reservation exists, 0 otherwise
- */
-int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr);
-
 /**
  * lmb_is_reserved_flags() - test if address is in reserved region with flag 
bits set
  *
diff --git a/lib/lmb.c b/lib/lmb.c
index 44f9820531..adc3abd5b4 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -565,11 +565,6 @@ int lmb_is_reserved_flags(struct lmb *lmb, phys_addr_t 
addr, int flags)
return 0;
 }
 
-int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr)
-{
-   return lmb_is_reserved_flags(lmb, addr, LMB_NONE);
-}
-
 __weak void board_lmb_reserve(struct lmb *lmb)
 {
/* please define platform specific board_lmb_reserve() */
-- 
2.34.1



[RFC PATCH v2 06/48] alist: add a function declaration for alist_expand_by()

2024-07-04 Thread Sughosh Ganu
The alist_expand_by() function is a global function. Add a declaration
for the function in the header.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 include/alist.h | 9 +
 1 file changed, 9 insertions(+)

diff --git a/include/alist.h b/include/alist.h
index bab146c35d..d7cc27c14c 100644
--- a/include/alist.h
+++ b/include/alist.h
@@ -224,4 +224,13 @@ void *alist_uninit_move_ptr(struct alist *alist, size_t 
*countp);
  */
 void alist_uninit(struct alist *alist);
 
+/**
+ * alist_expand_by() - Expand a list by the given amount
+ *
+ * @lst: alist to expand
+ * @inc_by: Amount to expand by
+ * Return: true if OK, false if out of memory
+ */
+bool alist_expand_by(struct alist *lst, uint inc_by);
+
 #endif /* __ALIST_H */
-- 
2.34.1



[RFC PATCH v2 05/48] alist: add a couple of helper functions

2024-07-04 Thread Sughosh Ganu
Add a couple of helper functions to detect an empty and full alist.

Signed-off-by: Sughosh Ganu 
---
Changes since V1: New patch

 include/alist.h | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/include/alist.h b/include/alist.h
index a68afc9fff..bab146c35d 100644
--- a/include/alist.h
+++ b/include/alist.h
@@ -82,6 +82,28 @@ static inline bool alist_err(struct alist *lst)
return lst->flags & ALISTF_FAIL;
 }
 
+/**
+ * alist_full() - Check if the alist is full
+ *
+ * @lst: List to check
+ * Return: true if full, false otherwise
+ */
+static inline bool alist_full(struct alist *lst)
+{
+   return lst->count == lst->alloc;
+}
+
+/**
+ * alist_empty() - Check if the alist is empty
+ *
+ * @lst: List to check
+ * Return: true if empty, false otherwise
+ */
+static inline bool alist_empty(struct alist *lst)
+{
+   return !lst->count && lst->alloc;
+}
+
 /**
  * alist_get_ptr() - Get the value of a pointer
  *
-- 
2.34.1



[RFC PATCH v2 04/48] lib: Convert str_to_list() to use alist

2024-07-04 Thread Sughosh Ganu
From: Simon Glass 

Use this new data structure in the utility function.

Signed-off-by: Simon Glass 
Signed-off-by: Sughosh Ganu 
---
 lib/strto.c | 35 +++
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/lib/strto.c b/lib/strto.c
index f83ac67c66..f059408755 100644
--- a/lib/strto.c
+++ b/lib/strto.c
@@ -9,6 +9,7 @@
  * Wirzenius wrote this portably, Torvalds fucked it up :-)
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -226,37 +227,39 @@ void str_to_upper(const char *in, char *out, size_t len)
 
 const char **str_to_list(const char *instr)
 {
-   const char **ptr;
-   char *str, *p;
-   int count, i;
+   struct alist alist;
+   char *str, *p, *start;
 
/* don't allocate if the string is empty */
str = *instr ? strdup(instr) : (char *)instr;
if (!str)
return NULL;
 
-   /* count the number of space-separated strings */
-   for (count = 0, p = str; *p; p++) {
+   alist_init_struct(, char *);
+
+   if (*str)
+   alist_add(, , char *);
+   for (start = str, p = str; *p; p++) {
if (*p == ' ') {
-   count++;
*p = '\0';
+   start = p + 1;
+   if (*start)
+   alist_add(, , char *);
}
}
-   if (p != str && p[-1])
-   count++;
 
-   /* allocate the pointer array, allowing for a NULL terminator */
-   ptr = calloc(count + 1, sizeof(char *));
-   if (!ptr) {
-   if (*str)
+   /* terminate list */
+   p = NULL;
+   alist_add(, , char *);
+   if (alist_err()) {
+   alist_uninit();
+
+   if (*instr)
free(str);
return NULL;
}
 
-   for (i = 0, p = str; i < count; p += strlen(p) + 1, i++)
-   ptr[i] = p;
-
-   return ptr;
+   return alist_uninit_move(, NULL, const char *);
 }
 
 void str_free_list(const char **ptr)
-- 
2.34.1



[RFC PATCH v2 03/48] alist: Add support for an allocated pointer list

2024-07-04 Thread Sughosh Ganu
From: Simon Glass 

In various places it is useful to have an array of structures, but allow
it to grow. In some cases we work around it by setting maximum number of
entries, using a Kconfig option. In other places we use a linked list,
which does not provide for random access and can complicate the code.

Introduce a new data structure, which is a variable-sized list of structs
each of the same, pre-set size. It provides O(1) access and is reasonably
efficient at expanding linearly, since it doubles in size when it runs out
of space.

Signed-off-by: Simon Glass 
Signed-off-by: Sughosh Ganu 
---
 include/alist.h   | 205 ++
 lib/Makefile  |   1 +
 lib/alist.c   | 154 ++
 test/lib/Makefile |   1 +
 test/lib/alist.c  | 197 
 5 files changed, 558 insertions(+)
 create mode 100644 include/alist.h
 create mode 100644 lib/alist.c
 create mode 100644 test/lib/alist.c

diff --git a/include/alist.h b/include/alist.h
new file mode 100644
index 00..a68afc9fff
--- /dev/null
+++ b/include/alist.h
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Handles a contiguous list of pointers which be allocated and freed
+ *
+ * Copyright 2023 Google LLC
+ * Written by Simon Glass 
+ */
+
+#ifndef __ALIST_H
+#define __ALIST_H
+
+#include 
+#include 
+#include 
+
+/**
+ * struct alist - object list that can be allocated and freed
+ *
+ * Holds a list of objects, each of the same size. The object is typically a
+ * C struct. The array is alloced in memory can change in size.
+ *
+ * The list rememebers the size of the list, but has a separate count of how
+ * much space is allocated, This allows it increase in size in steps as more
+ * elements are added, which is more efficient that reallocating the list every
+ * time a single item is added
+ *
+ * Two types of access are provided:
+ *
+ * alist_get...(index)
+ * gets an existing element, if its index is less that size
+ *
+ * alist_ensure(index)
+ * address an existing element, or creates a new one if not present
+ *
+ * @data: object data of size `@obj_size * @alloc`. The list can grow as
+ * needed but never shrinks
+ * @obj_size: Size of each object in bytes
+ * @count: number of objects in array
+ * @alloc: allocated length of array, to which @count can grow
+ * @flags: flags for the alist (ALISTF_...)
+ */
+struct alist {
+   void *data;
+   u16 obj_size;
+   u16 count;
+   u16 alloc;
+   u16 flags;
+};
+
+/**
+ * enum alist_flags - Flags for the alist
+ *
+ * @ALIST_FAIL: true if any allocation has failed. Once this has happened, the
+ * alist is dead and cannot grow further
+ */
+enum alist_flags {
+   ALISTF_FAIL = BIT(0),
+};
+
+/**
+ * alist_has() - Check if an index is within the list range
+ *
+ * Checks if index is within the current alist count
+ *
+ * @lst: alist to check
+ * @index: Index to check
+ * Returns: true if value, else false
+ */
+static inline bool alist_has(struct alist *lst, uint index)
+{
+   return index < lst->count;
+}
+
+/**
+ * alist_err() - Check if the alist is still valid
+ *
+ * @lst: List to check
+ * Return: false if OK, true if any previous allocation failed
+ */
+static inline bool alist_err(struct alist *lst)
+{
+   return lst->flags & ALISTF_FAIL;
+}
+
+/**
+ * alist_get_ptr() - Get the value of a pointer
+ *
+ * @lst: alist to check
+ * @index: Index to read from
+ * Returns: pointer, if present, else NULL
+ */
+const void *alist_get_ptr(struct alist *lst, uint index);
+
+/**
+ * alist_getd() - Get the value of a pointer directly, with no checking
+ *
+ * This must only be called on indexes for which alist_has() returns true
+ *
+ * @lst: alist to check
+ * @index: Index to read from
+ * Returns: pointer value (may be NULL)
+ */
+static inline const void *alist_getd(struct alist *lst, uint index)
+{
+   return lst->data + index * lst->obj_size;
+}
+
+#define alist_get(_lst, _index, _struct)   \
+   ((const _struct *)alist_get_ptr(_lst, _index))
+
+/**
+ * alist_ensure_ptr() - Ensure an object exists at a given index
+ *
+ * This provides read/write access to an array element. If it does not exist,
+ * it is allocated, reading for the caller to store the object into
+ *
+ * Allocates a object at the given index if needed
+ *
+ * @lst: alist to check
+ * @index: Index to address
+ * Returns: pointer where struct can be read/written, or NULL if out of memory
+ */
+void *alist_ensure_ptr(struct alist *lst, uint index);
+
+/**
+ * alist_ensure() - Address a struct, the correct object type
+ *
+ * Use as:
+ * struct my_struct *ptr = alist_ensure(, 4, struct my_struct);
+ */
+#define alist_ensure(_lst, _index, _struct)\
+   ((_struct *)alist_ensure_ptr(_lst, _index))
+
+/**
+ * alist_add_ptr() - Ad a new object to the list
+ *
+ * @lst: alist to add to
+ * @obj: Pointer to object to copy in
+ * Return

[RFC PATCH v2 02/48] lib: Handle a special case with str_to_list()

2024-07-04 Thread Sughosh Ganu
From: Simon Glass 

The current implementation can return an extra result at the end when
the string ends with a space. Fix this by adding a special case.

Signed-off-by: Simon Glass 
Signed-off-by: Sughosh Ganu 
---
 lib/strto.c   | 4 +++-
 test/str_ut.c | 4 +---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/strto.c b/lib/strto.c
index 5157332d6c..f83ac67c66 100644
--- a/lib/strto.c
+++ b/lib/strto.c
@@ -236,12 +236,14 @@ const char **str_to_list(const char *instr)
return NULL;
 
/* count the number of space-separated strings */
-   for (count = *str != '\0', p = str; *p; p++) {
+   for (count = 0, p = str; *p; p++) {
if (*p == ' ') {
count++;
*p = '\0';
}
}
+   if (p != str && p[-1])
+   count++;
 
/* allocate the pointer array, allowing for a NULL terminator */
ptr = calloc(count + 1, sizeof(char *));
diff --git a/test/str_ut.c b/test/str_ut.c
index 389779859a..96e048975d 100644
--- a/test/str_ut.c
+++ b/test/str_ut.c
@@ -342,9 +342,7 @@ static int test_str_to_list(struct unit_test_state *uts)
ut_asserteq_str("space", ptr[3]);
ut_assertnonnull(ptr[4]);
ut_asserteq_str("", ptr[4]);
-   ut_assertnonnull(ptr[5]);
-   ut_asserteq_str("", ptr[5]);
-   ut_assertnull(ptr[6]);
+   ut_assertnull(ptr[5]);
str_free_list(ptr);
ut_assertok(ut_check_delta(start));
 
-- 
2.34.1



[RFC PATCH v2 01/48] malloc: Support testing with realloc()

2024-07-04 Thread Sughosh Ganu
From: Simon Glass 

At present in tests it is possible to cause an out-of-memory condition
with malloc() but not realloc(). Add support to realloc() too, so code
which uses that function can be tested.

Signed-off-by: Simon Glass 
Signed-off-by: Sughosh Ganu 
---
 common/dlmalloc.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index 9549c59f35..65b130fabc 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -1758,6 +1758,10 @@ Void_t* rEALLOc_impl(oldmem, bytes) Void_t* oldmem; 
size_t bytes;
panic("pre-reloc realloc() is not supported");
}
 #endif
+  if (CONFIG_IS_ENABLED(UNIT_TEST) && malloc_testing) {
+if (--malloc_max_allocs < 0)
+  return NULL;
+  }
 
   newp= oldp= mem2chunk(oldmem);
   newsize = oldsize = chunksize(oldp);
-- 
2.34.1



[RFC PATCH v2 00/48] Make U-Boot memory reservations coherent

2024-07-04 Thread Sughosh Ganu


The aim of this patch series is to fix the current state of
incoherence between modules when it comes to memory usage. The primary
issue that this series is trying to fix is that the EFI memory module
which is responsible for allocating and freeing memory, does not have
any visibility of the memory that is being used by the LMB
module. This is further complicated by the fact that the LMB
allocations are caller specific -- the LMB memory map is not global
nor persistent. This means that the memory "allocated" by the LMB
module might be relevant only for a given function. Hence one of the
requirements for making the memory usage visible across modules is to
make LMB allocations persistent and global, and then have means to
communicate the use of memory across modules.

The first set of patches in this series work on making the LMB memory
map persistent and global. This is being done keeping in mind the
usage of LMB memory by platforms where the same memory region can be
used to load multiple different images. What is not allowed is to
overwrite memory that has been allocated by the other module,
currently the EFI memory module. This is being achieved by introducing
a new flag, LMB_NOOVERWRITE, which represents memory which cannot be
re-requested once allocated.

A review comment on the earlier version was to do away with the static
arrays for the LMB lists of free and used memory. This version
uses the alloced list data structure for the LMB lists.

The second set of patches are making changes to the EFI memory module
to make use of the LMB functions to allocate and free memory. A
*_flags() version of LMB API's has been introduced for the same. The
earlier version was using notification mechanism from both LMB and EFI
modules to maintain memory coherence. This version makes use of the
LMB API functions for the memory allocations. This is based on review
comments of EFI maintainers.

Patches 1 - 4 are from Simon Glass and are adding support for the
alloced list data structure.

Patches 5 - 33 are for making the LMB memory map persistent and
global.

Patches 34 - 48 are for making EFI memory allocations work with LMB
API's.

Note: 

* Once the general direction of these patches has been agreed
  upon, I plan to split these patches into two series, with the above
  split.

* I am running the CI over a patch from Rasmus Villemoes -
  
RFC-test-cyclic-try-to-avoid-spurious-test-failures-due-to-cyclic-callbacks.patch
  I get spurious watchdog timeout errors without this patch.

* Because this is common code, and I was not able to disable LMB
  config(some code under boot/ fails to build), all of the patches
  need to be applied together when testing.

Todo's
--

There needs to be a test written for testing the various scenarios of
memory being allocated and freed by different modules, namely LMB and
EFI. I have written a couple of commands for testing the changes that
I have made. I will be working on this once there is agreement on the
patches.

Secondly, there were comments on the earlier series about things like
code size impact etc, but I have not looked at those right now. I will
look at these aspects in the following version.


Simon Glass (4):
  malloc: Support testing with realloc()
  lib: Handle a special case with str_to_list()
  alist: Add support for an allocated pointer list
  lib: Convert str_to_list() to use alist

Sughosh Ganu (44):
  alist: add a couple of helper functions
  alist: add a function declaration for alist_expand_by()
  lmb: remove the unused lmb_is_reserved() function
  lmb: staticize __lmb_alloc_base()
  lmb: remove call to lmb_init()
  lmb: remove local instances of the lmb structure variable
  lmb: pass a flag to image_setup_libfdt() for lmb reservations
  lmb: allow for resizing lmb regions
  lmb: make LMB memory map persistent and global
  lmb: remove config symbols used for lmb region count
  test: lmb: remove the test for max regions
  lmb: config: add lmb config symbols for SPL
  lmb: allow lmb module to be used in SPL
  lmb: introduce a function to add memory to the lmb memory map
  lmb: remove the lmb_init_and_reserve() function
  lmb: reserve common areas during board init
  lmb: remove lmb_init_and_reserve_range() function
  lmb: init: initialise the lmb data structures during board init
  lmb: use the BIT macro for lmb flags
  lmb: add a common implementation of arch_lmb_reserve()
  sandbox: spl: enable lmb in SPL
  sandbox: iommu: remove lmb allocation in the driver
  zynq: lmb: do not add to lmb map before relocation
  test: cedit: use allocated address for reading file
  test: lmb: tweak the tests for the persistent lmb memory map
  test: lmb: run lmb tests only manually
  test: lmb: add a separate class of unit tests for lmb
  test: lmb: invoke the LMB unit tests from a separate script
  test: bdinfo: dump the global LMB memory map
  lmb: add versions of the lmb API with flags
  lmb: add a flag to allow suppressing memory map change notification
  e

Re: [PATCH v3 07/18] binman: Keep the efi_capsule input file

2024-06-21 Thread Sughosh Ganu
On Fri, 21 Jun 2024 at 04:36, Simon Glass  wrote:
>
> There is no need to remove input files. It makes it harder to diagnose
> failures. Keep the payload file.
>
> There is no test for this condition, but one could be added.
>
> Signed-off-by: Simon Glass 
> Fixes: b617611b27a ("binman: capsule: Add support for generating...")
> ---

Acked-by: Sughosh Ganu 

Although I don't think this warrants a Fixes tag. It is not fixing any
issue as such.

-sughosh

>
> (no changes since v1)
>
>  tools/binman/etype/efi_capsule.py | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/tools/binman/etype/efi_capsule.py 
> b/tools/binman/etype/efi_capsule.py
> index 47da5da324b..03e55cbc4d9 100644
> --- a/tools/binman/etype/efi_capsule.py
> +++ b/tools/binman/etype/efi_capsule.py
> @@ -148,7 +148,6 @@ class Entry_efi_capsule(Entry_section):
>   self.fw_version,
>   self.oem_flags)
>  if ret is not None:
> -os.remove(payload)
>  return tools.read_file(capsule_fname)
>  else:
>  # Bintool is missing; just use the input data as the output
> --
> 2.34.1
>


Re: [RFC PATCH 04/31] lmb: remove local instances of the lmb structure variable

2024-06-13 Thread Sughosh Ganu
On Thu, 13 Jun 2024 at 22:57, Heinrich Schuchardt  wrote:
>
> On 13.06.24 18:59, Simon Glass wrote:
> > Hi Tom,
> >
> > On Thu, 13 Jun 2024 at 09:42, Tom Rini  wrote:
> >>
> >> On Thu, Jun 13, 2024 at 09:22:15AM -0600, Simon Glass wrote:
> >>> Hi Tom,
> >>>
> >>> On Wed, 12 Jun 2024 at 15:40, Tom Rini  wrote:
> 
>  On Wed, Jun 12, 2024 at 02:24:25PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Wed, 12 Jun 2024 at 11:22, Tom Rini  wrote:
> >>
> >> On Tue, Jun 11, 2024 at 08:41:39PM -0600, Simon Glass wrote:
> >>
> >> [snip]
> >>> Also IMO there is only really one LMB list today. We create it at the
> >>> start of bootm and then it is done when we boot. The file-loading
> >>> stuff is what makes all this confusing...and with bootstd that is
> >>> under control as well.
> >>>
> >>> At lot of this effort seems to be about dealing with random scripts
> >>> which load things. We want to make sure we complain if something
> >>> overlaps. But we should be making the bootstd case work nicely and
> >>> doing things within that framework. Also EFI sort-of has its own
> >>> thing, which it is very-much in control of.
> >>>
> >>> Overall I think this is a bit more subtle that just combining 
> >>> allocators.
> >>
> >> I think this gets to the main misunderstanding. The problem isn't
> >> handling bootstd, or EFI boot, or even assorted scripts. Those are all
> >> cases where things are otherwise (sufficiently) well-defined. The
> >> problem is "security" and that a "carefully crafted payload" could do
> >> something malicious. That's why we have to do all of this stuff sooner
> >> rather than later in our boot process.
> >
> > That's the first I have heard of this, actually, but a bit more detail
> > would help. How does the payload get loaded? I'm just not sure about
> > the overall goals. It seems that everyone else is already familiar -
> > can someone please take the time to point me to the details?
> 
>  Well, the short version I believe of the first CVE we got (and so
>  started abusing LMB) was along the lines of "load an image near where
>  the U-Boot stack is, smash things for fun and exploits".
> >>>
> >>> OK. I am surprised that LMB does not catch that. It is supposed to add
> >>> the stack and various other things right at the start before loading
> >>> any file. So even if it clears the LMB each time, it should not be
> >>> able to do that. Having said this, the code may be buggy as I don't
> >>> think we have tests for U-Boot's overall functional behaviour in these
> >>> situations.
> >>
> >> Right, LMB does catch the example I gave (because we made all of the
> >> load from storage/network functions init an lmb and we always make sure
> >> a new lmb gets U-Boot stack/etc). The next thing we didn't catch was
> >> "what if EFI does the loading?" and we've kludged around that, and in
> >> turn had some of the thorny questions. Some of that is what I think
> >> you're asking about in this part of the thread, to which the answer is
> >> "EFI spec says you need to place X in memory", so we just need to
> >> reserve it when it's asked for, so that something else can't come along
> >> and smash it maliciously.
> >
> > OK I see. Of course it isn't just EFI that has this issue. I believe
> > the answer (for small blocks) is to use malloc(), which I think we do
> > with a few exceptions which Ilias pointed out. For things like the TPM
> > log and ACPI tables we should probably use a bloblist, as we do on
> > x86. For large things (like loading a kernel) we should use LMB. I've
> > been thinking about how best to tie this to boot, as opposed to random
> > allocations in U-Boot itself, which would lead to fragmentation and
> > strange behaviour. I think bootstd is a great place to have a
> > persistent LMB. It can be attached to bootstd_priv.
> >
> > My hope is that EFI is just another boot method, where
> > already-allocating things are presented to the OS. Apart from the
> > Ilias exceptions, I believe this is how it works today.
> >
> > Where I think this heads in the wrong direction is using
> > EFI-allocation functions before we are booting an EFI image. EFI has
> > no concept of what is 'in empty space' so it leads to the lmb
> > conflict, the subject of this discussion.
>
> EFI binaries can return to the command line interface.
> EFI binaries may be drivers that stay resident and run in the background
> after returning to the command line interface. They might for instance
> provide block devices.
>
> Device-paths must be created from EFI pool memory as they may be freed
> via FreePool() according to the EFI specification. And these we create
> whenever a block-device is probed.
>
> We should not make any assumptions that conflict with the UEFI
> specification.
>
> In our initial discussion with Ilias one idea was to merge LMB and EFI
> memory management. 

Re: [RFC PATCH 15/31] efi_memory: add an event handler to update memory map

2024-06-12 Thread Sughosh Ganu
On Wed, 12 Jun 2024 at 12:16, Ilias Apalodimas
 wrote:
>
> On Mon, 10 Jun 2024 at 18:54, Simon Glass  wrote:
> >
> > Hi,
> >
> > On Mon, 10 Jun 2024 at 09:42, Sughosh Ganu  wrote:
> > >
> > > On Mon, 10 Jun 2024 at 20:47, Heinrich Schuchardt  
> > > wrote:
> > > >
> > > > On 07.06.24 20:52, Sughosh Ganu wrote:
> > > > > There are events that would be used to notify other interested modules
> > > > > of any changes in available and occupied memory. This would happen
> > > > > when a module allocates or reserves memory, or frees up memory. These
> > > >
> > > > I am worried about the "frees up memory" case.
> > > >
> > > > When LMB frees memory we cannot add it back to EFI conventional memory
> > > > as there might still be a file image lingering around that EFI should
> > > > not overwrite. It has to stay marked as EfiLoaderCode or EfiLoaderData.
> > >
> > > So here is my basic doubt. Why would LMB free up memory if it still
> > > has a valid image. If that is the case, the lmb_free API should not be
> > > called?
> > >
> > > -sughosh
> > >
> > >
> > > >
> > > > How do you ensure that if a region reserved by LMB notification as
> > > > EfiLoaderData is coalesced with some other allocation LMB is not
> > > > requested to mark the coalesced region as reserved?
> > > >
> > > > @Tom
> > > >
> > > > Clinging to the existing logic that you can do anything when loading
> > > > files is obviously leading us into coding hell.
> > > >
> > > > If somebody wants to load two images into the same location, he should
> > > > be forced to unload the first image. This will allow us to have a single
> > > > memory management system.
> >
> > It seems we really shouldn't use the words 'allocate' and 'free' when
> > talking about LMB. They are simply reservations.
>
> Correct and while at it can we please make the code less confusing to
> read. What we today mark as reserved isnt even trully reserved as it
> can be overwritten.
> struct lmb_region memory -> available memory we added on LMB. That's fine
> struct lmb_region reserved -> can we rename this to 'used' and rename
> LMB_NOOVERWRITE to LMB_RESERVED?

Okay. Will incorporate this change in the next version. Thanks.

-sughosh

>
> Thanks
> /Ilias
>
> > I believe we have got
> > into this situation due to an assumption that these two things are the
> > same, but in U-Boot they certainly are not. LMB is a very lighweight
> > and temporary reservation system to be used for a single boot process.
> >
> > Regards,
> > Simon
> >
> >
> > > >
> > > > Best regards
> > > >
> > > > Heinrich
> > > >
> > > > > changes in memory map should be notified to other interested modules
> > > > > so that the allocated memory does not get overwritten. Add an event
> > > > > handler in the EFI memory module to update the EFI memory map
> > > > > accordingly when such changes happen. As a consequence, any subsequent
> > > > > memory request would honour the updated memory map and only available
> > > > > memory would be allocated from.
> > > > >
> > > > > Signed-off-by: Sughosh Ganu 
> > > > > ---
> > > > >   lib/efi_loader/efi_memory.c | 70 
> > > > > ++---
> > > > >   1 file changed, 58 insertions(+), 12 deletions(-)
> > > > >
> > > > > diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> > > > > index 435e580fb3..93244161b0 100644
> > > > > --- a/lib/efi_loader/efi_memory.c
> > > > > +++ b/lib/efi_loader/efi_memory.c
> > > > > @@ -73,6 +73,10 @@ struct efi_pool_allocation {
> > > > >   #if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
> > > > >   extern bool is_addr_in_ram(uintptr_t addr);
> > > > >
> > > > > +static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
> > > > > + int memory_type,
> > > > > + bool overlap_only_ram);
> > > > > +
> > > > >   static void efi_map_update_notify(u64 addr, u64 size, u8 op)
> > > > >   {
> > > > >   stru

Re: [RFC PATCH 15/31] efi_memory: add an event handler to update memory map

2024-06-12 Thread Sughosh Ganu
hi Ilias,

On Wed, 12 Jun 2024 at 11:19, Ilias Apalodimas
 wrote:
>
> [...]
>
> > > > > > > > > +   struct event_lmb_map_update *lmb_map = 
> > > > > > > > > >data.lmb_map;
> > > > > > > > > +
> > > > > > > > > +   addr = (uintptr_t)map_sysmem(lmb_map->base, 0);
> > > > > > > > > +   pages = efi_size_in_pages(lmb_map->size + (addr & 
> > > > > > > > > EFI_PAGE_MASK));
> > > > > > > > > +   op = lmb_map->op;
> > > > > > > > > +   addr &= ~EFI_PAGE_MASK;
> > > > > > > > > +
> > > > > > > > > +   if (op != MAP_OP_RESERVE && op != MAP_OP_FREE) {
> > > > > > > > > +   log_debug("Invalid map update op received 
> > > > > > > > > (%d)\n", op);
> > > > > > > > > +   return -1;
> > > > > > > > > +   }
> > > > > > > > > +
> > > > > > > > > +   status = __efi_add_memory_map_pg(addr, pages,
> > > > > > > > > +op == MAP_OP_FREE ?
> > > > > > > > > +EFI_CONVENTIONAL_MEMORY :
> > > > > > > >
> > > > > > > > This is dangerous. LMB might turn memory that is marked as
> > > > > > > > EfiReservedMemory which the OS must respect into 
> > > > > > > > EfiBootServicesData
> > > > > > > > which the OS may discard.
> > > > > > > >
> > > > > > > > E.g. initr_lmb() is being called after efi_memory_init().
> > > > > > > >
> > > > > > > > Getting all cases of synchronization properly tested seems very 
> > > > > > > > hard to
> > > > > > > > me. Everything would be much easier if we had only a single 
> > > > > > > > memory
> > > > > > > > management system.
> > > > > > >
> > > > > > > Yes, Sughosh is working on the single memory reservation system 
> > > > > > > for
> > > > > > > everyone to use. This pairs with the single memory allocation 
> > > > > > > system
> > > > > > > (malloc) that we have. Parts of the code base that aren't keeping 
> > > > > > > these
> > > > > > > systems up to date / obeying their results need to be corrected.
> > > > > >
> > > > > > The EFI allocations don't happen until boot time...so why do we need
> > > > > > to do this now? We can instead have an EFI function to scan LMB and
> > > > > > add to its memory map.
> > > > >
> > > > > We're talking about reservations, not allocations. So yes, when 
> > > > > someone
> > > > > is making their reservation, they need to make it. I don't understand
> > > > > your question.
> > > >
> > > > As I understand it, this is used to tell EFI about a memory reservation.
> > >
> > > This patch, or this series? This series isn't about EFI. This patch is,
> > > yes.
> > >
> > > > But the EFI code can scan the LMB reservations just before booting and
> > > > update its tables. I don't see a need to keep them in sync before the
> > > > boot actually happens.
> > >
> > > But that wouldn't work. If something needs to reserve a region it needs
> > > to do it when it starts using it. It's not about the EFI map for the OS,
> > > it's about making sure that U-Boot doesn't scribble over a now-reserved
> > > area.
> >
> > I'm not convinced of that yet. EFI does not do allocations until it
> > starts loading images,
>
> It does in some cases. E.g The efi variables allocate some pages when
> the subsystem starts, the TCG protocol allocates the EventLog once
> it's installed and I am pretty sure we have more.
>
> > and it uses LMB for those (or at least it does
> > with bootstd). I'm just trying to keep this all as simple as possible.
>
> Heinrich already pointed out a potential danger in the current design.
> If an EFI allocation happens *before* LMB comes up, we might end up
> updating the efi memory map with the wrong attributes. That would lead
> to the OS discarding memory areas that should be preserved and we
> won't figure that out until the OS boots and blows up.

Like I mentioned in one of the earlier replies [1], this is actually
not an issue, as long as modules are freeing memory that was actually
allocated/reserved by them. In case of the EFI subsystem marking some
memory region as EfiReservedMemory, this will send a notification to
the LMB module, and the LMB module will mark this region as reserved.
So unless some LMB user decides on freeing up memory that was not
reserved by it, this should be just fine.

Making use of the LMB API's as the common backend for allocating
memory is a separate thing, and I will look into that. But the above
highlighted issue is not one, with correctly working code.

-sughosh

[1] - https://lists.denx.de/pipermail/u-boot/2024-June/555883.html


Re: [RFC PATCH 15/31] efi_memory: add an event handler to update memory map

2024-06-11 Thread Sughosh Ganu
On Tue, 11 Jun 2024 at 15:47, Heinrich Schuchardt  wrote:
>
> On 07.06.24 20:52, Sughosh Ganu wrote:
> > There are events that would be used to notify other interested modules
> > of any changes in available and occupied memory. This would happen
> > when a module allocates or reserves memory, or frees up memory. These
> > changes in memory map should be notified to other interested modules
> > so that the allocated memory does not get overwritten. Add an event
> > handler in the EFI memory module to update the EFI memory map
> > accordingly when such changes happen. As a consequence, any subsequent
> > memory request would honour the updated memory map and only available
> > memory would be allocated from.
> >
> > Signed-off-by: Sughosh Ganu 
> > ---
> >   lib/efi_loader/efi_memory.c | 70 ++---
> >   1 file changed, 58 insertions(+), 12 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> > index 435e580fb3..93244161b0 100644
> > --- a/lib/efi_loader/efi_memory.c
> > +++ b/lib/efi_loader/efi_memory.c
> > @@ -73,6 +73,10 @@ struct efi_pool_allocation {
> >   #if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
> >   extern bool is_addr_in_ram(uintptr_t addr);
> >
> > +static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
> > + int memory_type,
> > + bool overlap_only_ram);
> > +
> >   static void efi_map_update_notify(u64 addr, u64 size, u8 op)
> >   {
> >   struct event_efi_mem_map_update efi_map = {0};
> > @@ -84,6 +88,34 @@ static void efi_map_update_notify(u64 addr, u64 size, u8 
> > op)
> >   if (is_addr_in_ram((uintptr_t)addr))
> >   event_notify(EVT_EFI_MEM_MAP_UPDATE, _map, 
> > sizeof(efi_map));
> >   }
> > +
> > +static int lmb_mem_map_update_sync(void *ctx, struct event *event)
> > +{
> > + u8 op;
> > + u64 addr;
> > + u64 pages;
> > + efi_status_t status;
> > + struct event_lmb_map_update *lmb_map = >data.lmb_map;
> > +
> > + addr = (uintptr_t)map_sysmem(lmb_map->base, 0);
> > + pages = efi_size_in_pages(lmb_map->size + (addr & EFI_PAGE_MASK));
> > + op = lmb_map->op;
> > + addr &= ~EFI_PAGE_MASK;
> > +
> > + if (op != MAP_OP_RESERVE && op != MAP_OP_FREE) {
> > + log_debug("Invalid map update op received (%d)\n", op);
> > + return -1;
> > + }
> > +
> > + status = __efi_add_memory_map_pg(addr, pages,
> > +  op == MAP_OP_FREE ?
> > +  EFI_CONVENTIONAL_MEMORY :
>
> This is dangerous. LMB might turn memory that is marked as
> EfiReservedMemory which the OS must respect into EfiBootServicesData
> which the OS may discard.

If memory is being marked as EfiReservedMemory, that will also update
the LMB memory map to have it marked as reserved. So a correct
implementation should then not be freeing memory that is not allocated
by that module.

-sughosh

>
> E.g. initr_lmb() is being called after efi_memory_init().
>
> Getting all cases of synchronization properly tested seems very hard to
> me. Everything would be much easier if we had only a single memory
> management system.
>
> Best regards
>
> Heinrich
>
> > +  EFI_BOOT_SERVICES_DATA,
> > +  true);
> > +
> > + return status == EFI_SUCCESS ? 0 : -1;
> > +}
> > +EVENT_SPY_FULL(EVT_LMB_MAP_UPDATE, lmb_mem_map_update_sync);
> >   #endif /* MEM_MAP_UPDATE_NOTIFY */
> >
> >   /**
> > @@ -275,18 +307,9 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map,
> >   return EFI_CARVE_LOOP_AGAIN;
> >   }
> >
> > -/**
> > - * efi_add_memory_map_pg() - add pages to the memory map
> > - *
> > - * @start:   start address, must be a multiple of EFI_PAGE_SIZE
> > - * @pages:   number of pages to add
> > - * @memory_type: type of memory added
> > - * @overlap_only_ram:region may only overlap RAM
> > - * Return:   status code
> > - */
> > -static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
> > -   int memory_type,
> > -   bool overlap_only_ram)
> > +static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
> > + 

Re: [RFC PATCH 22/31] test: lmb: run the LMB tests only on sandbox

2024-06-11 Thread Sughosh Ganu
On Tue, 11 Jun 2024 at 15:31, Heinrich Schuchardt  wrote:
>
> On 11.06.24 10:55, Sughosh Ganu wrote:
> > On Mon, 10 Jun 2024 at 23:14, Tom Rini  wrote:
> >>
> >> On Sat, Jun 08, 2024 at 12:22:31AM +0530, Sughosh Ganu wrote:
> >>
> >>> The LMB memory map is now persistent and global. Running the tests for
> >>> the LMB module will result in the memory map getting reset, and this
> >>> will have side-effects on the rest of the working of the platform. Run
> >>> the LMB tests only on the sandbox platform, which is meant for running
> >>> such kinds of tests.
> >>>
> >>> Signed-off-by: Sughosh Ganu 
> >>
> >> I'm not sure about this. We can reset real hardware as often as we need,
> >> too. Did you run in to problems with this test on non-sandbox?
> >
> > But do we want to reset the state of the LMB memory map on real
> > hardware? This was working up until now because of the local nature of
> > the LMB variables. But if the LMB memory map is to be persistent,
> > should we allow it to be changed for running some test? That would
> > have side effects? I think running these tests on sandbox should
> > suffice. I mean there isn't any aspect of the LMB module that is not
> > getting tested on sandbox, right?
> >
> > -sughosh
>
> We should run tests on systems with different bitness and endianness.
>

I would think there are platforms in the CI suite that are big-endian,
because if there are, they are surely exercising the LMB memory
reservation functions multiple times. I am only talking about running
the unit tests on sandbox.

> As the LMB test does not rely on any sandbox driver we should be able to
> run it on any system.
>
> If the memory map is not usable anymore after the test, the system
> should be rebooted.

Yes, that will happen when the test is run in CI -- I am working on
changes to have the LMB tests run separately and then reboot the
system. But if the tests are run by a user manually, that might have
side-effects. Btw, even today, the LMB tests only get run on sandbox
as part of the CI run. What happens is that the tests are enabled to
be run on other platforms as well(snow as of now).

But OTOH, an explicit reboot can be called after having run the tests.
This would handle the scenario of a user running these manually from
command-line.

-sughosh

>
> Best regards
>
> Heinrich


Re: [RFC PATCH 09/31] lmb: allow for resizing lmb regions

2024-06-11 Thread Sughosh Ganu
On Tue, 11 Jun 2024 at 14:47, Heinrich Schuchardt  wrote:
>
> On 07.06.24 20:52, Sughosh Ganu wrote:
> > Allow for resizing of LMB regions if the region attributes match. The
> > current code returns a failure status on detecting an overlapping
> > address. This worked up until now since the LMB calls were not
> > persistent and global -- the LMB memory map was specific and private
> > to a given caller of the LMB API's.
> >
> > With the change in the LMB code to make the LMB reservations
> > persistent, there needs to be a check on whether the memory region can
> > be resized, and then do it if so. To distinguish between memory that
> > cannot be resized, add a new flag, LMB_NOOVERWRITE. Reserving a region
> > of memory with this attribute would indicate that the region cannot be
> > resized.
> >
> > Signed-off-by: Sughosh Ganu 
> > ---
> >   include/lmb.h |   1 +
> >   lib/lmb.c | 120 --
> >   2 files changed, 107 insertions(+), 14 deletions(-)
> >
> > diff --git a/include/lmb.h b/include/lmb.h
> > index 03bce2a50c..1d4cd255d2 100644
> > --- a/include/lmb.h
> > +++ b/include/lmb.h
> > @@ -20,6 +20,7 @@
> >   enum lmb_flags {
> >   LMB_NONE= 0x0,
> >   LMB_NOMAP   = 0x4,
> > + LMB_NOOVERWRITE = 0x8,
>
> Please, add the missing description for the new value. Using the first
> available bit (0x01) would be expected.
>
> Using the BIT macro would make it clearer that these are bits of a bitmap:
>
> enum lmb_flags {
> LMB_NONE= BIT(0),
> LMB_NOOVERWRITE = BIT(1),
> };

Noted. Will change.

-sughosh

>
> Best regards
>
> Heinrich
>
>
> >   };
> >
> >   /**
> > diff --git a/lib/lmb.c b/lib/lmb.c
> > index de5a2cf23b..0a4f3d5bcd 100644
> > --- a/lib/lmb.c
> > +++ b/lib/lmb.c
> > @@ -260,12 +260,88 @@ void lmb_add_memory(struct bd_info *bd)
> >   }
> >   }
> >
> > +static bool lmb_region_flags_match(struct lmb_region *rgn, unsigned long 
> > r1,
> > +enum lmb_flags flags)
> > +{
> > + return rgn->region[r1].flags == flags;
> > +}
> > +
> > +static long lmb_merge_overlap_regions(struct lmb_region *rgn, unsigned 
> > long i,
> > +   phys_addr_t base, phys_size_t size,
> > +   enum lmb_flags flags)
> > +{
> > + phys_size_t rgnsize;
> > + unsigned long rgn_cnt, idx;
> > + phys_addr_t rgnbase, rgnend;
> > + phys_addr_t mergebase, mergeend;
> > +
> > + rgn_cnt = 0;
> > + idx = i;
> > + /*
> > +  * First thing to do is to identify how many regions does
> > +  * the requested region overlap.
> > +  * If the flags match, combine all these overlapping
> > +  * regions into a single region, and remove the merged
> > +  * regions.
> > +  */
> > + while (idx < rgn->cnt - 1) {
> > + rgnbase = rgn->region[idx].base;
> > + rgnsize = rgn->region[idx].size;
> > +
> > + if (lmb_addrs_overlap(base, size, rgnbase,
> > +   rgnsize)) {
> > + if (!lmb_region_flags_match(rgn, idx, flags))
> > + return -1;
> > + rgn_cnt++;
> > + idx++;
> > + }
> > + }
> > +
> > + /* The merged region's base and size */
> > + rgnbase = rgn->region[i].base;
> > + mergebase = min(base, rgnbase);
> > + rgnend = rgn->region[idx].base + rgn->region[idx].size;
> > + mergeend = max(rgnend, (base + size));
> > +
> > + rgn->region[i].base = mergebase;
> > + rgn->region[i].size = mergeend - mergebase;
> > +
> > + /* Now remove the merged regions */
> > + while (--rgn_cnt)
> > + lmb_remove_region(rgn, i + 1);
> > +
> > + return 0;
> > +}
> > +
> > +static long lmb_resize_regions(struct lmb_region *rgn, unsigned long i,
> > +phys_addr_t base, phys_size_t size,
> > +enum lmb_flags flags)
> > +{
> > + long ret = 0;
> > + phys_addr_t rgnend;
> > +
> > + if (i == rgn->cnt - 1 ||
> > + base + size < rgn->region[i + 1].base) {
> > + if (!lmb_region_flags_match(rg

Re: [RFC PATCH 17/31] lmb: remove call to efi_lmb_reserve()

2024-06-11 Thread Sughosh Ganu
On Tue, 11 Jun 2024 at 14:42, Heinrich Schuchardt  wrote:
>
> On 07.06.24 20:52, Sughosh Ganu wrote:
> > The changes in the EFI memory map are now notified to the LMB
> > module. There is therefore no need to explicitly get the efi memory
> > map and set aside the EFI allocated memory.
> >
> > Signed-off-by: Sughosh Ganu 
> > ---
> >   lib/lmb.c | 35 ---
> >   1 file changed, 35 deletions(-)
> >
> > diff --git a/lib/lmb.c b/lib/lmb.c
> > index 3059609aea..c9f6ca692e 100644
> > --- a/lib/lmb.c
> > +++ b/lib/lmb.c
> > @@ -204,38 +204,6 @@ void arch_lmb_reserve_generic(ulong sp, ulong end, 
> > ulong align)
> >   }
> >   }
> >
> > -/**
> > - * efi_lmb_reserve() - add reservations for EFI memory
> > - *
> > - * Add reservations for all EFI memory areas that are not
> > - * EFI_CONVENTIONAL_MEMORY.
> > - *
> > - * Return:   0 on success, 1 on failure
> > - */
> > -static __maybe_unused int efi_lmb_reserve(void)
> > -{
> > - struct efi_mem_desc *memmap = NULL, *map;
> > - efi_uintn_t i, map_size = 0;
> > - efi_status_t ret;
> > -
> > - ret = efi_get_memory_map_alloc(_size, );
> > - if (ret != EFI_SUCCESS)
> > - return 1;
> > -
> > - for (i = 0, map = memmap; i < map_size / sizeof(*map); ++map, ++i) {
> > - if (map->type != EFI_CONVENTIONAL_MEMORY) {
> > - lmb_reserve_flags(map_to_sysmem((void *)(uintptr_t)
> > - map->physical_start),
> > -   map->num_pages * EFI_PAGE_SIZE,
> > -   map->type == 
> > EFI_RESERVED_MEMORY_TYPE
> > -   ? LMB_NOMAP : LMB_NONE);
>
>
> Now that you have removed the last usage of LMB_NOMAP, please, remove it
> from enum lmb_flags.

Not all instances are removed. This flag gets used for reserving FDT
memory areas as well. Used in
boot/image-fdt.c:boot_fdt_add_mem_rsv_regions().

-sughosh

> > - }
> > - efi_free_pool(memmap);
> > -
> > - return 0;
> > -}
> > -
> >   /**
> >* lmb_reserve_common() - Reserve memory region occupied by U-Boot image
> >* @fdt_blob: pointer to the FDT blob
> > @@ -255,9 +223,6 @@ void lmb_reserve_common(void *fdt_blob)
> >
> >   if (CONFIG_IS_ENABLED(OF_LIBFDT) && fdt_blob)
> >   boot_fdt_add_mem_rsv_regions(fdt_blob);
> > -
> > - if (CONFIG_IS_ENABLED(EFI_LOADER))
> > - efi_lmb_reserve();
> >   }
> >
> >   /**
>


Re: [RFC PATCH 00/31] Make U-Boot memory reservations coherent

2024-06-11 Thread Sughosh Ganu
On Tue, 11 Jun 2024 at 02:35, Tom Rini  wrote:
>
> On Sat, Jun 08, 2024 at 12:22:09AM +0530, Sughosh Ganu wrote:
>
> > The aim of this patch series is to fix the current state of
> > incoherence between modules when it comes to memory usage. The primary
> > issue that this series is trying to fix is that the EFI memory module
> > which is responsible for allocating and freeing memory, does not have
> > any visibility of the memory that is being used by the LMB
> > module. This is further complicated by the fact that the LMB
> > allocations are caller specific -- the LMB memory map is not global
> > nor persistent. This means that the memory "allocated" by the LMB
> > module might be relevant only for a given function. Hence one of the
> > requirements for making the memory usage visible across modules is to
> > make LMB allocations persistent and global, and then have means to
> > communicate the use of memory across modules.
> >
> > The first set of patches in this series work on making the LMB memory
> > map persistent and global. This is being done keeping in mind the
> > usage of LMB memory by platforms where the same memory region can be
> > used to load multiple different images. What is not allowed is to
> > overwrite memory that has been allocated by the other module,
> > currently the EFI memory module. This is being achieved by introducing
> > a new flag, LMB_NOOVERWRITE, which represents memory which cannot be
> > re-requested once allocated.
> >
> > The second set of patches are then introducing a notification
> > mechanism to indicate any changes to a respective module's memory
> > map. This way, any memory allocation/reservation by a module gets
> > notified to any interested listners, who then update their memory map
> > accordingly, thus keeping memory usage coherent.
> >
> > Todo's
> > --
> > I have run these patches through CI, but the LMB unit tests need an
> > overhaul. I have currently marked these tests for manual run, as
> > running these would obviously tamper the LMB memory map, thus
> > affecting subsequent tests. The current set of LMB tests are written
> > with the assumption of local LMB memory maps. This needs to be
> > reworked.
> >
> > Secondly, there needs to be a test written for testing the various
> > scenarios of memory being allocated and freed by different modules,
> > namely LMB and EFI. I have written a couple of commands for testing
> > the changes that I have made -- I have also included these temporary
> > commands to assist anyone who might want to test these changes. But I
> > will be working on adding a more comprehensive test.
> >
> > Lastly, as the series touches common code, there is obviously an
> > increase in the size of the image, moreover since the LMB memory is
> > now persistent, and the variables do not reside on the stack. I want
> > to check if there can be ways of decreasing the size impact of the
> > changes.
>
> So, I think you made some changes between your last CI run and posting?
> A ton of platforms (basically anything with EFI_LOADER disabled) fail to
> build now because the two "temp" commits at the end of the series are
> always enabled. I took those commits out and ran my world build size
> check tests and the results are at:
> https://gist.github.com/trini/d42bd392463c39766a5f872c190ccf27
>
> And 64bit ARM looks very reasonable, but I wonder if we can improve the
> 32bit ARM results?
>
> I also did an every commit run for a 32bit ARM board without EFI_LOADER
> (which is going to be the case for size constrained systems) and see
> that the series isn't bisect'able to start with, so please fix that for
> the next go-round. That said:

Yes, I should have mentioned it in the cover letter about issues with
bisectability, primarily because some code under boot/ uses the lmb
API's unconditionally, without having a check for LMB being enabled or
not.

> Summary of 30 commits for 1 boards (1 thread, 12 jobs per thread)
> 01: Added arm64 assembly for examples/api crt0
> 02: lmb: remove the unused lmb_is_reserved() function
> 03: lmb: staticize __lmb_alloc_base()
>arm: (for 1/1 boards) all -16.0 text -16.0
> omapl138_lcdk  : all -16 text -16
>u-boot: add: 0/-1, grow: 1/0 bytes: 172/-186 (-14)
>  function   old new   
> delta
>  lmb_alloc_base  40 212
> +172
>  __lmb_alloc_base   186   -
> -186
> 04: lmb: make the lmb reservations persistent
> 

Re: [RFC PATCH 22/31] test: lmb: run the LMB tests only on sandbox

2024-06-11 Thread Sughosh Ganu
On Mon, 10 Jun 2024 at 23:14, Tom Rini  wrote:
>
> On Sat, Jun 08, 2024 at 12:22:31AM +0530, Sughosh Ganu wrote:
>
> > The LMB memory map is now persistent and global. Running the tests for
> > the LMB module will result in the memory map getting reset, and this
> > will have side-effects on the rest of the working of the platform. Run
> > the LMB tests only on the sandbox platform, which is meant for running
> > such kinds of tests.
> >
> > Signed-off-by: Sughosh Ganu 
>
> I'm not sure about this. We can reset real hardware as often as we need,
> too. Did you run in to problems with this test on non-sandbox?

But do we want to reset the state of the LMB memory map on real
hardware? This was working up until now because of the local nature of
the LMB variables. But if the LMB memory map is to be persistent,
should we allow it to be changed for running some test? That would
have side effects? I think running these tests on sandbox should
suffice. I mean there isn't any aspect of the LMB module that is not
getting tested on sandbox, right?

-sughosh


Re: [RFC PATCH 08/31] lmb: replcace the lmb_init_and_reserve() function

2024-06-11 Thread Sughosh Ganu
On Mon, 10 Jun 2024 at 23:01, Tom Rini  wrote:
>
> On Sat, Jun 08, 2024 at 12:22:17AM +0530, Sughosh Ganu wrote:
> > With the changes to make the Logical Memory Block(LMB) allocations
> > persistent and with the common memory regions being reserved during
> > board init, the lmb_init_and_reserve() API can be removed and replaced
> > with a lmb_add_memory() API, which adds all the available memory to
> > the LMB pool.
> >
> > Signed-off-by: Sughosh Ganu 
> > ---
> >  arch/arm/mach-apple/board.c  |  2 +-
> >  arch/arm/mach-snapdragon/board.c |  2 +-
> >  arch/arm/mach-stm32mp/stm32mp1/cpu.c |  2 +-
> >  cmd/bdinfo.c |  2 +-
> >  cmd/load.c   |  2 +-
> >  fs/fs.c  |  2 +-
> >  include/lmb.h| 12 +++-
> >  lib/lmb.c| 15 +++
> >  net/tftp.c   |  2 +-
> >  net/wget.c   |  2 +-
> >  test/cmd/bdinfo.c| 10 +-
> >  11 files changed, 31 insertions(+), 22 deletions(-)
> >
> > diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c
> > index c877c7b94c..2e72d03edd 100644
> > --- a/arch/arm/mach-apple/board.c
> > +++ b/arch/arm/mach-apple/board.c
> > @@ -776,7 +776,7 @@ int board_late_init(void)
> >  {
> >   u32 status = 0;
> >
> > - lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
> > + lmb_add_memory(gd->bd);
> >
> >   /* somewhat based on the Linux Kernel boot requirements:
> >* align by 2M and maximal FDT size 2M
>
> We already reserved gd->bd as part of the initr_lmb call. So I think
> this commit needs rethinking, or am I missing something?

I believe the LMB memory API's also get called from SPL(not sure about
TPL/VPL though). The memory that gets added in the other commit is for
U-Boot main, post relocation. These calls will then be needed for
prior stages of U-Boot that want to use LMB memory.

-sughosh


Re: [RFC PATCH 15/31] efi_memory: add an event handler to update memory map

2024-06-10 Thread Sughosh Ganu
On Mon, 10 Jun 2024 at 20:47, Heinrich Schuchardt  wrote:
>
> On 07.06.24 20:52, Sughosh Ganu wrote:
> > There are events that would be used to notify other interested modules
> > of any changes in available and occupied memory. This would happen
> > when a module allocates or reserves memory, or frees up memory. These
>
> I am worried about the "frees up memory" case.
>
> When LMB frees memory we cannot add it back to EFI conventional memory
> as there might still be a file image lingering around that EFI should
> not overwrite. It has to stay marked as EfiLoaderCode or EfiLoaderData.

So here is my basic doubt. Why would LMB free up memory if it still
has a valid image. If that is the case, the lmb_free API should not be
called?

-sughosh


>
> How do you ensure that if a region reserved by LMB notification as
> EfiLoaderData is coalesced with some other allocation LMB is not
> requested to mark the coalesced region as reserved?
>
> @Tom
>
> Clinging to the existing logic that you can do anything when loading
> files is obviously leading us into coding hell.
>
> If somebody wants to load two images into the same location, he should
> be forced to unload the first image. This will allow us to have a single
> memory management system.
>
> Best regards
>
> Heinrich
>
> > changes in memory map should be notified to other interested modules
> > so that the allocated memory does not get overwritten. Add an event
> > handler in the EFI memory module to update the EFI memory map
> > accordingly when such changes happen. As a consequence, any subsequent
> > memory request would honour the updated memory map and only available
> > memory would be allocated from.
> >
> > Signed-off-by: Sughosh Ganu 
> > ---
> >   lib/efi_loader/efi_memory.c | 70 ++---
> >   1 file changed, 58 insertions(+), 12 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> > index 435e580fb3..93244161b0 100644
> > --- a/lib/efi_loader/efi_memory.c
> > +++ b/lib/efi_loader/efi_memory.c
> > @@ -73,6 +73,10 @@ struct efi_pool_allocation {
> >   #if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
> >   extern bool is_addr_in_ram(uintptr_t addr);
> >
> > +static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
> > + int memory_type,
> > + bool overlap_only_ram);
> > +
> >   static void efi_map_update_notify(u64 addr, u64 size, u8 op)
> >   {
> >   struct event_efi_mem_map_update efi_map = {0};
> > @@ -84,6 +88,34 @@ static void efi_map_update_notify(u64 addr, u64 size, u8 
> > op)
> >   if (is_addr_in_ram((uintptr_t)addr))
> >   event_notify(EVT_EFI_MEM_MAP_UPDATE, _map, 
> > sizeof(efi_map));
> >   }
> > +
> > +static int lmb_mem_map_update_sync(void *ctx, struct event *event)
> > +{
> > + u8 op;
> > + u64 addr;
> > + u64 pages;
> > + efi_status_t status;
> > + struct event_lmb_map_update *lmb_map = >data.lmb_map;
> > +
> > + addr = (uintptr_t)map_sysmem(lmb_map->base, 0);
> > + pages = efi_size_in_pages(lmb_map->size + (addr & EFI_PAGE_MASK));
> > + op = lmb_map->op;
> > + addr &= ~EFI_PAGE_MASK;
> > +
> > + if (op != MAP_OP_RESERVE && op != MAP_OP_FREE) {
> > + log_debug("Invalid map update op received (%d)\n", op);
> > + return -1;
> > + }
> > +
> > + status = __efi_add_memory_map_pg(addr, pages,
> > +  op == MAP_OP_FREE ?
> > +  EFI_CONVENTIONAL_MEMORY :
> > +  EFI_BOOT_SERVICES_DATA,
> > +  true);
> > +
> > + return status == EFI_SUCCESS ? 0 : -1;
> > +}
> > +EVENT_SPY_FULL(EVT_LMB_MAP_UPDATE, lmb_mem_map_update_sync);
> >   #endif /* MEM_MAP_UPDATE_NOTIFY */
> >
> >   /**
> > @@ -275,18 +307,9 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map,
> >   return EFI_CARVE_LOOP_AGAIN;
> >   }
> >
> > -/**
> > - * efi_add_memory_map_pg() - add pages to the memory map
> > - *
> > - * @start:   start address, must be a multiple of EFI_PAGE_SIZE
> > - * @pages:   number of pages to add
> > - * @memory_type: type of memory added
> > - * @overlap_only_ram:region may only overlap RAM
> > - * Return: 

Re: Proposal: U-Boot memory management

2024-06-10 Thread Sughosh Ganu
hi Simon,

On Mon, 10 Jun 2024 at 20:33, Simon Glass  wrote:
>
> Hi Sughosh,
>
> On Mon, 10 Jun 2024 at 08:40, Sughosh Ganu  wrote:
> >
> > hi Simon,
> >
> > On Mon, 10 Jun 2024 at 19:25, Simon Glass  wrote:
> > >
> > > Hi Sughosh,
> > >
> > > On Thu, 6 Jun 2024 at 13:18, Sughosh Ganu  wrote:
> > > >
> > > > hi Simon,
> > > >
> > > > On Wed, 29 May 2024 at 22:00, Simon Glass  wrote:
> > > > >
> > > > > +Sughosh Ganu for reference
> > > > >
> > > > >
> > > > > On Sun, 31 Dec 2023 at 09:16, Tom Rini  wrote:
> > > > > >
> > > > > > On Sun, Dec 31, 2023 at 04:40:06PM +0100, Heinrich Schuchardt wrote:
> > > > > > >
> > > > > > >
> > > > > > > Am 31. Dezember 2023 16:11:44 MEZ schrieb Tom Rini 
> > > > > > > :
> > > > > > > >On Sun, Dec 31, 2023 at 07:22:10AM -0700, Simon Glass wrote:
> > > > > > > >> Hi Tom,
> > > > > > > >>
> > > > > > > >> On Sun, Dec 31, 2023 at 6:54 AM Tom Rini  
> > > > > > > >> wrote:
> > > > > > > >> >
> > > > > > > >> > On Sun, Dec 31, 2023 at 05:48:23AM -0700, Simon Glass wrote:
> > > > > > > >> > > Hi,
> > > > > > > >> > >
> > > > > > > >> > > On Fri, Dec 29, 2023 at 10:52 AM Tom Rini 
> > > > > > > >> > >  wrote:
> > > > > > > >> > > >
> > > > > > > >> > > > On Fri, Dec 29, 2023 at 06:44:15PM +0100, Mark Kettenis 
> > > > > > > >> > > > wrote:
> > > > > > > >> > > > > > Date: Fri, 29 Dec 2023 11:17:44 -0500
> > > > > > > >> > > > > > From: Tom Rini 
> > > > > > > >> > > > > >
> > > > > > > >> > > > > > On Fri, Dec 29, 2023 at 05:05:17PM +0100, Heinrich 
> > > > > > > >> > > > > > Schuchardt wrote:
> > > > > > > >> > > > > > >
> > > > > > > >> > > > > > >
> > > > > > > >> > > > > > > Am 29. Dezember 2023 16:43:07 MEZ schrieb Tom Rini 
> > > > > > > >> > > > > > > :
> > > > > > > >> > > > > > > >On Fri, Dec 29, 2023 at 05:36:09AM +, Simon 
> > > > > > > >> > > > > > > >Glass wrote:
> > > > > > > >> > > > > > > >> Hi,
> > > > > > > >> > > > > > > >>
> > > > > > > >> > > > > > > >> On Sat, Dec 16, 2023 at 6:01 PM Simon Glass 
> > > > > > > >> > > > > > > >>  wrote:
> > > > > > > >> > > > > > > >> >
> > > > > > > >> > > > > > > >> > Hi,
> > > > > > > >> > > > > > > >> >
> > > > > > > >> > > > > > > >> > This records my thoughts after a discussion 
> > > > > > > >> > > > > > > >> > with Ilias & Heinrich re
> > > > > > > >> > > > > > > >> > memory allocation in U-Boot.
> > > > > > > >> > > > > > > >> >
> > > > > > > >> > > > > > > >> > 1. malloc()
> > > > > > > >> > > > > > > >> >
> > > > > > > >> > > > > > > >> > malloc() is used for programmatic memory 
> > > > > > > >> > > > > > > >> > allocation. It allows memory
> > > > > > > >> > > > > > > >> > to be freed. It is not designed for very 
> > > > > > > >> > > > > > > >> > large allocations (e.g. a
> > > > > > > >> > > > > > > >> > 10MB kernel or 100MB ramdisk).
> > > 

Re: [RFC PATCH 15/31] efi_memory: add an event handler to update memory map

2024-06-10 Thread Sughosh Ganu
On Mon, 10 Jun 2024 at 20:22, Sughosh Ganu  wrote:
>
> hi Ilias,
>
> On Mon, 10 Jun 2024 at 19:48, Ilias Apalodimas
>  wrote:
> >
> > Hi Sughosh
> >
> > On Mon, 10 Jun 2024 at 15:25, Sughosh Ganu  wrote:
> > >
> > > On Mon, 10 Jun 2024 at 17:40, Ilias Apalodimas
> > >  wrote:
> > > >
> > > > On Fri, 7 Jun 2024 at 21:54, Sughosh Ganu  
> > > > wrote:
> > > > >
> > > > > There are events that would be used to notify other interested modules
> > > > > of any changes in available and occupied memory. This would happen
> > > > > when a module allocates or reserves memory, or frees up memory. These
> > > > > changes in memory map should be notified to other interested modules
> > > > > so that the allocated memory does not get overwritten. Add an event
> > > > > handler in the EFI memory module to update the EFI memory map
> > > > > accordingly when such changes happen. As a consequence, any subsequent
> > > > > memory request would honour the updated memory map and only available
> > > > > memory would be allocated from.
> > > >
> > > > So the question here, is why do we need a notifier chain overall?
> > > > Can't we change the EFI subsystem and allocate memory with lmb now?
> > > > And any special functions we have in EFI (e.g allocate aligned memory)
> > > > can migrate to lmb()
> > >
> > > Like we discussed offline, that was my initial attempt -- to use the
> > > LMB allocation API's from inside the EFI allocate pages module. But I
> > > was facing a lot of corner case issues, primarily in keeping the two
> > > memory maps the same.
> >
> > I think it would worth discussing this a bit more. I like the idea of
> > having a single allocator more than having events to update memory
> > reservations
> >
> > > Which is why I moved to the current
> > > implementation of notifying other modules, and that too only for the
> > > addresses in the RAM region.
> >
> > The notification to 'other modules' i still done by updating the
> > static memory map though no?
> > So what corner cases we couldn't solve by having a single allocator?
>
> I can re-check what were the issues that I faced when trying with a
> single allocator. But please note that we are not making any
> significant gains by having a single allocator. Even with a common
> allocator(say LMB), it would still be required to have the same
> notification mechanism to update the EFI memory map. Else the EFI
> memory map would show regions of memory as conventional memory, while
> they are being used by the other subsystem. So, all in all, I think
> that the notification mechanism is not that inefficient. Thanks.

Or rather, "the notification mechanism is not inefficient".

-sughosh

>
> -sughosh
>
> >
> > Thanks
> > /Ilias
> > >
> > > -sughosh
> > >
> > > >
> > > > Cheers
> > > > /Ilias
> > > > >
> > > > > Signed-off-by: Sughosh Ganu 
> > > > > ---
> > > > >  lib/efi_loader/efi_memory.c | 70 
> > > > > ++---
> > > > >  1 file changed, 58 insertions(+), 12 deletions(-)
> > > > >
> > > > > diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> > > > > index 435e580fb3..93244161b0 100644
> > > > > --- a/lib/efi_loader/efi_memory.c
> > > > > +++ b/lib/efi_loader/efi_memory.c
> > > > > @@ -73,6 +73,10 @@ struct efi_pool_allocation {
> > > > >  #if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
> > > > >  extern bool is_addr_in_ram(uintptr_t addr);
> > > > >
> > > > > +static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
> > > > > +   int memory_type,
> > > > > +   bool overlap_only_ram);
> > > > > +
> > > > >  static void efi_map_update_notify(u64 addr, u64 size, u8 op)
> > > > >  {
> > > > > struct event_efi_mem_map_update efi_map = {0};
> > > > > @@ -84,6 +88,34 @@ static void efi_map_update_notify(u64 addr, u64 
> > > > > size, u8 op)
> > > > > if (is_addr_in_ram((uintptr_t)addr))
> > > > > event_notify(EVT_EFI_MEM_MAP_UPDATE, _map, 
> &g

Re: [RFC PATCH 15/31] efi_memory: add an event handler to update memory map

2024-06-10 Thread Sughosh Ganu
hi Ilias,

On Mon, 10 Jun 2024 at 19:48, Ilias Apalodimas
 wrote:
>
> Hi Sughosh
>
> On Mon, 10 Jun 2024 at 15:25, Sughosh Ganu  wrote:
> >
> > On Mon, 10 Jun 2024 at 17:40, Ilias Apalodimas
> >  wrote:
> > >
> > > On Fri, 7 Jun 2024 at 21:54, Sughosh Ganu  wrote:
> > > >
> > > > There are events that would be used to notify other interested modules
> > > > of any changes in available and occupied memory. This would happen
> > > > when a module allocates or reserves memory, or frees up memory. These
> > > > changes in memory map should be notified to other interested modules
> > > > so that the allocated memory does not get overwritten. Add an event
> > > > handler in the EFI memory module to update the EFI memory map
> > > > accordingly when such changes happen. As a consequence, any subsequent
> > > > memory request would honour the updated memory map and only available
> > > > memory would be allocated from.
> > >
> > > So the question here, is why do we need a notifier chain overall?
> > > Can't we change the EFI subsystem and allocate memory with lmb now?
> > > And any special functions we have in EFI (e.g allocate aligned memory)
> > > can migrate to lmb()
> >
> > Like we discussed offline, that was my initial attempt -- to use the
> > LMB allocation API's from inside the EFI allocate pages module. But I
> > was facing a lot of corner case issues, primarily in keeping the two
> > memory maps the same.
>
> I think it would worth discussing this a bit more. I like the idea of
> having a single allocator more than having events to update memory
> reservations
>
> > Which is why I moved to the current
> > implementation of notifying other modules, and that too only for the
> > addresses in the RAM region.
>
> The notification to 'other modules' i still done by updating the
> static memory map though no?
> So what corner cases we couldn't solve by having a single allocator?

I can re-check what were the issues that I faced when trying with a
single allocator. But please note that we are not making any
significant gains by having a single allocator. Even with a common
allocator(say LMB), it would still be required to have the same
notification mechanism to update the EFI memory map. Else the EFI
memory map would show regions of memory as conventional memory, while
they are being used by the other subsystem. So, all in all, I think
that the notification mechanism is not that inefficient. Thanks.

-sughosh

>
> Thanks
> /Ilias
> >
> > -sughosh
> >
> > >
> > > Cheers
> > > /Ilias
> > > >
> > > > Signed-off-by: Sughosh Ganu 
> > > > ---
> > > >  lib/efi_loader/efi_memory.c | 70 ++---
> > > >  1 file changed, 58 insertions(+), 12 deletions(-)
> > > >
> > > > diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> > > > index 435e580fb3..93244161b0 100644
> > > > --- a/lib/efi_loader/efi_memory.c
> > > > +++ b/lib/efi_loader/efi_memory.c
> > > > @@ -73,6 +73,10 @@ struct efi_pool_allocation {
> > > >  #if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
> > > >  extern bool is_addr_in_ram(uintptr_t addr);
> > > >
> > > > +static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
> > > > +   int memory_type,
> > > > +   bool overlap_only_ram);
> > > > +
> > > >  static void efi_map_update_notify(u64 addr, u64 size, u8 op)
> > > >  {
> > > > struct event_efi_mem_map_update efi_map = {0};
> > > > @@ -84,6 +88,34 @@ static void efi_map_update_notify(u64 addr, u64 
> > > > size, u8 op)
> > > > if (is_addr_in_ram((uintptr_t)addr))
> > > > event_notify(EVT_EFI_MEM_MAP_UPDATE, _map, 
> > > > sizeof(efi_map));
> > > >  }
> > > > +
> > > > +static int lmb_mem_map_update_sync(void *ctx, struct event *event)
> > > > +{
> > > > +   u8 op;
> > > > +   u64 addr;
> > > > +   u64 pages;
> > > > +   efi_status_t status;
> > > > +   struct event_lmb_map_update *lmb_map = >data.lmb_map;
> > > > +
> > > > +   addr = (uintptr_t)map_sysmem(lmb_map->base, 0);
> > > > +   pages = efi_size_in_pages(lmb_map->size + (addr & 
> > > > EFI_PAG

Re: Proposal: U-Boot memory management

2024-06-10 Thread Sughosh Ganu
hi Simon,

On Mon, 10 Jun 2024 at 19:25, Simon Glass  wrote:
>
> Hi Sughosh,
>
> On Thu, 6 Jun 2024 at 13:18, Sughosh Ganu  wrote:
> >
> > hi Simon,
> >
> > On Wed, 29 May 2024 at 22:00, Simon Glass  wrote:
> > >
> > > +Sughosh Ganu for reference
> > >
> > >
> > > On Sun, 31 Dec 2023 at 09:16, Tom Rini  wrote:
> > > >
> > > > On Sun, Dec 31, 2023 at 04:40:06PM +0100, Heinrich Schuchardt wrote:
> > > > >
> > > > >
> > > > > Am 31. Dezember 2023 16:11:44 MEZ schrieb Tom Rini 
> > > > > :
> > > > > >On Sun, Dec 31, 2023 at 07:22:10AM -0700, Simon Glass wrote:
> > > > > >> Hi Tom,
> > > > > >>
> > > > > >> On Sun, Dec 31, 2023 at 6:54 AM Tom Rini  
> > > > > >> wrote:
> > > > > >> >
> > > > > >> > On Sun, Dec 31, 2023 at 05:48:23AM -0700, Simon Glass wrote:
> > > > > >> > > Hi,
> > > > > >> > >
> > > > > >> > > On Fri, Dec 29, 2023 at 10:52 AM Tom Rini  
> > > > > >> > > wrote:
> > > > > >> > > >
> > > > > >> > > > On Fri, Dec 29, 2023 at 06:44:15PM +0100, Mark Kettenis 
> > > > > >> > > > wrote:
> > > > > >> > > > > > Date: Fri, 29 Dec 2023 11:17:44 -0500
> > > > > >> > > > > > From: Tom Rini 
> > > > > >> > > > > >
> > > > > >> > > > > > On Fri, Dec 29, 2023 at 05:05:17PM +0100, Heinrich 
> > > > > >> > > > > > Schuchardt wrote:
> > > > > >> > > > > > >
> > > > > >> > > > > > >
> > > > > >> > > > > > > Am 29. Dezember 2023 16:43:07 MEZ schrieb Tom Rini 
> > > > > >> > > > > > > :
> > > > > >> > > > > > > >On Fri, Dec 29, 2023 at 05:36:09AM +, Simon Glass 
> > > > > >> > > > > > > >wrote:
> > > > > >> > > > > > > >> Hi,
> > > > > >> > > > > > > >>
> > > > > >> > > > > > > >> On Sat, Dec 16, 2023 at 6:01 PM Simon Glass 
> > > > > >> > > > > > > >>  wrote:
> > > > > >> > > > > > > >> >
> > > > > >> > > > > > > >> > Hi,
> > > > > >> > > > > > > >> >
> > > > > >> > > > > > > >> > This records my thoughts after a discussion with 
> > > > > >> > > > > > > >> > Ilias & Heinrich re
> > > > > >> > > > > > > >> > memory allocation in U-Boot.
> > > > > >> > > > > > > >> >
> > > > > >> > > > > > > >> > 1. malloc()
> > > > > >> > > > > > > >> >
> > > > > >> > > > > > > >> > malloc() is used for programmatic memory 
> > > > > >> > > > > > > >> > allocation. It allows memory
> > > > > >> > > > > > > >> > to be freed. It is not designed for very large 
> > > > > >> > > > > > > >> > allocations (e.g. a
> > > > > >> > > > > > > >> > 10MB kernel or 100MB ramdisk).
> > > > > >> > > > > > > >> >
> > > > > >> > > > > > > >> > 2. lmb
> > > > > >> > > > > > > >> >
> > > > > >> > > > > > > >> > lmb is used for large blocks of memory, such as 
> > > > > >> > > > > > > >> > those needed for a
> > > > > >> > > > > > > >> > kernel or ramdisk. Allocation is only transitory, 
> > > > > >> > > > > > > >> > for the purposes of
> > > > > >> > > > > > > >> > loading some images and booting. If 

Re: [RFC PATCH 09/31] lmb: allow for resizing lmb regions

2024-06-10 Thread Sughosh Ganu
hi Ilias,

On Mon, 10 Jun 2024 at 19:52, Ilias Apalodimas
 wrote:
>
> Hi Sughosh
>
> On Mon, 10 Jun 2024 at 15:57, Sughosh Ganu  wrote:
> >
> > On Mon, 10 Jun 2024 at 18:17, Ilias Apalodimas
> >  wrote:
> > >
> > > On Mon, 10 Jun 2024 at 15:20, Sughosh Ganu  
> > > wrote:
> > > >
> > > > hi Ilias,
> > > >
> > > > On Mon, 10 Jun 2024 at 17:34, Ilias Apalodimas
> > > >  wrote:
> > > > >
> > > > > Hi Sughosh
> > > > >
> > > > >
> > > > > On Fri, 7 Jun 2024 at 21:54, Sughosh Ganu  
> > > > > wrote:
> > > > > >
> > > > > > Allow for resizing of LMB regions if the region attributes match. 
> > > > > > The
> > > > > > current code returns a failure status on detecting an overlapping
> > > > > > address. This worked up until now since the LMB calls were not
> > > > > > persistent and global -- the LMB memory map was specific and private
> > > > > > to a given caller of the LMB API's.
> > > > > >
> > > > > > With the change in the LMB code to make the LMB reservations
> > > > > > persistent, there needs to be a check on whether the memory region 
> > > > > > can
> > > > > > be resized, and then do it if so. To distinguish between memory that
> > > > > > cannot be resized, add a new flag, LMB_NOOVERWRITE. Reserving a 
> > > > > > region
> > > > > > of memory with this attribute would indicate that the region cannot 
> > > > > > be
> > > > > > resized.
> > > > >
> > > > > Can you think of a memory region that needs to be protected from 
> > > > > resizing?
> > > >
> > > > Actually, I think I could use a better term instead of 'resize'. The
> > > > aim of this patch is to allow re-allocation/re-reservation of the same
> > > > region of memory -- this will only be relevant for the LMB
> > > > reservations, as these are used for loading images into memory. All
> > > > other allocations(EFI currently) are true allocations in that these
> > > > should not get overwritten at all. Memory once allocated, say for
> > > > loading an EFI image, cannot be re-requested.
> > > >
> > > >
> > > > > I think we should design this a bit differently.  For example, think
> > > > > of someone loading a file in a memory region and then a subsystem
> > > > > trying to resize its reserved memory overwriting that region. Instead
> > > > > of this flag why don't we add
> > > > > - A flag that indicates whether this region can be re-used (IOW
> > > > > overwrites it), but only if the 'subsytem id' defined below matches
> > > > > - a u32 that indicates the subsystem ID that initiated the transaction
> > > > > -- e.g EFI, load command, U-Boot core .. etc
> > > > >
> > > > > Resizing can be enabled unconditionally in that case as long as there
> > > > > is enough space. The only requirement would be that the request comes
> > > > > from the same subsystem that reserved the memory in the beginning
> > > >
> > > > Like I mentioned above, resizing(or rather re-allocations) should only
> > > > be allowed for the LMB subsystem. Any other module should not be
> > > > returned an already allocated address. Which is why I mark any memory
> > > > map update coming from the EFI module as no-overwrite.
> > >
> > > And what happens if someone tries to overwrite 'load' memory? Won't
> > > you still corrupt whatever is loaded on that region as it's not marked
> > > for protection?
> >
> > Yes, but that is the expected behavior in U-Boot for LMB memory.
> > Consider the following flow,
> >
> > 1) load hostfs - $some_addr $some_image
> > 2) fs.write $some_addr $some_destination $filesize
> > 3) load hostfs - $some_addr $some_other_image
> > 4) fs.write $some_addr $some_other_destination $filesize
> >
> > The above flow is very much valid, and this exercises the same region
> > of LMB memory. Which is why we need to allow re-using the same memory
> > address for LMB. This worked up until now since all LMB
> > allocations/reservations were private. This is user visible behaviour,
> > and used in many scripts used by platforms to read and write fi

Re: [RFC PATCH 09/31] lmb: allow for resizing lmb regions

2024-06-10 Thread Sughosh Ganu
On Mon, 10 Jun 2024 at 18:29, Heinrich Schuchardt  wrote:
>
> On 10.06.24 14:20, Sughosh Ganu wrote:
> > hi Ilias,
> >
> > On Mon, 10 Jun 2024 at 17:34, Ilias Apalodimas
> >  wrote:
> >>
> >> Hi Sughosh
> >>
> >>
> >> On Fri, 7 Jun 2024 at 21:54, Sughosh Ganu  wrote:
> >>>
> >>> Allow for resizing of LMB regions if the region attributes match. The
> >>> current code returns a failure status on detecting an overlapping
> >>> address. This worked up until now since the LMB calls were not
> >>> persistent and global -- the LMB memory map was specific and private
> >>> to a given caller of the LMB API's.
> >>>
> >>> With the change in the LMB code to make the LMB reservations
> >>> persistent, there needs to be a check on whether the memory region can
> >>> be resized, and then do it if so. To distinguish between memory that
> >>> cannot be resized, add a new flag, LMB_NOOVERWRITE. Reserving a region
> >>> of memory with this attribute would indicate that the region cannot be
> >>> resized.
> >>
> >> Can you think of a memory region that needs to be protected from resizing?
> >
> > Actually, I think I could use a better term instead of 'resize'. The
> > aim of this patch is to allow re-allocation/re-reservation of the same
> > region of memory -- this will only be relevant for the LMB
> > reservations, as these are used for loading images into memory. All
> > other allocations(EFI currently) are true allocations in that these
> > should not get overwritten at all. Memory once allocated, say for
> > loading an EFI image, cannot be re-requested.
> >
> >
> >> I think we should design this a bit differently.  For example, think
> >> of someone loading a file in a memory region and then a subsystem
> >> trying to resize its reserved memory overwriting that region. Instead
> >> of this flag why don't we add
> >> - A flag that indicates whether this region can be re-used (IOW
> >> overwrites it), but only if the 'subsytem id' defined below matches
> >> - a u32 that indicates the subsystem ID that initiated the transaction
> >> -- e.g EFI, load command, U-Boot core .. etc
> >>
> >> Resizing can be enabled unconditionally in that case as long as there
> >> is enough space. The only requirement would be that the request comes
> >> from the same subsystem that reserved the memory in the beginning
> >
> > Like I mentioned above, resizing(or rather re-allocations) should only
> > be allowed for the LMB subsystem. Any other module should not be
> > returned an already allocated address. Which is why I mark any memory
> > map update coming from the EFI module as no-overwrite.
> >
> > -sughosh
> >>
> >> Thanks
> >> /Ilias
> >>
> >>>
> >>> Signed-off-by: Sughosh Ganu 
> >>> ---
> >>>   include/lmb.h |   1 +
> >>>   lib/lmb.c | 120 --
> >>>   2 files changed, 107 insertions(+), 14 deletions(-)
> >>>
> >>> diff --git a/include/lmb.h b/include/lmb.h
> >>> index 03bce2a50c..1d4cd255d2 100644
> >>> --- a/include/lmb.h
> >>> +++ b/include/lmb.h
> >>> @@ -20,6 +20,7 @@
> >>>   enum lmb_flags {
> >>>  LMB_NONE= 0x0,
> >>>  LMB_NOMAP   = 0x4,
> >>> +   LMB_NOOVERWRITE = 0x8,
> >>>   };
> >>>
> >>>   /**
> >>> diff --git a/lib/lmb.c b/lib/lmb.c
> >>> index de5a2cf23b..0a4f3d5bcd 100644
> >>> --- a/lib/lmb.c
> >>> +++ b/lib/lmb.c
> >>> @@ -260,12 +260,88 @@ void lmb_add_memory(struct bd_info *bd)
> >>>  }
> >>>   }
> >>>
> >>> +static bool lmb_region_flags_match(struct lmb_region *rgn, unsigned long 
> >>> r1,
> >>> +  enum lmb_flags flags)
> >>> +{
> >>> +   return rgn->region[r1].flags == flags;
> >>> +}
> >>> +
> >>> +static long lmb_merge_overlap_regions(struct lmb_region *rgn, unsigned 
> >>> long i,
> >>> + phys_addr_t base, phys_size_t size,
> >>> + enum lmb_flags flags)
> >>> +{
> >>> +   phys_size_t rgnsize;
> >>> +   unsigne

Re: [RFC PATCH 09/31] lmb: allow for resizing lmb regions

2024-06-10 Thread Sughosh Ganu
On Mon, 10 Jun 2024 at 18:17, Ilias Apalodimas
 wrote:
>
> On Mon, 10 Jun 2024 at 15:20, Sughosh Ganu  wrote:
> >
> > hi Ilias,
> >
> > On Mon, 10 Jun 2024 at 17:34, Ilias Apalodimas
> >  wrote:
> > >
> > > Hi Sughosh
> > >
> > >
> > > On Fri, 7 Jun 2024 at 21:54, Sughosh Ganu  wrote:
> > > >
> > > > Allow for resizing of LMB regions if the region attributes match. The
> > > > current code returns a failure status on detecting an overlapping
> > > > address. This worked up until now since the LMB calls were not
> > > > persistent and global -- the LMB memory map was specific and private
> > > > to a given caller of the LMB API's.
> > > >
> > > > With the change in the LMB code to make the LMB reservations
> > > > persistent, there needs to be a check on whether the memory region can
> > > > be resized, and then do it if so. To distinguish between memory that
> > > > cannot be resized, add a new flag, LMB_NOOVERWRITE. Reserving a region
> > > > of memory with this attribute would indicate that the region cannot be
> > > > resized.
> > >
> > > Can you think of a memory region that needs to be protected from resizing?
> >
> > Actually, I think I could use a better term instead of 'resize'. The
> > aim of this patch is to allow re-allocation/re-reservation of the same
> > region of memory -- this will only be relevant for the LMB
> > reservations, as these are used for loading images into memory. All
> > other allocations(EFI currently) are true allocations in that these
> > should not get overwritten at all. Memory once allocated, say for
> > loading an EFI image, cannot be re-requested.
> >
> >
> > > I think we should design this a bit differently.  For example, think
> > > of someone loading a file in a memory region and then a subsystem
> > > trying to resize its reserved memory overwriting that region. Instead
> > > of this flag why don't we add
> > > - A flag that indicates whether this region can be re-used (IOW
> > > overwrites it), but only if the 'subsytem id' defined below matches
> > > - a u32 that indicates the subsystem ID that initiated the transaction
> > > -- e.g EFI, load command, U-Boot core .. etc
> > >
> > > Resizing can be enabled unconditionally in that case as long as there
> > > is enough space. The only requirement would be that the request comes
> > > from the same subsystem that reserved the memory in the beginning
> >
> > Like I mentioned above, resizing(or rather re-allocations) should only
> > be allowed for the LMB subsystem. Any other module should not be
> > returned an already allocated address. Which is why I mark any memory
> > map update coming from the EFI module as no-overwrite.
>
> And what happens if someone tries to overwrite 'load' memory? Won't
> you still corrupt whatever is loaded on that region as it's not marked
> for protection?

Yes, but that is the expected behaviour in U-Boot for LMB memory.
Consider the following flow,

1) load hostfs - $some_addr $some_image
2) fs.write $some_addr $some_destination $filesize
3) load hostfs - $some_addr $some_other_image
4) fs.write $some_addr $some_other_destination $filesize

The above flow is very much valid, and this exercises the same region
of LMB memory. Which is why we need to allow re-using the same memory
address for LMB. This worked up until now since all LMB
allocations/reservations were private. This is user visible behaviour,
and used in many scripts used by platforms to read and write files. So
even after making the LMB memory map global and persistent, this
aspect of re-use of LMB memory must be maintained.

-sughosh

>
> /Ilias
> >
> > -sughosh
> > >
> > > Thanks
> > > /Ilias
> > >
> > > >
> > > > Signed-off-by: Sughosh Ganu 
> > > > ---
> > > >  include/lmb.h |   1 +
> > > >  lib/lmb.c | 120 --
> > > >  2 files changed, 107 insertions(+), 14 deletions(-)
> > > >
> > > > diff --git a/include/lmb.h b/include/lmb.h
> > > > index 03bce2a50c..1d4cd255d2 100644
> > > > --- a/include/lmb.h
> > > > +++ b/include/lmb.h
> > > > @@ -20,6 +20,7 @@
> > > >  enum lmb_flags {
> > > > LMB_NONE= 0x0,
> > > > LMB_NOMAP   = 0x4,
> > > > +   LMB_NOOVERWRITE = 0x8,
> > > >  };
> > > >
> 

Re: [RFC PATCH 15/31] efi_memory: add an event handler to update memory map

2024-06-10 Thread Sughosh Ganu
On Mon, 10 Jun 2024 at 17:40, Ilias Apalodimas
 wrote:
>
> On Fri, 7 Jun 2024 at 21:54, Sughosh Ganu  wrote:
> >
> > There are events that would be used to notify other interested modules
> > of any changes in available and occupied memory. This would happen
> > when a module allocates or reserves memory, or frees up memory. These
> > changes in memory map should be notified to other interested modules
> > so that the allocated memory does not get overwritten. Add an event
> > handler in the EFI memory module to update the EFI memory map
> > accordingly when such changes happen. As a consequence, any subsequent
> > memory request would honour the updated memory map and only available
> > memory would be allocated from.
>
> So the question here, is why do we need a notifier chain overall?
> Can't we change the EFI subsystem and allocate memory with lmb now?
> And any special functions we have in EFI (e.g allocate aligned memory)
> can migrate to lmb()

Like we discussed offline, that was my initial attempt -- to use the
LMB allocation API's from inside the EFI allocate pages module. But I
was facing a lot of corner case issues, primarily in keeping the two
memory maps the same. Which is why I moved to the current
implementation of notifying other modules, and that too only for the
addresses in the RAM region.

-sughosh

>
> Cheers
> /Ilias
> >
> > Signed-off-by: Sughosh Ganu 
> > ---
> >  lib/efi_loader/efi_memory.c | 70 ++---
> >  1 file changed, 58 insertions(+), 12 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> > index 435e580fb3..93244161b0 100644
> > --- a/lib/efi_loader/efi_memory.c
> > +++ b/lib/efi_loader/efi_memory.c
> > @@ -73,6 +73,10 @@ struct efi_pool_allocation {
> >  #if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
> >  extern bool is_addr_in_ram(uintptr_t addr);
> >
> > +static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
> > +   int memory_type,
> > +   bool overlap_only_ram);
> > +
> >  static void efi_map_update_notify(u64 addr, u64 size, u8 op)
> >  {
> > struct event_efi_mem_map_update efi_map = {0};
> > @@ -84,6 +88,34 @@ static void efi_map_update_notify(u64 addr, u64 size, u8 
> > op)
> > if (is_addr_in_ram((uintptr_t)addr))
> > event_notify(EVT_EFI_MEM_MAP_UPDATE, _map, 
> > sizeof(efi_map));
> >  }
> > +
> > +static int lmb_mem_map_update_sync(void *ctx, struct event *event)
> > +{
> > +   u8 op;
> > +   u64 addr;
> > +   u64 pages;
> > +   efi_status_t status;
> > +   struct event_lmb_map_update *lmb_map = >data.lmb_map;
> > +
> > +   addr = (uintptr_t)map_sysmem(lmb_map->base, 0);
> > +   pages = efi_size_in_pages(lmb_map->size + (addr & EFI_PAGE_MASK));
> > +   op = lmb_map->op;
> > +   addr &= ~EFI_PAGE_MASK;
> > +
> > +   if (op != MAP_OP_RESERVE && op != MAP_OP_FREE) {
> > +   log_debug("Invalid map update op received (%d)\n", op);
> > +   return -1;
> > +   }
> > +
> > +   status = __efi_add_memory_map_pg(addr, pages,
> > +op == MAP_OP_FREE ?
> > +EFI_CONVENTIONAL_MEMORY :
> > +EFI_BOOT_SERVICES_DATA,
> > +true);
> > +
> > +   return status == EFI_SUCCESS ? 0 : -1;
> > +}
> > +EVENT_SPY_FULL(EVT_LMB_MAP_UPDATE, lmb_mem_map_update_sync);
> >  #endif /* MEM_MAP_UPDATE_NOTIFY */
> >
> >  /**
> > @@ -275,18 +307,9 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map,
> > return EFI_CARVE_LOOP_AGAIN;
> >  }
> >
> > -/**
> > - * efi_add_memory_map_pg() - add pages to the memory map
> > - *
> > - * @start: start address, must be a multiple of EFI_PAGE_SIZE
> > - * @pages: number of pages to add
> > - * @memory_type:   type of memory added
> > - * @overlap_only_ram:  region may only overlap RAM
> > - * Return: status code
> > - */
> > -static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
> > - int memory_type,
> > - bool overlap_only_ram)
> > +static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
> > +  

Re: [RFC PATCH 09/31] lmb: allow for resizing lmb regions

2024-06-10 Thread Sughosh Ganu
hi Ilias,

On Mon, 10 Jun 2024 at 17:34, Ilias Apalodimas
 wrote:
>
> Hi Sughosh
>
>
> On Fri, 7 Jun 2024 at 21:54, Sughosh Ganu  wrote:
> >
> > Allow for resizing of LMB regions if the region attributes match. The
> > current code returns a failure status on detecting an overlapping
> > address. This worked up until now since the LMB calls were not
> > persistent and global -- the LMB memory map was specific and private
> > to a given caller of the LMB API's.
> >
> > With the change in the LMB code to make the LMB reservations
> > persistent, there needs to be a check on whether the memory region can
> > be resized, and then do it if so. To distinguish between memory that
> > cannot be resized, add a new flag, LMB_NOOVERWRITE. Reserving a region
> > of memory with this attribute would indicate that the region cannot be
> > resized.
>
> Can you think of a memory region that needs to be protected from resizing?

Actually, I think I could use a better term instead of 'resize'. The
aim of this patch is to allow re-allocation/re-reservation of the same
region of memory -- this will only be relevant for the LMB
reservations, as these are used for loading images into memory. All
other allocations(EFI currently) are true allocations in that these
should not get overwritten at all. Memory once allocated, say for
loading an EFI image, cannot be re-requested.


> I think we should design this a bit differently.  For example, think
> of someone loading a file in a memory region and then a subsystem
> trying to resize its reserved memory overwriting that region. Instead
> of this flag why don't we add
> - A flag that indicates whether this region can be re-used (IOW
> overwrites it), but only if the 'subsytem id' defined below matches
> - a u32 that indicates the subsystem ID that initiated the transaction
> -- e.g EFI, load command, U-Boot core .. etc
>
> Resizing can be enabled unconditionally in that case as long as there
> is enough space. The only requirement would be that the request comes
> from the same subsystem that reserved the memory in the beginning

Like I mentioned above, resizing(or rather re-allocations) should only
be allowed for the LMB subsystem. Any other module should not be
returned an already allocated address. Which is why I mark any memory
map update coming from the EFI module as no-overwrite.

-sughosh
>
> Thanks
> /Ilias
>
> >
> > Signed-off-by: Sughosh Ganu 
> > ---
> >  include/lmb.h |   1 +
> >  lib/lmb.c | 120 --
> >  2 files changed, 107 insertions(+), 14 deletions(-)
> >
> > diff --git a/include/lmb.h b/include/lmb.h
> > index 03bce2a50c..1d4cd255d2 100644
> > --- a/include/lmb.h
> > +++ b/include/lmb.h
> > @@ -20,6 +20,7 @@
> >  enum lmb_flags {
> > LMB_NONE= 0x0,
> > LMB_NOMAP   = 0x4,
> > +   LMB_NOOVERWRITE = 0x8,
> >  };
> >
> >  /**
> > diff --git a/lib/lmb.c b/lib/lmb.c
> > index de5a2cf23b..0a4f3d5bcd 100644
> > --- a/lib/lmb.c
> > +++ b/lib/lmb.c
> > @@ -260,12 +260,88 @@ void lmb_add_memory(struct bd_info *bd)
> > }
> >  }
> >
> > +static bool lmb_region_flags_match(struct lmb_region *rgn, unsigned long 
> > r1,
> > +  enum lmb_flags flags)
> > +{
> > +   return rgn->region[r1].flags == flags;
> > +}
> > +
> > +static long lmb_merge_overlap_regions(struct lmb_region *rgn, unsigned 
> > long i,
> > + phys_addr_t base, phys_size_t size,
> > + enum lmb_flags flags)
> > +{
> > +   phys_size_t rgnsize;
> > +   unsigned long rgn_cnt, idx;
> > +   phys_addr_t rgnbase, rgnend;
> > +   phys_addr_t mergebase, mergeend;
> > +
> > +   rgn_cnt = 0;
> > +   idx = i;
> > +   /*
> > +* First thing to do is to identify how many regions does
> > +* the requested region overlap.
> > +* If the flags match, combine all these overlapping
> > +* regions into a single region, and remove the merged
> > +* regions.
> > +*/
> > +   while (idx < rgn->cnt - 1) {
> > +   rgnbase = rgn->region[idx].base;
> > +   rgnsize = rgn->region[idx].size;
> > +
> > +   if (lmb_addrs_overlap(base, size, rgnbase,
> > + rgnsize)) {
> > +   if (!lmb_region_flags_match(rgn, idx, flags))
> > +   

Re: [RFC PATCH 11/31] lib: Kconfig: add a config symbol for getting memory map updates

2024-06-10 Thread Sughosh Ganu
hi Ilias,

On Mon, 10 Jun 2024 at 17:15, Ilias Apalodimas
 wrote:
>
> On Fri, 7 Jun 2024 at 21:54, Sughosh Ganu  wrote:
> >
> > Add a Kconfig symbol to enable getting updates on any memory map
> > changes that might be done by some other module. This notification
> > mechanism can then be used to have a synchronous view of allocated and
> > free memory.
>
> Is there any chance we want to build a firmware that allows memory not
> to be reserved?
> I think we should make the feature mandatory

LMB is enabled for all architectures, but the EFI code is not. This
config is only for enabling the notification code. Which is why it is
enabled only when LMB and EFI_LOADER configs are enabled.

-sughosh

>
> Cheers
> /Ilias
> >
> > Signed-off-by: Sughosh Ganu 
> > ---
> >  lib/Kconfig | 9 +
> >  1 file changed, 9 insertions(+)
> >
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index 189e6eb31a..9ea02ae006 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -74,6 +74,15 @@ config HAVE_PRIVATE_LIBGCC
> >  config LIB_UUID
> > bool
> >
> > +config MEM_MAP_UPDATE_NOTIFY
> > +   bool "Get notified of any changes to the memory map"
> > +   default y if EVENT && LMB && EFI_LOADER
> > +   help
> > + Enable this option to get notification on any changes to the
> > + memory that is allocated or freed. This will allow different
> > + modules that allocate memory to have a synchronous view of 
> > available
> > + and allocated memory.
> > +
> >  config RANDOM_UUID
> > bool "GPT Random UUID generation"
> > select LIB_UUID
> > --
> > 2.34.1
> >


Re: [RFC PATCH 31/31] temp: cmd: efi: add a command to dump EFI memory map

2024-06-10 Thread Sughosh Ganu
On Sat, 8 Jun 2024 at 09:03, Heinrich Schuchardt  wrote:
>
>
>
> Am 7. Juni 2024 20:52:40 MESZ schrieb Sughosh Ganu :
> >Add a command to dump the EFI memory map.
>
> What are you missing in 'efidebug memmap'?

Nothing. I wasn't aware of this sub-command. Thanks for pointing it out.

-sughosh

>
> Best regards
>
> Heinrich
>
> >
> >Not for committing.
> >
> >Signed-off-by: Sughosh Ganu 
> >---
> > cmd/Makefile|  1 +
> > cmd/efi_map_dump.c  | 28 
> > include/efi_loader.h|  2 ++
> > lib/efi_loader/efi_memory.c | 32 
> > 4 files changed, 63 insertions(+)
> > create mode 100644 cmd/efi_map_dump.c
> >
> >diff --git a/cmd/Makefile b/cmd/Makefile
> >index 35fcc4af5a..315046def6 100644
> >--- a/cmd/Makefile
> >+++ b/cmd/Makefile
> >@@ -11,6 +11,7 @@ obj-y += help.o
> > obj-y += panic.o
> > obj-y += version.o
> > obj-y += efi_memory.o
> >+obj-y += efi_map_dump.o
> >
> > # command
> > obj-$(CONFIG_CMD_ARMFFA) += armffa.o
> >diff --git a/cmd/efi_map_dump.c b/cmd/efi_map_dump.c
> >new file mode 100644
> >index 00..f2a5932767
> >--- /dev/null
> >+++ b/cmd/efi_map_dump.c
> >@@ -0,0 +1,28 @@
> >+// SPDX-License-Identifier: GPL-2.0+
> >+/*
> >+ *  Allocate and Free EFI memory
> >+ *
> >+ *  Copyright (c) 2024 Linaro Limited
> >+ */
> >+
> >+#include 
> >+#include 
> >+
> >+static int do_efi_map_dump(struct cmd_tbl *cmdtp, int flag, int argc,
> >+ char *const argv[])
> >+{
> >+//printf("%s: argc => %d\n", __func__, argc);
> >+
> >+  if (argc != 1)
> >+  return CMD_RET_USAGE;
> >+
> >+  dump_efi_memory_map();
> >+
> >+  return CMD_RET_SUCCESS;
> >+}
> >+
> >+U_BOOT_CMD(
> >+  efi_map_dump, 1, 0, do_efi_map_dump,
> >+  "Dump the EFI memory map",
> >+  ""
> >+);
> >diff --git a/include/efi_loader.h b/include/efi_loader.h
> >index 9600941aa3..40f894f182 100644
> >--- a/include/efi_loader.h
> >+++ b/include/efi_loader.h
> >@@ -791,6 +791,8 @@ efi_status_t efi_get_memory_map(efi_uintn_t 
> >*memory_map_size,
> >   uint32_t *descriptor_version);
> > /* Adds a range into the EFI memory map */
> > efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type);
> >+/* Dump the contents of the EFI memory map */
> >+void dump_efi_memory_map(void);
> > /* Adds a conventional range into the EFI memory map */
> > efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
> >u64 ram_top);
> >diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> >index 93244161b0..7ab1b86140 100644
> >--- a/lib/efi_loader/efi_memory.c
> >+++ b/lib/efi_loader/efi_memory.c
> >@@ -47,6 +47,8 @@ static LIST_HEAD(efi_mem);
> > void *efi_bounce_buffer;
> > #endif
> >
> >+static uint64_t desc_get_end(struct efi_mem_desc *desc);
> >+
> > /**
> >  * struct efi_pool_allocation - memory block allocated from pool
> >  *
> >@@ -118,6 +120,36 @@ static int lmb_mem_map_update_sync(void *ctx, struct 
> >event *event)
> > EVENT_SPY_FULL(EVT_LMB_MAP_UPDATE, lmb_mem_map_update_sync);
> > #endif /* MEM_MAP_UPDATE_NOTIFY */
> >
> >+static void dump_efi_mem_desc(struct efi_mem_desc *desc)
> >+{
> >+  u64 end;
> >+
> >+  end = desc_get_end(desc);
> >+
> >+  printf("---\n");
> >+  printf("Memory Range   [0x%llx - 0x%llx]\n",
> >+ desc->physical_start, end);
> >+  printf("Num Pages  [0x%llx]\n", desc->num_pages);
> >+  printf("Memory Type[0x%x]\n", desc->type);
> >+  printf("Attribute  [0x%llx]\n", desc->attribute);
> >+  printf("---\n");
> >+}
> >+
> >+void dump_efi_memory_map(void)
> >+{
> >+  struct list_head *lhandle;
> >+
> >+  list_for_each(lhandle, _mem) {
> >+  struct efi_mem_list *lmem;
> >+  struct efi_mem_desc *desc;
> >+
> >+  lmem = list_entry(lhandle, struct efi_mem_list, link);
> >+  desc = >desc;
> >+
> >+  dump_efi_mem_desc(desc);
> >+  }
> >+}
> >+
> > /**
> >  * checksum() - calculate checksum for memory allocated from pool
> >  *


Re: [RFC PATCH 30/31] temp: cmd: efi_mem: add a command to test efi alloc/free

2024-06-10 Thread Sughosh Ganu
On Sat, 8 Jun 2024 at 09:07, Heinrich Schuchardt  wrote:
>
>
>
> Am 7. Juni 2024 20:52:39 MESZ schrieb Sughosh Ganu :
> >Not for committing.
>
> Best put "DON'T MERGE" into the title to avoid mishaps in future versions.

Will do.

>
> In the final series we should have unit test covering all relevant aspects of 
> the memory system.

Yes, that's the plan.

-sughosh

>
> Best regards
>
> Heinrich
>
> >
> >Signed-off-by: Sughosh Ganu 
> >---
> > cmd/Makefile |   1 +
> > cmd/efi_memory.c | 155 +++
> > 2 files changed, 156 insertions(+)
> > create mode 100644 cmd/efi_memory.c
> >
> >diff --git a/cmd/Makefile b/cmd/Makefile
> >index 87133cc27a..35fcc4af5a 100644
> >--- a/cmd/Makefile
> >+++ b/cmd/Makefile
> >@@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
> > obj-y += help.o
> > obj-y += panic.o
> > obj-y += version.o
> >+obj-y += efi_memory.o
> >
> > # command
> > obj-$(CONFIG_CMD_ARMFFA) += armffa.o
> >diff --git a/cmd/efi_memory.c b/cmd/efi_memory.c
> >new file mode 100644
> >index 00..52ddcb7146
> >--- /dev/null
> >+++ b/cmd/efi_memory.c
> >@@ -0,0 +1,155 @@
> >+// SPDX-License-Identifier: GPL-2.0+
> >+/*
> >+ *  Allocate and Free EFI memory
> >+ *
> >+ *  Copyright (c) 2024 Linaro Limited
> >+ */
> >+
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+
> >+#include 
> >+
> >+static int do_efi_mem_free(struct cmd_tbl *cmdtp, int flag, int argc,
> >+ char * const argv[])
> >+{
> >+  uint64_t addr = 0, size = 0;
> >+  efi_uintn_t pages;
> >+  efi_status_t status;
> >+
> >+  if (argc != 3)
> >+  return CMD_RET_USAGE;
> >+
> >+  argc--; argv++;
> >+
> >+  size = simple_strtoul(argv[0], NULL, 16);
> >+  if (!size) {
> >+  printf("Enter valid size for free in Hex\n");
> >+  return CMD_RET_USAGE;
> >+  }
> >+
> >+
> >+  addr = simple_strtoul(argv[1], NULL, 16);
> >+  if (!addr) {
> >+  printf("Enter a valid address in Hex\n");
> >+  return CMD_RET_USAGE;
> >+  }
> >+
> >+  pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK));
> >+
> >+  status = efi_free_pages(addr, pages);
> >+  if (status != EFI_SUCCESS) {
> >+  printf("Unable to free memory, error (%#lx)\n", status);
> >+  return CMD_RET_FAILURE;
> >+  }
> >+
> >+  return CMD_RET_SUCCESS;
> >+}
> >+
> >+static int do_efi_mem_alloc(struct cmd_tbl *cmdtp, int flag, int argc,
> >+  char * const argv[])
> >+{
> >+  enum efi_allocate_type type;
> >+  uint64_t addr = 0, size = 0;
> >+  efi_uintn_t pages;
> >+  efi_status_t status;
> >+  bool max = false;
> >+
> >+  if (argc < 2)
> >+  return CMD_RET_USAGE;
> >+
> >+  argc--; argv++;
> >+
> >+  if (!strcmp("max", argv[0])) {
> >+  if (argc != 3)
> >+  return CMD_RET_USAGE;
> >+
> >+  max = true;
> >+  argv++;
> >+  argc--;
> >+  }
> >+
> >+  size = simple_strtoul(argv[0], NULL, 16);
> >+  if (!size) {
> >+  printf("Enter valid size for allocation in Hex\n");
> >+  return CMD_RET_USAGE;
> >+  }
> >+
> >+  if (max || argc == 2) {
> >+  addr = simple_strtoul(argv[1], NULL, 16);
> >+  if (!addr) {
> >+  printf("Enter a valid address in Hex\n");
> >+  return CMD_RET_USAGE;
> >+  }
> >+  }
> >+
> >+  if (max)
> >+  type = EFI_ALLOCATE_MAX_ADDRESS;
> >+  else if (addr)
> >+  type = EFI_ALLOCATE_ADDRESS;
> >+  else
> >+  type = EFI_ALLOCATE_ANY_PAGES;
> >+
> >+  pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK));
> >+  status = efi_allocate_pages(type, EFI_BOOT_SERVICES_DATA, pages,
> >+  );
> >+  if (status != EFI_SUCCESS) {
> >+  printf("efi_allocate_pages failed %lx\n", status);
> >+  return CMD_RET_FAILURE;
> >+  

Re: [RFC PATCH 26/31] test: lmb: run lmb tests only manually

2024-06-10 Thread Sughosh Ganu
On Sat, 8 Jun 2024 at 10:09, Heinrich Schuchardt  wrote:
>
> On 6/7/24 20:52, Sughosh Ganu wrote:
> > The LMB code has been changed so that the memory reservations and
> > allocations are now persistent and global. With this change, the
> > design of the LMB tests needs to be changed accordingly. For now, mark
> > the LMB tests to be run only manually. The tests won't be run as part
> > of the unit test suite, and thus would not interfere with the running
> > of the rest of the tests.
>
> We should run important tests in the CI.
>
> You could trigger the 'manual' test from a Python test and reboot the
> system to get into an initial state.

Yes, that is one of the solutions that I have in mind. Will work on
this for the next version. Thanks.

-sughosh

>
> Best regards
>
> Heinrich
>
> >
> > Signed-off-by: Sughosh Ganu 
> > ---
> >   test/lib/lmb.c | 49 -
> >   1 file changed, 24 insertions(+), 25 deletions(-)
> >
> > diff --git a/test/lib/lmb.c b/test/lib/lmb.c
> > index 67a6be5bc3..813f7e3100 100644
> > --- a/test/lib/lmb.c
> > +++ b/test/lib/lmb.c
> > @@ -195,7 +195,7 @@ static int test_multi_alloc_512mb_x2(struct 
> > unit_test_state *uts,
> >   }
> >
> >   /* Create a memory region with one reserved region and allocate */
> > -static int lib_test_lmb_simple(struct unit_test_state *uts)
> > +static int lib_test_lmb_simple_norun(struct unit_test_state *uts)
> >   {
> >   int ret;
> >
> > @@ -207,10 +207,10 @@ static int lib_test_lmb_simple(struct unit_test_state 
> > *uts)
> >   /* simulate 512 MiB RAM beginning at 1.5GiB */
> >   return test_multi_alloc_512mb(uts, 0xE000);
> >   }
> > -LIB_TEST(lib_test_lmb_simple, 0);
> > +LIB_TEST(lib_test_lmb_simple_norun, UT_TESTF_MANUAL);
> >
> >   /* Create two memory regions with one reserved region and allocate */
> > -static int lib_test_lmb_simple_x2(struct unit_test_state *uts)
> > +static int lib_test_lmb_simple_x2_norun(struct unit_test_state *uts)
> >   {
> >   int ret;
> >
> > @@ -222,7 +222,7 @@ static int lib_test_lmb_simple_x2(struct 
> > unit_test_state *uts)
> >   /* simulate 512 MiB RAM beginning at 3.5GiB and 1 GiB */
> >   return test_multi_alloc_512mb_x2(uts, 0xE000, 0x4000);
> >   }
> > -LIB_TEST(lib_test_lmb_simple_x2, 0);
> > +LIB_TEST(lib_test_lmb_simple_x2_norun, UT_TESTF_MANUAL);
> >
> >   /* Simulate 512 MiB RAM, allocate some blocks that fit/don't fit */
> >   static int test_bigblock(struct unit_test_state *uts, const phys_addr_t 
> > ram)
> > @@ -275,7 +275,7 @@ static int test_bigblock(struct unit_test_state *uts, 
> > const phys_addr_t ram)
> >   return 0;
> >   }
> >
> > -static int lib_test_lmb_big(struct unit_test_state *uts)
> > +static int lib_test_lmb_big_norun(struct unit_test_state *uts)
> >   {
> >   int ret;
> >
> > @@ -287,7 +287,7 @@ static int lib_test_lmb_big(struct unit_test_state *uts)
> >   /* simulate 512 MiB RAM beginning at 1.5GiB */
> >   return test_bigblock(uts, 0xE000);
> >   }
> > -LIB_TEST(lib_test_lmb_big, 0);
> > +LIB_TEST(lib_test_lmb_big_norun, UT_TESTF_MANUAL);
> >
> >   /* Simulate 512 MiB RAM, allocate a block without previous reservation */
> >   static int test_noreserved(struct unit_test_state *uts, const phys_addr_t 
> > ram,
> > @@ -348,7 +348,7 @@ static int test_noreserved(struct unit_test_state *uts, 
> > const phys_addr_t ram,
> >   return 0;
> >   }
> >
> > -static int lib_test_lmb_noreserved(struct unit_test_state *uts)
> > +static int lib_test_lmb_noreserved_norun(struct unit_test_state *uts)
> >   {
> >   int ret;
> >
> > @@ -360,10 +360,9 @@ static int lib_test_lmb_noreserved(struct 
> > unit_test_state *uts)
> >   /* simulate 512 MiB RAM beginning at 1.5GiB */
> >   return test_noreserved(uts, 0xE000, 4, 1);
> >   }
> > +LIB_TEST(lib_test_lmb_noreserved_norun, UT_TESTF_MANUAL);
> >
> > -LIB_TEST(lib_test_lmb_noreserved, 0);
> > -
> > -static int lib_test_lmb_unaligned_size(struct unit_test_state *uts)
> > +static int lib_test_lmb_unaligned_size_norun(struct unit_test_state *uts)
> >   {
> >   int ret;
> >
> > @@ -375,13 +374,13 @@ static int lib_test_lmb_unaligned_size(struct 
> > unit_test_state *uts)
> >   /* simulate 512 MiB RAM beginning at 1.5GiB */
> >   return test_noreserved(uts, 0xE000, 5, 8);
> >   }
> > -LIB

[RFC PATCH 31/31] temp: cmd: efi: add a command to dump EFI memory map

2024-06-07 Thread Sughosh Ganu
Add a command to dump the EFI memory map.

Not for committing.

Signed-off-by: Sughosh Ganu 
---
 cmd/Makefile|  1 +
 cmd/efi_map_dump.c  | 28 
 include/efi_loader.h|  2 ++
 lib/efi_loader/efi_memory.c | 32 
 4 files changed, 63 insertions(+)
 create mode 100644 cmd/efi_map_dump.c

diff --git a/cmd/Makefile b/cmd/Makefile
index 35fcc4af5a..315046def6 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -11,6 +11,7 @@ obj-y += help.o
 obj-y += panic.o
 obj-y += version.o
 obj-y += efi_memory.o
+obj-y += efi_map_dump.o
 
 # command
 obj-$(CONFIG_CMD_ARMFFA) += armffa.o
diff --git a/cmd/efi_map_dump.c b/cmd/efi_map_dump.c
new file mode 100644
index 00..f2a5932767
--- /dev/null
+++ b/cmd/efi_map_dump.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Allocate and Free EFI memory
+ *
+ *  Copyright (c) 2024 Linaro Limited
+ */
+
+#include 
+#include 
+
+static int do_efi_map_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+  char *const argv[])
+{
+// printf("%s: argc => %d\n", __func__, argc);
+
+   if (argc != 1)
+   return CMD_RET_USAGE;
+
+   dump_efi_memory_map();
+
+   return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+   efi_map_dump, 1, 0, do_efi_map_dump,
+   "Dump the EFI memory map",
+   ""
+);
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 9600941aa3..40f894f182 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -791,6 +791,8 @@ efi_status_t efi_get_memory_map(efi_uintn_t 
*memory_map_size,
uint32_t *descriptor_version);
 /* Adds a range into the EFI memory map */
 efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type);
+/* Dump the contents of the EFI memory map */
+void dump_efi_memory_map(void);
 /* Adds a conventional range into the EFI memory map */
 efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
 u64 ram_top);
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 93244161b0..7ab1b86140 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -47,6 +47,8 @@ static LIST_HEAD(efi_mem);
 void *efi_bounce_buffer;
 #endif
 
+static uint64_t desc_get_end(struct efi_mem_desc *desc);
+
 /**
  * struct efi_pool_allocation - memory block allocated from pool
  *
@@ -118,6 +120,36 @@ static int lmb_mem_map_update_sync(void *ctx, struct event 
*event)
 EVENT_SPY_FULL(EVT_LMB_MAP_UPDATE, lmb_mem_map_update_sync);
 #endif /* MEM_MAP_UPDATE_NOTIFY */
 
+static void dump_efi_mem_desc(struct efi_mem_desc *desc)
+{
+   u64 end;
+
+   end = desc_get_end(desc);
+
+   printf("---\n");
+   printf("Memory Range   [0x%llx - 0x%llx]\n",
+  desc->physical_start, end);
+   printf("Num Pages  [0x%llx]\n", desc->num_pages);
+   printf("Memory Type[0x%x]\n", desc->type);
+   printf("Attribute  [0x%llx]\n", desc->attribute);
+   printf("---\n");
+}
+
+void dump_efi_memory_map(void)
+{
+   struct list_head *lhandle;
+
+   list_for_each(lhandle, _mem) {
+   struct efi_mem_list *lmem;
+   struct efi_mem_desc *desc;
+
+   lmem = list_entry(lhandle, struct efi_mem_list, link);
+   desc = >desc;
+
+   dump_efi_mem_desc(desc);
+   }
+}
+
 /**
  * checksum() - calculate checksum for memory allocated from pool
  *
-- 
2.34.1



[RFC PATCH 30/31] temp: cmd: efi_mem: add a command to test efi alloc/free

2024-06-07 Thread Sughosh Ganu
Not for committing.

Signed-off-by: Sughosh Ganu 
---
 cmd/Makefile |   1 +
 cmd/efi_memory.c | 155 +++
 2 files changed, 156 insertions(+)
 create mode 100644 cmd/efi_memory.c

diff --git a/cmd/Makefile b/cmd/Makefile
index 87133cc27a..35fcc4af5a 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-y += help.o
 obj-y += panic.o
 obj-y += version.o
+obj-y += efi_memory.o
 
 # command
 obj-$(CONFIG_CMD_ARMFFA) += armffa.o
diff --git a/cmd/efi_memory.c b/cmd/efi_memory.c
new file mode 100644
index 00..52ddcb7146
--- /dev/null
+++ b/cmd/efi_memory.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Allocate and Free EFI memory
+ *
+ *  Copyright (c) 2024 Linaro Limited
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static int do_efi_mem_free(struct cmd_tbl *cmdtp, int flag, int argc,
+  char * const argv[])
+{
+   uint64_t addr = 0, size = 0;
+   efi_uintn_t pages;
+   efi_status_t status;
+
+   if (argc != 3)
+   return CMD_RET_USAGE;
+
+   argc--; argv++;
+
+   size = simple_strtoul(argv[0], NULL, 16);
+   if (!size) {
+   printf("Enter valid size for free in Hex\n");
+   return CMD_RET_USAGE;
+   }
+
+   
+   addr = simple_strtoul(argv[1], NULL, 16);
+   if (!addr) {
+   printf("Enter a valid address in Hex\n");
+   return CMD_RET_USAGE;
+   }
+
+   pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK));
+
+   status = efi_free_pages(addr, pages);
+   if (status != EFI_SUCCESS) {
+   printf("Unable to free memory, error (%#lx)\n", status);
+   return CMD_RET_FAILURE;
+   }
+
+   return CMD_RET_SUCCESS;
+}
+
+static int do_efi_mem_alloc(struct cmd_tbl *cmdtp, int flag, int argc,
+   char * const argv[])
+{
+   enum efi_allocate_type type;
+   uint64_t addr = 0, size = 0;
+   efi_uintn_t pages;
+   efi_status_t status;
+   bool max = false;
+
+   if (argc < 2)
+   return CMD_RET_USAGE;
+
+   argc--; argv++;
+
+   if (!strcmp("max", argv[0])) {
+   if (argc != 3)
+   return CMD_RET_USAGE;
+
+   max = true;
+   argv++;
+   argc--;
+   }
+
+   size = simple_strtoul(argv[0], NULL, 16);
+   if (!size) {
+   printf("Enter valid size for allocation in Hex\n");
+   return CMD_RET_USAGE;
+   }
+
+   if (max || argc == 2) {
+   addr = simple_strtoul(argv[1], NULL, 16);
+   if (!addr) {
+   printf("Enter a valid address in Hex\n");
+   return CMD_RET_USAGE;
+   }
+   }
+
+   if (max)
+   type = EFI_ALLOCATE_MAX_ADDRESS;
+   else if (addr)
+   type = EFI_ALLOCATE_ADDRESS;
+   else
+   type = EFI_ALLOCATE_ANY_PAGES;
+
+   pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK));
+   status = efi_allocate_pages(type, EFI_BOOT_SERVICES_DATA, pages,
+   );
+   if (status != EFI_SUCCESS) {
+   printf("efi_allocate_pages failed %lx\n", status);
+   return CMD_RET_FAILURE;
+   } else {
+   printf("Address returned %#llx\n", addr);
+   }
+
+   return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_efi_mem_sub[] = {
+   U_BOOT_CMD_MKENT(alloc, 3, 0, do_efi_mem_alloc,
+   "", ""),
+   U_BOOT_CMD_MKENT(free, 2, 0, do_efi_mem_free,
+   "", ""),
+};
+
+static int do_efi_mem(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+   struct cmd_tbl *cp;
+   efi_status_t r;
+
+   if (argc < 3)
+   return CMD_RET_USAGE;
+
+   argc--; argv++;
+
+   /* Initialize UEFI subsystem */
+   r = efi_init_obj_list();
+   if (r != EFI_SUCCESS) {
+   printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
+  r & ~EFI_ERROR_MASK);
+   return CMD_RET_FAILURE;
+   }
+
+   cp = find_cmd_tbl(argv[0], cmd_efi_mem_sub,
+ ARRAY_SIZE(cmd_efi_mem_sub));
+   if (!cp)
+   return CMD_RET_USAGE;
+
+   return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_LONGHELP(efi_mem,
+   "Functions to allocate and free memory\n"
+   "\n"
+   "efi_mem alloc  [addr]\n"
+   "efi_mem alloc max  \n"
+   "efi_mem free  \n"
+   "\n"
+);
+
+U_BOOT_CMD(
+   efi_mem, CONFIG_SYS_MAXARGS, 0, do_efi_mem,
+   "Allocate and free EFI memory",
+   efi_mem_help_text
+);
-- 
2.34.1



[RFC PATCH 29/31] temp: mx6sabresd: bump up the size limit of the board

2024-06-07 Thread Sughosh Ganu
With the changes to add notifications for any changes to the LMB map,
the size of the image exceeds the limit set. Bump up the image size
limit for now to get the platform to build.

This is not for committing.

Signed-off-by: Sughosh Ganu 
---
Note: @Fabio Estevam, please check if it would be okay to increase the
board size limit. Else other ways to reduce image size will have to be
checked.

 configs/mx6sabresd_defconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configs/mx6sabresd_defconfig b/configs/mx6sabresd_defconfig
index 868f6b1551..7308ae2ec6 100644
--- a/configs/mx6sabresd_defconfig
+++ b/configs/mx6sabresd_defconfig
@@ -23,7 +23,7 @@ CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_PCI=y
 CONFIG_LTO=y
 CONFIG_HAS_BOARD_SIZE_LIMIT=y
-CONFIG_BOARD_SIZE_LIMIT=715766
+CONFIG_BOARD_SIZE_LIMIT=718108
 CONFIG_FIT=y
 CONFIG_SPL_FIT_PRINT=y
 CONFIG_SPL_LOAD_FIT=y
-- 
2.34.1



[RFC PATCH 28/31] cmd: bdinfo: only dump the current LMB memory

2024-06-07 Thread Sughosh Ganu
The LMB memory map is now persistent and global. There is therefore no
need to add memory to the LMB memory map as part of the bdinfo
command. Only dump the current available and reserved memory as part
of the bdinfo command.

Signed-off-by: Sughosh Ganu 
---
 cmd/bdinfo.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index fc408e9820..0f343203ef 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -163,7 +163,6 @@ static int bdinfo_print_all(struct bd_info *bd)
bdinfo_print_num_l("multi_dtb_fit", (ulong)gd->multi_dtb_fit);
 #endif
if (IS_ENABLED(CONFIG_LMB) && gd->fdt_blob) {
-   lmb_add_memory(gd->bd);
lmb_dump_all_force();
if (IS_ENABLED(CONFIG_OF_REAL))
printf("devicetree  = %s\n", fdtdec_get_srcname());
-- 
2.34.1



[RFC PATCH 27/31] test: bdinfo: dump the global LMB memory map

2024-06-07 Thread Sughosh Ganu
The LMB code has been changed to make the memory reservations
persistent and global. Make corresponding change the the
lmb_test_dump_all() function to print the global LMB added and
reserved memory.

Signed-off-by: Sughosh Ganu 
---
 test/cmd/bdinfo.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c
index 8ba785fc31..2f90c04b70 100644
--- a/test/cmd/bdinfo.c
+++ b/test/cmd/bdinfo.c
@@ -25,6 +25,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+extern struct lmb lmb;
+
 /* Declare a new bdinfo test */
 #define BDINFO_TEST(_name, _flags) UNIT_TEST(_name, _flags, bdinfo_test)
 
@@ -125,11 +127,11 @@ static int lmb_test_dump_region(struct unit_test_state 
*uts,
return 0;
 }
 
-static int lmb_test_dump_all(struct unit_test_state *uts, struct lmb *lmb)
+static int lmb_test_dump_all(struct unit_test_state *uts)
 {
ut_assert_nextline("lmb_dump_all:");
-   ut_assertok(lmb_test_dump_region(uts, >memory, "memory"));
-   ut_assertok(lmb_test_dump_region(uts, >reserved, "reserved"));
+   ut_assertok(lmb_test_dump_region(uts, , "memory"));
+   ut_assertok(lmb_test_dump_region(uts, , "reserved"));
 
return 0;
 }
@@ -191,10 +193,8 @@ static int bdinfo_test_all(struct unit_test_state *uts)
 #endif
 
if (IS_ENABLED(CONFIG_LMB) && gd->fdt_blob) {
-   struct lmb lmb;
-
lmb_add_memory(gd->bd);
-   ut_assertok(lmb_test_dump_all(uts, ));
+   ut_assertok(lmb_test_dump_all(uts));
if (IS_ENABLED(CONFIG_OF_REAL))
ut_assert_nextline("devicetree  = %s", 
fdtdec_get_srcname());
}
-- 
2.34.1



[RFC PATCH 26/31] test: lmb: run lmb tests only manually

2024-06-07 Thread Sughosh Ganu
The LMB code has been changed so that the memory reservations and
allocations are now persistent and global. With this change, the
design of the LMB tests needs to be changed accordingly. For now, mark
the LMB tests to be run only manually. The tests won't be run as part
of the unit test suite, and thus would not interfere with the running
of the rest of the tests.

Signed-off-by: Sughosh Ganu 
---
 test/lib/lmb.c | 49 -
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 67a6be5bc3..813f7e3100 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -195,7 +195,7 @@ static int test_multi_alloc_512mb_x2(struct unit_test_state 
*uts,
 }
 
 /* Create a memory region with one reserved region and allocate */
-static int lib_test_lmb_simple(struct unit_test_state *uts)
+static int lib_test_lmb_simple_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -207,10 +207,10 @@ static int lib_test_lmb_simple(struct unit_test_state 
*uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_multi_alloc_512mb(uts, 0xE000);
 }
-LIB_TEST(lib_test_lmb_simple, 0);
+LIB_TEST(lib_test_lmb_simple_norun, UT_TESTF_MANUAL);
 
 /* Create two memory regions with one reserved region and allocate */
-static int lib_test_lmb_simple_x2(struct unit_test_state *uts)
+static int lib_test_lmb_simple_x2_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -222,7 +222,7 @@ static int lib_test_lmb_simple_x2(struct unit_test_state 
*uts)
/* simulate 512 MiB RAM beginning at 3.5GiB and 1 GiB */
return test_multi_alloc_512mb_x2(uts, 0xE000, 0x4000);
 }
-LIB_TEST(lib_test_lmb_simple_x2, 0);
+LIB_TEST(lib_test_lmb_simple_x2_norun, UT_TESTF_MANUAL);
 
 /* Simulate 512 MiB RAM, allocate some blocks that fit/don't fit */
 static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram)
@@ -275,7 +275,7 @@ static int test_bigblock(struct unit_test_state *uts, const 
phys_addr_t ram)
return 0;
 }
 
-static int lib_test_lmb_big(struct unit_test_state *uts)
+static int lib_test_lmb_big_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -287,7 +287,7 @@ static int lib_test_lmb_big(struct unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_bigblock(uts, 0xE000);
 }
-LIB_TEST(lib_test_lmb_big, 0);
+LIB_TEST(lib_test_lmb_big_norun, UT_TESTF_MANUAL);
 
 /* Simulate 512 MiB RAM, allocate a block without previous reservation */
 static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram,
@@ -348,7 +348,7 @@ static int test_noreserved(struct unit_test_state *uts, 
const phys_addr_t ram,
return 0;
 }
 
-static int lib_test_lmb_noreserved(struct unit_test_state *uts)
+static int lib_test_lmb_noreserved_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -360,10 +360,9 @@ static int lib_test_lmb_noreserved(struct unit_test_state 
*uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_noreserved(uts, 0xE000, 4, 1);
 }
+LIB_TEST(lib_test_lmb_noreserved_norun, UT_TESTF_MANUAL);
 
-LIB_TEST(lib_test_lmb_noreserved, 0);
-
-static int lib_test_lmb_unaligned_size(struct unit_test_state *uts)
+static int lib_test_lmb_unaligned_size_norun(struct unit_test_state *uts)
 {
int ret;
 
@@ -375,13 +374,13 @@ static int lib_test_lmb_unaligned_size(struct 
unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_noreserved(uts, 0xE000, 5, 8);
 }
-LIB_TEST(lib_test_lmb_unaligned_size, 0);
+LIB_TEST(lib_test_lmb_unaligned_size_norun, UT_TESTF_MANUAL);
 
 /*
  * Simulate a RAM that starts at 0 and allocate down to address 0, which must
  * fail as '0' means failure for the lmb_alloc functions.
  */
-static int lib_test_lmb_at_0(struct unit_test_state *uts)
+static int lib_test_lmb_at_0_norun(struct unit_test_state *uts)
 {
const phys_addr_t ram = 0;
const phys_size_t ram_size = 0x2000;
@@ -417,9 +416,9 @@ static int lib_test_lmb_at_0(struct unit_test_state *uts)
 
return 0;
 }
-LIB_TEST(lib_test_lmb_at_0, 0);
+LIB_TEST(lib_test_lmb_at_0_norun, UT_TESTF_MANUAL);
 
-static int lib_test_lmb_overlapping_add(struct unit_test_state *uts)
+static int lib_test_lmb_overlapping_add_norun(struct unit_test_state *uts)
 {
const phys_addr_t ram = 0x4000;
const phys_size_t ram_size = 0x2000;
@@ -433,10 +432,10 @@ static int lib_test_lmb_overlapping_add(struct 
unit_test_state *uts)
 
return 0;
 }
-LIB_TEST(lib_test_lmb_overlapping_add, 0);
+LIB_TEST(lib_test_lmb_overlapping_add_norun, UT_TESTF_MANUAL);
 
 /* Check that calling lmb_reserve with overlapping regions fails. */
-static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
+static int lib_test_lmb_overlapping_reserve_norun(struct unit_test_state *uts)
 {
const phys_addr_t ram = 0x4000;
const

[RFC PATCH 25/31] test: lmb: adjust the test case to handle overlapping regions

2024-06-07 Thread Sughosh Ganu
The LMB code can now accept reserving and adding overlapping regions
of memory. Adjust the test for checking the reservation of overlapping
memory regions to work with this corresponding change in the LMB code.

Signed-off-by: Sughosh Ganu 
---
 test/lib/lmb.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 9b0e023b67..67a6be5bc3 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -451,15 +451,15 @@ static int lib_test_lmb_overlapping_reserve(struct 
unit_test_state *uts)
ut_asserteq(ret, 0);
ASSERT_LMB(, ram, ram_size, 1, 0x4001, 0x1,
   0, 0, 0, 0);
-   /* allocate overlapping region should fail */
+   /* allocate overlapping region should return the coalesced count */
ret = lmb_reserve(0x40011000, 0x1);
-   ut_asserteq(ret, -1);
-   ASSERT_LMB(, ram, ram_size, 1, 0x4001, 0x1,
+   ut_asserteq(ret, 1);
+   ASSERT_LMB(, ram, ram_size, 1, 0x4001, 0x11000,
   0, 0, 0, 0);
/* allocate 3nd region */
ret = lmb_reserve(0x4003, 0x1);
ut_asserteq(ret, 0);
-   ASSERT_LMB(, ram, ram_size, 2, 0x4001, 0x1,
+   ASSERT_LMB(, ram, ram_size, 2, 0x4001, 0x11000,
   0x4003, 0x1, 0, 0);
/* allocate 2nd region , This should coalesced all region into one */
ret = lmb_reserve(0x4002, 0x1);
-- 
2.34.1



[RFC PATCH 24/31] test: lmb: add a test case for checking overlapping region add

2024-06-07 Thread Sughosh Ganu
Memory managed by LMB is now persistent and global. With that, it
could be possible for multiple callers to try to add memory that has
already been added. Add a test case to check that the LMB module
handles it as expected.

Signed-off-by: Sughosh Ganu 
---
 test/lib/lmb.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 260ebcfcd3..9b0e023b67 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -419,6 +419,22 @@ static int lib_test_lmb_at_0(struct unit_test_state *uts)
 }
 LIB_TEST(lib_test_lmb_at_0, 0);
 
+static int lib_test_lmb_overlapping_add(struct unit_test_state *uts)
+{
+   const phys_addr_t ram = 0x4000;
+   const phys_size_t ram_size = 0x2000;
+   long ret;
+
+   ret = lmb_add(ram, ram_size);
+   ut_asserteq(ret, 0);
+
+   ret = lmb_add(ram, ram_size);
+   ut_asserteq(ret, 0);
+
+   return 0;
+}
+LIB_TEST(lib_test_lmb_overlapping_add, 0);
+
 /* Check that calling lmb_reserve with overlapping regions fails. */
 static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
 {
-- 
2.34.1



[RFC PATCH 23/31] test: lmb: initialise the lmb structure before tests

2024-06-07 Thread Sughosh Ganu
The LMB allocations are now persistent and global, and with that all
the local instances of the structure variable have been removed. Every
LMB test cases that are run require a clean slate of the structure --
facilitate that by adding an initialisation function which gets called
at the start of every test.

Signed-off-by: Sughosh Ganu 
---
 include/lmb.h  |  4 
 lib/lmb.c  | 17 +
 test/lib/lmb.c | 18 ++
 3 files changed, 39 insertions(+)

diff --git a/include/lmb.h b/include/lmb.h
index 1d4cd255d2..08ece0a90b 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -148,6 +148,10 @@ void arch_lmb_reserve_generic(ulong sp, ulong end, ulong 
align);
  */
 void lmb_reserve_common(void *fdt_blob);
 
+#if defined(CONFIG_SANDBOX)
+void lmb_init(void);
+#endif /* CONFIG_SANDBOX */
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_LMB_H */
diff --git a/lib/lmb.c b/lib/lmb.c
index c9f6ca692e..2798ce0989 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -718,3 +718,20 @@ static int efi_mem_map_update_sync(void *ctx, struct event 
*event)
 }
 EVENT_SPY_FULL(EVT_EFI_MEM_MAP_UPDATE, efi_mem_map_update_sync);
 #endif /* MEM_MAP_UPDATE_NOTIFY */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+void lmb_init(void)
+{
+#if IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
+   lmb.memory.max = CONFIG_LMB_MAX_REGIONS;
+   lmb.reserved.max = CONFIG_LMB_MAX_REGIONS;
+#else
+   lmb.memory.max = CONFIG_LMB_MEMORY_REGIONS;
+   lmb.reserved.max = CONFIG_LMB_RESERVED_REGIONS;
+   lmb.memory.region = memory_regions;
+   lmb.reserved.region = reserved_regions;
+#endif
+   lmb.memory.cnt = 0;
+   lmb.reserved.cnt = 0;
+}
+#endif /* SANDBOX */
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index ace1ddf4e4..260ebcfcd3 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -77,6 +77,8 @@ static int test_multi_alloc(struct unit_test_state *uts, 
const phys_addr_t ram,
ut_assert(alloc_64k_addr >= ram + 8);
ut_assert(alloc_64k_end <= ram_end - 8);
 
+   lmb_init();
+
if (ram0_size) {
ret = lmb_add(ram0, ram0_size);
ut_asserteq(ret, 0);
@@ -235,6 +237,8 @@ static int test_bigblock(struct unit_test_state *uts, const 
phys_addr_t ram)
/* check for overflow */
ut_assert(ram_end == 0 || ram_end > ram);
 
+   lmb_init();
+
ret = lmb_add(ram, ram_size);
ut_asserteq(ret, 0);
 
@@ -299,6 +303,8 @@ static int test_noreserved(struct unit_test_state *uts, 
const phys_addr_t ram,
/* check for overflow */
ut_assert(ram_end == 0 || ram_end > ram);
 
+   lmb_init();
+
ret = lmb_add(ram, ram_size);
ut_asserteq(ret, 0);
ASSERT_LMB(, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
@@ -382,6 +388,8 @@ static int lib_test_lmb_at_0(struct unit_test_state *uts)
long ret;
phys_addr_t a, b;
 
+   lmb_init();
+
ret = lmb_add(ram, ram_size);
ut_asserteq(ret, 0);
 
@@ -418,6 +426,8 @@ static int lib_test_lmb_overlapping_reserve(struct 
unit_test_state *uts)
const phys_size_t ram_size = 0x2000;
long ret;
 
+   lmb_init();
+
ret = lmb_add(ram, ram_size);
ut_asserteq(ret, 0);
 
@@ -473,6 +483,8 @@ static int test_alloc_addr(struct unit_test_state *uts, 
const phys_addr_t ram)
/* check for overflow */
ut_assert(ram_end == 0 || ram_end > ram);
 
+   lmb_init();
+
ret = lmb_add(ram, ram_size);
ut_asserteq(ret, 0);
 
@@ -597,6 +609,8 @@ static int test_get_unreserved_size(struct unit_test_state 
*uts,
/* check for overflow */
ut_assert(ram_end == 0 || ram_end > ram);
 
+   lmb_init();
+
ret = lmb_add(ram, ram_size);
ut_asserteq(ret, 0);
 
@@ -664,6 +678,8 @@ static int lib_test_lmb_max_regions(struct unit_test_state 
*uts)
phys_addr_t offset;
int ret, i;
 
+   lmb_init();
+
ut_asserteq(lmb.memory.cnt, 0);
ut_asserteq(lmb.memory.max, CONFIG_LMB_MAX_REGIONS);
ut_asserteq(lmb.reserved.cnt, 0);
@@ -722,6 +738,8 @@ static int lib_test_lmb_flags(struct unit_test_state *uts)
const phys_size_t ram_size = 0x2000;
long ret;
 
+   lmb_init();
+
ret = lmb_add(ram, ram_size);
ut_asserteq(ret, 0);
 
-- 
2.34.1



[RFC PATCH 22/31] test: lmb: run the LMB tests only on sandbox

2024-06-07 Thread Sughosh Ganu
The LMB memory map is now persistent and global. Running the tests for
the LMB module will result in the memory map getting reset, and this
will have side-effects on the rest of the working of the platform. Run
the LMB tests only on the sandbox platform, which is meant for running
such kinds of tests.

Signed-off-by: Sughosh Ganu 
---
 test/lib/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/lib/Makefile b/test/lib/Makefile
index e75a263e6a..9154e07993 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_EFI_LOADER) += efi_device_path.o
 obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
 obj-y += hexdump.o
 obj-$(CONFIG_SANDBOX) += kconfig.o
-obj-y += lmb.o
+obj-$(CONFIG_SANDBOX) += lmb.o
 obj-y += longjmp.o
 obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
 obj-$(CONFIG_SSCANF) += sscanf.o
-- 
2.34.1



[RFC PATCH 21/31] test: event: update the expected event dump output

2024-06-07 Thread Sughosh Ganu
With the addition of two events for notification of any changes to
memory that is occupied and is free, the output of the event_dump.py
script has changed. Update the expected event log to incorporate this
change.

Signed-off-by: Sughosh Ganu 
---
 test/py/tests/test_event_dump.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py
index e282c67335..b14e098895 100644
--- a/test/py/tests/test_event_dump.py
+++ b/test/py/tests/test_event_dump.py
@@ -16,9 +16,11 @@ def test_event_dump(u_boot_console):
 out = util.run_and_log(cons, ['scripts/event_dump.py', sandbox])
 expect = '''.*Event typeId  Source 
location
   --  
--
+EVT_EFI_MEM_MAP_UPDATE  efi_mem_map_update_sync   .*lib/lmb.c:.*
 EVT_FT_FIXUP  bootmeth_vbe_ft_fixup   .*boot/vbe_request.c:.*
 EVT_FT_FIXUP  bootmeth_vbe_simple_ft_fixup.*boot/vbe_simple_os.c:.*
 EVT_LAST_STAGE_INIT   install_smbios_table
.*lib/efi_loader/efi_smbios.c:.*
+EVT_LMB_MAP_UPDATElmb_mem_map_update_sync 
.*lib/efi_loader/efi_memory.c:.*
 EVT_MISC_INIT_F   sandbox_early_getopt_check  
.*arch/sandbox/cpu/start.c:.*
 EVT_TEST  h_adder_simple  .*test/common/event.c:'''
 assert re.match(expect, out, re.MULTILINE) is not None
-- 
2.34.1



[RFC PATCH 20/31] test: cedit: use allocated address for reading file

2024-06-07 Thread Sughosh Ganu
Instead of a randomly selected address, use an LMB allocated one for
reading the file into memory. With the LMB map now being persistent
and global, the address used for reading the file might be already
allocated as non-overwritable, resulting in a failure. Get a valid
address from LMB and then read the file to that address.

Signed-off-by: Sughosh Ganu 
---
 test/boot/cedit.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index aa41719048..1f4147da89 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -62,7 +63,7 @@ static int cedit_fdt(struct unit_test_state *uts)
struct video_priv *vid_priv;
extern struct expo *cur_exp;
struct scene_obj_menu *menu;
-   ulong addr = 0x1000;
+   ulong addr;
struct ofprop prop;
struct scene *scn;
oftree tree;
@@ -87,6 +88,8 @@ static int cedit_fdt(struct unit_test_state *uts)
str = abuf_data(>buf);
strcpy(str, "my-machine");
 
+   addr = lmb_alloc(1024, 1024);
+   ut_asserteq(!!addr, !0);
ut_assertok(run_command("cedit write_fdt hostfs - settings.dtb", 0));
ut_assertok(run_commandf("load hostfs - %lx settings.dtb", addr));
ut_assert_nextlinen("1024 bytes read");
-- 
2.34.1



[RFC PATCH 19/31] zynq: lmb: do not add to lmb map before relocation

2024-06-07 Thread Sughosh Ganu
The LMB memory is typically not needed very early in the platform's
boot. Do not add memory to the LMB map before relocation. Reservation
of common areas and adding of memory is done after relocation.

Signed-off-by: Sughosh Ganu 
---
 board/xilinx/common/board.c | 31 ---
 1 file changed, 31 deletions(-)

diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 7be1b6e511..38967fc705 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -13,7 +13,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -666,36 +665,6 @@ int embedded_dtb_select(void)
 }
 #endif
 
-#if defined(CONFIG_LMB)
-
-#ifndef MMU_SECTION_SIZE
-#define MMU_SECTION_SIZE(1 * 1024 * 1024)
-#endif
-
-phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
-{
-   phys_size_t size;
-   phys_addr_t reg;
-
-   if (!total_size)
-   return gd->ram_top;
-
-   if (!IS_ALIGNED((ulong)gd->fdt_blob, 0x8))
-   panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob);
-
-   /* found enough not-reserved memory to relocated U-Boot */
-   lmb_add(gd->ram_base, gd->ram_size);
-   boot_fdt_add_mem_rsv_regions((void *)gd->fdt_blob);
-   size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE);
-   reg = lmb_alloc(size, MMU_SECTION_SIZE);
-
-   if (!reg)
-   reg = gd->ram_top - size;
-
-   return reg + size;
-}
-#endif
-
 #ifdef CONFIG_OF_BOARD_SETUP
 #define MAX_RAND_SIZE 8
 int ft_board_setup(void *blob, struct bd_info *bd)
-- 
2.34.1



[RFC PATCH 18/31] sandbox: iommu: remove lmb allocation in the driver

2024-06-07 Thread Sughosh Ganu
The sandbox iommu driver uses the LMB module to allocate a particular
range of memory for the device virtual address(DVA). This used to work
earlier since the LMB memory map was caller specific and not
global. But with the change to make the LMB allocations global and
persistent, adding this memory range has other side effects. On the
other hand, the sandbox iommu test expects to see this particular
value of the DVA. Use the DVA address directly, instead of mapping it
in the LMB memory map, and then have it allocated.

Signed-off-by: Sughosh Ganu 
---
 drivers/iommu/sandbox_iommu.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/sandbox_iommu.c b/drivers/iommu/sandbox_iommu.c
index c5bb88d299..67293e20f4 100644
--- a/drivers/iommu/sandbox_iommu.c
+++ b/drivers/iommu/sandbox_iommu.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 
+#define DVA_ADDR   0x89abc000
 #define IOMMU_PAGE_SIZESZ_4K
 
 static dma_addr_t sandbox_iommu_map(struct udevice *dev, void *addr,
@@ -22,7 +23,7 @@ static dma_addr_t sandbox_iommu_map(struct udevice *dev, void 
*addr,
off = virt_to_phys(addr) - paddr;
psize = ALIGN(size + off, IOMMU_PAGE_SIZE);
 
-   dva = lmb_alloc(psize, IOMMU_PAGE_SIZE);
+   dva = (phys_addr_t)DVA_ADDR;
 
return dva + off;
 }
@@ -36,8 +37,6 @@ static void sandbox_iommu_unmap(struct udevice *dev, 
dma_addr_t addr,
dva = ALIGN_DOWN(addr, IOMMU_PAGE_SIZE);
psize = size + (addr - dva);
psize = ALIGN(psize, IOMMU_PAGE_SIZE);
-
-   lmb_free(dva, psize);
 }
 
 static struct iommu_ops sandbox_iommu_ops = {
@@ -47,8 +46,6 @@ static struct iommu_ops sandbox_iommu_ops = {
 
 static int sandbox_iommu_probe(struct udevice *dev)
 {
-   lmb_add(0x89abc000, SZ_16K);
-
return 0;
 }
 
-- 
2.34.1



[RFC PATCH 17/31] lmb: remove call to efi_lmb_reserve()

2024-06-07 Thread Sughosh Ganu
The changes in the EFI memory map are now notified to the LMB
module. There is therefore no need to explicitly get the efi memory
map and set aside the EFI allocated memory.

Signed-off-by: Sughosh Ganu 
---
 lib/lmb.c | 35 ---
 1 file changed, 35 deletions(-)

diff --git a/lib/lmb.c b/lib/lmb.c
index 3059609aea..c9f6ca692e 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -204,38 +204,6 @@ void arch_lmb_reserve_generic(ulong sp, ulong end, ulong 
align)
}
 }
 
-/**
- * efi_lmb_reserve() - add reservations for EFI memory
- *
- * Add reservations for all EFI memory areas that are not
- * EFI_CONVENTIONAL_MEMORY.
- *
- * Return: 0 on success, 1 on failure
- */
-static __maybe_unused int efi_lmb_reserve(void)
-{
-   struct efi_mem_desc *memmap = NULL, *map;
-   efi_uintn_t i, map_size = 0;
-   efi_status_t ret;
-
-   ret = efi_get_memory_map_alloc(_size, );
-   if (ret != EFI_SUCCESS)
-   return 1;
-
-   for (i = 0, map = memmap; i < map_size / sizeof(*map); ++map, ++i) {
-   if (map->type != EFI_CONVENTIONAL_MEMORY) {
-   lmb_reserve_flags(map_to_sysmem((void *)(uintptr_t)
-   map->physical_start),
- map->num_pages * EFI_PAGE_SIZE,
- map->type == EFI_RESERVED_MEMORY_TYPE
- ? LMB_NOMAP : LMB_NONE);
-   }
-   }
-   efi_free_pool(memmap);
-
-   return 0;
-}
-
 /**
  * lmb_reserve_common() - Reserve memory region occupied by U-Boot image
  * @fdt_blob: pointer to the FDT blob
@@ -255,9 +223,6 @@ void lmb_reserve_common(void *fdt_blob)
 
if (CONFIG_IS_ENABLED(OF_LIBFDT) && fdt_blob)
boot_fdt_add_mem_rsv_regions(fdt_blob);
-
-   if (CONFIG_IS_ENABLED(EFI_LOADER))
-   efi_lmb_reserve();
 }
 
 /**
-- 
2.34.1



[RFC PATCH 16/31] lmb: add an event handler to update memory map

2024-06-07 Thread Sughosh Ganu
There are events that would be used to notify other interested modules
of any changes in available and occupied memory. This would happen
when a module allocates or reserves memory, or frees up memory. These
changes in memory map should be notified to other interested modules
so that the allocated memory does not get overwritten. Add an event
handler in the LMB module to update it's memory map accordingly when
such changes happen. As a consequence, any subsequent memory request
would honour the updated memory map and allocations would only happen
from available memory.

Signed-off-by: Sughosh Ganu 
---
 lib/Kconfig |  1 +
 lib/lmb.c   | 34 ++
 2 files changed, 35 insertions(+)

diff --git a/lib/Kconfig b/lib/Kconfig
index 9ea02ae006..9e465a748b 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -,6 +,7 @@ config LMB
bool "Enable the logical memory blocks library (lmb)"
default y if ARC || ARM || M68K || MICROBLAZE || MIPS || \
 NIOS2 || PPC || RISCV || SANDBOX || SH || X86 || XTENSA
+   select EVENT
help
  Support the library logical memory blocks.
 
diff --git a/lib/lmb.c b/lib/lmb.c
index 313735dbe3..3059609aea 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -16,6 +16,7 @@
 
 #include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -719,3 +720,36 @@ __weak void arch_lmb_reserve(void)
 {
/* please define platform specific arch_lmb_reserve() */
 }
+
+#if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
+static long lmb_reserve_nooverwrite(phys_addr_t base, phys_size_t size)
+{
+   struct lmb_region *_rgn = 
+
+   return lmb_add_region_flags(_rgn, base, size, LMB_NOOVERWRITE);
+}
+
+static int efi_mem_map_update_sync(void *ctx, struct event *event)
+{
+   u8 op;
+   long ret;
+   phys_addr_t addr;
+   phys_size_t size;
+   struct event_efi_mem_map_update *efi_map = >data.efi_mem_map;
+
+   addr = virt_to_phys((void *)(uintptr_t)efi_map->base);
+   size = efi_map->size;
+   op = efi_map->op;
+
+   if (op != MAP_OP_RESERVE && op != MAP_OP_FREE) {
+   log_debug("Invalid map update op received (%d)\n", op);
+   return -1;
+   }
+
+   ret = op == MAP_OP_RESERVE ? lmb_reserve_nooverwrite(addr, size) :
+   __lmb_free(addr, size);
+
+   return !ret ? 0 : -1;
+}
+EVENT_SPY_FULL(EVT_EFI_MEM_MAP_UPDATE, efi_mem_map_update_sync);
+#endif /* MEM_MAP_UPDATE_NOTIFY */
-- 
2.34.1



[RFC PATCH 15/31] efi_memory: add an event handler to update memory map

2024-06-07 Thread Sughosh Ganu
There are events that would be used to notify other interested modules
of any changes in available and occupied memory. This would happen
when a module allocates or reserves memory, or frees up memory. These
changes in memory map should be notified to other interested modules
so that the allocated memory does not get overwritten. Add an event
handler in the EFI memory module to update the EFI memory map
accordingly when such changes happen. As a consequence, any subsequent
memory request would honour the updated memory map and only available
memory would be allocated from.

Signed-off-by: Sughosh Ganu 
---
 lib/efi_loader/efi_memory.c | 70 ++---
 1 file changed, 58 insertions(+), 12 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 435e580fb3..93244161b0 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -73,6 +73,10 @@ struct efi_pool_allocation {
 #if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
 extern bool is_addr_in_ram(uintptr_t addr);
 
+static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
+   int memory_type,
+   bool overlap_only_ram);
+
 static void efi_map_update_notify(u64 addr, u64 size, u8 op)
 {
struct event_efi_mem_map_update efi_map = {0};
@@ -84,6 +88,34 @@ static void efi_map_update_notify(u64 addr, u64 size, u8 op)
if (is_addr_in_ram((uintptr_t)addr))
event_notify(EVT_EFI_MEM_MAP_UPDATE, _map, sizeof(efi_map));
 }
+
+static int lmb_mem_map_update_sync(void *ctx, struct event *event)
+{
+   u8 op;
+   u64 addr;
+   u64 pages;
+   efi_status_t status;
+   struct event_lmb_map_update *lmb_map = >data.lmb_map;
+
+   addr = (uintptr_t)map_sysmem(lmb_map->base, 0);
+   pages = efi_size_in_pages(lmb_map->size + (addr & EFI_PAGE_MASK));
+   op = lmb_map->op;
+   addr &= ~EFI_PAGE_MASK;
+
+   if (op != MAP_OP_RESERVE && op != MAP_OP_FREE) {
+   log_debug("Invalid map update op received (%d)\n", op);
+   return -1;
+   }
+
+   status = __efi_add_memory_map_pg(addr, pages,
+op == MAP_OP_FREE ?
+EFI_CONVENTIONAL_MEMORY :
+EFI_BOOT_SERVICES_DATA,
+true);
+
+   return status == EFI_SUCCESS ? 0 : -1;
+}
+EVENT_SPY_FULL(EVT_LMB_MAP_UPDATE, lmb_mem_map_update_sync);
 #endif /* MEM_MAP_UPDATE_NOTIFY */
 
 /**
@@ -275,18 +307,9 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map,
return EFI_CARVE_LOOP_AGAIN;
 }
 
-/**
- * efi_add_memory_map_pg() - add pages to the memory map
- *
- * @start: start address, must be a multiple of EFI_PAGE_SIZE
- * @pages: number of pages to add
- * @memory_type:   type of memory added
- * @overlap_only_ram:  region may only overlap RAM
- * Return: status code
- */
-static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
- int memory_type,
- bool overlap_only_ram)
+static efi_status_t __efi_add_memory_map_pg(u64 start, u64 pages,
+   int memory_type,
+   bool overlap_only_ram)
 {
struct list_head *lhandle;
struct efi_mem_list *newlist;
@@ -395,6 +418,29 @@ static efi_status_t efi_add_memory_map_pg(u64 start, u64 
pages,
}
}
 
+   return EFI_SUCCESS;
+}
+
+/**
+ * efi_add_memory_map_pg() - add pages to the memory map
+ *
+ * @start: start address, must be a multiple of EFI_PAGE_SIZE
+ * @pages: number of pages to add
+ * @memory_type:   type of memory added
+ * @overlap_only_ram:  region may only overlap RAM
+ * Return: status code
+ */
+static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
+ int memory_type,
+ bool overlap_only_ram)
+{
+   efi_status_t status;
+
+   status = __efi_add_memory_map_pg(start, pages, memory_type,
+overlap_only_ram);
+   if (status != EFI_SUCCESS)
+   return status;
+
if (CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY))
efi_map_update_notify(start, pages << EFI_PAGE_SHIFT,
  memory_type == EFI_CONVENTIONAL_MEMORY ?
-- 
2.34.1



[RFC PATCH 14/31] lmb: notify of any changes to the LMB memory map

2024-06-07 Thread Sughosh Ganu
In U-Boot, LMB and EFI are two primary modules who provide memory
allocation and reservation API's. Both these modules operate with the
same regions of memory for allocations. Use the LMB memory map update
event to notify other interested listeners about a change in it's
memory map. This can then be used by the other module to allocate
memory only from available regions, instead of overwriting already
allocated memory.

Signed-off-by: Sughosh Ganu 
---
 lib/lmb.c | 49 +++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/lib/lmb.c b/lib/lmb.c
index 0a4f3d5bcd..313735dbe3 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -7,6 +7,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -18,8 +19,13 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define MAP_OP_RESERVE (u8)0x1
+#define MAP_OP_FREE(u8)0x2
+
 #define LMB_ALLOC_ANYWHERE 0
 
+extern bool is_addr_in_ram(uintptr_t addr);
+
 #if !IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
 struct lmb_property memory_regions[CONFIG_LMB_MEMORY_REGIONS];
 struct lmb_property reserved_regions[CONFIG_LMB_RESERVED_REGIONS];
@@ -39,6 +45,19 @@ struct lmb lmb = {
.reserved.cnt = 0,
 };
 
+static void lmb_map_update_notify(phys_addr_t addr, phys_size_t size,
+ u8 op)
+{
+   struct event_lmb_map_update lmb_map = {0};
+
+   lmb_map.base = addr;
+   lmb_map.size = size;
+   lmb_map.op = op;
+
+   if (is_addr_in_ram((uintptr_t)addr))
+   event_notify(EVT_LMB_MAP_UPDATE, _map, sizeof(lmb_map));
+}
+
 static void lmb_dump_region(struct lmb_region *rgn, char *name)
 {
unsigned long long base, size, end;
@@ -450,7 +469,7 @@ long lmb_add(phys_addr_t base, phys_size_t size)
return lmb_add_region(_rgn, base, size);
 }
 
-long lmb_free(phys_addr_t base, phys_size_t size)
+static long __lmb_free(phys_addr_t base, phys_size_t size)
 {
struct lmb_region *rgn = 
phys_addr_t rgnbegin, rgnend;
@@ -500,11 +519,33 @@ long lmb_free(phys_addr_t base, phys_size_t size)
rgn->region[i].flags);
 }
 
+long lmb_free(phys_addr_t base, phys_size_t size)
+{
+   long ret;
+
+   ret = __lmb_free(base, size);
+   if (ret < 0)
+   return ret;
+
+   if (CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY))
+   lmb_map_update_notify(base, size, MAP_OP_FREE);
+
+   return 0;
+}
+
 long lmb_reserve_flags(phys_addr_t base, phys_size_t size, enum lmb_flags 
flags)
 {
+   long ret = 0;
struct lmb_region *_rgn = 
 
-   return lmb_add_region_flags(_rgn, base, size, flags);
+   ret = lmb_add_region_flags(_rgn, base, size, flags);
+   if (ret < 0)
+   return -1;
+
+   if (CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY))
+   lmb_map_update_notify(base, size, MAP_OP_RESERVE);
+
+   return ret;
 }
 
 long lmb_reserve(phys_addr_t base, phys_size_t size)
@@ -563,6 +604,10 @@ static phys_addr_t __lmb_alloc_base(phys_size_t size, 
ulong align,
if (lmb_add_region(, base,
   size) < 0)
return 0;
+
+   if (CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY))
+   lmb_map_update_notify(base, size,
+ MAP_OP_RESERVE);
return base;
}
res_base = lmb.reserved.region[rgn].base;
-- 
2.34.1



[RFC PATCH 13/31] efi_memory: notify of any changes to the EFI memory map

2024-06-07 Thread Sughosh Ganu
In U-Boot, LMB and EFI are two primary modules who provide memory
allocation and reservation API's. Both these modules operate with the
same regions of memory for allocations. Use the EFI memory map update
event to notify other interested listeners about a change in the EFI
memory map. This can then be used by the other module to allocate
memory only from available regions, instead of overwriting already
allocated memory.

Signed-off-by: Sughosh Ganu 
---
 lib/efi_loader/efi_memory.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 12cf23fa3f..435e580fb3 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -8,6 +8,7 @@
 #define LOG_CATEGORY LOGC_EFI
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -36,6 +37,9 @@ struct efi_mem_list {
 #define EFI_CARVE_OVERLAPS_NONRAM  -3
 #define EFI_CARVE_OUT_OF_RESOURCES -4
 
+#define MAP_OP_RESERVE (u8)0x1
+#define MAP_OP_FREE(u8)0x2
+
 /* This list contains all memory map items */
 static LIST_HEAD(efi_mem);
 
@@ -66,6 +70,22 @@ struct efi_pool_allocation {
char data[] __aligned(ARCH_DMA_MINALIGN);
 };
 
+#if CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY)
+extern bool is_addr_in_ram(uintptr_t addr);
+
+static void efi_map_update_notify(u64 addr, u64 size, u8 op)
+{
+   struct event_efi_mem_map_update efi_map = {0};
+
+   efi_map.base = addr;
+   efi_map.size = size;
+   efi_map.op = op;
+
+   if (is_addr_in_ram((uintptr_t)addr))
+   event_notify(EVT_EFI_MEM_MAP_UPDATE, _map, sizeof(efi_map));
+}
+#endif /* MEM_MAP_UPDATE_NOTIFY */
+
 /**
  * checksum() - calculate checksum for memory allocated from pool
  *
@@ -375,6 +395,11 @@ static efi_status_t efi_add_memory_map_pg(u64 start, u64 
pages,
}
}
 
+   if (CONFIG_IS_ENABLED(MEM_MAP_UPDATE_NOTIFY))
+   efi_map_update_notify(start, pages << EFI_PAGE_SHIFT,
+ memory_type == EFI_CONVENTIONAL_MEMORY ?
+ MAP_OP_FREE : MAP_OP_RESERVE);
+
return EFI_SUCCESS;
 }
 
-- 
2.34.1



[RFC PATCH 12/31] add a function to check if an address is in RAM memory

2024-06-07 Thread Sughosh Ganu
Add a function to check if a given address falls within the RAM
address used by U-Boot. This will be used to notify other modules if
the address gets allocated, so as to not get re-allocated by some
other module.

Signed-off-by: Sughosh Ganu 
---
 arch/sandbox/cpu/cpu.c | 5 +
 common/board_r.c   | 5 +
 2 files changed, 10 insertions(+)

diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index 0ed85b354c..d7a0176497 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -413,3 +413,8 @@ int sandbox_load_other_fdt(void **fdtp, int *sizep)
 
return 0;
 }
+
+bool __maybe_unused is_addr_in_ram(uintptr_t addr)
+{
+   return is_in_sandbox_mem((const void *)addr);
+}
diff --git a/common/board_r.c b/common/board_r.c
index a9f0b0cec1..aabc0cdf26 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -72,6 +72,11 @@ DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
 
+__weak bool __maybe_unused is_addr_in_ram(uintptr_t addr)
+{
+   return addr >= gd->ram_base && addr <= gd->ram_top;
+}
+
 __weak int board_flash_wp_on(void)
 {
/*
-- 
2.34.1



[RFC PATCH 11/31] lib: Kconfig: add a config symbol for getting memory map updates

2024-06-07 Thread Sughosh Ganu
Add a Kconfig symbol to enable getting updates on any memory map
changes that might be done by some other module. This notification
mechanism can then be used to have a synchronous view of allocated and
free memory.

Signed-off-by: Sughosh Ganu 
---
 lib/Kconfig | 9 +
 1 file changed, 9 insertions(+)

diff --git a/lib/Kconfig b/lib/Kconfig
index 189e6eb31a..9ea02ae006 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -74,6 +74,15 @@ config HAVE_PRIVATE_LIBGCC
 config LIB_UUID
bool
 
+config MEM_MAP_UPDATE_NOTIFY
+   bool "Get notified of any changes to the memory map"
+   default y if EVENT && LMB && EFI_LOADER
+   help
+ Enable this option to get notification on any changes to the
+ memory that is allocated or freed. This will allow different
+ modules that allocate memory to have a synchronous view of available
+ and allocated memory.
+
 config RANDOM_UUID
bool "GPT Random UUID generation"
select LIB_UUID
-- 
2.34.1



[RFC PATCH 10/31] event: add events to notify memory map changes

2024-06-07 Thread Sughosh Ganu
Add events which would be used for notifying changes in the respective
modules' memory map. This is to be used for having a synchronous view
of the memory that is currently in use, and that is available for
allocations.

Signed-off-by: Sughosh Ganu 
---
 common/event.c  |  4 
 include/event.h | 28 
 2 files changed, 32 insertions(+)

diff --git a/common/event.c b/common/event.c
index 16c2ba6cc9..067ee9ee4e 100644
--- a/common/event.c
+++ b/common/event.c
@@ -48,6 +48,10 @@ const char *const type_name[] = {
 
/* main loop events */
"main_loop",
+
+   "lmb_map_update",
+
+   "efi_map_update",
 };
 
 _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
diff --git a/include/event.h b/include/event.h
index fb353ad623..9d8be7a103 100644
--- a/include/event.h
+++ b/include/event.h
@@ -153,6 +153,22 @@ enum event_t {
 */
EVT_MAIN_LOOP,
 
+   /**
+* @EVT_LMB_MAP_UPDATE:
+* This event is triggered on an update to the LMB reserved memory
+* region. This can be used to notify about any LMB memory allocation
+* or freeing of memory having occurred.
+*/
+   EVT_LMB_MAP_UPDATE,
+
+   /**
+* @EVT_EFI_MEM_MAP_UPDATE:
+* This event is triggered on an update to the EFI  memory map.
+* This can be used to notify about any EFI memory allocation
+* or freeing of memory having occurred.
+*/
+   EVT_EFI_MEM_MAP_UPDATE,
+
/**
 * @EVT_COUNT:
 * This constants holds the maximum event number + 1 and is used when
@@ -203,6 +219,18 @@ union event_data {
oftree tree;
struct bootm_headers *images;
} ft_fixup;
+
+   struct event_lmb_map_update {
+   u64 base;
+   u64 size;
+   u8 op;
+   } lmb_map;
+
+   struct event_efi_mem_map_update {
+   u64 base;
+   u64 size;
+   u8  op;
+   } efi_mem_map;
 };
 
 /**
-- 
2.34.1



[RFC PATCH 09/31] lmb: allow for resizing lmb regions

2024-06-07 Thread Sughosh Ganu
Allow for resizing of LMB regions if the region attributes match. The
current code returns a failure status on detecting an overlapping
address. This worked up until now since the LMB calls were not
persistent and global -- the LMB memory map was specific and private
to a given caller of the LMB API's.

With the change in the LMB code to make the LMB reservations
persistent, there needs to be a check on whether the memory region can
be resized, and then do it if so. To distinguish between memory that
cannot be resized, add a new flag, LMB_NOOVERWRITE. Reserving a region
of memory with this attribute would indicate that the region cannot be
resized.

Signed-off-by: Sughosh Ganu 
---
 include/lmb.h |   1 +
 lib/lmb.c | 120 --
 2 files changed, 107 insertions(+), 14 deletions(-)

diff --git a/include/lmb.h b/include/lmb.h
index 03bce2a50c..1d4cd255d2 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -20,6 +20,7 @@
 enum lmb_flags {
LMB_NONE= 0x0,
LMB_NOMAP   = 0x4,
+   LMB_NOOVERWRITE = 0x8,
 };
 
 /**
diff --git a/lib/lmb.c b/lib/lmb.c
index de5a2cf23b..0a4f3d5bcd 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -260,12 +260,88 @@ void lmb_add_memory(struct bd_info *bd)
}
 }
 
+static bool lmb_region_flags_match(struct lmb_region *rgn, unsigned long r1,
+  enum lmb_flags flags)
+{
+   return rgn->region[r1].flags == flags;
+}
+
+static long lmb_merge_overlap_regions(struct lmb_region *rgn, unsigned long i,
+ phys_addr_t base, phys_size_t size,
+ enum lmb_flags flags)
+{
+   phys_size_t rgnsize;
+   unsigned long rgn_cnt, idx;
+   phys_addr_t rgnbase, rgnend;
+   phys_addr_t mergebase, mergeend;
+
+   rgn_cnt = 0;
+   idx = i;
+   /*
+* First thing to do is to identify how many regions does
+* the requested region overlap.
+* If the flags match, combine all these overlapping
+* regions into a single region, and remove the merged
+* regions.
+*/
+   while (idx < rgn->cnt - 1) {
+   rgnbase = rgn->region[idx].base;
+   rgnsize = rgn->region[idx].size;
+
+   if (lmb_addrs_overlap(base, size, rgnbase,
+ rgnsize)) {
+   if (!lmb_region_flags_match(rgn, idx, flags))
+   return -1;
+   rgn_cnt++;
+   idx++;
+   }
+   }
+
+   /* The merged region's base and size */
+   rgnbase = rgn->region[i].base;
+   mergebase = min(base, rgnbase);
+   rgnend = rgn->region[idx].base + rgn->region[idx].size;
+   mergeend = max(rgnend, (base + size));
+
+   rgn->region[i].base = mergebase;
+   rgn->region[i].size = mergeend - mergebase;
+
+   /* Now remove the merged regions */
+   while (--rgn_cnt)
+   lmb_remove_region(rgn, i + 1);
+
+   return 0;
+}
+
+static long lmb_resize_regions(struct lmb_region *rgn, unsigned long i,
+  phys_addr_t base, phys_size_t size,
+  enum lmb_flags flags)
+{
+   long ret = 0;
+   phys_addr_t rgnend;
+
+   if (i == rgn->cnt - 1 ||
+   base + size < rgn->region[i + 1].base) {
+   if (!lmb_region_flags_match(rgn, i, flags))
+   return -1;
+
+   rgnend = rgn->region[i].base + rgn->region[i].size;
+   rgn->region[i].base = min(base, rgn->region[i].base);
+   rgnend = max(base + size, rgnend);
+   rgn->region[i].size = rgnend - rgn->region[i].base;
+   } else {
+   ret = lmb_merge_overlap_regions(rgn, i, base, size, flags);
+   }
+
+   return ret;
+}
+
 /* This routine called with relocation disabled. */
 static long lmb_add_region_flags(struct lmb_region *rgn, phys_addr_t base,
 phys_size_t size, enum lmb_flags flags)
 {
unsigned long coalesced = 0;
-   long adjacent, i;
+   long ret, i;
 
if (rgn->cnt == 0) {
rgn->region[0].base = base;
@@ -290,23 +366,32 @@ static long lmb_add_region_flags(struct lmb_region *rgn, 
phys_addr_t base,
return -1; /* regions with new flags */
}
 
-   adjacent = lmb_addrs_adjacent(base, size, rgnbase, rgnsize);
-   if (adjacent > 0) {
+   ret = lmb_addrs_adjacent(base, size, rgnbase, rgnsize);
+   if (ret > 0) {
if (flags != rgnflags)
break;
rgn->region[i].base -= size;
rgn->region[i].size += size;
coalesce

[RFC PATCH 08/31] lmb: replcace the lmb_init_and_reserve() function

2024-06-07 Thread Sughosh Ganu
With the changes to make the Logical Memory Block(LMB) allocations
persistent and with the common memory regions being reserved during
board init, the lmb_init_and_reserve() API can be removed and replaced
with a lmb_add_memory() API, which adds all the available memory to
the LMB pool.

Signed-off-by: Sughosh Ganu 
---
 arch/arm/mach-apple/board.c  |  2 +-
 arch/arm/mach-snapdragon/board.c |  2 +-
 arch/arm/mach-stm32mp/stm32mp1/cpu.c |  2 +-
 cmd/bdinfo.c |  2 +-
 cmd/load.c   |  2 +-
 fs/fs.c  |  2 +-
 include/lmb.h| 12 +++-
 lib/lmb.c| 15 +++
 net/tftp.c   |  2 +-
 net/wget.c   |  2 +-
 test/cmd/bdinfo.c| 10 +-
 11 files changed, 31 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c
index c877c7b94c..2e72d03edd 100644
--- a/arch/arm/mach-apple/board.c
+++ b/arch/arm/mach-apple/board.c
@@ -776,7 +776,7 @@ int board_late_init(void)
 {
u32 status = 0;
 
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
+   lmb_add_memory(gd->bd);
 
/* somewhat based on the Linux Kernel boot requirements:
 * align by 2M and maximal FDT size 2M
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index a63c8bec45..b3c9a21419 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -282,7 +282,7 @@ int board_late_init(void)
 {
u32 status = 0;
 
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
+   lmb_add_memory(gd->bd);
 
/* We need to be fairly conservative here as we support boards with 
just 1G of TOTAL RAM */
status |= env_set_hex("kernel_addr_r", addr_alloc(SZ_128M));
diff --git a/arch/arm/mach-stm32mp/stm32mp1/cpu.c 
b/arch/arm/mach-stm32mp/stm32mp1/cpu.c
index a223297034..8e3f001f74 100644
--- a/arch/arm/mach-stm32mp/stm32mp1/cpu.c
+++ b/arch/arm/mach-stm32mp/stm32mp1/cpu.c
@@ -143,7 +143,7 @@ int mach_cpu_init(void)
 void enable_caches(void)
 {
/* parse device tree when data cache is still activated */
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
+   lmb_add_memory(gd->bd);
 
/* I-cache is already enabled in start.S: icache_enable() not needed */
 
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index e08d3e2cf3..fc408e9820 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -163,7 +163,7 @@ static int bdinfo_print_all(struct bd_info *bd)
bdinfo_print_num_l("multi_dtb_fit", (ulong)gd->multi_dtb_fit);
 #endif
if (IS_ENABLED(CONFIG_LMB) && gd->fdt_blob) {
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
+   lmb_add_memory(gd->bd);
lmb_dump_all_force();
if (IS_ENABLED(CONFIG_OF_REAL))
printf("devicetree  = %s\n", fdtdec_get_srcname());
diff --git a/cmd/load.c b/cmd/load.c
index f019111991..9918523806 100644
--- a/cmd/load.c
+++ b/cmd/load.c
@@ -154,7 +154,7 @@ static ulong load_serial(long offset)
int line_count =  0;
long ret;
 
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
+   lmb_add_memory(gd->bd);
 
while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
type = srec_decode(record, , , binbuf);
diff --git a/fs/fs.c b/fs/fs.c
index 3c54eaa366..f72d3962d1 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -549,7 +549,7 @@ static int fs_read_lmb_check(const char *filename, ulong 
addr, loff_t offset,
if (len && len < read_len)
read_len = len;
 
-   lmb_init_and_reserve(gd->bd, (void *)gd->fdt_blob);
+   lmb_add_memory(gd->bd);
lmb_dump_all();
 
if (lmb_alloc_addr(addr, read_len) == addr)
diff --git a/include/lmb.h b/include/lmb.h
index f3e3f716e5..03bce2a50c 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -84,7 +84,17 @@ struct lmb {
struct lmb_region reserved;
 };
 
-void lmb_init_and_reserve(struct bd_info *bd, void *fdt_blob);
+/**
+ * lmb_add_memory() - Add memory range for LMB allocations
+ * @bd: pointer to board info structure
+ *
+ * Add the entire available memory range to the pool of memory that
+ * can be used by the LMB module for allocations.
+ *
+ * Return: None
+ *
+ */
+void lmb_add_memory(struct bd_info *bd);
 long lmb_add(phys_addr_t base, phys_size_t size);
 long lmb_reserve(phys_addr_t base, phys_size_t size);
 /**
diff --git a/lib/lmb.c b/lib/lmb.c
index 5c056800c3..de5a2cf23b 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -240,8 +240,17 @@ void lmb_reserve_common(void *fdt_blob)
efi_lmb_reserve();
 }
 
-/* Initialize the struct, add memory and call arch/board reserve functions */
-void lmb_init_and_reserve(struct bd_info *bd,

[RFC PATCH 07/31] lmb: remove lmb_init_and_reserve_range() function

2024-06-07 Thread Sughosh Ganu
With the move to make the LMB allocations persistent and the common
memory regions being reserved during board init, the
lmb_init_and_reserve_range() API can be replaced with a simple
lmb_add() call.

Signed-off-by: Sughosh Ganu 
---
 boot/bootm.c  | 2 +-
 include/lmb.h | 2 --
 lib/lmb.c | 8 
 3 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/boot/bootm.c b/boot/bootm.c
index cd1003120c..73e72a710d 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -248,7 +248,7 @@ static void boot_start_lmb(void)
mem_start = env_get_bootm_low();
mem_size = env_get_bootm_size();
 
-   lmb_init_and_reserve_range(mem_start, mem_size, NULL);
+   lmb_add(mem_start, mem_size);
 }
 #else
 #define lmb_reserve(base, size)
diff --git a/include/lmb.h b/include/lmb.h
index d2b829ace1..f3e3f716e5 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -85,8 +85,6 @@ struct lmb {
 };
 
 void lmb_init_and_reserve(struct bd_info *bd, void *fdt_blob);
-void lmb_init_and_reserve_range(phys_addr_t base, phys_size_t size,
-   void *fdt_blob);
 long lmb_add(phys_addr_t base, phys_size_t size);
 long lmb_reserve(phys_addr_t base, phys_size_t size);
 /**
diff --git a/lib/lmb.c b/lib/lmb.c
index 8003aae6f7..5c056800c3 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -253,14 +253,6 @@ void lmb_init_and_reserve(struct bd_info *bd, void 
*fdt_blob)
lmb_reserve_common(fdt_blob);
 }
 
-/* Initialize the struct, add memory and call arch/board reserve functions */
-void lmb_init_and_reserve_range(phys_addr_t base, phys_size_t size,
-   void *fdt_blob)
-{
-   lmb_add(base, size);
-   lmb_reserve_common(fdt_blob);
-}
-
 /* This routine called with relocation disabled. */
 static long lmb_add_region_flags(struct lmb_region *rgn, phys_addr_t base,
 phys_size_t size, enum lmb_flags flags)
-- 
2.34.1



[RFC PATCH 06/31] lmb: reserve and add common memory regions post relocation

2024-06-07 Thread Sughosh Ganu
The LMB module provides API's for allocating chunks of memory. The LMB
module should not be allocating memory regions that are in use, or
that might be occupied by the U-Boot image. Prevent allocations of
memory areas used by the U-Boot image by reserving these regions once
U-Boot has been relocated. Also add the rest of the memory that is
available for allocations to the LMB's memory map.

Signed-off-by: Sughosh Ganu 
---
 common/board_r.c | 15 +++
 include/lmb.h| 14 ++
 lib/lmb.c| 14 +-
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/common/board_r.c b/common/board_r.c
index da0b80f24f..a9f0b0cec1 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -555,6 +556,17 @@ static int run_main_loop(void)
return 0;
 }
 
+#if defined(CONFIG_LMB)
+static int initr_lmb(void)
+{
+   lmb_reserve_common((void *)gd->fdt_blob);
+
+   lmb_add_memory(gd->bd);
+
+   return 0;
+}
+#endif
+
 /*
  * Over time we hope to remove these functions with code fragments and
  * stub functions, and instead call the relevant function directly.
@@ -613,6 +625,9 @@ static init_fnc_t init_sequence_r[] = {
 #endif
 #ifdef CONFIG_EFI_LOADER
efi_memory_init,
+#endif
+#if defined(CONFIG_LMB)
+   initr_lmb,
 #endif
initr_binman,
 #ifdef CONFIG_FSP_VERSION2
diff --git a/include/lmb.h b/include/lmb.h
index 8f8a32c2ca..d2b829ace1 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -125,6 +125,20 @@ void board_lmb_reserve(void);
 void arch_lmb_reserve(void);
 void arch_lmb_reserve_generic(ulong sp, ulong end, ulong align);
 
+/**
+ * lmb_reserve_common() - Reserve memory region occupied by U-Boot image
+ * @fdt_blob: pointer to the FDT blob
+ *
+ * Reserve common areas of memory that are occupied by the U-Boot image.
+ * This function gets called once U-Boot has been relocated, so that any
+ * request for memory allocations would not touch memory region occupied
+ * by the U-Boot image, heap, bss etc.
+ *
+ * Return: None
+ *
+ */
+void lmb_reserve_common(void *fdt_blob);
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_LMB_H */
diff --git a/lib/lmb.c b/lib/lmb.c
index b0c9e2ef30..8003aae6f7 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -216,7 +216,19 @@ static __maybe_unused int efi_lmb_reserve(void)
return 0;
 }
 
-static void lmb_reserve_common(void *fdt_blob)
+/**
+ * lmb_reserve_common() - Reserve memory region occupied by U-Boot image
+ * @fdt_blob: pointer to the FDT blob
+ *
+ * Reserve common areas of memory that are occupied by the U-Boot image.
+ * This function gets called once U-Boot has been relocated, so that any
+ * request for memory allocations would not touch memory region occupied
+ * by the U-Boot image, heap, bss etc.
+ *
+ * Return: None
+ *
+ */
+void lmb_reserve_common(void *fdt_blob)
 {
arch_lmb_reserve();
board_lmb_reserve();
-- 
2.34.1



  1   2   3   4   5   6   7   8   9   10   >