From 194527e0fe9e1ba95aff0c5a742c65063e4c2f1a Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sun, 3 Mar 2019 01:38:07 -0800 Subject: [PATCH] Fix address-marking bugs * Non-blocksize-aligned regions could fail to be found. Have the bootloader load them aligned. * Consolidating used frame blocks in the bootstrap means these would have been impossible to free as address space * mark_permanent wasn't actually removing blocks from the free list --- src/boot/loader.cpp | 17 +++++++++++++---- src/kernel/memory_bootstrap.cpp | 1 - .../kutil/include/kutil/address_manager.h | 2 +- .../kutil/include/kutil/buddy_allocator.h | 1 + 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index b7225ec..d0b630f 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -14,13 +14,20 @@ loader_alloc_pages( EFI_BOOT_SERVICES *bootsvc, EFI_MEMORY_TYPE mem_type, size_t *length, - void **pages) + void **pages, + bool align) { EFI_STATUS status; size_t page_count = ((*length - 1) / PAGE_SIZE) + 1; EFI_PHYSICAL_ADDRESS addr = (EFI_PHYSICAL_ADDRESS)*pages; + if (align) { + // Align addr to the next multiple of N pages + size_t align_size = page_count * PAGE_SIZE; + addr = ((addr - 1) & ~(align_size - 1)) + align_size; + } + status = bootsvc->AllocatePages(AllocateAddress, mem_type, page_count, &addr); if (status == EFI_NOT_FOUND || status == EFI_OUT_OF_RESOURCES) { // couldn't get the address we wanted, try loading the kernel anywhere @@ -66,7 +73,8 @@ loader_load_initrd( bootsvc, memtype_initrd, &data->initrd_length, - &data->initrd); + &data->initrd, + true); CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating pages"); status = file->Read(file, &data->initrd_length, data->initrd); @@ -153,7 +161,7 @@ loader_load_elf( length = prog_header.mem_size; void *addr = (void *)(prog_header.vaddr - KERNEL_VIRT_ADDRESS); - status = loader_alloc_pages(bootsvc, memtype_kernel, &length, &addr); + status = loader_alloc_pages(bootsvc, memtype_kernel, &length, &addr, false); CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating kernel pages"); if (data->kernel == 0) @@ -239,7 +247,8 @@ loader_load_kernel( bootsvc, memtype_data, &data->data_length, - &data->data); + &data->data, + true); CHECK_EFI_STATUS_OR_RETURN(status, L"loader_alloc_pages: kernel data"); return EFI_SUCCESS; diff --git a/src/kernel/memory_bootstrap.cpp b/src/kernel/memory_bootstrap.cpp index fde325b..2f276b9 100644 --- a/src/kernel/memory_bootstrap.cpp +++ b/src/kernel/memory_bootstrap.cpp @@ -304,7 +304,6 @@ memory_initialize(uint16_t scratch_pages, const void *memory_map, size_t map_len // Now go back through these lists and consolidate block_slab.append(frame_block::consolidate(free)); - block_slab.append(frame_block::consolidate(used)); region_allocator region_slab(page_size, allocator); region_slab.allocate(); // Allocate some buddy regions for the address_manager diff --git a/src/libraries/kutil/include/kutil/address_manager.h b/src/libraries/kutil/include/kutil/address_manager.h index 0ef7336..b2c21c1 100644 --- a/src/libraries/kutil/include/kutil/address_manager.h +++ b/src/libraries/kutil/include/kutil/address_manager.h @@ -8,7 +8,7 @@ namespace kutil { using address_manager = buddy_allocator< - 16, // Min allocation: 64KiB + 12, // Min allocation: 4KiB 36 // Max allocation: 64GiB >; diff --git a/src/libraries/kutil/include/kutil/buddy_allocator.h b/src/libraries/kutil/include/kutil/buddy_allocator.h index fc4c5fe..60df8e1 100644 --- a/src/libraries/kutil/include/kutil/buddy_allocator.h +++ b/src/libraries/kutil/include/kutil/buddy_allocator.h @@ -132,6 +132,7 @@ public: for (unsigned i = size_max; i >= size_min; --i) { for (auto *r : free_bucket(i)) { if (start >= r->address && end <= r->end()) { + free_bucket(i).remove(r); delete_region(r, start, end); return; }