| .. SPDX-License-Identifier: GPL-2.0+ |
| |
| Logical Memory Blocks (LMB) |
| =========================== |
| |
| U-Boot has support for reserving chunks of memory which is primarily |
| used for loading images to the DRAM memory, before these are booted, |
| or written to non-volatile storage medium. This functionality is |
| provided through the Logical Memory Blocks (LMB) module. |
| |
| Introduction |
| ------------ |
| |
| The LMB module manages allocation requests for memory region not |
| occupied by the U-Boot image. Allocation requests that are made |
| through malloc() and similar functions result in memory getting |
| allocated from the heap region, which is part of the U-Boot |
| image. Typically, the heap memory is a few MiB in size. Loading an |
| image like the linux kernel might require lot more memory than what |
| the heap can provide. Such allocations are usually handled through the |
| LMB module. |
| |
| The U-Boot image typically gets relocated to the top of the usable |
| DRAM memory region. A typical memory layout looks as follows:: |
| |
| |
| |
| |
| |
| | | |
| | | |
| | | |
| | | |
| | | |
| --- +--------------+ <--- U-Boot ram top |
| | | | |
| | | Text | |
| | +--------------+ |
| | | | |
| | | Data | |
| | +--------------+ |
| | | | |
| | | BSS | |
| U-Boot Image +--------------+ |
| | | | |
| | | Heap | |
| | | | |
| | +--------------+ |
| | | | |
| | | | |
| | | Stack | |
| | | | |
| | | | |
| --- +--------------+ |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| +--------------+ <--- ram start |
| |
| |
| |
| The region of memory below the U-Boot image is the one controlled by |
| the LMB module. |
| |
| |
| Types of LMB Allocations |
| ------------------------ |
| |
| There are two classes of allocation requests that get made to the LMB |
| module. One type of allocation requests are requesting memory of a |
| particular number of bytes. This type of allocation is similar to that |
| done using the malloc type of function calls. The other type of |
| allocations, are requests made for a specific memory address. The |
| second type of allocations are usually made for loading images to a |
| particular memory address. |
| |
| |
| LMB design Pre 2025.01 |
| ---------------------- |
| |
| The earlier versions of U-Boot (pre 2025.01 release) |
| had a local memory map based LMB implementation whereby it was |
| possible to declare the LMB map inside a function or a C file. This |
| design resulted in temporary, non-global LMB maps, which also allowed |
| for re-use of memory. This meant that it was possible to use a region |
| of memory to load some image, and subsequently the same region of |
| memory could be used for loading a different image. A typical example |
| of this usage would be loading an image to a memory address, followed |
| by writing that image to some non-volatile storage medium. Once this |
| is done, the same address can be used for loading a different image |
| and then writing it to it's non-volatile storage |
| destination. Typically, environment variables like `loadaddr`, |
| `kernel_addr_r`, `ramdisk_addr_r` are used for loading images to |
| memory regions. |
| |
| |
| Current LMB implementation |
| -------------------------- |
| |
| Changes were made in the 2025.01 release to make the LMB memory map |
| global and persistent. With this, the LMB memory map is the same |
| across all of U-Boot, and also persists as long as U-Boot is |
| active. Even with this change, there has been consistency as far as |
| re-use of memory is concerned to maintain backward compatibility. It |
| is allowed for re-requesting the same region of memory if the memory |
| region has a particular attribute (LMB_NONE). |
| |
| As part of the platform boot, DRAM memory available for use in U-Boot |
| gets added to the LMB memory map. Any allocation requests made |
| subsequently will be made from this memory added as part of the board |
| init. |
| |
| |
| Allocation API |
| -------------- |
| |
| Any request for non-heap memory can be made through the LMB allocation |
| API. |
| |
| .. code-block:: c |
| |
| int lmb_alloc_mem(enum lmb_mem_type type, u64 align, |
| phys_addr_t *addr, phys_size_t size, |
| u32 flags); |
| |
| Correspondingly, the allocated memory can be free'd |
| |
| .. code-block:: c |
| |
| long lmb_free(phys_addr_t base, phys_size_t size, u32 flags); |
| |
| For a detailed API description, please refer to the header file. |
| |
| |
| UEFI allocations with LMB as the backend |
| ---------------------------------------- |
| |
| The UEFI specification describes boot-time API's for allocation of |
| memory. These API's use the same memory that is being used by the LMB |
| module. Pre 2025.01 release, there wasn't any synchronisation between |
| the EFI sub-system and the LMB module about the memory that was |
| getting allocated by each of these modules. This was the primary |
| reason for making the LMB memory map global and persistent. With this |
| change, the EFI memory allocation API's have also been changed to use |
| the LMB module as the backend for the allocation requests. Any other |
| sub-system which might wish to use the same memory region for it's use |
| can then use the LMB as the backend for the memory allocations and |
| it's associated book-keeping. |
| |
| |
| API documentation |
| ----------------- |
| |
| .. kernel-doc:: include/lmb.h |
| |