From a1c4e56a568a6c79b3e3e9f14d13424921f567cc Mon Sep 17 00:00:00 2001 From: Baptiste Wicht Date: Tue, 21 Jan 2014 22:31:19 +0100 Subject: [PATCH] Start review of memory --- kernel/include/paging.hpp | 2 ++ kernel/src/boot/boot_32.cpp | 2 +- kernel/src/isrs.s | 4 +-- kernel/src/kernel.cpp | 7 +++- kernel/src/memory.cpp | 7 ++-- kernel/src/paging.cpp | 70 +++++++++++++++++++++++++++++-------- 6 files changed, 70 insertions(+), 22 deletions(-) diff --git a/kernel/include/paging.hpp b/kernel/include/paging.hpp index 8f0763b1..fc559fdb 100644 --- a/kernel/include/paging.hpp +++ b/kernel/include/paging.hpp @@ -32,6 +32,8 @@ constexpr T* page_align(T* addr){ return reinterpret_cast((reinterpret_cast(addr) / paging::PAGE_SIZE) * paging::PAGE_SIZE); } +void init(); + void* physical_address(void* virt); bool page_present(void* virt); bool page_free_or_set(void* virt, void* physical); diff --git a/kernel/src/boot/boot_32.cpp b/kernel/src/boot/boot_32.cpp index 6759d8bb..6bae493a 100644 --- a/kernel/src/boot/boot_32.cpp +++ b/kernel/src/boot/boot_32.cpp @@ -59,7 +59,7 @@ void setup_paging(){ //PDPT[0] -> PDT *reinterpret_cast(PML4T + 1 * paging::PAGE_SIZE) = PML4T + 2 * paging::PAGE_SIZE + 0x7; - //PDT[0] -> PD + //PD[0] -> PT *reinterpret_cast(PML4T + 2 * paging::PAGE_SIZE) = PML4T + 3 * paging::PAGE_SIZE + 0x7; //Map the first MiB diff --git a/kernel/src/isrs.s b/kernel/src/isrs.s index 0370966b..310f332b 100644 --- a/kernel/src/isrs.s +++ b/kernel/src/isrs.s @@ -64,12 +64,10 @@ create_irq_dummy 30 create_irq_dummy 31 isr_common_handler: - restore_kernel_segments + //TODO Kernel segments should be restored call _fault_handler - restore_user_segments - // TODO At this point, it is absolutely not safe to return since most // registers will get trashed the fault handler must hang diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index b4dcecd7..eba52ecc 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -6,6 +6,8 @@ //======================================================================= #include "kernel.hpp" +#include "physical_allocator.hpp" +#include "paging.hpp" #include "memory.hpp" #include "timer.hpp" #include "shell.hpp" @@ -18,7 +20,6 @@ #include "vesa.hpp" #include "console.hpp" #include "gdt.hpp" -#include "physical_allocator.hpp" extern "C" { @@ -31,15 +32,19 @@ void kernel_main(){ interrupt::setup_interrupts(); + //Prepare memory init_physical_allocator(); + paging::init(); init_memory_manager(); + //Install drivers install_timer(); //acpi::init(); keyboard::install_driver(); disks::detect_disks(); vesa::init(); + //Only install system calls when everything else is ready install_system_calls(); //Call global constructors diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index 0daebb60..edb03bb2 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -103,6 +103,8 @@ malloc_header_chunk* malloc_head = 0; uintptr_t min_address; //Address of the first block being allocated uintptr_t max_address; //Address of the next block being allocated +uintptr_t current_virtual = 0x400000; + uint64_t* allocate_block(uint64_t blocks){ auto memory = allocate_physical_memory(blocks); @@ -116,9 +118,10 @@ uint64_t* allocate_block(uint64_t blocks){ max_address = memory; - auto block = reinterpret_cast(memory); + paging::map_pages(reinterpret_cast(current_virtual), reinterpret_cast(memory), blocks); - paging::identity_map_pages(block, blocks); + auto block = reinterpret_cast(current_virtual); + current_virtual += blocks * BLOCK_SIZE; _allocated_memory += blocks * BLOCK_SIZE; diff --git a/kernel/src/paging.cpp b/kernel/src/paging.cpp index 6c7889c3..abf36f81 100644 --- a/kernel/src/paging.cpp +++ b/kernel/src/paging.cpp @@ -6,6 +6,7 @@ //======================================================================= #include "paging.hpp" +#include "physical_allocator.hpp" #include "stl/types.hpp" #include "stl/algorithms.hpp" @@ -14,8 +15,8 @@ namespace { typedef uint64_t* page_entry; typedef page_entry* pt_t; -typedef pt_t* pdt_t; -typedef pdt_t* pdpt_t; +typedef pt_t* pd_t; +typedef pd_t* pdpt_t; typedef pdpt_t* pml4t_t; //Memory from 0x70000 can be used for pages @@ -38,6 +39,45 @@ inline void flush_tlb(void* page){ } //end of anonymous namespace +void paging::init(){ + //PD[0] already points to a valid PT (0x73000) + auto pt = reinterpret_cast(0x73000); + + auto pd = reinterpret_cast(0x72000); + + auto physical = allocate_physical_memory(1); + + pt[256] = reinterpret_cast(physical | PRESENT | WRITE | USER); + flush_tlb(reinterpret_cast(0x100000)); + + auto it = reinterpret_cast(0x100000); + std::fill(it, it + paging::PAGE_SIZE / sizeof(size_t), 0); + + pd[1] = reinterpret_cast(physical | PRESENT | WRITE | USER); + + //Use PD[1] as pt + pt = reinterpret_cast(0x100000); + + for(size_t pd_index = 2; pd_index < 512; ++pd_index){ + //1. Allocate space for the new Page Table + physical = allocate_physical_memory(1); + + //2. Compute logical address + uint64_t logical = 0x200000 + (pd_index - 2) * paging::PAGE_SIZE; + + //2. Map it using the valid entries in the first PT + pt[pd_index - 2] = reinterpret_cast(physical | PRESENT | WRITE | USER); + flush_tlb(reinterpret_cast(logical)); + + //3. Clear the new PT + it = reinterpret_cast(logical); + std::fill(it, it + paging::PAGE_SIZE / sizeof(size_t), 0); + + //4. Set it in PD + pd[pd_index] = reinterpret_cast(physical | PRESENT | WRITE | USER); + } +} + //TODO Update to support offsets at the end of virt //TODO Improve to support a status void* paging::physical_address(void* virt){ @@ -54,8 +94,8 @@ void* paging::physical_address(void* virt){ pml4t_t pml4t = reinterpret_cast(0x70000); auto pdpt = reinterpret_cast(reinterpret_cast(pml4t[pml4]) & ~0xFFF); - auto pdt = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); - auto pt = reinterpret_cast(reinterpret_cast(pdt[directory]) & ~0xFFF); + auto pd = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); + auto pt = reinterpret_cast(reinterpret_cast(pd[directory]) & ~0xFFF); return reinterpret_cast(reinterpret_cast(pt[table]) & ~0xFFF); } @@ -76,12 +116,12 @@ bool paging::page_present(void* virt){ return false; } - auto pdt = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); - if(!(reinterpret_cast(pdt[directory]) & PRESENT)){ + auto pd = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); + if(!(reinterpret_cast(pd[directory]) & PRESENT)){ return false; } - auto pt = reinterpret_cast(reinterpret_cast(pdt[directory]) & ~0xFFF); + auto pt = reinterpret_cast(reinterpret_cast(pd[directory]) & ~0xFFF); return reinterpret_cast(pt[table]) & PRESENT; } @@ -120,17 +160,17 @@ bool paging::map(void* virt, void* physical, uint8_t flags){ //Init new page if necessary if(!(reinterpret_cast(pdpt[directory_ptr]) & PRESENT)){ - pdpt[directory_ptr] = reinterpret_cast(init_new_page() | USER | WRITE | PRESENT); + pdpt[directory_ptr] = reinterpret_cast(init_new_page() | USER | WRITE | PRESENT); } - auto pdt = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); + auto pd = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); //Init new page if necessary - if(!(reinterpret_cast(pdt[directory]) & PRESENT)){ - pdt[directory] = reinterpret_cast(init_new_page() | USER | WRITE | PRESENT); + if(!(reinterpret_cast(pd[directory]) & PRESENT)){ + pd[directory] = reinterpret_cast(init_new_page() | USER | WRITE | PRESENT); } - auto pt = reinterpret_cast(reinterpret_cast(pdt[directory]) & ~0xFFF); + auto pt = reinterpret_cast(reinterpret_cast(pd[directory]) & ~0xFFF); //Check if the page is already present if(reinterpret_cast(pt[table]) & PRESENT){ @@ -204,14 +244,14 @@ bool paging::unmap(void* virt){ return true; } - auto pdt = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); + auto pd = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); //If not present, returns directly - if(!(reinterpret_cast(pdt[directory]) & PRESENT)){ + if(!(reinterpret_cast(pd[directory]) & PRESENT)){ return true; } - auto pt = reinterpret_cast(reinterpret_cast(pdt[directory]) & ~0xFFF); + auto pt = reinterpret_cast(reinterpret_cast(pd[directory]) & ~0xFFF); //Unmap the virtual address pt[table] = 0x0;