From 5b77f28089ec51da9db136012e93fbc93117f01d Mon Sep 17 00:00:00 2001 From: Baptiste Wicht Date: Wed, 22 Jan 2014 21:15:03 +0100 Subject: [PATCH] Map the paging structures themselves --- kernel/src/paging.cpp | 129 ++++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 48 deletions(-) diff --git a/kernel/src/paging.cpp b/kernel/src/paging.cpp index baf00cb4..2c84c8ab 100644 --- a/kernel/src/paging.cpp +++ b/kernel/src/paging.cpp @@ -39,11 +39,7 @@ constexpr const size_t pde_allocations = 2_MiB; constexpr const size_t pte_allocations = 4_KiB; //Virtual address where the paging structures are stored -constexpr const size_t virtual_paging_start = 0x100000; - -inline void flush_tlb(void* page){ - asm volatile("invlpg [%0]" :: "r" (reinterpret_cast(page)) : "memory"); -} +constexpr const size_t virtual_paging_start = 0x101000; constexpr size_t entries(size_t entry_size){ return entry_size >= kernel_virtual_size ? @@ -69,6 +65,42 @@ size_t physical_pdpt_start; size_t physical_pd_start; size_t physical_pt_start; +constexpr size_t pml4_entry(void* virt){ + return (reinterpret_cast(virt) >> 39) & 0x1FF; +} + +constexpr size_t pdpt_entry(void* virt){ + return (reinterpret_cast(virt) >> 30) & 0x1FF; +} + +constexpr size_t pd_entry(void* virt){ + return (reinterpret_cast(virt) >> 21) & 0x1FF; +} + +constexpr size_t pt_entry(void* virt){ + return (reinterpret_cast(virt) >> 12) & 0x1FF; +} + +constexpr pml4t_t find_pml4t(){ + return reinterpret_cast(virtual_pml4t_start); +} + +constexpr pdpt_t find_pdpt(pml4t_t pml4t, size_t pml4e){ + return reinterpret_cast(reinterpret_cast(pml4t[pml4e]) & ~0xFFF); +} + +constexpr pd_t find_pd(pdpt_t pdpt, size_t pdpte){ + return reinterpret_cast(reinterpret_cast(pdpt[pdpte]) & ~0xFFF); +} + +constexpr pt_t find_pt(pd_t pd, size_t pde){ + return reinterpret_cast(reinterpret_cast(pd[pde]) & ~0xFFF); +} + +inline void flush_tlb(void* page){ + asm volatile("invlpg [%0]" :: "r" (reinterpret_cast(page)) : "memory"); +} + size_t early_map_page(size_t physical){ //PD[0] already points to a valid PT (0x73000) auto pt = reinterpret_cast(0x73000); @@ -76,11 +108,17 @@ size_t early_map_page(size_t physical){ pt[256] = reinterpret_cast(physical | paging::PRESENT | paging::WRITE); flush_tlb(reinterpret_cast(0x100000)); + return 0x100000; +} + +size_t early_map_page_clear(size_t physical){ + auto virt = early_map_page(physical); + //Clear the new allocated block of memory - auto it = reinterpret_cast(0x100000); + auto it = reinterpret_cast(virt); std::fill(it, it + paging::PAGE_SIZE / sizeof(size_t), 0); - return 0x100000; + return virt; } } //end of anonymous namespace @@ -107,41 +145,41 @@ void paging::init(){ auto high_flags = PRESENT | WRITE | USER; //1. Prepare PML4T - auto virt = early_map_page(physical_pml4t_start); + auto virt = early_map_page_clear(physical_pml4t_start); for(size_t i = 0; i < pml4_entries; ++i){ (reinterpret_cast(virt))[i] = reinterpret_cast((physical_pdpt_start + i * PAGE_SIZE) | high_flags); } //2. Prepare each PDPT for(size_t i = 0; i < pml4_entries; ++i){ - virt = early_map_page(physical_pdpt_start + i * PAGE_SIZE); + virt = early_map_page_clear(physical_pdpt_start + i * PAGE_SIZE); for(size_t j = 0; j + i * 512 < pdpt_entries; ++j){ auto r = j + i * 512; - (reinterpret_cast(virt))[r] = reinterpret_cast((physical_pd_start + i * PAGE_SIZE) | high_flags); + (reinterpret_cast(virt))[j] = reinterpret_cast((physical_pd_start + r * PAGE_SIZE) | high_flags); } } //3. Prepare each PD for(size_t i = 0; i < pdpt_entries; ++i){ - virt = early_map_page(physical_pd_start + i * PAGE_SIZE); + virt = early_map_page_clear(physical_pd_start + i * PAGE_SIZE); for(size_t j = 0; j + i * 512 < pd_entries; ++j){ auto r = j + i * 512; - (reinterpret_cast(virt))[r] = reinterpret_cast((physical_pt_start + i * PAGE_SIZE) | high_flags); + (reinterpret_cast(virt))[j] = reinterpret_cast((physical_pt_start + r * PAGE_SIZE) | high_flags); } } //4. Prepare each PT for(size_t i = 0; i < pd_entries; ++i){ - early_map_page(physical_pt_start + i * PAGE_SIZE); + early_map_page_clear(physical_pt_start + i * PAGE_SIZE); } //5. Identity map the first MiB - virt = early_map_page(physical_pt_start); + virt = early_map_page_clear(physical_pt_start); auto page_table_ptr = reinterpret_cast(virt); auto phys = PRESENT | WRITE; for(size_t i = 0; i < 256; ++i){ @@ -152,44 +190,39 @@ void paging::init(){ ++page_table_ptr; } - //6. Use the new structure as the new paging structure (in CR3) + //6. Map all the paging structures + + auto phys_page = physical_memory; + auto virt_page = virtual_paging_start; + + size_t current_pt_index = 0; + uintptr_t current_virt = 0; + for(size_t i = 0; i < physical_memory_pages; ++i){ + auto pml4e = pml4_entry(reinterpret_cast(virt_page)); + auto pdpte = pdpt_entry(reinterpret_cast(virt_page)); + auto pde = pd_entry(reinterpret_cast(virt_page)); + auto pte = pt_entry(reinterpret_cast(virt_page)); + + auto pt_index = pde * 512 + pdpte * 512 * 512 + pml4e * 512 * 512 * 512; + auto physical = physical_pt_start + pt_index * paging::PAGE_SIZE; + + if(pt_index != current_pt_index || current_virt == 0){ + current_virt = early_map_page(physical); + } + + (reinterpret_cast(current_virt))[pte] = reinterpret_cast(phys_page | PRESENT | WRITE); + + current_pt_index = pt_index; + + virt_page += paging::PAGE_SIZE; + phys_page += paging::PAGE_SIZE; + } + + //7. Use the new structure as the new paging structure (in CR3) asm volatile("mov rax, %0; mov cr3, rax" : : "m"(physical_pml4t_start) : "memory", "rax"); } -constexpr size_t pml4_entry(void* virt){ - return (reinterpret_cast(virt) >> 39) & 0x1FF; -} - -constexpr size_t pdpt_entry(void* virt){ - return (reinterpret_cast(virt) >> 30) & 0x1FF; -} - -constexpr size_t pd_entry(void* virt){ - return (reinterpret_cast(virt) >> 21) & 0x1FF; -} - -constexpr size_t pt_entry(void* virt){ - return (reinterpret_cast(virt) >> 12) & 0x1FF; -} - -constexpr pml4t_t find_pml4t(){ - //TODO Change address - return reinterpret_cast(0x70000); -} - -constexpr pdpt_t find_pdpt(pml4t_t pml4t, size_t pml4e){ - return reinterpret_cast(reinterpret_cast(pml4t[pml4e]) & ~0xFFF); -} - -constexpr pd_t find_pd(pdpt_t pdpt, size_t pdpte){ - return reinterpret_cast(reinterpret_cast(pdpt[pdpte]) & ~0xFFF); -} - -constexpr pt_t find_pt(pd_t pd, size_t pde){ - return reinterpret_cast(reinterpret_cast(pd[pde]) & ~0xFFF); -} - //TODO Update to support offsets at the end of virt //TODO Improve to support a status void* paging::physical_address(void* virt){