Message ID | 20241008181435.1753814-4-sughosh.ganu@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | Make EFI memory allocations synchronous with LMB | expand |
Hi Sughosh, On Tue, 8 Oct 2024 at 12:14, Sughosh Ganu <sughosh.ganu@linaro.org> wrote: > > 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 <sughosh.ganu@linaro.org> > --- > Changes since V1: None > > lib/efi_loader/Kconfig | 1 + > lib/efi_loader/efi_memory.c | 74 ++++++++++--------------------------- > 2 files changed, 21 insertions(+), 54 deletions(-) > Please check my recent series [1] which shows how to avoid needing to worry about lmb until the app starts, at which point I believe we can just add the lmb map to the EFI map so we know where the images are? But without my series, this patch is needed. I do wonder what addresses lmb happens to allocate with this? From the top? From the bottom? > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > index e58b8825605..5a576720606 100644 > --- a/lib/efi_loader/Kconfig > +++ b/lib/efi_loader/Kconfig > @@ -20,6 +20,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 c6f1dd09456..90e07ed6a2d 100644 > --- a/lib/efi_loader/efi_memory.c > +++ b/lib/efi_loader/efi_memory.c > @@ -9,6 +9,7 @@ > > #include <efi_loader.h> > #include <init.h> > +#include <lmb.h> > #include <log.h> > #include <malloc.h> > #include <mapmem.h> > @@ -432,53 +433,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 efi_mem_list *lmem; > - > - /* > - * 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_entry(lmem, &efi_mem, link) { > - struct efi_mem_desc *desc = &lmem->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 > * > @@ -493,6 +447,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; > > @@ -508,33 +463,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, pages, memory_type, true); > if (ret != EFI_SUCCESS) > @@ -555,6 +512,9 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type, > */ > efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) > { > + u64 len; > + uint flags; > + long status; > efi_status_t ret; > > ret = efi_check_allocated(memory, true); > @@ -568,6 +528,12 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) > return EFI_INVALID_PARAMETER; > } > > + flags = LMB_NOOVERWRITE | LMB_NONOTIFY; > + len = (u64)pages << EFI_PAGE_SHIFT; > + status = lmb_free_flags(memory, len, flags); > + if (status) > + return EFI_NOT_FOUND; > + > ret = efi_add_memory_map_pg(memory, pages, EFI_CONVENTIONAL_MEMORY, > false); > if (ret != EFI_SUCCESS) > -- > 2.34.1 > Regards, SImon [1] https://patchwork.ozlabs.org/project/uboot/list/?series=427729
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index e58b8825605..5a576720606 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -20,6 +20,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 c6f1dd09456..90e07ed6a2d 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -9,6 +9,7 @@ #include <efi_loader.h> #include <init.h> +#include <lmb.h> #include <log.h> #include <malloc.h> #include <mapmem.h> @@ -432,53 +433,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 efi_mem_list *lmem; - - /* - * 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_entry(lmem, &efi_mem, link) { - struct efi_mem_desc *desc = &lmem->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 * @@ -493,6 +447,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; @@ -508,33 +463,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, pages, memory_type, true); if (ret != EFI_SUCCESS) @@ -555,6 +512,9 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type, */ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) { + u64 len; + uint flags; + long status; efi_status_t ret; ret = efi_check_allocated(memory, true); @@ -568,6 +528,12 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) return EFI_INVALID_PARAMETER; } + flags = LMB_NOOVERWRITE | LMB_NONOTIFY; + len = (u64)pages << EFI_PAGE_SHIFT; + status = lmb_free_flags(memory, len, flags); + if (status) + return EFI_NOT_FOUND; + ret = efi_add_memory_map_pg(memory, pages, EFI_CONVENTIONAL_MEMORY, false); if (ret != EFI_SUCCESS)
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 <sughosh.ganu@linaro.org> --- Changes since V1: None lib/efi_loader/Kconfig | 1 + lib/efi_loader/efi_memory.c | 74 ++++++++++--------------------------- 2 files changed, 21 insertions(+), 54 deletions(-)