From fe58f0774556512a2442f339eef42bce651e3bed Mon Sep 17 00:00:00 2001 From: Baptiste Wicht Date: Thu, 6 Feb 2014 22:13:58 +0100 Subject: [PATCH] Always release virtual memory --- kernel/include/physical_pointer.hpp | 72 +++++++++++++++++++++++++++++ kernel/src/paging.cpp | 54 +++++++--------------- kernel/src/scheduler.cpp | 28 +++-------- 3 files changed, 96 insertions(+), 58 deletions(-) create mode 100644 kernel/include/physical_pointer.hpp diff --git a/kernel/include/physical_pointer.hpp b/kernel/include/physical_pointer.hpp new file mode 100644 index 00000000..d715b0f1 --- /dev/null +++ b/kernel/include/physical_pointer.hpp @@ -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 + T as(){ + return reinterpret_cast(virt); + } + + template + T* as_ptr(){ + return reinterpret_cast(virt); + } + + uintptr_t get(){ + return virt; + } + + operator bool() const { + return virt != 0; + } +}; + +#endif diff --git a/kernel/src/paging.cpp b/kernel/src/paging.cpp index 0ed3cc2d..7e522715 100644 --- a/kernel/src/paging.cpp +++ b/kernel/src/paging.cpp @@ -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(virt); + auto pml4t = cr3_ptr.as(); for(size_t i = 0; i < pml4_entries; ++i){ pml4t[i] = reinterpret_cast((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(virt); + auto it = ptr.as_ptr(); 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(virtual_cr3); + auto pml4t = cr3_ptr.as(); if(!(reinterpret_cast(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(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(virtual_pdpt); + auto pdpt = pdpt_ptr.as(); if(!(reinterpret_cast(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(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(virtual_pd); + auto pd = pd_ptr.as(); if(!(reinterpret_cast(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(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(virtual_pt); + auto pt = pt_ptr.as(); //Map to the physical address pt[pte] = reinterpret_cast(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; } diff --git a/kernel/src/scheduler.cpp b/kernel/src/scheduler.cpp index 95295300..98b80de8 100644 --- a/kernel/src/scheduler.cpp +++ b/kernel/src/scheduler.cpp @@ -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(virt); + auto it = phys_ptr.as_ptr(); 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(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(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(rsp); @@ -375,10 +365,6 @@ void init_context(scheduler::process_t& process, const char* buffer){ regs->rflags = 0x200; process.context = reinterpret_cast(scheduler::user_rsp - sizeof(interrupt::syscall_regs) * 8); - - paging::unmap_pages(virt, pages); - - //TODO virt should be deallocated } void start() __attribute__((noreturn));