Merge patch series "lmb: use a single API for all allocations"

Sughosh Ganu <sughosh.ganu@linaro.org> says:

The LMB module has a bunch for API's which are used for allocating
memory. There are a couple of API's for requesting memory, and two
more for reserving regions of memory. Replace these different API's
with a single one, lmb_alloc_mem(). The type of allocation to be made
is specified through one of the parameters to the function.

Additionally, the two API's for reserving regions of memory,
lmb_reserve() and lmb_alloc_addr() are the same with one
difference. One can reserve any memory region with lmb_reserve(),
while lmb_alloc_addr() actually checks that the memory region being
requested is part of the LMB memory map. Reserving memory that is not
part of the LMB memory map is pretty futile -- the allocation
functions do not allocate memory which has not been added to the LMB
memory map.

This series also removes the functionality allowing for reserving
memory regions outside the LMB memory map. Any request for reserving a
region of memory outside the LMB memory map now returns an -EINVAL
error.

Certain places in the common code using the LMB API's were not
checking the return value of the functions. Checks have been added for
them. There are some calls being made from the architecture/platform
specific code which too do not check the return value. Those have been
kept the same, as I do not have the platform with me to check if it
causes any issues on those platforms.

In addition, there is a patch which refactors code in
lmb_overlaps_region() and lmb_can_reserve_region() so that both
functionalities can be put in a single function, lmb_overlap_checks().

Finally, a new patch has been added which checks the return value of
the lmb allocation function before copying the device-tree to the
allocated address.

Link: https://lore.kernel.org/r/20250617104346.1379981-1-sughosh.ganu@linaro.org
[trini: Rework arch/arm/mach-snapdragon/board.c merge]
Signed-off-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
Tom Rini
2025-06-25 09:57:01 -06:00
20 changed files with 583 additions and 285 deletions

View File

@@ -46,6 +46,7 @@ Implementation
cedit
event
global_data
lmb
logging
makefiles
menus

166
doc/develop/lmb.rst Normal file
View File

@@ -0,0 +1,166 @@
.. 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