summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2018-09-16 17:05:29 +0200
committerAlexander Graf <agraf@suse.de>2018-09-23 21:55:30 +0200
commit7b05667ce23914f6989f8c2ade1ac96ce4ff4eb6 (patch)
treec23d4d7ec60a9bae0e71491d291d2b94c5a4eac3 /lib
parent79276eb2430d02c84a31fc5613e41aba05429184 (diff)
efi_loader: Merge memory map entries
We currently do not combine memory entries that are adjacent and have the same attributes. The problem with that is that our memory map can easily grow multiple hundreds of entries in a simple UEFI Shell environment. So let's make sure we always combine all entries to make the memory map as small as possible. That way every other piece of code that loops through it should also gain some nice speed ups. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/efi_memory.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 4f8cb545ad..5bd4f4d7fc 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -65,9 +65,54 @@ static int efi_mem_cmp(void *priv, struct list_head *a, struct list_head *b)
return -1;
}
+static uint64_t desc_get_end(struct efi_mem_desc *desc)
+{
+ return desc->physical_start + (desc->num_pages << EFI_PAGE_SHIFT);
+}
+
static void efi_mem_sort(void)
{
+ struct list_head *lhandle;
+ struct efi_mem_list *prevmem = NULL;
+ bool merge_again = true;
+
list_sort(NULL, &efi_mem, efi_mem_cmp);
+
+ /* Now merge entries that can be merged */
+ while (merge_again) {
+ merge_again = false;
+ list_for_each(lhandle, &efi_mem) {
+ struct efi_mem_list *lmem;
+ struct efi_mem_desc *prev = &prevmem->desc;
+ struct efi_mem_desc *cur;
+ uint64_t pages;
+
+ lmem = list_entry(lhandle, struct efi_mem_list, link);
+ if (!prevmem) {
+ prevmem = lmem;
+ continue;
+ }
+
+ cur = &lmem->desc;
+
+ if ((desc_get_end(cur) == prev->physical_start) &&
+ (prev->type == cur->type) &&
+ (prev->attribute == cur->attribute)) {
+ /* There is an existing map before, reuse it */
+ pages = cur->num_pages;
+ prev->num_pages += pages;
+ prev->physical_start -= pages << EFI_PAGE_SHIFT;
+ prev->virtual_start -= pages << EFI_PAGE_SHIFT;
+ list_del(&lmem->link);
+ free(lmem);
+
+ merge_again = true;
+ break;
+ }
+
+ prevmem = lmem;
+ }
+ }
}
/** efi_mem_carve_out - unmap memory region