diff --git a/kernel/include/memory/MemoryManager.h b/kernel/include/memory/MemoryManager.h index bc74e762..926c79cc 100644 --- a/kernel/include/memory/MemoryManager.h +++ b/kernel/include/memory/MemoryManager.h @@ -20,6 +20,9 @@ namespace MemoryManager void* get_page(int flags = MAP_READ_WRITE); void* get_pages(uint64_t count, int flags = MAP_READ_WRITE); + void* get_page_at(uint64_t addr, int flags = MAP_READ_WRITE); + void* get_pages_at(uint64_t addr, uint64_t count, int flags = MAP_READ_WRITE); + void release_page(void* page); void release_pages(void* pages, uint64_t count); } \ No newline at end of file diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 97cb2eed..599c73fb 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -90,14 +90,6 @@ void MemoryManager::release_mapping(void* mapping) void* MemoryManager::get_page(int flags) { - void* physicalAddress = PMM::request_page(); - if (PMM_DID_FAIL(physicalAddress)) - { -#ifdef MM_DEBUG - kwarnln("OOM while allocating one page of memory. this is not good..."); -#endif - return 0; - } uint64_t virtualAddress = KernelHeap::request_virtual_page(); if (!virtualAddress) { @@ -106,8 +98,21 @@ void* MemoryManager::get_page(int flags) #endif return 0; } - kernelVMM.map(virtualAddress, (uint64_t)physicalAddress, flags); - return (void*)virtualAddress; + return get_page_at(virtualAddress, flags); +} + +void* MemoryManager::get_page_at(uint64_t addr, int flags) +{ + void* physicalAddress = PMM::request_page(); + if (PMM_DID_FAIL(physicalAddress)) + { +#ifdef MM_DEBUG + kwarnln("OOM while allocating one page of memory. this is not good..."); +#endif + return 0; + } + kernelVMM.map(addr, (uint64_t)physicalAddress, flags); + return (void*)addr; } void MemoryManager::release_page(void* page) @@ -134,6 +139,16 @@ void* MemoryManager::get_pages(uint64_t count, int flags) return 0; // Out of virtual address in the kernel heap range (-128M to -64M). This should be difficult to // achieve... } + return get_pages_at(virtualAddress, count, flags); +} + +void* MemoryManager::get_pages_at(uint64_t addr, uint64_t count, int flags) +{ + if (!count) return 0; + if (count == 1) return get_page_at(addr, flags); +#ifdef MM_DEBUG + kdbgln("allocating several pages (%ld), at address %ld", count, addr); +#endif for (uint64_t i = 0; i < count; i++) { void* physicalAddress = PMM::request_page(); @@ -144,15 +159,14 @@ void* MemoryManager::get_pages(uint64_t count, int flags) #ifdef MM_DEBUG kwarnln("OOM while allocating page %ld of memory. this might be recoverable..."); #endif - release_pages((void*)virtualAddress, i); // release the pages we have already mapped return 0; } - kernelVMM.map(virtualAddress + (i * 4096), (uint64_t)physicalAddress, flags); + kernelVMM.map(addr + (i * 4096), (uint64_t)physicalAddress, flags); #ifdef MM_DEBUG kdbgln("allocating virtual %lx, physical %lx", virtualAddress + (i * 4096), (uint64_t)physicalAddress); #endif } - return (void*)virtualAddress; + return (void*)addr; } void MemoryManager::release_pages(void* pages, uint64_t count)