| .. 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 | |