From f139fc2229d42626d14c64f4dfc2147677de6925 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Fri, 28 Apr 2023 14:45:09 +0300 Subject: [PATCH] Kernel: namespace and function renames MMU moved to namespace kernel Kernel::Memory::Heap moved to just Kernel MMU::map_{page,range} renamed to identity_map_{page,range} Add MMU::get_page_flags --- kernel/arch/i386/MMU.cpp | 351 ++++++++------- kernel/arch/x86_64/MMU.cpp | 422 ++++++++++-------- kernel/include/kernel/Memory/Heap.h | 3 +- kernel/include/kernel/Memory/MMU.h | 71 +-- kernel/include/kernel/Process.h | 2 +- kernel/kernel/ACPI.cpp | 10 +- kernel/kernel/APIC.cpp | 6 +- kernel/kernel/Memory/Heap.cpp | 4 +- kernel/kernel/Process.cpp | 4 +- kernel/kernel/Terminal/VesaTerminalDriver.cpp | 4 +- kernel/kernel/Thread.cpp | 2 +- kernel/kernel/kernel.cpp | 2 +- 12 files changed, 473 insertions(+), 408 deletions(-) diff --git a/kernel/arch/i386/MMU.cpp b/kernel/arch/i386/MMU.cpp index 3af146103..051437531 100644 --- a/kernel/arch/i386/MMU.cpp +++ b/kernel/arch/i386/MMU.cpp @@ -8,198 +8,221 @@ #define MMU_DEBUG_PRINT 0 // bits 31-12 set -#define PAGE_MASK 0xfffff000 -#define PAGE_SIZE 0x00001000 +#define PAGE_MASK 0xfffff000 +#define FLAGS_MASK 0x00000fff -static MMU* s_instance = nullptr; - -void MMU::initialize() +namespace Kernel { - ASSERT(s_instance == nullptr); - s_instance = new MMU(); - ASSERT(s_instance); - s_instance->initialize_kernel(); - s_instance->load(); -} -MMU& MMU::get() -{ - ASSERT(s_instance); - return *s_instance; -} + static MMU* s_instance = nullptr; -static uint64_t* allocate_page_aligned_page() -{ - uint64_t* page = (uint64_t*)kmalloc(PAGE_SIZE, PAGE_SIZE); - ASSERT(page); - ASSERT(((uintptr_t)page % PAGE_SIZE) == 0); - memset(page, 0, PAGE_SIZE); - return page; -} - -void MMU::initialize_kernel() -{ - m_highest_paging_struct = (uint64_t*)kmalloc(sizeof(uint64_t) * 4, 32); - ASSERT(m_highest_paging_struct); - ASSERT(((uintptr_t)m_highest_paging_struct % 32) == 0); - - // allocate all page directories - for (int i = 0; i < 4; i++) + void MMU::initialize() { - uint64_t* page_directory = allocate_page_aligned_page(); - m_highest_paging_struct[i] = (uint64_t)page_directory | Flags::Present; + ASSERT(s_instance == nullptr); + s_instance = new MMU(); + ASSERT(s_instance); + s_instance->initialize_kernel(); + s_instance->load(); } - // FIXME: We should just identity map until g_kernel_end - - // create and identity map first 6 MiB - uint64_t* page_directory1 = (uint64_t*)(m_highest_paging_struct[0] & PAGE_MASK); - for (uint64_t i = 0; i < 3; i++) + MMU& MMU::get() { - uint64_t* page_table = allocate_page_aligned_page(); - for (uint64_t j = 0; j < 512; j++) - page_table[j] = (i << 21) | (j << 12) | Flags::ReadWrite | Flags::Present; - - page_directory1[i] = (uint64_t)page_table | Flags::ReadWrite | Flags::Present; + ASSERT(s_instance); + return *s_instance; } - // dont map first page (0 -> 4 KiB) so that nullptr dereference - // causes page fault :) - uint64_t* page_table1 = (uint64_t*)(page_directory1[0] & PAGE_MASK); - page_table1[0] = 0; -} - -MMU::MMU() -{ - if (s_instance == nullptr) - return; - - // Here we copy the s_instances paging structs since they are - // global for every process - - uint64_t* global_pdpt = s_instance->m_highest_paging_struct; - - uint64_t* pdpt = (uint64_t*)kmalloc(sizeof(uint64_t) * 4, 32); - ASSERT(pdpt); - - for (uint32_t pdpte = 0; pdpte < 4; pdpte++) + static uint64_t* allocate_page_aligned_page() { - if (!(global_pdpt[pdpte] & Flags::Present)) - continue; + uint64_t* page = (uint64_t*)kmalloc(PAGE_SIZE, PAGE_SIZE); + ASSERT(page); + ASSERT(((uintptr_t)page % PAGE_SIZE) == 0); + memset(page, 0, PAGE_SIZE); + return page; + } - uint64_t* global_pd = (uint64_t*)(global_pdpt[pdpte] & PAGE_MASK); + void MMU::initialize_kernel() + { + m_highest_paging_struct = (uint64_t*)kmalloc(sizeof(uint64_t) * 4, 32); + ASSERT(m_highest_paging_struct); + ASSERT(((uintptr_t)m_highest_paging_struct % 32) == 0); - uint64_t* pd = allocate_page_aligned_page(); - pdpt[pdpte] = (uint64_t)pd | (global_pdpt[pdpte] & ~PAGE_MASK); - - for (uint32_t pde = 0; pde < 512; pde++) + // allocate all page directories + for (int i = 0; i < 4; i++) { - if (!(global_pd[pde] & Flags::Present)) + uint64_t* page_directory = allocate_page_aligned_page(); + m_highest_paging_struct[i] = (uint64_t)page_directory | Flags::Present; + } + + // FIXME: We should just identity map until g_kernel_end + + // create and identity map first 6 MiB + uint64_t* page_directory1 = (uint64_t*)(m_highest_paging_struct[0] & PAGE_MASK); + for (uint64_t i = 0; i < 3; i++) + { + uint64_t* page_table = allocate_page_aligned_page(); + for (uint64_t j = 0; j < 512; j++) + page_table[j] = (i << 21) | (j << 12) | Flags::ReadWrite | Flags::Present; + + page_directory1[i] = (uint64_t)page_table | Flags::ReadWrite | Flags::Present; + } + + // dont map first page (0 -> 4 KiB) so that nullptr dereference + // causes page fault :) + uint64_t* page_table1 = (uint64_t*)(page_directory1[0] & PAGE_MASK); + page_table1[0] = 0; + } + + MMU::MMU() + { + if (s_instance == nullptr) + return; + + // Here we copy the s_instances paging structs since they are + // global for every process + + uint64_t* global_pdpt = s_instance->m_highest_paging_struct; + + uint64_t* pdpt = (uint64_t*)kmalloc(sizeof(uint64_t) * 4, 32); + ASSERT(pdpt); + + for (uint32_t pdpte = 0; pdpte < 4; pdpte++) + { + if (!(global_pdpt[pdpte] & Flags::Present)) continue; - uint64_t* global_pt = (uint64_t*)(global_pd[pde] & PAGE_MASK); + uint64_t* global_pd = (uint64_t*)(global_pdpt[pdpte] & PAGE_MASK); - uint64_t* pt = allocate_page_aligned_page(); - pd[pde] = (uint64_t)pt | (global_pd[pde] & ~PAGE_MASK); + uint64_t* pd = allocate_page_aligned_page(); + pdpt[pdpte] = (uint64_t)pd | (global_pdpt[pdpte] & ~PAGE_MASK); - memcpy(pt, global_pt, PAGE_SIZE); + for (uint32_t pde = 0; pde < 512; pde++) + { + if (!(global_pd[pde] & Flags::Present)) + continue; + + uint64_t* global_pt = (uint64_t*)(global_pd[pde] & PAGE_MASK); + + uint64_t* pt = allocate_page_aligned_page(); + pd[pde] = (uint64_t)pt | (global_pd[pde] & ~PAGE_MASK); + + memcpy(pt, global_pt, PAGE_SIZE); + } } + + m_highest_paging_struct = pdpt; } - m_highest_paging_struct = pdpt; -} - -MMU::~MMU() -{ - uint64_t* pdpt = m_highest_paging_struct; - for (uint32_t pdpte = 0; pdpte < 512; pdpte++) + MMU::~MMU() { - if (!(pdpt[pdpte] & Flags::Present)) - continue; - uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); - for (uint32_t pde = 0; pde < 512; pde++) + uint64_t* pdpt = m_highest_paging_struct; + for (uint32_t pdpte = 0; pdpte < 512; pdpte++) { - if (!(pd[pde] & Flags::Present)) + if (!(pdpt[pdpte] & Flags::Present)) continue; - kfree((void*)(pd[pde] & PAGE_MASK)); + uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); + for (uint32_t pde = 0; pde < 512; pde++) + { + if (!(pd[pde] & Flags::Present)) + continue; + kfree((void*)(pd[pde] & PAGE_MASK)); + } + kfree(pd); } - kfree(pd); + kfree(pdpt); } - kfree(pdpt); -} -void MMU::load() -{ - asm volatile("movl %0, %%cr3" :: "r"(m_highest_paging_struct)); -} - -void MMU::map_page_at(paddr_t paddr, vaddr_t vaddr, uint8_t flags) -{ -#if MMU_DEBUG_PRINT - dprintln("AllocatePage(0x{8H})", address); -#endif - ASSERT(flags & Flags::Present); - - ASSERT(!(paddr & ~PAGE_MASK)); - ASSERT(!(vaddr & ~PAGE_MASK)); - - uint32_t pdpte = (vaddr & 0xC0000000) >> 30; - uint32_t pde = (vaddr & 0x3FE00000) >> 21; - uint32_t pte = (vaddr & 0x001FF000) >> 12; - - uint64_t* page_directory = (uint64_t*)(m_highest_paging_struct[pdpte] & PAGE_MASK); - if (!(page_directory[pde] & Flags::Present)) + void MMU::load() { - uint64_t* page_table = allocate_page_aligned_page(); - page_directory[pde] = (uint64_t)page_table; + asm volatile("movl %0, %%cr3" :: "r"(m_highest_paging_struct)); + } + + void MMU::map_page_at(paddr_t paddr, vaddr_t vaddr, uint8_t flags) + { + #if MMU_DEBUG_PRINT + dprintln("AllocatePage(0x{8H})", address); + #endif + ASSERT(flags & Flags::Present); + + ASSERT(!(paddr & ~PAGE_MASK)); + ASSERT(!(vaddr & ~PAGE_MASK)); + + uint32_t pdpte = (vaddr & 0xC0000000) >> 30; + uint32_t pde = (vaddr & 0x3FE00000) >> 21; + uint32_t pte = (vaddr & 0x001FF000) >> 12; + + uint64_t* page_directory = (uint64_t*)(m_highest_paging_struct[pdpte] & PAGE_MASK); + if (!(page_directory[pde] & Flags::Present)) + { + uint64_t* page_table = allocate_page_aligned_page(); + page_directory[pde] = (uint64_t)page_table; + } + page_directory[pde] |= flags; + + uint64_t* page_table = (uint64_t*)(page_directory[pde] & PAGE_MASK); + page_table[pte] = paddr | flags; + } + + void MMU::identity_map_page(paddr_t address, uint8_t flags) + { + address &= PAGE_MASK; + map_page_at(address, address, flags); + } + + void MMU::identity_map_range(paddr_t address, ptrdiff_t size, uint8_t flags) + { + paddr_t s_page = address & PAGE_MASK; + paddr_t e_page = (address + size - 1) & PAGE_MASK; + for (paddr_t page = s_page; page <= e_page; page += PAGE_SIZE) + identity_map_page(page, flags); + } + + void MMU::unmap_page(vaddr_t address) + { + #if MMU_DEBUG_PRINT + dprintln("UnAllocatePage(0x{8H})", address & PAGE_MASK); + #endif + + uint32_t pdpte = (address & 0xC0000000) >> 30; + uint32_t pde = (address & 0x3FE00000) >> 21; + uint32_t pte = (address & 0x001FF000) >> 12; + + uint64_t* page_directory = (uint64_t*)(m_highest_paging_struct[pdpte] & PAGE_MASK); + if (!(page_directory[pde] & Flags::Present)) + return; + + uint64_t* page_table = (uint64_t*)(page_directory[pde] & PAGE_MASK); + if (!(page_table[pte] & Flags::Present)) + return; + + page_table[pte] = 0; + + // TODO: Unallocate the page table if this was the only allocated page + } + + void MMU::unmap_range(vaddr_t address, ptrdiff_t size) + { + uintptr_t s_page = address & PAGE_MASK; + uintptr_t e_page = (address + size - 1) & PAGE_MASK; + for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE) + unmap_page(page); + } + + + uint8_t MMU::get_page_flags(vaddr_t address) const + { + uint32_t pdpte = (address & 0xC0000000) >> 30; + uint32_t pde = (address & 0x3FE00000) >> 21; + uint32_t pte = (address & 0x001FF000) >> 12; + + uint64_t* page_directory = (uint64_t*)(m_highest_paging_struct[pdpte] & PAGE_MASK); + if (!(page_directory[pde] & Flags::Present)) + return 0; + + uint64_t* page_table = (uint64_t*)(page_directory[pde] & PAGE_MASK); + if (!(page_table[pte] & Flags::Present)) + return 0; + + return page_table[pte] & FLAGS_MASK; } - page_directory[pde] |= flags; - uint64_t* page_table = (uint64_t*)(page_directory[pde] & PAGE_MASK); - page_table[pte] = paddr | flags; -} - -void MMU::map_page(uintptr_t address, uint8_t flags) -{ - address &= PAGE_MASK; - map_page_at(address, address, flags); -} - -void MMU::map_range(uintptr_t address, ptrdiff_t size, uint8_t flags) -{ - uintptr_t s_page = address & PAGE_MASK; - uintptr_t e_page = (address + size - 1) & PAGE_MASK; - for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE) - map_page(page, flags); -} - -void MMU::unmap_page(uintptr_t address) -{ -#if MMU_DEBUG_PRINT - dprintln("UnAllocatePage(0x{8H})", address & PAGE_MASK); -#endif - - uint32_t pdpte = (address & 0xC0000000) >> 30; - uint32_t pde = (address & 0x3FE00000) >> 21; - uint32_t pte = (address & 0x001FF000) >> 12; - - uint64_t* page_directory = (uint64_t*)(m_highest_paging_struct[pdpte] & PAGE_MASK); - if (!(page_directory[pde] & Flags::Present)) - return; - - uint64_t* page_table = (uint64_t*)(page_directory[pde] & PAGE_MASK); - if (!(page_table[pte] & Flags::Present)) - return; - - page_table[pte] = 0; - - // TODO: Unallocate the page table if this was the only allocated page -} - -void MMU::unmap_range(uintptr_t address, ptrdiff_t size) -{ - uintptr_t s_page = address & PAGE_MASK; - uintptr_t e_page = (address + size - 1) & PAGE_MASK; - for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE) - unmap_page(page); } diff --git a/kernel/arch/x86_64/MMU.cpp b/kernel/arch/x86_64/MMU.cpp index 311db566d..8fded3d77 100644 --- a/kernel/arch/x86_64/MMU.cpp +++ b/kernel/arch/x86_64/MMU.cpp @@ -2,8 +2,8 @@ #include #include -#define PAGE_SIZE 0x1000 -#define PAGE_MASK ~(PAGE_SIZE - 1) +#define FLAGS_MASK (PAGE_SIZE - 1) +#define PAGE_MASK (~FLAGS_MASK) #define CLEANUP_STRUCTURE(s) \ for (uint64_t i = 0; i < 512; i++) \ @@ -11,240 +11,274 @@ return; \ kfree(s) -static MMU* s_instance = nullptr; - -void MMU::initialize() -{ - ASSERT(s_instance == nullptr); - s_instance = new MMU(); - ASSERT(s_instance); - s_instance->initialize_kernel(); - s_instance->load(); -} - -MMU& MMU::get() -{ - ASSERT(s_instance); - return *s_instance; -} - -static uint64_t* allocate_page_aligned_page() -{ - void* page = kmalloc(PAGE_SIZE, PAGE_SIZE); - ASSERT(page); - memset(page, 0, PAGE_SIZE); - return (uint64_t*)page; -} extern uint8_t g_kernel_end[]; -void MMU::initialize_kernel() +namespace Kernel { - // FIXME: We should just identity map until g_kernel_end - - ASSERT((uintptr_t)g_kernel_end <= 6 * (1 << 20)); - - // Identity map from 0 -> 6 MiB - m_highest_paging_struct = allocate_page_aligned_page(); - uint64_t* pdpt = allocate_page_aligned_page(); - m_highest_paging_struct[0] = (uint64_t)pdpt | Flags::ReadWrite | Flags::Present; + static MMU* s_instance = nullptr; - uint64_t* pd = allocate_page_aligned_page(); - pdpt[0] = (uint64_t)pd | Flags::ReadWrite | Flags::Present; - - for (uint32_t i = 0; i < 3; i++) + void MMU::initialize() { - uint64_t* pt = allocate_page_aligned_page(); - for (uint64_t j = 0; j < 512; j++) - pt[j] = (i << 21) | (j << 12) | Flags::ReadWrite | Flags::Present; - pd[i] = (uint64_t)pt | Flags::ReadWrite | Flags::Present; + ASSERT(s_instance == nullptr); + s_instance = new MMU(); + ASSERT(s_instance); + s_instance->initialize_kernel(); + s_instance->load(); } - // Unmap 0 -> 4 KiB - uint64_t* pt1 = (uint64_t*)(pd[0] & PAGE_MASK); - pt1[0] = 0; -} - -MMU::MMU() -{ - if (s_instance == nullptr) - return; - - // Here we copy the s_instances paging structs since they are - // global for every process - - uint64_t* global_pml4 = s_instance->m_highest_paging_struct; - - uint64_t* pml4 = allocate_page_aligned_page(); - for (uint32_t pml4e = 0; pml4e < 512; pml4e++) + MMU& MMU::get() { - if (!(global_pml4[pml4e] & Flags::Present)) - continue; + ASSERT(s_instance); + return *s_instance; + } - uint64_t* global_pdpt = (uint64_t*)(global_pml4[pml4e] & PAGE_MASK); + static uint64_t* allocate_page_aligned_page() + { + void* page = kmalloc(PAGE_SIZE, PAGE_SIZE); + ASSERT(page); + memset(page, 0, PAGE_SIZE); + return (uint64_t*)page; + } + void MMU::initialize_kernel() + { + // FIXME: We should just identity map until g_kernel_end + + ASSERT((uintptr_t)g_kernel_end <= 6 * (1 << 20)); + + // Identity map from 0 -> 6 MiB + m_highest_paging_struct = allocate_page_aligned_page(); + uint64_t* pdpt = allocate_page_aligned_page(); - pml4[pml4e] = (uint64_t)pdpt | (global_pml4[pml4e] & ~PAGE_MASK); + m_highest_paging_struct[0] = (uint64_t)pdpt | Flags::ReadWrite | Flags::Present; - for (uint32_t pdpte = 0; pdpte < 512; pdpte++) + uint64_t* pd = allocate_page_aligned_page(); + pdpt[0] = (uint64_t)pd | Flags::ReadWrite | Flags::Present; + + for (uint32_t i = 0; i < 3; i++) { - if (!(global_pdpt[pdpte] & Flags::Present)) + uint64_t* pt = allocate_page_aligned_page(); + for (uint64_t j = 0; j < 512; j++) + pt[j] = (i << 21) | (j << 12) | Flags::ReadWrite | Flags::Present; + pd[i] = (uint64_t)pt | Flags::ReadWrite | Flags::Present; + } + + // Unmap 0 -> 4 KiB + uint64_t* pt1 = (uint64_t*)(pd[0] & PAGE_MASK); + pt1[0] = 0; + } + + MMU::MMU() + { + if (s_instance == nullptr) + return; + + // Here we copy the s_instances paging structs since they are + // global for every process + + uint64_t* global_pml4 = s_instance->m_highest_paging_struct; + + uint64_t* pml4 = allocate_page_aligned_page(); + for (uint32_t pml4e = 0; pml4e < 512; pml4e++) + { + if (!(global_pml4[pml4e] & Flags::Present)) continue; - uint64_t* global_pd = (uint64_t*)(global_pdpt[pdpte] & PAGE_MASK); + uint64_t* global_pdpt = (uint64_t*)(global_pml4[pml4e] & PAGE_MASK); - uint64_t* pd = allocate_page_aligned_page(); - pdpt[pdpte] = (uint64_t)pd | (global_pdpt[pdpte] & ~PAGE_MASK); + uint64_t* pdpt = allocate_page_aligned_page(); + pml4[pml4e] = (uint64_t)pdpt | (global_pml4[pml4e] & FLAGS_MASK); - for (uint32_t pde = 0; pde < 512; pde++) + for (uint32_t pdpte = 0; pdpte < 512; pdpte++) { - if (!(global_pd[pde] & Flags::Present)) + if (!(global_pdpt[pdpte] & Flags::Present)) continue; - uint64_t* global_pt = (uint64_t*)(global_pd[pde] & PAGE_MASK); + uint64_t* global_pd = (uint64_t*)(global_pdpt[pdpte] & PAGE_MASK); - uint64_t* pt = allocate_page_aligned_page(); - pd[pde] = (uint64_t)pt | (global_pd[pde] & ~PAGE_MASK); + uint64_t* pd = allocate_page_aligned_page(); + pdpt[pdpte] = (uint64_t)pd | (global_pdpt[pdpte] & FLAGS_MASK); - memcpy(pt, global_pt, PAGE_SIZE); + for (uint32_t pde = 0; pde < 512; pde++) + { + if (!(global_pd[pde] & Flags::Present)) + continue; + + uint64_t* global_pt = (uint64_t*)(global_pd[pde] & PAGE_MASK); + + uint64_t* pt = allocate_page_aligned_page(); + pd[pde] = (uint64_t)pt | (global_pd[pde] & FLAGS_MASK); + + memcpy(pt, global_pt, PAGE_SIZE); + } } } + + m_highest_paging_struct = pml4; } - m_highest_paging_struct = pml4; -} - -MMU::~MMU() -{ - uint64_t* pml4 = m_highest_paging_struct; - for (uint32_t pml4e = 0; pml4e < 512; pml4e++) + MMU::~MMU() { + uint64_t* pml4 = m_highest_paging_struct; + for (uint32_t pml4e = 0; pml4e < 512; pml4e++) + { + if (!(pml4[pml4e] & Flags::Present)) + continue; + uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK); + for (uint32_t pdpte = 0; pdpte < 512; pdpte++) + { + if (!(pdpt[pdpte] & Flags::Present)) + continue; + uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); + for (uint32_t pde = 0; pde < 512; pde++) + { + if (!(pd[pde] & Flags::Present)) + continue; + kfree((void*)(pd[pde] & PAGE_MASK)); + } + kfree(pd); + } + kfree(pdpt); + } + kfree(pml4); + } + + void MMU::load() + { + asm volatile("movq %0, %%cr3" :: "r"(m_highest_paging_struct)); + } + + void MMU::identity_map_page(paddr_t address, uint8_t flags) + { + address &= PAGE_MASK; + map_page_at(address, address, flags); + } + + void MMU::identity_map_range(paddr_t address, ptrdiff_t size, uint8_t flags) + { + paddr_t s_page = address & PAGE_MASK; + paddr_t e_page = (address + size - 1) & PAGE_MASK; + for (paddr_t page = s_page; page <= e_page; page += PAGE_SIZE) + identity_map_page(page, flags); + } + + void MMU::unmap_page(vaddr_t address) + { + ASSERT((address >> 48) == 0); + + address &= PAGE_MASK; + + uint64_t pml4e = (address >> 39) & 0x1FF; + uint64_t pdpte = (address >> 30) & 0x1FF; + uint64_t pde = (address >> 21) & 0x1FF; + uint64_t pte = (address >> 12) & 0x1FF; + + uint64_t* pml4 = m_highest_paging_struct; if (!(pml4[pml4e] & Flags::Present)) - continue; + return; + uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK); - for (uint32_t pdpte = 0; pdpte < 512; pdpte++) + if (!(pdpt[pdpte] & Flags::Present)) + return; + + uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); + if (!(pd[pde] & Flags::Present)) + return; + + uint64_t* pt = (uint64_t*)(pd[pde] & PAGE_MASK); + if (!(pt[pte] & Flags::Present)) + return; + + pt[pte] = 0; + + CLEANUP_STRUCTURE(pt); + pd[pde] = 0; + CLEANUP_STRUCTURE(pd); + pdpt[pdpte] = 0; + CLEANUP_STRUCTURE(pdpt); + pml4[pml4e] = 0; + } + + void MMU::unmap_range(vaddr_t address, ptrdiff_t size) + { + vaddr_t s_page = address & PAGE_MASK; + vaddr_t e_page = (address + size - 1) & PAGE_MASK; + for (vaddr_t page = s_page; page <= e_page; page += PAGE_SIZE) + unmap_page(page); + } + + void MMU::map_page_at(paddr_t paddr, vaddr_t vaddr, uint8_t flags) + { + ASSERT((paddr >> 48) == 0); + ASSERT((vaddr >> 48) == 0); + + ASSERT(paddr % PAGE_SIZE == 0); + ASSERT(vaddr % PAGE_SIZE == 0);; + + ASSERT(flags & Flags::Present); + + uint64_t pml4e = (vaddr >> 39) & 0x1FF; + uint64_t pdpte = (vaddr >> 30) & 0x1FF; + uint64_t pde = (vaddr >> 21) & 0x1FF; + uint64_t pte = (vaddr >> 12) & 0x1FF; + + uint64_t* pml4 = m_highest_paging_struct; + if ((pml4[pml4e] & flags) != flags) + { + if (!(pml4[pml4e] & Flags::Present)) + pml4[pml4e] = (uint64_t)allocate_page_aligned_page(); + pml4[pml4e] = (pml4[pml4e] & PAGE_MASK) | flags; + } + + uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK); + if ((pdpt[pdpte] & flags) != flags) { if (!(pdpt[pdpte] & Flags::Present)) - continue; - uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); - for (uint32_t pde = 0; pde < 512; pde++) - { - if (!(pd[pde] & Flags::Present)) - continue; - kfree((void*)(pd[pde] & PAGE_MASK)); - } - kfree(pd); + pdpt[pdpte] = (uint64_t)allocate_page_aligned_page(); + pdpt[pdpte] = (pdpt[pdpte] & PAGE_MASK) | flags; } - kfree(pdpt); + + uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); + if ((pd[pde] & flags) != flags) + { + if (!(pd[pde] & Flags::Present)) + pd[pde] = (uint64_t)allocate_page_aligned_page(); + pd[pde] = (pd[pde] & PAGE_MASK) | flags; + } + + uint64_t* pt = (uint64_t*)(pd[pde] & PAGE_MASK); + if ((pt[pte] & flags) != flags) + pt[pte] = paddr | flags; } - kfree(pml4); -} -void MMU::load() -{ - asm volatile("movq %0, %%cr3" :: "r"(m_highest_paging_struct)); -} - -void MMU::map_page(uintptr_t address, uint8_t flags) -{ - address &= PAGE_MASK; - map_page_at(address, address, flags); -} - -void MMU::map_range(uintptr_t address, ptrdiff_t size, uint8_t flags) -{ - uintptr_t s_page = address & PAGE_MASK; - uintptr_t e_page = (address + size - 1) & PAGE_MASK; - for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE) - map_page(page, flags); -} - -void MMU::unmap_page(uintptr_t address) -{ - ASSERT((address >> 48) == 0); - - address &= PAGE_MASK; - - uint64_t pml4e = (address >> 39) & 0x1FF; - uint64_t pdpte = (address >> 30) & 0x1FF; - uint64_t pde = (address >> 21) & 0x1FF; - uint64_t pte = (address >> 12) & 0x1FF; - - uint64_t* pml4 = m_highest_paging_struct; - if (!(pml4[pml4e] & Flags::Present)) - return; - - uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK); - if (!(pdpt[pdpte] & Flags::Present)) - return; - - uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); - if (!(pd[pde] & Flags::Present)) - return; - - uint64_t* pt = (uint64_t*)(pd[pde] & PAGE_MASK); - if (!(pt[pte] & Flags::Present)) - return; - - pt[pte] = 0; - - CLEANUP_STRUCTURE(pt); - pd[pde] = 0; - CLEANUP_STRUCTURE(pd); - pdpt[pdpte] = 0; - CLEANUP_STRUCTURE(pdpt); - pml4[pml4e] = 0; -} - -void MMU::unmap_range(uintptr_t address, ptrdiff_t size) -{ - uintptr_t s_page = address & PAGE_MASK; - uintptr_t e_page = (address + size - 1) & PAGE_MASK; - for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE) - unmap_page(page); -} - -void MMU::map_page_at(paddr_t paddr, vaddr_t vaddr, uint8_t flags) -{ - ASSERT((paddr >> 48) == 0); - ASSERT((vaddr >> 48) == 0); - - ASSERT((paddr & ~PAGE_MASK) == 0); - ASSERT((vaddr & ~PAGE_MASK) == 0);; - - ASSERT(flags & Flags::Present); - - uint64_t pml4e = (vaddr >> 39) & 0x1FF; - uint64_t pdpte = (vaddr >> 30) & 0x1FF; - uint64_t pde = (vaddr >> 21) & 0x1FF; - uint64_t pte = (vaddr >> 12) & 0x1FF; - - uint64_t* pml4 = m_highest_paging_struct; - if ((pml4[pml4e] & flags) != flags) + uint8_t MMU::get_page_flags(vaddr_t address) const { + ASSERT(address % PAGE_SIZE == 0); + + uint64_t pml4e = (address >> 39) & 0x1FF; + uint64_t pdpte = (address >> 30) & 0x1FF; + uint64_t pde = (address >> 21) & 0x1FF; + uint64_t pte = (address >> 12) & 0x1FF; + + uint64_t* pml4 = m_highest_paging_struct; if (!(pml4[pml4e] & Flags::Present)) - pml4[pml4e] = (uint64_t)allocate_page_aligned_page(); - pml4[pml4e] = (pml4[pml4e] & PAGE_MASK) | flags; - } + return 0; - uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK); - if ((pdpt[pdpte] & flags) != flags) - { + uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK); if (!(pdpt[pdpte] & Flags::Present)) - pdpt[pdpte] = (uint64_t)allocate_page_aligned_page(); - pdpt[pdpte] = (pdpt[pdpte] & PAGE_MASK) | flags; - } + return 0; - uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); - if ((pd[pde] & flags) != flags) - { + uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); if (!(pd[pde] & Flags::Present)) - pd[pde] = (uint64_t)allocate_page_aligned_page(); - pd[pde] = (pd[pde] & PAGE_MASK) | flags; + return 0; + + uint64_t* pt = (uint64_t*)(pd[pde] & PAGE_MASK); + if (!(pt[pte] & Flags::Present)) + return 0; + + return pt[pte] & FLAGS_MASK; } - uint64_t* pt = (uint64_t*)(pd[pde] & PAGE_MASK); - if ((pt[pte] & flags) != flags) - pt[pte] = paddr | flags; } diff --git a/kernel/include/kernel/Memory/Heap.h b/kernel/include/kernel/Memory/Heap.h index f970d3b06..9f34b869d 100644 --- a/kernel/include/kernel/Memory/Heap.h +++ b/kernel/include/kernel/Memory/Heap.h @@ -7,9 +7,10 @@ #define PAGE_SIZE 4096 -namespace Kernel::Memory +namespace Kernel { + using vaddr_t = uintptr_t; using paddr_t = uintptr_t; class PhysicalRange diff --git a/kernel/include/kernel/Memory/MMU.h b/kernel/include/kernel/Memory/MMU.h index 38e1c47da..41aece4c1 100644 --- a/kernel/include/kernel/Memory/MMU.h +++ b/kernel/include/kernel/Memory/MMU.h @@ -1,41 +1,44 @@ #pragma once -#include -#include +#include -class MMU +namespace Kernel { -public: - enum Flags : uint8_t + + class MMU { - Present = 1, - ReadWrite = 2, - UserSupervisor = 4, + public: + enum Flags : uint8_t + { + Present = 1, + ReadWrite = 2, + UserSupervisor = 4, + }; + + public: + static void initialize(); + static MMU& get(); + + MMU(); + ~MMU(); + + void identity_map_page(paddr_t, uint8_t); + void identity_map_range(paddr_t, ptrdiff_t, uint8_t); + + void unmap_page(vaddr_t); + void unmap_range(vaddr_t, ptrdiff_t); + + void map_page_at(paddr_t, vaddr_t, uint8_t); + + uint8_t get_page_flags(vaddr_t) const; + + void load(); + + private: + void initialize_kernel(); + + private: + uint64_t* m_highest_paging_struct; }; - using vaddr_t = uintptr_t; - using paddr_t = uintptr_t; - -public: - static void initialize(); - static MMU& get(); - - MMU(); - ~MMU(); - - void map_page(uintptr_t, uint8_t); - void map_range(uintptr_t, ptrdiff_t, uint8_t); - - void unmap_page(uintptr_t); - void unmap_range(uintptr_t, ptrdiff_t); - - void map_page_at(paddr_t, vaddr_t, uint8_t); - - void load(); - -private: - void initialize_kernel(); - -private: - uint64_t* m_highest_paging_struct; -}; +} diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 3a7673bc1..b29c50276 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -82,7 +82,7 @@ namespace Kernel BAN::ErrorOr get_free_fd(); BAN::Vector m_open_files; - BAN::Vector m_allocated_pages; + BAN::Vector m_allocated_pages; mutable RecursiveSpinLock m_lock; diff --git a/kernel/kernel/ACPI.cpp b/kernel/kernel/ACPI.cpp index 8c25800ae..3655733dc 100644 --- a/kernel/kernel/ACPI.cpp +++ b/kernel/kernel/ACPI.cpp @@ -105,7 +105,7 @@ namespace Kernel if (rsdp->revision >= 2) { const XSDT* xsdt = (const XSDT*)rsdp->xsdt_address; - MMU::get().map_page((uintptr_t)xsdt, MMU::Flags::Present); + MMU::get().identity_map_page((uintptr_t)xsdt, MMU::Flags::Present); BAN::ScopeGuard _([xsdt] { MMU::get().unmap_page((uintptr_t)xsdt); }); if (memcmp(xsdt->signature, "XSDT", 4) != 0) @@ -120,7 +120,7 @@ namespace Kernel else { const RSDT* rsdt = (const RSDT*)(uintptr_t)rsdp->rsdt_address; - MMU::get().map_page((uintptr_t)rsdt, MMU::Flags::Present); + MMU::get().identity_map_page((uintptr_t)rsdt, MMU::Flags::Present); BAN::ScopeGuard _([rsdt] { MMU::get().unmap_page((uintptr_t)rsdt); }); if (memcmp(rsdt->signature, "RSDT", 4) != 0) @@ -133,13 +133,13 @@ namespace Kernel m_entry_count = (rsdt->length - sizeof(SDTHeader)) / 4; } - MMU::get().map_range(m_header_table, m_entry_count * m_entry_size, MMU::Flags::Present); + MMU::get().identity_map_range(m_header_table, m_entry_count * m_entry_size, MMU::Flags::Present); for (uint32_t i = 0; i < m_entry_count; i++) { auto* header = get_header_from_index(i); - MMU::get().map_page((uintptr_t)header, MMU::Flags::Present); - MMU::get().map_range((uintptr_t)header, header->length, MMU::Flags::Present); + MMU::get().identity_map_page((uintptr_t)header, MMU::Flags::Present); + MMU::get().identity_map_range((uintptr_t)header, header->length, MMU::Flags::Present); } return {}; diff --git a/kernel/kernel/APIC.cpp b/kernel/kernel/APIC.cpp index 413b84ed5..22a6b643f 100644 --- a/kernel/kernel/APIC.cpp +++ b/kernel/kernel/APIC.cpp @@ -81,6 +81,8 @@ union RedirectionEntry }; }; +using namespace Kernel; + APIC* APIC::create() { uint32_t ecx, edx; @@ -144,10 +146,10 @@ APIC* APIC::create() return nullptr; } - MMU::get().map_page(apic->m_local_apic, MMU::Flags::ReadWrite | MMU::Flags::Present); + MMU::get().identity_map_page(apic->m_local_apic, MMU::Flags::ReadWrite | MMU::Flags::Present); for (auto& io_apic : apic->m_io_apics) { - MMU::get().map_page(io_apic.address, MMU::Flags::ReadWrite | MMU::Flags::Present); + MMU::get().identity_map_page(io_apic.address, MMU::Flags::ReadWrite | MMU::Flags::Present); io_apic.max_redirs = io_apic.read(IOAPIC_MAX_REDIRS); } diff --git a/kernel/kernel/Memory/Heap.cpp b/kernel/kernel/Memory/Heap.cpp index caad448d7..08562561b 100644 --- a/kernel/kernel/Memory/Heap.cpp +++ b/kernel/kernel/Memory/Heap.cpp @@ -4,7 +4,7 @@ extern uint8_t g_kernel_end[]; -namespace Kernel::Memory +namespace Kernel { PhysicalRange::PhysicalRange(paddr_t start, size_t size) @@ -36,7 +36,7 @@ namespace Kernel::Memory m_list_pages = BAN::Math::div_round_up(m_total_pages * sizeof(node), PAGE_SIZE); m_reservable_pages = m_total_pages - m_list_pages; - MMU::get().map_range(m_start, m_list_pages * PAGE_SIZE, MMU::Flags::ReadWrite | MMU::Flags::Present); + MMU::get().identity_map_range(m_start, m_list_pages * PAGE_SIZE, MMU::Flags::ReadWrite | MMU::Flags::Present); // Initialize page list so that every page points to the next one node* page_list = (node*)m_start; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 7ff22490a..8026db20d 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -77,7 +77,7 @@ namespace Kernel MUST(process->m_allocated_pages.reserve(page_end - page_start + 1)); for (size_t page = page_start; page <= page_end; page++) { - auto paddr = Memory::Heap::get().take_free_page(); + auto paddr = Heap::get().take_free_page(); MUST(process->m_allocated_pages.push_back(paddr)); process->m_mmu->map_page_at(paddr, page * 4096, flags); } @@ -115,7 +115,7 @@ namespace Kernel delete m_mmu; } for (auto paddr : m_allocated_pages) - Memory::Heap::get().release_page(paddr); + Heap::get().release_page(paddr); } void Process::add_thread(Thread* thread) diff --git a/kernel/kernel/Terminal/VesaTerminalDriver.cpp b/kernel/kernel/Terminal/VesaTerminalDriver.cpp index ec45f0e71..2862ed3a9 100644 --- a/kernel/kernel/Terminal/VesaTerminalDriver.cpp +++ b/kernel/kernel/Terminal/VesaTerminalDriver.cpp @@ -4,6 +4,8 @@ #include #include +using namespace Kernel; + VesaTerminalDriver* VesaTerminalDriver::create() { if (!(g_multiboot_info->flags & MULTIBOOT_FLAGS_FRAMEBUFFER)) @@ -34,7 +36,7 @@ VesaTerminalDriver* VesaTerminalDriver::create() return nullptr; } - MMU::get().map_range(framebuffer.addr, framebuffer.pitch * framebuffer.height, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present); + MMU::get().identity_map_range(framebuffer.addr, framebuffer.pitch * framebuffer.height, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present); auto* driver = new VesaTerminalDriver( framebuffer.width, diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index 73bb47997..bfb5adbdc 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -44,7 +44,7 @@ namespace Kernel delete thread; return BAN::Error::from_errno(ENOMEM); } - process->mmu().map_range(thread->stack_base(), thread->stack_size(), MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present); + process->mmu().identity_map_range(thread->stack_base(), thread->stack_size(), MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present); return thread; } diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 79481d5df..e3fecf0ed 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -139,7 +139,7 @@ extern "C" void kernel_main() ASSERT(tty1); dprintln("TTY initialized"); - Memory::Heap::initialize(); + Heap::initialize(); dprintln("Heap initialzed"); parse_command_line();