diff mbox

[U-Boot,v3,5/7] efi_loader: Readd freed pages to memory pool

Message ID 2f2cfb59ecf0457095c9c09b0e310677@rwthex-w2-b.rwth-ad.de
State Accepted
Delegated to: Alexander Graf
Headers show

Commit Message

Stefan Brüns Oct. 1, 2016, 9:32 p.m. UTC
Currently each allocation creates a new mapping. Readding the mapping
as free memory (EFI_CONVENTIONAL_MEMORY) potentially allows to hand out
an existing mapping, thus limiting the number of mapping descriptors in
the memory map.

Mitigates a problem with current (4.8rc7) linux kernels when doing an
efi_get_memory map, resulting in an infinite loop. Space for the memory
map is reserved with allocate_pool (implicitly creating a new mapping) and
filled. If there is insufficient slack space (8 entries) in the map, the
space is freed and a new round is started, with space for one more entry.
As each round increases requirement and allocation by exactly one, there
is never enough slack space. (At least 32 entries are allocated, so as
long as there are less than 24 entries, there is enough slack).
Earlier kernels reserved no slack, and did less allocations, so this
problem was not visible.

Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
Reviewed-by: Alexander Graf <agraf@suse.de>
---
 include/efi_loader.h        |  2 +-
 lib/efi_loader/efi_memory.c | 11 +++++++++--
 2 files changed, 10 insertions(+), 3 deletions(-)

Comments

Alexander Graf Oct. 13, 2016, 2:34 p.m. UTC | #1
> Currently each allocation creates a new mapping. Readding the mapping
> as free memory (EFI_CONVENTIONAL_MEMORY) potentially allows to hand out
> an existing mapping, thus limiting the number of mapping descriptors in
> the memory map.
> 
> Mitigates a problem with current (4.8rc7) linux kernels when doing an
> efi_get_memory map, resulting in an infinite loop. Space for the memory
> map is reserved with allocate_pool (implicitly creating a new mapping) and
> filled. If there is insufficient slack space (8 entries) in the map, the
> space is freed and a new round is started, with space for one more entry.
> As each round increases requirement and allocation by exactly one, there
> is never enough slack space. (At least 32 entries are allocated, so as
> long as there are less than 24 entries, there is enough slack).
> Earlier kernels reserved no slack, and did less allocations, so this
> problem was not visible.
> 
> Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
> Reviewed-by: Alexander Graf <agraf@suse.de>

Thanks, applied to
diff mbox

Patch

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 341d4a4..6d64f4b 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -117,7 +117,7 @@  void *efi_alloc(uint64_t len, int memory_type);
 /* More specific EFI memory allocator, called by EFI payloads */
 efi_status_t efi_allocate_pages(int type, int memory_type, unsigned long pages,
 				uint64_t *memory);
-/* EFI memory free function. Not implemented today */
+/* EFI memory free function. */
 efi_status_t efi_free_pages(uint64_t memory, unsigned long pages);
 /* EFI memory allocator for small allocations, called by EFI payloads */
 efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index fa5c639..7051948 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -335,8 +335,15 @@  void *efi_alloc(uint64_t len, int memory_type)
 
 efi_status_t efi_free_pages(uint64_t memory, unsigned long pages)
 {
-	/* We don't free, let's cross our fingers we have plenty RAM */
-	return EFI_SUCCESS;
+	uint64_t r = 0;
+
+	r = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
+	/* Merging of adjacent free regions is missing */
+
+	if (r == memory)
+		return EFI_SUCCESS;
+
+	return EFI_NOT_FOUND;
 }
 
 efi_status_t efi_allocate_pool(int pool_type, unsigned long size,