Lots of fussing about getting the PageEntry stuff right
I think I got something I am mostly happy with... :-)
This commit is contained in:
parent
7414aec667
commit
65513588f8
2 changed files with 90 additions and 50 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* Pager.cc
|
/* PageAllocator.cc
|
||||||
* vim: set tw=80:
|
* vim: set tw=80:
|
||||||
* Eryn Wells <eryn@erynwells.me>
|
* Eryn Wells <eryn@erynwells.me>
|
||||||
*/
|
*/
|
||||||
|
@ -7,89 +7,123 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Attributes.hh"
|
#include "Attributes.hh"
|
||||||
#include "Pager.hh"
|
|
||||||
#include "kstd/Bitmap.hh"
|
#include "kstd/Bitmap.hh"
|
||||||
|
#include "kstd/Memory.hh"
|
||||||
|
#include "kstd/PrintFormat.hh"
|
||||||
#include "memory/Memory.hh"
|
#include "memory/Memory.hh"
|
||||||
|
#include "memory/PageAllocator.hh"
|
||||||
|
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
|
|
||||||
struct PageDirectoryEntry
|
struct PageEntry
|
||||||
{
|
{
|
||||||
PageDirectoryEntry();
|
PageEntry();
|
||||||
|
|
||||||
/** Mark the whole entry not present. */
|
enum class Present { No = 0, Yes = 1 };
|
||||||
void setNotPresent();
|
enum class ReadWrite { No = 0, Yes = 1 };
|
||||||
bool isNotPresent() const;
|
enum class UserAccess { No = 0, Yes = 1 };
|
||||||
|
|
||||||
|
void set(Present present);
|
||||||
|
void set(ReadWrite readWrite);
|
||||||
|
void set(UserAccess user);
|
||||||
|
|
||||||
void setAddress(void* address);
|
void setAddress(void* address);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
static const u8 OneBit = 0;
|
struct Flag {
|
||||||
static const u8 ReadWriteBit = 1;
|
static const u8 Present = 0;
|
||||||
static const u8 UserAccessBit = 2;
|
static const u8 ReadWrite = 1;
|
||||||
static const u8 PageWriteThroughBit = 3;
|
static const u8 UserAccess = 2;
|
||||||
static const u8 PageCacheDisabledBit = 4;
|
static const u8 PageWriteThrough = 3;
|
||||||
static const u8 AccessedBit = 5;
|
static const u8 PageCacheDisabled = 4;
|
||||||
static const u8 DirtyBit = 6;
|
static const u8 Accessed = 5;
|
||||||
static const u8 ZeroBit = 7;
|
static const u8 Dirty = 6;
|
||||||
static const u32 IgnoredMask = 0x00000F00;
|
static const u8 PageAttributeTable = 7;
|
||||||
|
static const u8 Global = 8;
|
||||||
|
};
|
||||||
|
|
||||||
static const u32 AddressMask = 0xFFFFF000;
|
static const u32 AddressMask = 0xFFFFF000;
|
||||||
static const u32 FlagMask = 0x00000FFF;
|
|
||||||
|
|
||||||
u32 mEntry;
|
u32 mEntry;
|
||||||
|
|
||||||
void setRequiredBits();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PageEntry::PageEntry()
|
||||||
PageDirectoryEntry::PageDirectoryEntry()
|
|
||||||
: mEntry(0)
|
: mEntry(0)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(PageDirectoryEntry) == 4, "PageDirectoryEntry must be 4 bytes long.");
|
static_assert(sizeof(PageEntry) == 4, "PageEntry must be 4 bytes long.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
PageDirectoryEntry::isNotPresent()
|
|
||||||
const
|
|
||||||
{
|
|
||||||
return mEntry == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PageDirectoryEntry::setNotPresent()
|
PageEntry::set(Present present)
|
||||||
{
|
{
|
||||||
mEntry = 0;
|
if (present == Present::Yes) {
|
||||||
|
kstd::Bit::set(mEntry, Flag::Present);
|
||||||
|
} else {
|
||||||
|
kstd::Bit::clear(mEntry, Flag::Present);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PageEntry::set(ReadWrite rw)
|
||||||
|
{
|
||||||
|
if (rw == ReadWrite::Yes) {
|
||||||
|
kstd::Bit::set(mEntry, Flag::ReadWrite);
|
||||||
|
} else {
|
||||||
|
kstd::Bit::clear(mEntry, Flag::ReadWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PageDirectoryEntry::setAddress(void* address)
|
PageEntry::set(UserAccess user)
|
||||||
|
{
|
||||||
|
if (user == UserAccess::Yes) {
|
||||||
|
kstd::Bit::set(mEntry, Flag::UserAccess);
|
||||||
|
} else {
|
||||||
|
kstd::Bit::clear(mEntry, Flag::UserAccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PageEntry::setAddress(void* address)
|
||||||
{
|
{
|
||||||
kstd::Bit::setMask(mEntry, memory::pageAlignDown(uptr(address)), AddressMask);
|
kstd::Bit::setMask(mEntry, memory::pageAlignDown(uptr(address)), AddressMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PageDirectoryEntry::setRequiredBits()
|
struct PageDirectoryEntry
|
||||||
|
: public PageEntry
|
||||||
{
|
{
|
||||||
kstd::Bit::set(mEntry, OneBit);
|
void setFlagsForSystemDirectory();
|
||||||
kstd::Bit::clear(mEntry, ZeroBit);
|
};
|
||||||
kstd::Bit::clearMask(mEntry, IgnoredMask);
|
|
||||||
|
void
|
||||||
|
PageDirectoryEntry::setFlagsForSystemDirectory()
|
||||||
|
{
|
||||||
|
set(PageEntry::Present::Yes);
|
||||||
|
set(PageEntry::ReadWrite::Yes);
|
||||||
|
set(PageEntry::UserAccess::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct PageTableEntry
|
||||||
|
: public PageEntry
|
||||||
|
{ };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Public
|
* Public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
PageAllocator::initialize(const StartupInformation& startupInformation,
|
PageAllocator::initialize(const StartupInformation& startupInformation,
|
||||||
void* pageDirectory)
|
FrameAllocator* frameAllocator)
|
||||||
{
|
{
|
||||||
mPageDirectory = reinterpret_cast<PageDirectoryEntry*>(pageDirectory);
|
mPageDirectory = reinterpret_cast<PageDirectoryEntry*>(frameAllocator->allocate());
|
||||||
for (usize i = 0; i < NumberOfEntries; i++) {
|
kstd::printFormat("Page directory at 0x%08lX\n", uptr(mPageDirectory));
|
||||||
mPageDirectory[i].setNotPresent();
|
kstd::Memory::zero(mPageDirectory, memory::pageSize * (memory::pageSize / sizeof(PageDirectoryEntry)));
|
||||||
}
|
|
||||||
|
auto& firstPageTable = mPageDirectory[0];
|
||||||
|
firstPageTable.setAddress(frameAllocator->allocate());
|
||||||
|
firstPageTable.setFlagsForSystemDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Pager.hh
|
/* PageAllocator.hh
|
||||||
* vim: set tw=80:
|
* vim: set tw=80:
|
||||||
* Eryn Wells <eryn@erynwells.me>
|
* Eryn Wells <eryn@erynwells.me>
|
||||||
*/
|
*/
|
||||||
|
@ -6,8 +6,8 @@
|
||||||
* Page tables 'n stuff.
|
* Page tables 'n stuff.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MEMORY_PAGE_HH__
|
#ifndef __MEMORY_PAGEALLOCATOR_HH__
|
||||||
#define __MEMORY_PAGE_HH__
|
#define __MEMORY_PAGEALLOCATOR_HH__
|
||||||
|
|
||||||
#include "StartupInformation.hh"
|
#include "StartupInformation.hh"
|
||||||
#include "kstd/Types.hh"
|
#include "kstd/Types.hh"
|
||||||
|
@ -21,7 +21,13 @@ struct PageDirectoryEntry;
|
||||||
*/
|
*/
|
||||||
struct PageAllocator
|
struct PageAllocator
|
||||||
{
|
{
|
||||||
void initialize(const StartupInformation& startupInformation, void* pageDirectory);
|
/**
|
||||||
|
* Initialize the page allocator.
|
||||||
|
*
|
||||||
|
* @param [in] startupInformation The kernel startup information struct.
|
||||||
|
* @param [in] frameAllocator The kernel's page frame allocator.
|
||||||
|
*/
|
||||||
|
void initialize(const StartupInformation& startupInformation, FrameAllocator* frameAllocator);
|
||||||
|
|
||||||
// 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.
|
// 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.
|
||||||
|
|
||||||
|
@ -34,4 +40,4 @@ private:
|
||||||
|
|
||||||
} /* namespace kernel */
|
} /* namespace kernel */
|
||||||
|
|
||||||
#endif /* __MEMORY_PAGE_HH__ */
|
#endif /* __MEMORY_PAGEALLOCATOR_HH__ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue