From 68166e58ca4caf4fbc5022cc6c26158f14293583 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 10 Apr 2021 20:43:01 -0500 Subject: [PATCH] Implemented C x86 paging, removed C++ code --- include/mmgr.h | 5 +- src/memorymanager.hpp | 55 ------- src/x86/memorymanagerx86.cpp | 31 ---- src/x86/memorymanagerx86.hpp | 29 ---- src/x86/mmap.cpp | 292 ----------------------------------- src/x86/mmgr.c | 121 +++++++++++++++ src/x86/pagetableentry.cpp | 132 ---------------- src/x86/pagetableentry.hpp | 83 ---------- 8 files changed, 124 insertions(+), 624 deletions(-) delete mode 100644 src/memorymanager.hpp delete mode 100644 src/x86/memorymanagerx86.cpp delete mode 100644 src/x86/memorymanagerx86.hpp delete mode 100644 src/x86/mmap.cpp create mode 100644 src/x86/mmgr.c delete mode 100644 src/x86/pagetableentry.cpp delete mode 100644 src/x86/pagetableentry.hpp diff --git a/include/mmgr.h b/include/mmgr.h index 0bc0f53..dc80161 100644 --- a/include/mmgr.h +++ b/include/mmgr.h @@ -1,5 +1,6 @@ #pragma once +#include "pageallocator.h" #include "types/physaddr.h" /** @@ -9,7 +10,7 @@ * * @return physaddr_t */ -physaddr_t create_address_space(); +physaddr_t create_address_space(struct page_stack_t *page_stack); /** * @brief Load an existing top-level page table @@ -26,7 +27,7 @@ void load_address_space(physaddr_t table); * @param flags * @return int */ -int map_page(void *page, physaddr_t frame, int flags); +int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int flags); /** * @brief Unmaps a single page, returning the physical address of the frame it diff --git a/src/memorymanager.hpp b/src/memorymanager.hpp deleted file mode 100644 index 72d8237..0000000 --- a/src/memorymanager.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef MEMORYMANAGER_H -#define MEMORYMANAGER_H - -#include "systypes.hpp" - -class MemoryManager -{ -public: - - /** - * @brief Returns the size of a single page on the present platform. - * - * @return the size in bytes of a single page - */ - virtual unsigned int getPageSize() const = 0; - - /** - * Allocates space for a new top-level page table, and initializes it to - * point only to the kernel's page tables. - * - * @returns the physical address of the new top-level page table - */ - virtual physaddr_t createAddressSpace() = 0; - - /** - * Loads the given top-level page table(s). - * - * @param table the top-level page table to load - */ - virtual void loadAddressSpace(physaddr_t table) = 0; - - /** - * Maps a single page to a single frame. Allocates a new page table if one - * does not exist for that frame. - * - * @param page the virtual address of the page to map - * @param frame the physical address of the frame to map to - * @param flags flags to apply to the entry - * - * @returns zero upon success, nonzero on failure - */ - virtual int mapPage(void* page, physaddr_t frame, int flags) = 0; - - /** - * Deletes the page table entry for the specified page. Does not deallocate - * redundant page tables or modify higher level tables; these are cleaned up - * after the owning process ends. - * - * @param page the virtual address of the page to unmap - */ - virtual physaddr_t unmapPage(void* page) = 0; - -}; - -#endif \ No newline at end of file diff --git a/src/x86/memorymanagerx86.cpp b/src/x86/memorymanagerx86.cpp deleted file mode 100644 index b4aaefc..0000000 --- a/src/x86/memorymanagerx86.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "memorymanagerx86.hpp" - -unsigned int MemoryManagerx86::getPageSize() const -{ - return pageSize; -} - -physaddr_t MemoryManagerx86::createAddressSpace() -{ - if(((size_t) table & 0xFFF) != 0) - return -1; - PageTableEntry* newDirectory = (PageTableEntry*) table; - newDirectory[1022] = m_pageDirectory[1022]; - newDirectory[1023] = m_pageDirectory[1023]; - return 0; -} - -void MemoryManagerx86::loadAddressSpace(physaddr_t table) -{ - -} - -int MemoryManagerx86::mapPage(void *page, physaddr_t frame, int flags) -{ - -} - -physaddr_t MemoryManagerx86::unmapPage(void *page) -{ - -} \ No newline at end of file diff --git a/src/x86/memorymanagerx86.hpp b/src/x86/memorymanagerx86.hpp deleted file mode 100644 index ed3273e..0000000 --- a/src/x86/memorymanagerx86.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef MEMORYMANAGERX86_H -#define MEMORYMANAGERX86_H - -#include "../memorymanager.hpp" -#include "pagetableentry.hpp" - -class MemoryManagerx86 : public MemoryManager -{ -public: - - virtual unsigned int getPageSize() const; - - virtual physaddr_t createAddressSpace(); - - virtual void loadAddressSpace(physaddr_t table); - - virtual int mapPage(void* page, physaddr_t frame, int flags); - - virtual physaddr_t unmapPage(void* page); - -private: - - static const unsigned int pageSize = 4096; - - PageTableEntry *m_pageTables, *m_pageDirectory; - -}; - -#endif \ No newline at end of file diff --git a/src/x86/mmap.cpp b/src/x86/mmap.cpp deleted file mode 100644 index 3cddf3b..0000000 --- a/src/x86/mmap.cpp +++ /dev/null @@ -1,292 +0,0 @@ -#include "../mmap.hpp" -#include "../kernelstate.hpp" - -class PageTableEntry { -public: - - PageTableEntry() - { - this->present = 0; - this->rw = 0; - this->usermode = 0; - this->writeThrough = 0; - this->cacheDisable = 0; - this->accessed = 0; - this->dirty = 0; - this->pat = 0; - this->global = 0; - this->shared = 0; - this->ignored = 0; - this->physicalAddress = 0; - } - - bool getAccessed() const - { - return accessed == 1; - } - - bool getCacheDisable() const - { - return cacheDisable == 1; - } - - void setCacheDisable(bool cacheDisable) - { - this->cacheDisable = cacheDisable ? 1 : 0; - } - - bool getDirty() const - { - return dirty == 1; - } - - bool getGlobal() const - { - return global == 1; - } - - void setGlobal(bool global) - { - this->global = global ? 1 : 0; - } - - bool getPat() const - { - return pat == 1; - } - - void setPat(bool pat) - { - this->pat = pat ? 1 : 0; - } - - physaddr_t getPhysicalAddress() const - { - physaddr_t physicalAddress = this->physicalAddress; - return physicalAddress << 12; - } - - physaddr_t setPhysicalAddress(physaddr_t physicalAddress) - { - this->physicalAddress = physicalAddress >> 12; - return this->physicalAddress << 12; - } - - bool getPresent() const - { - return present == 1; - } - - void setPresent(bool present) - { - this->present = present ? 1 : 0; - } - - bool getRw() const - { - return rw == 1; - } - - void setRw(bool rw) - { - this->rw = rw ? 1 : 0; - } - - bool getShared() const - { - return shared == 1; - } - - void setShared(bool shared) - { - this->shared = shared ? 1 : 0; - } - - bool getUsermode() const - { - return usermode == 1; - } - - void setUsermode(bool usermode) - { - this->usermode = usermode ? 1 : 0; - } - - bool getWriteThrough() const - { - return writeThrough == 1; - } - - void setWriteThrough(bool writeThrough) - { - this->writeThrough = writeThrough ? 1 : 0; - } - - physaddr_t operator=(physaddr_t rhs) - { - return setPhysicalAddress(rhs); - } - - PageTableEntry operator=(PageTableEntry rhs) - { - uint32_t* iThis = (uint32_t*) this; - uint32_t* iThat = (uint32_t*) &rhs; - *iThis = *iThat; - return rhs; - } - -private: - uint32_t present : 1; - uint32_t rw : 1; - uint32_t usermode : 1; - uint32_t writeThrough : 1; - uint32_t cacheDisable : 1; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t pat : 1; - uint32_t global : 1; - uint32_t shared : 1; - uint32_t ignored : 2; - uint32_t physicalAddress : 20; -}; - -int kernelns::mmap(void* start, size_t length, int flags) -{ - if((size_t) start % 4096 != 0) - return -1; - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - size_t tableIndex = (size_t) start / 4096; - for(int i = (int) length; i > 0; i -= 4096) - { - size_t directoryIndex = tableIndex / 1024; - if(!pageDirectory[directoryIndex].getPresent()) - { - physaddr_t newPT = State::pageAllocator.allocate(4096); - if(newPT == 0) - return -1; - pageDirectory[directoryIndex] = newPT; - pageDirectory[directoryIndex].setPresent(true); - pageDirectory[directoryIndex].setUsermode(false); - pageDirectory[directoryIndex].setRw(true); - } - if(!pageTables[tableIndex].getPresent()) - { - physaddr_t page = State::pageAllocator.allocate(4096); - pageTables[tableIndex] = page; - pageTables[tableIndex].setPresent(true); - pageTables[tableIndex].setUsermode(false); - if(flags & MMAP_RW) - pageTables[tableIndex].setRw(true); - } - tableIndex++; - } - return 0; -} - -int kernelns::mmap(void* start, physaddr_t p_start, size_t length, int flags) -{ - if((size_t) start % 4096 != 0 || p_start % 4096 != 0) - return -1; - physaddr_t page = p_start; - for(int i = (int) length; i > 0; i -= 4096) - { - if(mapPage(start, page, flags) != 0) - return -1; - page += 4096; - } - return 0; -} - -int kernelns::mapPage(void* start, physaddr_t p_start, int flags) -{ - if((size_t) start % 4096 != 0 || p_start % 4096 != 0) - return -1; - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - size_t tableIndex = (size_t) start / 4096; - physaddr_t page = p_start; - size_t directoryIndex = tableIndex / 1024; - if(!pageDirectory[directoryIndex].getPresent()) - { - physaddr_t newPT = State::pageAllocator.allocate(4096); - if(newPT == 0) - return -1; - pageDirectory[directoryIndex] = newPT; - pageDirectory[directoryIndex].setPresent(true); - pageDirectory[directoryIndex].setUsermode(false); - pageDirectory[directoryIndex].setRw(true); - } - if(!pageTables[tableIndex].getPresent()) - { - pageTables[tableIndex] = page; - pageTables[tableIndex].setPresent(true); - pageTables[tableIndex].setUsermode(false); - if(flags & MMAP_RW) - pageTables[tableIndex].setRw(true); - } - return 0; -} - -int kernelns::munmap(void* start, size_t length) -{ - if((size_t) start % 4096 != 0) - return -1; - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - size_t tableIndex = (size_t) start / 4096; - for(int i = (int) length; i > 0; i -= 4096) - { - size_t directoryIndex = tableIndex / 1024; - if(pageDirectory[directoryIndex].getPresent()) - { - pageTables[tableIndex] = 0; - pageTables[tableIndex].setPresent(false); - pageTables[tableIndex].setUsermode(false); - pageTables[tableIndex].setRw(false); - } - tableIndex++; - } - return 0; -} - -bool kernelns::isMapped(void* addr) -{ - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - size_t tableIndex = (size_t) addr / 4096; - size_t directoryIndex = tableIndex / 1024; - if(pageDirectory[directoryIndex].getPresent()) - { - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - return pageTables[tableIndex].getPresent(); - } - return false; -} - -physaddr_t kernelns::getPhysicalAddress(void* addr) -{ - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - size_t tableIndex = (size_t) addr / 4096; - return pageTables[tableIndex].getPhysicalAddress() + ((size_t) addr & 0xFFF); -} - -int kernelns::createAddressSpace(void* table) -{ - if(((size_t) table & 0xFFF) != 0) - return -1; - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - PageTableEntry* newDirectory = (PageTableEntry*) table; - newDirectory[1022] = pageDirectory[1022]; - newDirectory[1023] = pageDirectory[1023]; - return 0; -} - -int kernelns::loadAddressSpace(physaddr_t table) -{ - if((table & 0xFFF) != 0) - return -1; - asm("mov %0, %%cr3" - : - : "r" (table)); - return 0; -} \ No newline at end of file diff --git a/src/x86/mmgr.c b/src/x86/mmgr.c new file mode 100644 index 0000000..80ce59e --- /dev/null +++ b/src/x86/mmgr.c @@ -0,0 +1,121 @@ +#include "mmgr.h" +#include "pageallocator.h" +#include "string.h" +#include "types/status.h" +#include + +const size_t page_size = 4096; + +const size_t page_bits = 12; + +struct page_table_entry_t +{ + uint32_t present : 1; + + uint32_t rw : 1; + + uint32_t usermode : 1; + + uint32_t writeThrough : 1; + + uint32_t cacheDisable : 1; + + uint32_t accessed : 1; + + uint32_t dirty : 1; + + uint32_t pat : 1; + + uint32_t global : 1; + + uint32_t shared : 1; + + uint32_t ignored : 2; + + uint32_t physicalAddress : 20; +}; + +struct page_table_entry_t *page_tables = (struct page_table_entry_t*) 0xFFC00000; + +struct page_table_entry_t *page_directory = (struct page_table_entry_t*) 0xFFFFF000; + +physaddr_t create_address_space(struct page_stack_t *page_stack) +{ + physaddr_t table = reserve_page(page_stack); + if(table == S_OUT_OF_MEMORY) + { + return S_OUT_OF_MEMORY; + } + struct page_table_entry_t buffer = page_directory[0]; + page_directory[0] = table; + asm volatile("invlpg $0xFFC00000" ::: "memory"); + memset((void*) page_tables, 0, 1022 * 4); + page_tables[1022] = page_directory[1022]; + page_tables[1023] = page_directory[1023]; + page_directory[0] = buffer; + asm volatile("invlpg $0xFFC00000" ::: "memory"); + return table; +} + +void load_address_space(physaddr_t table) +{ + asm volatile("mov %0, %%cr3" + : + : "r" (table) + : "memory"); +} + +int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int flags) +{ + if((size_t) page % page_size != 0 || frame % page_size != 0) + { + return S_OUT_OF_BOUNDS; + } + size_t table_index = (size_t) page / page_size; + size_t directory_index = table_index / (page_size / sizeof(struct page_table_entry_t)); + if(!page_directory[directory_index].present) + { + physaddr_t new_table = reserve_page(page_stack); + if(new_table == S_OUT_OF_MEMORY) + { + return S_OUT_OF_MEMORY; + } + page_directory[directory_index] = new_table >> page_bits; + page_directory[directory_index].present = 1; + page_directory[directory_index].usermode = 0; + page_directory[directory_index].rw = 1; + } + page_tables[table_index] = frame >> 12; + page_tables[table_index].present = 1; + page_tables[table_index].usermode = 1; + page_tables[table_index].rw = 1; + asm volatile("invlpg (%0)" + : + : "r" (page) + : "memory"); + return S_OK; +} + +physaddr_t unmap_page(void *page) +{ + if((size_t) page % page_size != 0) + { + return S_OUT_OF_BOUNDS; + } + size_t table_index = (size_t) page / page_size; + size_t directory_index = table_index / (page_size / sizeof(struct page_table_entry_t)); + if(!page_directory[directory_index].present || !page_tables[table_index].present) + { + return S_OUT_OF_BOUNDS; + } + else + { + physaddr_t frame = page_tables[table_index].physicalAddress << page_bits; + memset(&page_tables[table_index], 0, sizeof(struct page_table_entry_t)); + asm volatile("invlpg (%0)" + : + : "r" (page) + : "memory"); + return frame; + } +} \ No newline at end of file diff --git a/src/x86/pagetableentry.cpp b/src/x86/pagetableentry.cpp deleted file mode 100644 index 5e50799..0000000 --- a/src/x86/pagetableentry.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "pagetableentry.hpp" - -PageTableEntry::PageTableEntry() -{ - this->present = 0; - this->rw = 0; - this->usermode = 0; - this->writeThrough = 0; - this->cacheDisable = 0; - this->accessed = 0; - this->dirty = 0; - this->pat = 0; - this->global = 0; - this->shared = 0; - this->ignored = 0; - this->physicalAddress = 0; -} - -bool PageTableEntry::getAccessed() const -{ - return accessed == 1; -} - -bool PageTableEntry::getCacheDisable() const -{ - return cacheDisable == 1; -} - -void PageTableEntry::setCacheDisable(bool cacheDisable) -{ - this->cacheDisable = cacheDisable ? 1 : 0; -} - -bool PageTableEntry::getDirty() const -{ - return dirty == 1; -} - -bool PageTableEntry::getGlobal() const -{ - return global == 1; -} - -void PageTableEntry::setGlobal(bool global) -{ - this->global = global ? 1 : 0; -} - -bool PageTableEntry::getPat() const -{ - return pat == 1; -} - -void PageTableEntry::setPat(bool pat) -{ - this->pat = pat ? 1 : 0; -} - -physaddr_t PageTableEntry::getPhysicalAddress() const -{ - physaddr_t physicalAddress = this->physicalAddress; - return physicalAddress << 12; -} - -physaddr_t PageTableEntry::setPhysicalAddress(physaddr_t physicalAddress) -{ - this->physicalAddress = physicalAddress >> 12; - return this->physicalAddress << 12; -} - -bool PageTableEntry::getPresent() const -{ - return present == 1; -} - -void PageTableEntry::setPresent(bool present) -{ - this->present = present ? 1 : 0; -} - -bool PageTableEntry::getRw() const -{ - return rw == 1; -} - -void PageTableEntry::setRw(bool rw) -{ - this->rw = rw ? 1 : 0; -} - -bool PageTableEntry::getShared() const -{ - return shared == 1; -} - -void PageTableEntry::setShared(bool shared) -{ - this->shared = shared ? 1 : 0; -} - -bool PageTableEntry::getUsermode() const -{ - return usermode == 1; -} - -void PageTableEntry::setUsermode(bool usermode) -{ - this->usermode = usermode ? 1 : 0; -} - -bool PageTableEntry::getWriteThrough() const -{ - return writeThrough == 1; -} - -void PageTableEntry::setWriteThrough(bool writeThrough) -{ - this->writeThrough = writeThrough ? 1 : 0; -} - -physaddr_t PageTableEntry::operator=(physaddr_t rhs) -{ - return setPhysicalAddress(rhs); -} - -PageTableEntry PageTableEntry::operator=(PageTableEntry rhs) -{ - uint32_t *iThis = (uint32_t *)this; - uint32_t *iThat = (uint32_t *)&rhs; - *iThis = *iThat; - return rhs; -} \ No newline at end of file diff --git a/src/x86/pagetableentry.hpp b/src/x86/pagetableentry.hpp deleted file mode 100644 index 1a5381c..0000000 --- a/src/x86/pagetableentry.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef PAGETABLEENTRY_H -#define PAGETABLEENTRY_H - -#include "../systypes.hpp" - -class PageTableEntry { -public: - - PageTableEntry(); - - bool getAccessed() const; - - bool getCacheDisable() const; - - void setCacheDisable(bool cacheDisable); - - bool getDirty() const; - - bool getGlobal() const; - - void setGlobal(bool global); - - bool getPat() const; - - void setPat(bool pat); - - physaddr_t getPhysicalAddress() const; - - physaddr_t setPhysicalAddress(physaddr_t physicalAddress); - - bool getPresent() const; - - void setPresent(bool present); - - bool getRw() const; - - void setRw(bool rw); - - bool getShared() const; - - void setShared(bool shared); - - bool getUsermode() const; - - void setUsermode(bool usermode); - - bool getWriteThrough() const; - - void setWriteThrough(bool writeThrough); - - physaddr_t operator=(physaddr_t rhs); - - PageTableEntry operator=(PageTableEntry rhs); - -private: - - uint32_t present : 1; - - uint32_t rw : 1; - - uint32_t usermode : 1; - - uint32_t writeThrough : 1; - - uint32_t cacheDisable : 1; - - uint32_t accessed : 1; - - uint32_t dirty : 1; - - uint32_t pat : 1; - - uint32_t global : 1; - - uint32_t shared : 1; - - uint32_t ignored : 2; - - uint32_t physicalAddress : 20; - -}; - -#endif \ No newline at end of file