Author: bonefish Date: 2010-01-08 16:58:08 +0100 (Fri, 08 Jan 2010) New Revision: 34947 Changeset: http://dev.haiku-os.org/changeset/34947/haiku Modified: haiku/trunk/src/system/boot/platform/bios_ia32/mmu.cpp Log: * Changed/fixed mmu_map_physical_memory() semantics: It does now always allocate all pages the given range intersects with. When not page aligned it could fail to allocate the last page. * mmu_free(): - Adjusted semantics to be compatible with mmu_map_physical_memory(). - The validity check was broken, because page number and addresses were mixed, and because KERNEL_BASE + kMaxKernelSize doesn't mark the end of the allocated virtual ranges. - The final check against sNextVirtualAddress was broken. Modified: haiku/trunk/src/system/boot/platform/bios_ia32/mmu.cpp =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/mmu.cpp 2010-01-08 11:42:44 UTC (rev 34946) +++ haiku/trunk/src/system/boot/platform/bios_ia32/mmu.cpp 2010-01-08 15:58:08 UTC (rev 34947) @@ -361,6 +361,12 @@ // #pragma mark - +/*! + Neither \a virtualAddress nor \a size need to be aligned, but the function + will map all pages the range intersects with. + If physicalAddress is not page-aligned, the returned virtual address will + have the same "misalignment". +*/ extern "C" addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags) { @@ -368,6 +374,7 @@ addr_t pageOffset = physicalAddress & (B_PAGE_SIZE - 1); physicalAddress -= pageOffset; + size += pageOffset; for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) { map_page(get_next_virtual_page(), physicalAddress + offset, flags); @@ -421,6 +428,8 @@ /*! This will unmap the allocated chunk of memory from the virtual address space. It might not actually free memory (as its implementation is very simple), but it might. + Neither \a virtualAddress nor \a size need to be aligned, but the function + will unmap all pages the range intersects with. */ extern "C" void mmu_free(void *virtualAddress, size_t size) @@ -428,23 +437,23 @@ TRACE(("mmu_free(virtualAddress = %p, size: %ld)\n", virtualAddress, size)); addr_t address = (addr_t)virtualAddress; - size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE; - // get number of pages to map + addr_t pageOffset = address % B_PAGE_SIZE; + address -= pageOffset; + size = (size + pageOffset + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE; // is the address within the valid range? - if (address < KERNEL_BASE - || address + size >= KERNEL_BASE + kMaxKernelSize) { + if (address < KERNEL_BASE || address + size > sNextVirtualAddress) { panic("mmu_free: asked to unmap out of range region (%p, size %lx)\n", (void *)address, size); } // unmap all pages within the range - for (uint32 i = 0; i < size; i++) { + for (size_t i = 0; i < size; i += B_PAGE_SIZE) { unmap_page(address); address += B_PAGE_SIZE; } - if (address == sNextVirtualAddress) { + if (address + size == sNextVirtualAddress) { // we can actually reuse the virtual address space sNextVirtualAddress -= size; }