mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-08-04 01:36:10 -04:00
Finish memory allocation for programs
This commit is contained in:
parent
55f34aa4b2
commit
2df9def686
@ -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)));
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>&){
|
||||
|
Loading…
x
Reference in New Issue
Block a user