From 0463b9511c7d8ccfcdb6c0c837434d15a409bf4b Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 20 Feb 2025 14:57:23 -0500 Subject: [PATCH] bootloader: Refactor semantics of platform_allocate_region() functions. This cleans up a lot of subtle or hidden inconsistencies: * Drop the "exactAddress" parameter. It was added in hrev15708 (2005), but all callers in all bootloaders passed "false" to it until 2022, when one codepath in the ARM32 EFI loader started using it. * Adjust EFI's platform_allocate_lomem to platform_allocate_region_below, and add a platform_assign_kernel_address_for_region(). This allows the aforementioned ARM EFI codepath to continue to do what it wants, which is to get an identity-mapped trampoline page, without having functions with confusingly different semantics ("allocate_lomem" assigned the virtual addresses as identity-mapped unconditionally, but it didn't insert these into the virtual allocated ranges.) This also paves the way for other EFI loaders to use this method to allocate memory below whatever default the boot services would give us. * Drop fixed virtual address allocation for all arches on EFI, with the exception of fixed addresses inside KERNEL_LOAD_BASE, same as on other boot platforms. Anything which wants fixed virtual addresses outside that region can use the new "assign kernel address" method. * Validate kernel base and size against kMaxKernelSize, instead of assuming it fits. This matches behavior of other boot platforms. Ideally we would have some more generic routine for mapping the kernel, but this suffices for now. Tested with x86_64 and ARM; both still boot (well, ARM boots as far as it did before this commit, anyway.) Change-Id: Ieb4fba752994101191a2335cb5395eb2b726fcbb Reviewed-on: https://review.haiku-os.org/c/haiku/+/9024 Reviewed-by: waddlesplash --- headers/private/kernel/boot/platform.h | 2 +- src/system/boot/arch/m68k/mmu.cpp | 3 +- src/system/boot/loader/elf.cpp | 5 +- .../boot/loader/file_systems/tarfs/tarfs.cpp | 2 +- src/system/boot/loader/kernel_args.cpp | 6 +- src/system/boot/platform/amiga_m68k/mmu.cpp | 3 +- src/system/boot/platform/atari_m68k/mmu.cpp | 3 +- src/system/boot/platform/bios_ia32/mmu.cpp | 3 +- .../boot/platform/efi/arch/arm/arch_mmu.cpp | 9 ++- .../boot/platform/efi/arch/arm/arch_start.cpp | 35 +++++---- .../boot/platform/efi/arch/arm64/arch_mmu.h | 2 +- .../platform/efi/arch/riscv64/arch_smp.cpp | 4 +- .../platform/efi/arch/riscv64/arch_start.cpp | 2 +- .../boot/platform/efi/arch/x86/arch_mmu.cpp | 4 +- .../boot/platform/efi/arch/x86/arch_smp.cpp | 2 +- .../boot/platform/efi/arch/x86/arch_start.cpp | 2 +- .../platform/efi/arch/x86_64/arch_mmu.cpp | 2 +- src/system/boot/platform/efi/debug.cpp | 2 +- src/system/boot/platform/efi/mmu.cpp | 76 ++++++++++++------- src/system/boot/platform/efi/mmu.h | 5 +- src/system/boot/platform/efi/start.cpp | 3 +- src/system/boot/platform/next_m68k/mmu.cpp | 3 +- .../boot/platform/openfirmware/heap.cpp | 2 +- src/system/boot/platform/openfirmware/mmu.cpp | 5 +- src/system/boot/platform/pxe_ia32/network.cpp | 2 +- src/system/boot/platform/riscv/mmu.cpp | 9 +-- .../platform/u-boot/arch/ppc/arch_mmu.cpp | 3 +- 27 files changed, 109 insertions(+), 90 deletions(-) diff --git a/headers/private/kernel/boot/platform.h b/headers/private/kernel/boot/platform.h index 9b1b943e2a..375d0aac76 100644 --- a/headers/private/kernel/boot/platform.h +++ b/headers/private/kernel/boot/platform.h @@ -26,7 +26,7 @@ extern void platform_free_heap_region(void *_base, size_t size); /* MMU/memory functions */ extern status_t platform_allocate_region(void **_virtualAddress, size_t size, - uint8 protection, bool exactAddress); + uint8 protection); extern status_t platform_free_region(void *address, size_t size); extern status_t platform_bootloader_address_to_kernel_address(void *address, addr_t *_result); extern status_t platform_kernel_address_to_bootloader_address(addr_t address, void **_result); diff --git a/src/system/boot/arch/m68k/mmu.cpp b/src/system/boot/arch/m68k/mmu.cpp index 741296b940..95d5c20b97 100644 --- a/src/system/boot/arch/m68k/mmu.cpp +++ b/src/system/boot/arch/m68k/mmu.cpp @@ -645,8 +645,7 @@ mmu_init(void) extern "C" status_t -platform_allocate_region(void **_address, size_t size, uint8 protection, - bool /*exactAddress*/) +platform_allocate_region(void **_address, size_t size, uint8 protection) { void *address = mmu_allocate(*_address, size); if (address == NULL) diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index 4ca4251bfe..899c5cd542 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -81,7 +81,7 @@ struct ELF32Class { void** _mappedAddress) { status_t status = platform_allocate_region((void**)_address, size, - protection, false); + protection); if (status != B_OK) return status; @@ -139,8 +139,7 @@ struct ELF64Class { void* address = (void*)*_address; #endif - status_t status = platform_allocate_region(&address, size, protection, - false); + status_t status = platform_allocate_region(&address, size, protection); if (status != B_OK) return status; diff --git a/src/system/boot/loader/file_systems/tarfs/tarfs.cpp b/src/system/boot/loader/file_systems/tarfs/tarfs.cpp index b8f2f706ec..7cfd57c72a 100644 --- a/src/system/boot/loader/file_systems/tarfs/tarfs.cpp +++ b/src/system/boot/loader/file_systems/tarfs/tarfs.cpp @@ -788,7 +788,7 @@ TarFS::Volume::_Inflate(boot::Partition* partition, void* cookie, off_t offset, if (!out) { // allocate memory for the uncompressed data if (platform_allocate_region((void**)&out, kTarRegionSize, - B_READ_AREA | B_WRITE_AREA, false) != B_OK) { + B_READ_AREA | B_WRITE_AREA) != B_OK) { TRACE(("tarfs: allocating region failed!\n")); return B_NO_MEMORY; } diff --git a/src/system/boot/loader/kernel_args.cpp b/src/system/boot/loader/kernel_args.cpp index d7989f7b81..f5db893645 100644 --- a/src/system/boot/loader/kernel_args.cpp +++ b/src/system/boot/loader/kernel_args.cpp @@ -435,7 +435,7 @@ kernel_args_malloc(size_t size, uint8 alignment) // the block is so large, we'll allocate a new block for it void* block = NULL; if (platform_allocate_region(&block, alignedSize, - B_READ_AREA | B_WRITE_AREA, false) != B_OK) { + B_READ_AREA | B_WRITE_AREA) != B_OK) { return NULL; } @@ -450,10 +450,8 @@ kernel_args_malloc(size_t size, uint8 alignment) // just allocate a new block and "close" the old one void* block = NULL; - if (platform_allocate_region(&block, kChunkSize, B_READ_AREA | B_WRITE_AREA, - false) != B_OK) { + if (platform_allocate_region(&block, kChunkSize, B_READ_AREA | B_WRITE_AREA) != B_OK) return NULL; - } sFirstFree = (void*)((addr_t)block + alignedSize); sLast = block; diff --git a/src/system/boot/platform/amiga_m68k/mmu.cpp b/src/system/boot/platform/amiga_m68k/mmu.cpp index d03a7210cf..c0d46704ea 100644 --- a/src/system/boot/platform/amiga_m68k/mmu.cpp +++ b/src/system/boot/platform/amiga_m68k/mmu.cpp @@ -643,8 +643,7 @@ mmu_init(void) extern "C" status_t -platform_allocate_region(void **_address, size_t size, uint8 protection, - bool /*exactAddress*/) +platform_allocate_region(void **_address, size_t size, uint8 protection) { void *address = mmu_allocate(*_address, size); if (address == NULL) diff --git a/src/system/boot/platform/atari_m68k/mmu.cpp b/src/system/boot/platform/atari_m68k/mmu.cpp index 92fedd80f1..b69194277c 100644 --- a/src/system/boot/platform/atari_m68k/mmu.cpp +++ b/src/system/boot/platform/atari_m68k/mmu.cpp @@ -648,8 +648,7 @@ mmu_init(void) extern "C" status_t -platform_allocate_region(void **_address, size_t size, uint8 protection, - bool /*exactAddress*/) +platform_allocate_region(void **_address, size_t size, uint8 protection) { void *address = mmu_allocate(*_address, size); if (address == NULL) diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index 4894d1bb27..ae53684f34 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -806,8 +806,7 @@ mmu_init(void) extern "C" status_t -platform_allocate_region(void **_address, size_t size, uint8 protection, - bool /*exactAddress*/) +platform_allocate_region(void **_address, size_t size, uint8 protection) { void *address = mmu_allocate(*_address, size); if (address == NULL) diff --git a/src/system/boot/platform/efi/arch/arm/arch_mmu.cpp b/src/system/boot/platform/efi/arch/arm/arch_mmu.cpp index 137a75d811..54897ed667 100644 --- a/src/system/boot/platform/efi/arch/arm/arch_mmu.cpp +++ b/src/system/boot/platform/efi/arch/arm/arch_mmu.cpp @@ -219,7 +219,7 @@ static void arch_mmu_allocate_page_tables(void) { if (platform_allocate_region((void **)&sPageDirectory, - ARM_MMU_L1_TABLE_SIZE + ALIGN_PAGEDIR + PAGE_TABLE_AREA_SIZE, 0, false) != B_OK) + ARM_MMU_L1_TABLE_SIZE + ALIGN_PAGEDIR + PAGE_TABLE_AREA_SIZE, 0) != B_OK) panic("Failed to allocate page directory."); sPageDirectory = (uint32 *)ROUNDUP((uint32)sPageDirectory, ALIGN_PAGEDIR); memset(sPageDirectory, 0, ARM_MMU_L1_TABLE_SIZE); @@ -238,10 +238,13 @@ arch_mmu_allocate_page_tables(void) static void arch_mmu_allocate_vector_table(void) { - if (platform_allocate_region((void **)&sVectorTable, B_PAGE_SIZE, 0, false) != B_OK) + void *vectorTable = NULL; + if (platform_allocate_region(&vectorTable, B_PAGE_SIZE, 0) != B_OK) panic("Failed to allocate vector table."); + if (platform_assign_kernel_address_for_region(vectorTable, (addr_t)sVectorTable) != B_OK) + panic("Failed to assign vector table address"); - memset(sVectorTable, 0, B_PAGE_SIZE); + memset(vectorTable, 0, B_PAGE_SIZE); } diff --git a/src/system/boot/platform/efi/arch/arm/arch_start.cpp b/src/system/boot/platform/efi/arch/arm/arch_start.cpp index 4e51b66bf4..52ef378a4e 100644 --- a/src/system/boot/platform/efi/arch/arm/arch_start.cpp +++ b/src/system/boot/platform/efi/arch/arm/arch_start.cpp @@ -58,25 +58,30 @@ static void * allocate_trampoline_page(void) { void *trampolinePage = NULL; - if (platform_allocate_lomem(&trampolinePage, B_PAGE_SIZE) == B_OK) - return trampolinePage; + if (platform_allocate_region_below(&trampolinePage, B_PAGE_SIZE, + KERNEL_LOAD_BASE - B_PAGE_SIZE) == B_OK) { + if (platform_assign_kernel_address_for_region(trampolinePage, + (addr_t)trampolinePage) == B_OK) { + return trampolinePage; + } - trampolinePage = (void *)get_next_virtual_address(B_PAGE_SIZE); - if (platform_allocate_region(&trampolinePage, B_PAGE_SIZE, 0, true) == B_OK) - return trampolinePage; + if (platform_free_region(trampolinePage, B_PAGE_SIZE) != B_OK) + return NULL; + } trampolinePage = NULL; - if (platform_allocate_region(&trampolinePage, B_PAGE_SIZE, 0, false) != B_OK) - return NULL; + if (platform_allocate_region(&trampolinePage, B_PAGE_SIZE, 0) == B_OK) { + if (platform_assign_kernel_address_for_region(trampolinePage, + (addr_t)trampolinePage) == B_OK) { + ASSERT_ALWAYS((uint32)trampolinePage >= 0x88000000); + return trampolinePage; + } - if (platform_free_region(trampolinePage, B_PAGE_SIZE) != B_OK) - return NULL; + if (platform_free_region(trampolinePage, B_PAGE_SIZE) != B_OK) + return NULL; + } - if (platform_allocate_region(&trampolinePage, B_PAGE_SIZE, 0, true) != B_OK) - return NULL; - - ASSERT_ALWAYS((uint32_t)trampolinePage >= 0x88000000); - return trampolinePage; + return NULL; } @@ -86,7 +91,7 @@ arch_start_kernel(addr_t kernelEntry) // Allocate virtual memory for kernel args struct kernel_args *kernelArgs = NULL; if (platform_allocate_region((void **)&kernelArgs, - sizeof(struct kernel_args), 0, false) != B_OK) + sizeof(struct kernel_args), 0) != B_OK) panic("Failed to allocate kernel args."); addr_t virtKernelArgs; diff --git a/src/system/boot/platform/efi/arch/arm64/arch_mmu.h b/src/system/boot/platform/efi/arch/arm64/arch_mmu.h index 2c4ceee511..8d9e3ebcc1 100644 --- a/src/system/boot/platform/efi/arch/arm64/arch_mmu.h +++ b/src/system/boot/platform/efi/arch/arm64/arch_mmu.h @@ -240,7 +240,7 @@ public: uint64* page = NULL; #if 0 // BUG: allocation here overlaps assigned memory ... - if (platform_allocate_region((void **)&page, size, 0, false) == B_OK) { + if (platform_allocate_region((void **)&page, size, 0) == B_OK) { #else // TODO: luckly size == B_PAGE_SIZE == 4KB ... page = reinterpret_cast(mmu_allocate_page()); diff --git a/src/system/boot/platform/efi/arch/riscv64/arch_smp.cpp b/src/system/boot/platform/efi/arch/riscv64/arch_smp.cpp index d46de71723..e46b4d84c4 100644 --- a/src/system/boot/platform/efi/arch/riscv64/arch_smp.cpp +++ b/src/system/boot/platform/efi/arch/riscv64/arch_smp.cpp @@ -189,9 +189,9 @@ arch_smp_init_other_cpus(void) void * stack = NULL; const size_t size = KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; - if (platform_allocate_region(&stack, size, 0, false) != B_OK) { + if (platform_allocate_region(&stack, size, 0) != B_OK) panic("Unable to allocate AP stack"); - } + memset(stack, 0, size); gKernelArgs.cpu_kstack[i].start = fix_address((uint64_t)stack); gKernelArgs.cpu_kstack[i].size = size; diff --git a/src/system/boot/platform/efi/arch/riscv64/arch_start.cpp b/src/system/boot/platform/efi/arch/riscv64/arch_start.cpp index 6a9acc65e8..d976ed0c27 100644 --- a/src/system/boot/platform/efi/arch/riscv64/arch_start.cpp +++ b/src/system/boot/platform/efi/arch/riscv64/arch_start.cpp @@ -48,7 +48,7 @@ arch_start_kernel(addr_t kernelEntry) // Allocate virtual memory for kernel args struct kernel_args *kernelArgs = NULL; if (platform_allocate_region((void **)&kernelArgs, - sizeof(struct kernel_args), 0, false) != B_OK) + sizeof(struct kernel_args), 0) != B_OK) panic("Failed to allocate kernel args."); addr_t virtKernelArgs; diff --git a/src/system/boot/platform/efi/arch/x86/arch_mmu.cpp b/src/system/boot/platform/efi/arch/x86/arch_mmu.cpp index 9b62196a50..e9ade68298 100644 --- a/src/system/boot/platform/efi/arch/x86/arch_mmu.cpp +++ b/src/system/boot/platform/efi/arch/x86/arch_mmu.cpp @@ -97,7 +97,7 @@ arch_mmu_init_gdt(gdt_idt_descr &bootGDTDescriptor) segment_descriptor *bootGDT = NULL; if (platform_allocate_region((void **)&bootGDT, - BOOT_GDT_SEGMENT_COUNT * sizeof(segment_descriptor), 0, false) != B_OK) { + BOOT_GDT_SEGMENT_COUNT * sizeof(segment_descriptor), 0) != B_OK) { panic("Failed to allocate GDT.\n"); } @@ -224,7 +224,7 @@ static void arch_mmu_allocate_page_directory(void) { if (platform_allocate_region((void **)&sPageDirectory, - B_PAGE_SIZE + ALIGN_PAGEDIR, 0, false) != B_OK) + B_PAGE_SIZE + ALIGN_PAGEDIR, 0) != B_OK) panic("Failed to allocate page directory."); sPageDirectory = (uint32_t *)ROUNDUP((uint32_t)sPageDirectory, ALIGN_PAGEDIR); memset(sPageDirectory, 0, B_PAGE_SIZE); diff --git a/src/system/boot/platform/efi/arch/x86/arch_smp.cpp b/src/system/boot/platform/efi/arch/x86/arch_smp.cpp index 28274e9335..cd3e1389ec 100644 --- a/src/system/boot/platform/efi/arch/x86/arch_smp.cpp +++ b/src/system/boot/platform/efi/arch/x86/arch_smp.cpp @@ -242,7 +242,7 @@ arch_smp_init_other_cpus(void) // create a final stack the trampoline code will put the ap processor on void * stack = NULL; const size_t size = KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; - if (platform_allocate_region(&stack, size, 0, false) != B_OK) { + if (platform_allocate_region(&stack, size, 0) != B_OK) { panic("Unable to allocate AP stack"); } memset(stack, 0, size); diff --git a/src/system/boot/platform/efi/arch/x86/arch_start.cpp b/src/system/boot/platform/efi/arch/x86/arch_start.cpp index 8ce30741ce..dfe6ca3180 100644 --- a/src/system/boot/platform/efi/arch/x86/arch_start.cpp +++ b/src/system/boot/platform/efi/arch/x86/arch_start.cpp @@ -64,7 +64,7 @@ arch_start_kernel(addr_t kernelEntry) // Allocate virtual memory for kernel args struct kernel_args *kernelArgs = NULL; if (platform_allocate_region((void **)&kernelArgs, - sizeof(struct kernel_args), 0, false) != B_OK) + sizeof(struct kernel_args), 0) != B_OK) panic("Failed to allocate kernel args."); addr_t virtKernelArgs; diff --git a/src/system/boot/platform/efi/arch/x86_64/arch_mmu.cpp b/src/system/boot/platform/efi/arch/x86_64/arch_mmu.cpp index d73550d59a..3b96eab985 100644 --- a/src/system/boot/platform/efi/arch/x86_64/arch_mmu.cpp +++ b/src/system/boot/platform/efi/arch/x86_64/arch_mmu.cpp @@ -201,7 +201,7 @@ arch_mmu_generate_post_efi_page_tables(size_t memory_map_size, // Allocate the top level PML4. pml4 = NULL; - if (platform_allocate_region((void**)&pml4, B_PAGE_SIZE, 0, false) != B_OK) + if (platform_allocate_region((void**)&pml4, B_PAGE_SIZE, 0) != B_OK) panic("Failed to allocate PML4."); gKernelArgs.arch_args.phys_pgdir = (uint32_t)(addr_t)pml4; memset(pml4, 0, B_PAGE_SIZE); diff --git a/src/system/boot/platform/efi/debug.cpp b/src/system/boot/platform/efi/debug.cpp index 91e0ec20b8..1279318603 100644 --- a/src/system/boot/platform/efi/debug.cpp +++ b/src/system/boot/platform/efi/debug.cpp @@ -87,7 +87,7 @@ allocate_ring_buffer(void) void* buffer = NULL; size_t size = 1024 * 1024; - if (platform_allocate_region(&buffer, size, 0, false) != B_OK) + if (platform_allocate_region(&buffer, size, 0) != B_OK) return; sDebugSyslogBuffer = create_ring_buffer_etc(buffer, size, 0); diff --git a/src/system/boot/platform/efi/mmu.cpp b/src/system/boot/platform/efi/mmu.cpp index baca4fc1ab..956c09d211 100644 --- a/src/system/boot/platform/efi/mmu.cpp +++ b/src/system/boot/platform/efi/mmu.cpp @@ -42,7 +42,9 @@ struct memory_region { }; -static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + 32 * 1024 * 1024; +static const size_t kMaxKernelSize = 0x2000000; // 32 MB +static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize; + static memory_region *allocated_regions = NULL; @@ -91,24 +93,14 @@ get_current_virtual_address() // addresses to kernel addresses. extern "C" status_t -platform_allocate_region(void **_address, size_t size, uint8 /* protection */, - bool exactAddress) +platform_allocate_region(void **_address, size_t size, uint8 protection) { TRACE("%s: called\n", __func__); - efi_physical_addr addr; size_t pages = ROUNDUP(size, B_PAGE_SIZE) / B_PAGE_SIZE; - efi_status status; - - if (exactAddress) { - addr = (efi_physical_addr)(addr_t)*_address; - status = kBootServices->AllocatePages(AllocateAddress, - EfiLoaderData, pages, &addr); - } else { - addr = 0; - status = kBootServices->AllocatePages(AllocateAnyPages, - EfiLoaderData, pages, &addr); - } + efi_physical_addr addr = 0; + efi_status status = kBootServices->AllocatePages(AllocateAnyPages, + EfiLoaderData, pages, &addr); if (status != EFI_SUCCESS) return B_NO_MEMORY; @@ -121,14 +113,9 @@ platform_allocate_region(void **_address, size_t size, uint8 /* protection */, memory_region *region = new(std::nothrow) memory_region { next: allocated_regions, -#ifdef __riscv - // Disables allocation at fixed virtual address vaddr: 0, -#else - vaddr: *_address == NULL ? 0 : (addr_t)*_address, -#endif paddr: (phys_addr_t)addr, - size: size + size: size, }; if (region == NULL) { @@ -136,6 +123,20 @@ platform_allocate_region(void **_address, size_t size, uint8 /* protection */, return B_NO_MEMORY; } + if (*_address != NULL) { + // This is only useful for mapping the kernel itself. + // Validate base and size, but don't check for duplicates. + addr_t virtualAddress = (addr_t)*_address; + if (virtualAddress < KERNEL_LOAD_BASE + || (virtualAddress + size) > (KERNEL_LOAD_BASE + kMaxKernelSize)) { + kBootServices->FreePages(addr, pages); + delete region; + return B_BAD_VALUE; + } + + region->vaddr = virtualAddress; + } + #ifdef TRACE_MMU //region->dprint("Allocated"); #endif @@ -146,11 +147,11 @@ platform_allocate_region(void **_address, size_t size, uint8 /* protection */, extern "C" status_t -platform_allocate_lomem(void **_address, size_t size) +platform_allocate_region_below(void **_address, size_t size, phys_addr_t maxAddress) { TRACE("%s: called\n", __func__); - efi_physical_addr addr = KERNEL_LOAD_BASE - B_PAGE_SIZE; + efi_physical_addr addr = maxAddress; size_t pages = ROUNDUP(size, B_PAGE_SIZE) / B_PAGE_SIZE; efi_status status = kBootServices->AllocatePages(AllocateMaxAddress, EfiLoaderData, pages, &addr); @@ -159,7 +160,7 @@ platform_allocate_lomem(void **_address, size_t size) memory_region *region = new(std::nothrow) memory_region { next: allocated_regions, - vaddr: (addr_t)addr, + vaddr: 0, paddr: (phys_addr_t)addr, size: size }; @@ -234,6 +235,29 @@ convert_physical_ranges() } +extern "C" status_t +platform_assign_kernel_address_for_region(void *address, addr_t assign) +{ + // Double cast needed to avoid sign extension issues on 32-bit architecture + phys_addr_t addr = (phys_addr_t)(addr_t)address; + + for (memory_region *region = allocated_regions; region; + region = region->next) { + if (region->paddr <= addr && addr < region->paddr + region->size) { + if (region->paddr != addr) + return EINVAL; + if (region->vaddr != 0) + return EALREADY; + + region->vaddr = assign; + return B_OK; + } + } + + return B_ERROR; +} + + extern "C" status_t platform_bootloader_address_to_kernel_address(void *address, addr_t *_result) { @@ -249,9 +273,9 @@ platform_bootloader_address_to_kernel_address(void *address, addr_t *_result) region = region->next) { if (region->paddr <= addr && addr < region->paddr + region->size) { // Lazily allocate virtual memory. - if (region->vaddr == 0) { + if (region->vaddr == 0) region->vaddr = get_next_virtual_address(region->size); - } + *_result = region->vaddr + (addr - region->paddr); //dprintf("Converted bootloader address %p in region %#lx-%#lx to %#lx\n", // address, region->paddr, region->paddr + region->size, *_result); diff --git a/src/system/boot/platform/efi/mmu.h b/src/system/boot/platform/efi/mmu.h index 447954c91a..12a9ac754e 100644 --- a/src/system/boot/platform/efi/mmu.h +++ b/src/system/boot/platform/efi/mmu.h @@ -41,13 +41,16 @@ bool mmu_next_region(void** cookie, addr_t* vaddr, phys_addr_t* paddr, size_t* s extern addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags); +extern status_t platform_assign_kernel_address_for_region(void *address, addr_t assign); + extern status_t platform_kernel_address_to_bootloader_address(addr_t address, void **_result); extern status_t platform_bootloader_address_to_kernel_address(void *address, addr_t *_result); -extern status_t platform_allocate_lomem(void **_address, size_t size); +extern status_t platform_allocate_region_below(void **_address, + size_t size, phys_addr_t maxAddress); #ifdef __cplusplus } diff --git a/src/system/boot/platform/efi/start.cpp b/src/system/boot/platform/efi/start.cpp index 2ccb802f46..831963b2f7 100644 --- a/src/system/boot/platform/efi/start.cpp +++ b/src/system/boot/platform/efi/start.cpp @@ -197,8 +197,7 @@ platform_start_kernel(void) // map in a kernel stack void *stack_address = NULL; if (platform_allocate_region(&stack_address, - KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false) - != B_OK) { + KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0) != B_OK) { panic("Unabled to allocate a stack"); } gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address); diff --git a/src/system/boot/platform/next_m68k/mmu.cpp b/src/system/boot/platform/next_m68k/mmu.cpp index 6740226356..79eb6a3f05 100644 --- a/src/system/boot/platform/next_m68k/mmu.cpp +++ b/src/system/boot/platform/next_m68k/mmu.cpp @@ -136,8 +136,7 @@ mmu_init(void) extern "C" status_t -platform_allocate_region(void **_address, size_t size, uint8 protection, - bool /*exactAddress*/) +platform_allocate_region(void **_address, size_t size, uint8 protection) { return B_UNSUPPORTED; } diff --git a/src/system/boot/platform/openfirmware/heap.cpp b/src/system/boot/platform/openfirmware/heap.cpp index ccd97b008d..4e0c83411a 100644 --- a/src/system/boot/platform/openfirmware/heap.cpp +++ b/src/system/boot/platform/openfirmware/heap.cpp @@ -27,7 +27,7 @@ platform_allocate_heap_region(size_t size, void **_base) *_base = NULL; status_t error = platform_allocate_region(_base, size, - B_READ_AREA | B_WRITE_AREA, false); + B_READ_AREA | B_WRITE_AREA); if (error != B_OK) return error; diff --git a/src/system/boot/platform/openfirmware/mmu.cpp b/src/system/boot/platform/openfirmware/mmu.cpp index 4f47608268..7c6bc2fc72 100644 --- a/src/system/boot/platform/openfirmware/mmu.cpp +++ b/src/system/boot/platform/openfirmware/mmu.cpp @@ -12,14 +12,13 @@ status_t -platform_allocate_region(void **_address, size_t size, uint8 protection, - bool exactAddress) +platform_allocate_region(void **_address, size_t size, uint8 protection) { if (size == 0) return B_BAD_VALUE; void *address = arch_mmu_allocate(*_address, size, protection, - exactAddress); + false); if (address == NULL) return B_NO_MEMORY; diff --git a/src/system/boot/platform/pxe_ia32/network.cpp b/src/system/boot/platform/pxe_ia32/network.cpp index abf5f0e78a..6e500ba68e 100644 --- a/src/system/boot/platform/pxe_ia32/network.cpp +++ b/src/system/boot/platform/pxe_ia32/network.cpp @@ -433,7 +433,7 @@ TFTP::ReceiveFile(const char* fileName, uint8** data, size_t* size) // allocate memory for the data uint8* fileData = NULL; if (platform_allocate_region((void**)&fileData, fileSize, - B_READ_AREA | B_WRITE_AREA, false) != B_OK) { + B_READ_AREA | B_WRITE_AREA) != B_OK) { TRACE(("TFTP: allocating memory for file data failed\n")); return B_NO_MEMORY; } diff --git a/src/system/boot/platform/riscv/mmu.cpp b/src/system/boot/platform/riscv/mmu.cpp index 9640533571..c19bcb4da0 100644 --- a/src/system/boot/platform/riscv/mmu.cpp +++ b/src/system/boot/platform/riscv/mmu.cpp @@ -297,14 +297,10 @@ GetSatp() // #pragma mark - extern "C" status_t -platform_allocate_region(void** address, size_t size, uint8 protection, - bool exactAddress) +platform_allocate_region(void** address, size_t size, uint8 protection) { size = ROUNDUP(size, B_PAGE_SIZE); - if (exactAddress) - return B_ERROR; - ObjectDeleter region(new(std::nothrow) MemoryRegion()); if (!region.IsSet()) return B_NO_MEMORY; @@ -417,8 +413,7 @@ mmu_init_for_kernel(addr_t& satp) void* stack_address = NULL; if (platform_allocate_region(&stack_address, KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, - B_READ_AREA | B_WRITE_AREA, false) - != B_OK) { + B_READ_AREA | B_WRITE_AREA) != B_OK) { panic("Unabled to allocate a stack"); } gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address); diff --git a/src/system/boot/platform/u-boot/arch/ppc/arch_mmu.cpp b/src/system/boot/platform/u-boot/arch/ppc/arch_mmu.cpp index 1c69149d38..37f69d405f 100644 --- a/src/system/boot/platform/u-boot/arch/ppc/arch_mmu.cpp +++ b/src/system/boot/platform/u-boot/arch/ppc/arch_mmu.cpp @@ -350,8 +350,7 @@ mmu_init(void* fdt) extern "C" status_t -platform_allocate_region(void **_address, size_t size, uint8 protection, - bool /*exactAddress*/) +platform_allocate_region(void **_address, size_t size, uint8 protection) { TRACE(("platform_allocate_region(&%p, %zd)\n", *_address, size));