Finish memory allocation for programs

This commit is contained in:
Baptiste Wicht 2014-01-09 20:36:40 +01:00
parent 55f34aa4b2
commit 2df9def686
5 changed files with 115 additions and 58 deletions

View File

@ -15,14 +15,6 @@ void init_memory_manager();
void* k_malloc(uint64_t bytes);
void k_free(void* block);
/*!
* \brief Allocates bytes of memory at the given address.
* \param address The virtual address where memory should be put.
* \param bytes The number of bytes to allocate.
* \return The address of the physical allocated memory, 0 indicates failure.
*/
void* k_malloc(uint64_t address, uint64_t bytes);
template<typename T>
T* k_malloc(){
return reinterpret_cast<T*>(k_malloc(sizeof(T)));

View File

@ -34,6 +34,9 @@ bool identity_map(void* virt, size_t pages);
bool map(void* virt, void* physical);
bool map(void* virt, void* physical, size_t pages);
bool unmap(void* virt);
bool unmap(void* virt, size_t pages);
} //end of namespace paging
#endif

View File

@ -304,34 +304,6 @@ void* k_malloc(uint64_t bytes){
return b;
}
void* k_malloc(uint64_t address, uint64_t bytes){
auto page = reinterpret_cast<uintptr_t>(paging::page_align(reinterpret_cast<void*>(address)));
//1. Verify that all the necessary pages are free
while(page < address + bytes){
//If the virtual address is already mapped, indicates failure
if(paging::page_present(reinterpret_cast<void*>(page))){
return nullptr;
}
page += paging::PAGE_SIZE;
}
//2. Allocate enough physical memory
auto physical = k_malloc(bytes);
//3. Map physical allocated memory to the necessary virtual emory
auto left_padding = page % paging::PAGE_SIZE;
auto pages = ((bytes + left_padding) / paging::PAGE_SIZE) + 1;
if(!paging::map(paging::page_align(reinterpret_cast<void*>(address)), physical, pages)){
return nullptr;
}
return physical;
}
malloc_header_chunk* left_block(malloc_header_chunk* b){
auto left_footer = reinterpret_cast<malloc_footer_chunk*>(
reinterpret_cast<uintptr_t>(b) - sizeof(malloc_footer_chunk));

View File

@ -6,7 +6,6 @@
//=======================================================================
#include "paging.hpp"
#include "console.hpp"
#include "stl/types.hpp"
#include "stl/algorithms.hpp"
@ -176,6 +175,65 @@ bool paging::map(void* virt, void* physical, size_t pages){
return true;
}
bool paging::unmap(void* virt){
//The address must be page-aligned
if(!page_aligned(virt)){
return false;
}
//Find the correct indexes inside the paging table for the virtual address
auto table = (reinterpret_cast<uintptr_t>(virt) >> 12) & 0x1FF;
auto directory = (reinterpret_cast<uintptr_t>(virt) >> 21) & 0x1FF;
auto directory_ptr = (reinterpret_cast<uintptr_t>(virt) >> 30) & 0x1FF;
auto pml4 = (reinterpret_cast<uintptr_t>(virt) >> 39) & 0x1FF;
pml4t_t pml4t = reinterpret_cast<pml4t_t>(0x70000);
//If not present, returns directly
if(!(reinterpret_cast<uintptr_t>(pml4t[pml4]) & PRESENT)){
return true;
}
auto pdpt = reinterpret_cast<pdpt_t>(reinterpret_cast<uintptr_t>(pml4t[pml4]) & ~0xFFF);
//If not present, returns directly
if(!(reinterpret_cast<uintptr_t>(pdpt[directory_ptr]) & PRESENT)){
return true;
}
auto pdt = reinterpret_cast<pdt_t>(reinterpret_cast<uintptr_t>(pdpt[directory_ptr]) & ~0xFFF);
//If not present, returns directly
if(!(reinterpret_cast<uintptr_t>(pdt[directory]) & PRESENT)){
return true;
}
auto pt = reinterpret_cast<pt_t>(reinterpret_cast<uintptr_t>(pdt[directory]) & ~0xFFF);
//Unmap the virtual address
pt[table] = 0x0;
return true;
}
bool paging::unmap(void* virt, size_t pages){
//The address must be page-aligned
if(!page_aligned(virt)){
return false;
}
//Unmap each page
for(size_t page = 0; page < pages; ++page){
auto virt_addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(virt) + page * PAGE_SIZE);
if(!unmap(virt_addr)){
return false;
}
}
return true;
}
bool paging::identity_map(void* virt){
return map(virt, virt);
}

View File

@ -16,6 +16,7 @@
#include "e820.hpp"
#include "rtc.hpp"
#include "elf.hpp"
#include "paging.hpp"
//Commands
#include "sysinfo.hpp"
@ -745,52 +746,83 @@ void exec_command(const std::vector<std::string>& params){
auto buffer = content.c_str();
auto header = reinterpret_cast<elf::elf_header*>(buffer);
auto section_header_table = reinterpret_cast<elf::section_header*>(buffer + header->e_shoff);
auto program_header_table = reinterpret_cast<elf::program_header*>(buffer + header->e_phoff);
auto allocated_segments = new void*[header->e_shnum];
auto allocated_segments = new void*[header->e_phnum];
bool failed = false;
for(size_t s = 0; s < header->e_shnum; ++s){
auto& s_header = section_header_table[s];
for(size_t p = 0; p < header->e_phnum; ++p){
auto& p_header = program_header_table[p];
allocated_segments[s] = nullptr;
allocated_segments[p] = nullptr;
if(s_header.sh_flags & 0x2){
auto memory = k_malloc(s_header.sh_addr, s_header.sh_size);
if(p_header.p_type == 1){
//1. Verify that there is nothing at the necessary virtual address
auto address = p_header.p_vaddr;
auto page = reinterpret_cast<uintptr_t>(paging::page_align(reinterpret_cast<void*>(address)));
k_printf("%h (virt) was allocated in %h (phys)\n", reinterpret_cast<size_t>(s_header.sh_addr), reinterpret_cast<size_t>(memory));
//1. Verify that all the necessary pages are free
while(page < address + p_header.p_memsz){
//If the virtual address is already mapped, indicates failure
if(paging::page_present(reinterpret_cast<void*>(page))){
failed = true;
break;
}
page += paging::PAGE_SIZE;
}
if(failed){
break;
}
//2. Get some physical memory
auto memory = k_malloc(paging::PAGE_SIZE + p_header.p_memsz);
if(!memory){
failed = true;
break;
}
auto test_a = reinterpret_cast<size_t*>(reinterpret_cast<size_t>(memory) + 64);
k_print_line(*test_a);
//3. Find a start of a page inside the physical memory
auto test_b = reinterpret_cast<size_t*>(s_header.sh_addr + 64);
k_print_line(*test_b);
auto aligned_memory = paging::page_aligned(memory) ? memory : reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(memory) / paging::PAGE_SIZE + 1) * paging::PAGE_SIZE);
allocated_segments[s] = memory;
//4. Map physical allocated memory to the necessary virtual memory
auto left_padding = address % paging::PAGE_SIZE;
auto pages = ((p_header.p_memsz+ left_padding) / paging::PAGE_SIZE) + 1;
if(!paging::map(aligned_memory, paging::page_align(reinterpret_cast<void*>(address)), pages)){
failed = true;
break;
}
allocated_segments[p] = memory;
}
}
if(!failed){
if(failed){
//TODO
} else {
k_print_line("Unable to allocate memory for the application");
}
k_print_line("Free");
//Release physical memory
for(size_t i = 0; i < header->e_shnum; ++i){
auto a = allocated_segments[i];
for(size_t p = 0; p < header->e_phnum; ++p){
auto& p_header = program_header_table[p];
auto a = allocated_segments[p];
if(a){
k_free(a);
auto aligned_memory = paging::page_aligned(a) ? a : reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(a) / paging::PAGE_SIZE + 1) * paging::PAGE_SIZE);
auto left_padding = p_header.p_vaddr % paging::PAGE_SIZE;
auto pages = ((p_header.p_memsz+ left_padding) / paging::PAGE_SIZE) + 1;
paging::unmap(aligned_memory, pages);
}
}
//TODO Release all the allocated segments
}
void shutdown_command(const std::vector<std::string>&){