From 8b813adf6df7c4ec2c988888a5b6ef2e398aa103 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Sat, 12 Oct 2024 14:37:32 -0400 Subject: [PATCH] bootloader/bios_ia32: Allocate physical memory from the kernel separate from the bootloader. Just start the kernel allocations after the end of the identity map (i.e. the first 8 MB of RAM.) This way, we can avoid putting the bootloader heap and page table memory into the kernel ranges at all, which avoids leaking it. --- src/system/boot/platform/bios_ia32/mmu.cpp | 39 +++++++++++++--------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index 1a580f44cc..b070665e97 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -73,7 +73,7 @@ segment_descriptor gBootGDT[BOOT_GDT_SEGMENT_COUNT]; static const uint32 kDefaultPageTableFlags = 0x07; // present, user, R/W static const size_t kMaxKernelSize = 0x1000000; // 16 MB for the kernel -static const size_t kIdentityMapEnd = (8 * 1024 * 1024); +static const size_t kIdentityMapEnd = 0x0800000; // 8 MB // working page directory and page table static uint32 *sPageDirectory = 0; @@ -81,6 +81,7 @@ static uint32 *sPageDirectory = 0; #ifdef _PXE_ENV static addr_t sNextPhysicalAddress = 0x112000; +static addr_t sNextPhysicalKernelAddress = kIdentityMapEnd; static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize; static addr_t sNextPageTableAddress = 0x7d000; @@ -90,6 +91,7 @@ static const uint32 kPageTableRegionEnd = 0x8b000; #else static addr_t sNextPhysicalAddress = 0x100000; +static addr_t sNextPhysicalKernelAddress = kIdentityMapEnd; static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize; static addr_t sNextPageTableAddress = 0x90000; @@ -100,7 +102,7 @@ static const uint32 kPageTableRegionEnd = 0x9e000; static addr_t -get_next_virtual_address(size_t size) +allocate_virtual(size_t size) { addr_t address = sNextVirtualAddress; sNextVirtualAddress += size; @@ -110,18 +112,29 @@ get_next_virtual_address(size_t size) static addr_t -get_next_physical_address(size_t size) +allocate_physical(size_t size, bool forKernel) { uint64 base; + if (!forKernel) { + base = sNextPhysicalAddress; + if ((base + size) > kIdentityMapEnd) { + panic("Out of identity-map physical memory!"); + return 0; + } + + sNextPhysicalAddress += size; + return base; + } + if (!get_free_address_range(gKernelArgs.physical_allocated_range, - gKernelArgs.num_physical_allocated_ranges, sNextPhysicalAddress, + gKernelArgs.num_physical_allocated_ranges, sNextPhysicalKernelAddress, size, &base)) { panic("Out of physical memory!"); return 0; } insert_physical_allocated_range(base, size); - sNextPhysicalAddress = base + size; + sNextPhysicalKernelAddress = base + size; // TODO: Can overflow theoretically. return base; @@ -131,14 +144,14 @@ get_next_physical_address(size_t size) static addr_t get_next_virtual_page() { - return get_next_virtual_address(B_PAGE_SIZE); + return allocate_virtual(B_PAGE_SIZE); } static addr_t get_next_physical_page() { - return get_next_physical_address(B_PAGE_SIZE); + return allocate_physical(B_PAGE_SIZE, true); } @@ -151,7 +164,7 @@ get_next_page_table() addr_t address = sNextPageTableAddress; if (address >= kPageTableRegionEnd) - return (uint32 *)get_next_physical_page(); + return (uint32 *)allocate_physical(B_PAGE_SIZE, false); sNextPageTableAddress += B_PAGE_SIZE; return (uint32 *)address; @@ -321,7 +334,7 @@ init_page_directory(void) TRACE("init_page_directory\n"); // allocate a new pgdir - sPageDirectory = (uint32 *)get_next_physical_page(); + sPageDirectory = (uint32 *)allocate_physical(B_PAGE_SIZE, false); gKernelArgs.arch_args.phys_pgdir = (uint32)sPageDirectory; // clear out the pgdir @@ -630,7 +643,7 @@ mmu_init(void) gKernelArgs.arch_args.virtual_end = KERNEL_LOAD_BASE; - gKernelArgs.physical_allocated_range[0].start = sNextPhysicalAddress; + gKernelArgs.physical_allocated_range[0].start = sNextPhysicalKernelAddress; gKernelArgs.physical_allocated_range[0].size = 0; gKernelArgs.num_physical_allocated_ranges = 1; // remember the start of the allocated physical pages @@ -813,13 +826,10 @@ platform_free_region(void *address, size_t size) ssize_t platform_allocate_heap_region(size_t size, void **_base) { - addr_t base = get_next_physical_address(size); + addr_t base = allocate_physical(size, false); if (base == 0) return B_NO_MEMORY; - if ((base + size) > kIdentityMapEnd) - panic("platform_allocate_heap_region: region end is beyond identity map"); - *_base = (void*)base; return size; } @@ -829,7 +839,6 @@ void platform_free_heap_region(void *_base, size_t size) { addr_t base = (addr_t)_base; - remove_physical_allocated_range(base, size); if (sNextPhysicalAddress == (base + size)) sNextPhysicalAddress -= size;