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 "assert.hpp"
#include "process.hpp"
#include "physical_pointer.hpp"
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){
return map_pages(virt, virt, pages, flags);
}
void paging::map_kernel_inside_user(scheduler::process_t& process){
auto virt = virtual_allocator::allocate(1);
map(virt, process.physical_cr3);
physical_pointer cr3_ptr(process.physical_cr3, 1);
//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
auto pml4t = reinterpret_cast<pml4t_t>(virt);
auto pml4t = cr3_ptr.as<pml4t_t>();
for(size_t i = 0; i < pml4_entries; ++i){
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){
auto virt = virtual_allocator::allocate(1);
physical_pointer ptr(physical, 1);
map(virt, physical);
auto it = reinterpret_cast<uint64_t*>(virt);
auto it = ptr.as_ptr<uint64_t>();
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
bool paging::user_map(scheduler::process_t& process, size_t virt, size_t physical){
//Get temporary virtual memory for CR3
auto virtual_cr3 = virtual_allocator::allocate(1);
physical_pointer cr3_ptr(process.physical_cr3, 1);
if(!map(virtual_cr3, process.physical_cr3)){
if(!cr3_ptr){
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 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)){
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);
}
auto virtual_pdpt = virtual_allocator::allocate(1);
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;
}
auto pdpt = reinterpret_cast<pdpt_t>(virtual_pdpt);
auto pdpt = pdpt_ptr.as<pdpt_t>();
if(!(reinterpret_cast<uintptr_t>(pdpt[pdpte]) & PRESENT)){
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);
}
auto virtual_pd = virtual_allocator::allocate(1);
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;
}
auto pd = reinterpret_cast<pd_t>(virtual_pd);
auto pd = pd_ptr.as<pd_t>();
if(!(reinterpret_cast<uintptr_t>(pd[pde]) & PRESENT)){
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);
}
auto virtual_pt = virtual_allocator::allocate(1);
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;
}
auto pt = reinterpret_cast<pt_t>(virtual_pt);
auto pt = pt_ptr.as<pt_t>();
//Map to the physical address
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;
}

View File

@ -20,6 +20,7 @@
#include "console.hpp"
#include "physical_allocator.hpp"
#include "virtual_allocator.hpp"
#include "physical_pointer.hpp"
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){
auto virt = virtual_allocator::allocate(pages);
physical_pointer phys_ptr(memory, pages);
paging::map_pages(virt, memory, pages);
auto it = reinterpret_cast<uint64_t*>(virt);
auto it = phys_ptr.as_ptr<uint64_t>();
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){
@ -325,15 +320,11 @@ bool create_paging(char* buffer, scheduler::process_t& process){
//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 = virtual_memory + left_padding;
auto memory_start = phys_ptr.get() + left_padding;
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 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;
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;
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));