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
This commit is contained in:
Justin C. Miller
2019-03-03 01:38:07 -08:00
parent 28cf5562ac
commit 194527e0fe
4 changed files with 15 additions and 6 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -8,7 +8,7 @@ namespace kutil {
using address_manager =
buddy_allocator<
16, // Min allocation: 64KiB
12, // Min allocation: 4KiB
36 // Max allocation: 64GiB
>;

View File

@@ -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;
}