summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorStefan Brüns <stefan.bruens@rwth-aachen.de>2016-10-01 23:32:27 +0200
committerAlexander Graf <agraf@suse.de>2016-10-18 09:08:07 +0200
commitb61d857b2ff3b0b099ef187d7ceebe26ea788578 (patch)
tree28998517dab172e26774c2d5ea2287d53ab6384d /lib
parent42417bc84d1d56f739d43d562773d4821cf1bf47 (diff)
efi_loader: Readd freed pages to memory pool
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> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/efi_memory.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index de28db6e44..d3a2ffdac6 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -336,8 +336,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,