From cb78f4cfaa1ab7bc033ad0e089de9fa84702d1fe Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 24 Apr 2016 19:21:35 -0400 Subject: [PATCH] PageAllocator! --- src/SConscript | 1 + src/memory/Pager.cc | 102 ++++++++++++++++++++++++++++++++++++++++++++ src/memory/Pager.hh | 37 ++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 src/memory/Pager.cc create mode 100644 src/memory/Pager.hh diff --git a/src/SConscript b/src/SConscript index b202123..4e6cb2e 100644 --- a/src/SConscript +++ b/src/SConscript @@ -26,6 +26,7 @@ files = [ 'memory/FrameAllocator.cc', 'memory/Memory.cc', + 'memory/Pager.cc', ] toolchain_bin = Dir(os.environ['POLKA_TOOLCHAIN']).Dir('bin') diff --git a/src/memory/Pager.cc b/src/memory/Pager.cc new file mode 100644 index 0000000..33b3f09 --- /dev/null +++ b/src/memory/Pager.cc @@ -0,0 +1,102 @@ +/* Pager.cc + * vim: set tw=80: + * Eryn Wells + */ +/** + * Page tables 'n stuff. + */ + +#include "Attributes.hh" +#include "Pager.hh" +#include "kstd/Bitmap.hh" +#include "memory/Memory.hh" + +namespace kernel { + +struct PageDirectoryEntry +{ + PageDirectoryEntry(); + + /** Mark the whole entry not present. */ + void setNotPresent(); + bool isNotPresent() const; + + void setAddress(void* address); + +private: + static const u8 OneBit = 0; + static const u8 ReadWriteBit = 1; + static const u8 UserAccessBit = 2; + static const u8 PageWriteThroughBit = 3; + static const u8 PageCacheDisabledBit = 4; + static const u8 AccessedBit = 5; + static const u8 DirtyBit = 6; + static const u8 ZeroBit = 7; + static const u32 IgnoredMask = 0x00000F00; + static const u32 AddressMask = 0xFFFFF000; + static const u32 FlagMask = 0x00000FFF; + + u32 mEntry; + + void setRequiredBits(); +}; + + +PageDirectoryEntry::PageDirectoryEntry() + : mEntry(0) +{ + static_assert(sizeof(PageDirectoryEntry) == 4, "PageDirectoryEntry must be 4 bytes long."); +} + + +bool +PageDirectoryEntry::isNotPresent() + const +{ + return mEntry == 0; +} + + +void +PageDirectoryEntry::setNotPresent() +{ + mEntry = 0; +} + + +void +PageDirectoryEntry::setAddress(void* address) +{ + kstd::Bit::setMask(mEntry, memory::pageAlignDown(uptr(address)), AddressMask); +} + +void +PageDirectoryEntry::setRequiredBits() +{ + kstd::Bit::set(mEntry, OneBit); + kstd::Bit::clear(mEntry, ZeroBit); + kstd::Bit::clearMask(mEntry, IgnoredMask); +} + +/* + * Public + */ + +void +PageAllocator::initialize(const StartupInformation& startupInformation, + void* pageDirectory) +{ + mPageDirectory = reinterpret_cast(pageDirectory); + for (usize i = 0; i < NumberOfEntries; i++) { + mPageDirectory[i].setNotPresent(); + } +} + +/* + * Private + */ + +const u16 PageAllocator::NumberOfEntries = 1024; + + +} /* namespace kernel */ diff --git a/src/memory/Pager.hh b/src/memory/Pager.hh new file mode 100644 index 0000000..3ba6b1b --- /dev/null +++ b/src/memory/Pager.hh @@ -0,0 +1,37 @@ +/* Pager.hh + * vim: set tw=80: + * Eryn Wells + */ +/** + * Page tables 'n stuff. + */ + +#ifndef __MEMORY_PAGE_HH__ +#define __MEMORY_PAGE_HH__ + +#include "StartupInformation.hh" +#include "kstd/Types.hh" + +namespace kernel { + +struct PageDirectoryEntry; + +/** + * Handles allocating pages + */ +struct PageAllocator +{ + void initialize(const StartupInformation& startupInformation, void* pageDirectory); + + // TODO: A method to install a page table into the system. For per-process page tables, I'll need a way to set the current page table so the system knows where to look. + +private: + static const u16 NumberOfEntries; + + /** The kernel's page directory. */ + PageDirectoryEntry* mPageDirectory; +}; + +} /* namespace kernel */ + +#endif /* __MEMORY_PAGE_HH__ */