diff --git a/kernel/include/memory.hpp b/kernel/include/memory.hpp index ba6b8651..a01acd66 100644 --- a/kernel/include/memory.hpp +++ b/kernel/include/memory.hpp @@ -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 T* k_malloc(){ return reinterpret_cast(k_malloc(sizeof(T))); diff --git a/kernel/include/paging.hpp b/kernel/include/paging.hpp index f3f76cd4..2235e101 100644 --- a/kernel/include/paging.hpp +++ b/kernel/include/paging.hpp @@ -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 diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index 8ba8bc77..36214c03 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -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(paging::page_align(reinterpret_cast(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(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(address)), physical, pages)){ - return nullptr; - } - - return physical; -} - malloc_header_chunk* left_block(malloc_header_chunk* b){ auto left_footer = reinterpret_cast( reinterpret_cast(b) - sizeof(malloc_footer_chunk)); diff --git a/kernel/src/paging.cpp b/kernel/src/paging.cpp index a896abfa..d0730034 100644 --- a/kernel/src/paging.cpp +++ b/kernel/src/paging.cpp @@ -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(virt) >> 12) & 0x1FF; + auto directory = (reinterpret_cast(virt) >> 21) & 0x1FF; + auto directory_ptr = (reinterpret_cast(virt) >> 30) & 0x1FF; + auto pml4 = (reinterpret_cast(virt) >> 39) & 0x1FF; + + pml4t_t pml4t = reinterpret_cast(0x70000); + + //If not present, returns directly + if(!(reinterpret_cast(pml4t[pml4]) & PRESENT)){ + return true; + } + + auto pdpt = reinterpret_cast(reinterpret_cast(pml4t[pml4]) & ~0xFFF); + + //If not present, returns directly + if(!(reinterpret_cast(pdpt[directory_ptr]) & PRESENT)){ + return true; + } + + auto pdt = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); + + //If not present, returns directly + if(!(reinterpret_cast(pdt[directory]) & PRESENT)){ + return true; + } + + auto pt = reinterpret_cast(reinterpret_cast(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(reinterpret_cast(virt) + page * PAGE_SIZE); + + if(!unmap(virt_addr)){ + return false; + } + } + + return true; +} + bool paging::identity_map(void* virt){ return map(virt, virt); } diff --git a/kernel/src/shell.cpp b/kernel/src/shell.cpp index d3bc6753..dedd96fd 100644 --- a/kernel/src/shell.cpp +++ b/kernel/src/shell.cpp @@ -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& params){ auto buffer = content.c_str(); auto header = reinterpret_cast(buffer); - auto section_header_table = reinterpret_cast(buffer + header->e_shoff); + auto program_header_table = reinterpret_cast(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(paging::page_align(reinterpret_cast(address))); - k_printf("%h (virt) was allocated in %h (phys)\n", reinterpret_cast(s_header.sh_addr), reinterpret_cast(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(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(reinterpret_cast(memory) + 64); - k_print_line(*test_a); + //3. Find a start of a page inside the physical memory - auto test_b = reinterpret_cast(s_header.sh_addr + 64); - k_print_line(*test_b); + auto aligned_memory = paging::page_aligned(memory) ? memory : reinterpret_cast((reinterpret_cast(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(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((reinterpret_cast(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&){