Always release virtual memory

This commit is contained in:
Baptiste Wicht 2014-02-06 22:13:58 +01:00
parent 4e99c62288
commit fe58f07745
3 changed files with 96 additions and 58 deletions

View File

@ -0,0 +1,72 @@
//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef PHYSICAL_POINTER_H
#define PHYSICAL_POINTER_H
#include "virtual_allocator.hpp"
#include "paging.hpp"
struct physical_pointer {
private:
size_t phys;
size_t pages;
size_t virt;
public:
physical_pointer(size_t phys_p, size_t pages_p) : phys(phys_p), pages(pages_p) {
if(pages > 0){
virt = virtual_allocator::allocate(pages);
if(virt){
if(pages == 1){
if(!paging::map(virt, phys)){
virt = 0;
}
} else {
if(!paging::map_pages(virt, phys, pages)){
virt = 0;
}
}
}
} else {
virt = 0;
}
}
~physical_pointer(){
if(virt){
if(pages == 1){
paging::unmap(virt);
} else {
paging::unmap_pages(virt, pages);
}
virtual_allocator::free(virt, pages);
}
}
template<typename T>
T as(){
return reinterpret_cast<T>(virt);
}
template<typename T>
T* as_ptr(){
return reinterpret_cast<T*>(virt);
}
uintptr_t get(){
return virt;
}
operator bool() const {
return virt != 0;
}
};
#endif

View File

@ -14,6 +14,7 @@
#include "console.hpp" #include "console.hpp"
#include "assert.hpp" #include "assert.hpp"
#include "process.hpp" #include "process.hpp"
#include "physical_pointer.hpp"
namespace { namespace {
@ -386,44 +387,30 @@ bool paging::identity_map(size_t virt, uint8_t flags){
bool paging::identity_map_pages(size_t virt, size_t pages, uint8_t flags){ bool paging::identity_map_pages(size_t virt, size_t pages, uint8_t flags){
return map_pages(virt, virt, pages, flags); return map_pages(virt, virt, pages, flags);
} }
void paging::map_kernel_inside_user(scheduler::process_t& process){ void paging::map_kernel_inside_user(scheduler::process_t& process){
auto virt = virtual_allocator::allocate(1); physical_pointer cr3_ptr(process.physical_cr3, 1);
map(virt, process.physical_cr3);
//As we are ensuring that the first PML4T entries are reserved to the //As we are ensuring that the first PML4T entries are reserved to the
//kernel, it is enough to link these ones to the kernel ones //kernel, it is enough to link these ones to the kernel ones
auto pml4t = reinterpret_cast<pml4t_t>(virt); auto pml4t = cr3_ptr.as<pml4t_t>();
for(size_t i = 0; i < pml4_entries; ++i){ for(size_t i = 0; i < pml4_entries; ++i){
pml4t[i] = reinterpret_cast<pdpt_t>((physical_pdpt_start + i * PAGE_SIZE) | USER | PRESENT); pml4t[i] = reinterpret_cast<pdpt_t>((physical_pdpt_start + i * PAGE_SIZE) | USER | PRESENT);
} }
unmap(virt);
//TODO Release virtual memory
} }
void clear_physical_page(size_t physical){ void clear_physical_page(size_t physical){
auto virt = virtual_allocator::allocate(1); physical_pointer ptr(physical, 1);
map(virt, physical); auto it = ptr.as_ptr<uint64_t>();
auto it = reinterpret_cast<uint64_t*>(virt);
std::fill_n(it, paging::PAGE_SIZE / sizeof(uint64_t), 0); std::fill_n(it, paging::PAGE_SIZE / sizeof(uint64_t), 0);
unmap(virt);
//TODO Release virtual memory
} }
//TODO It is highly inefficient to remap CR3 each time //TODO It is highly inefficient to remap CR3 each time
bool paging::user_map(scheduler::process_t& process, size_t virt, size_t physical){ bool paging::user_map(scheduler::process_t& process, size_t virt, size_t physical){
//Get temporary virtual memory for CR3 physical_pointer cr3_ptr(process.physical_cr3, 1);
auto virtual_cr3 = virtual_allocator::allocate(1);
if(!map(virtual_cr3, process.physical_cr3)){ if(!cr3_ptr){
return false; return false;
} }
@ -433,7 +420,7 @@ bool paging::user_map(scheduler::process_t& process, size_t virt, size_t physica
auto pde = pd_entry(virt); auto pde = pd_entry(virt);
auto pte = pt_entry(virt); auto pte = pt_entry(virt);
auto pml4t = reinterpret_cast<pml4t_t>(virtual_cr3); auto pml4t = cr3_ptr.as<pml4t_t>();
if(!(reinterpret_cast<uintptr_t>(pml4t[pml4e]) & PRESENT)){ if(!(reinterpret_cast<uintptr_t>(pml4t[pml4e]) & PRESENT)){
auto physical_pdpt = physical_allocator::allocate(1); auto physical_pdpt = physical_allocator::allocate(1);
@ -445,14 +432,14 @@ bool paging::user_map(scheduler::process_t& process, size_t virt, size_t physica
process.physical_paging.push_back(physical_pdpt); process.physical_paging.push_back(physical_pdpt);
} }
auto virtual_pdpt = virtual_allocator::allocate(1);
auto physical_pdpt = reinterpret_cast<uintptr_t>(pml4t[pml4e]) & ~0xFFF; auto physical_pdpt = reinterpret_cast<uintptr_t>(pml4t[pml4e]) & ~0xFFF;
physical_pointer pdpt_ptr(physical_pdpt, 1);
if(!map(virtual_pdpt, physical_pdpt)){ if(!pdpt_ptr){
return false; return false;
} }
auto pdpt = reinterpret_cast<pdpt_t>(virtual_pdpt); auto pdpt = pdpt_ptr.as<pdpt_t>();
if(!(reinterpret_cast<uintptr_t>(pdpt[pdpte]) & PRESENT)){ if(!(reinterpret_cast<uintptr_t>(pdpt[pdpte]) & PRESENT)){
auto physical_pd = physical_allocator::allocate(1); auto physical_pd = physical_allocator::allocate(1);
@ -464,14 +451,14 @@ bool paging::user_map(scheduler::process_t& process, size_t virt, size_t physica
process.physical_paging.push_back(physical_pd); process.physical_paging.push_back(physical_pd);
} }
auto virtual_pd = virtual_allocator::allocate(1);
auto physical_pd = reinterpret_cast<uintptr_t>(pdpt[pdpte]) & ~0xFFF; auto physical_pd = reinterpret_cast<uintptr_t>(pdpt[pdpte]) & ~0xFFF;
physical_pointer pd_ptr(physical_pd, 1);
if(!map(virtual_pd, physical_pd)){ if(!pd_ptr){
return false; return false;
} }
auto pd = reinterpret_cast<pd_t>(virtual_pd); auto pd = pd_ptr.as<pd_t>();
if(!(reinterpret_cast<uintptr_t>(pd[pde]) & PRESENT)){ if(!(reinterpret_cast<uintptr_t>(pd[pde]) & PRESENT)){
auto physical_pt = physical_allocator::allocate(1); auto physical_pt = physical_allocator::allocate(1);
@ -483,25 +470,18 @@ bool paging::user_map(scheduler::process_t& process, size_t virt, size_t physica
process.physical_paging.push_back(physical_pt); process.physical_paging.push_back(physical_pt);
} }
auto virtual_pt = virtual_allocator::allocate(1);
auto physical_pt = reinterpret_cast<uintptr_t>(pd[pde]) & ~0xFFF; auto physical_pt = reinterpret_cast<uintptr_t>(pd[pde]) & ~0xFFF;
physical_pointer pt_ptr(physical_pt, 1);
if(!map(virtual_pt, physical_pt)){ if(!pt_ptr){
return false; return false;
} }
auto pt = reinterpret_cast<pt_t>(virtual_pt); auto pt = pt_ptr.as<pt_t>();
//Map to the physical address //Map to the physical address
pt[pte] = reinterpret_cast<page_entry>(physical | WRITE | USER | PRESENT); pt[pte] = reinterpret_cast<page_entry>(physical | WRITE | USER | PRESENT);
paging::unmap(virtual_pt);
paging::unmap(virtual_pd);
paging::unmap(virtual_pdpt);
paging::unmap(virtual_cr3);
//TODO Release virtual memory
return true; return true;
} }

View File

@ -20,6 +20,7 @@
#include "console.hpp" #include "console.hpp"
#include "physical_allocator.hpp" #include "physical_allocator.hpp"
#include "virtual_allocator.hpp" #include "virtual_allocator.hpp"
#include "physical_pointer.hpp"
constexpr const bool DEBUG_SCHEDULER = true; constexpr const bool DEBUG_SCHEDULER = true;
@ -272,16 +273,10 @@ bool allocate_user_memory(scheduler::process_t& process, size_t address, size_t
} }
void clear_physical_memory(size_t memory, size_t pages){ void clear_physical_memory(size_t memory, size_t pages){
auto virt = virtual_allocator::allocate(pages); physical_pointer phys_ptr(memory, pages);
paging::map_pages(virt, memory, pages); auto it = phys_ptr.as_ptr<uint64_t>();
auto it = reinterpret_cast<uint64_t*>(virt);
std::fill_n(it, (pages * paging::PAGE_SIZE) / sizeof(uint64_t), 0); std::fill_n(it, (pages * paging::PAGE_SIZE) / sizeof(uint64_t), 0);
paging::unmap_pages(virt, pages);
//TODO virt should be deallocated
} }
bool create_paging(char* buffer, scheduler::process_t& process){ bool create_paging(char* buffer, scheduler::process_t& process){
@ -325,15 +320,11 @@ bool create_paging(char* buffer, scheduler::process_t& process){
//Copy the code into memory //Copy the code into memory
auto virtual_memory = virtual_allocator::allocate(pages); physical_pointer phys_ptr(segment. physical, pages);
paging::map_pages(virtual_memory, segment.physical, pages); auto memory_start = phys_ptr.get() + left_padding;
auto memory_start = virtual_memory + left_padding;
std::copy_n(reinterpret_cast<char*>(memory_start), buffer + p_header.p_offset, p_header.p_memsz); std::copy_n(reinterpret_cast<char*>(memory_start), buffer + p_header.p_offset, p_header.p_memsz);
paging::unmap_pages(virtual_memory, pages);
} }
} }
@ -359,11 +350,10 @@ void init_context(scheduler::process_t& process, const char* buffer){
auto header = reinterpret_cast<const elf::elf_header*>(buffer); auto header = reinterpret_cast<const elf::elf_header*>(buffer);
auto pages = scheduler::user_stack_size / paging::PAGE_SIZE; auto pages = scheduler::user_stack_size / paging::PAGE_SIZE;
auto virt = virtual_allocator::allocate(pages);
paging::map_pages(virt, process.physical_user_stack, pages); physical_pointer phys_ptr(process.physical_user_stack, pages);
auto rsp = virt + scheduler::user_stack_size - 8; auto rsp = phys_ptr.get() + scheduler::user_stack_size - 8;
rsp -= sizeof(interrupt::syscall_regs) * 8; rsp -= sizeof(interrupt::syscall_regs) * 8;
auto regs = reinterpret_cast<interrupt::syscall_regs*>(rsp); auto regs = reinterpret_cast<interrupt::syscall_regs*>(rsp);
@ -375,10 +365,6 @@ void init_context(scheduler::process_t& process, const char* buffer){
regs->rflags = 0x200; regs->rflags = 0x200;
process.context = reinterpret_cast<interrupt::syscall_regs*>(scheduler::user_rsp - sizeof(interrupt::syscall_regs) * 8); process.context = reinterpret_cast<interrupt::syscall_regs*>(scheduler::user_rsp - sizeof(interrupt::syscall_regs) * 8);
paging::unmap_pages(virt, pages);
//TODO virt should be deallocated
} }
void start() __attribute__((noreturn)); void start() __attribute__((noreturn));