#pragma once #include class PhysicalAddress { public: PhysicalAddress() { } explicit PhysicalAddress(dword address) : m_address(address) { } dword get() const { return m_address; } void set(dword address) { m_address = address; } void mask(dword m) { m_address &= m; } private: dword m_address { 0 }; }; class LinearAddress { public: LinearAddress() { } explicit LinearAddress(dword address) : m_address(address) { } LinearAddress offset(dword o) const { return LinearAddress(m_address + o); } dword get() const { return m_address; } void set(dword address) { m_address = address; } void mask(dword m) { m_address &= m; } bool operator==(const LinearAddress& other) const { return m_address == other.m_address; } private: dword m_address { 0 }; }; class MemoryManager { public: static MemoryManager& the(); PhysicalAddress pageDirectoryBase() const { return PhysicalAddress(reinterpret_cast(m_pageDirectory)); } static void initialize(); private: MemoryManager(); ~MemoryManager(); void initializePaging(); void identityMap(LinearAddress, size_t length); struct PageDirectoryEntry { explicit PageDirectoryEntry(dword* pde) : m_pde(pde) { } dword* pageTableBase() { return reinterpret_cast(raw() & 0xfffff000u); } void setPageTableBase(dword value) { *m_pde &= 0xfff; *m_pde |= value & 0xfffff000; } dword raw() const { return *m_pde; } dword* ptr() { return m_pde; } enum Flags { Present = 1 << 0, ReadWrite = 1 << 1, UserSupervisor = 1 << 2, }; bool isPresent() const { return raw() & Present; } void setPresent(bool b) { setBit(Present, b); } bool isUserAllowed() const { return raw() & UserSupervisor; } void setUserAllowed(bool b) { setBit(UserSupervisor, b); } bool isWritable() const { return raw() & ReadWrite; } void setWritable(bool b) { setBit(ReadWrite, b); } void setBit(byte bit, bool value) { if (value) *m_pde |= bit; else *m_pde &= ~bit; } dword* m_pde; }; struct PageTableEntry { explicit PageTableEntry(dword* pte) : m_pte(pte) { } dword* physicalPageBase() { return reinterpret_cast(raw() & 0xfffff000u); } void setPhysicalPageBase(dword value) { *m_pte &= 0xfffu; *m_pte |= value & 0xfffff000u; } dword raw() const { return *m_pte; } dword* ptr() { return m_pte; } enum Flags { Present = 1 << 0, ReadWrite = 1 << 1, UserSupervisor = 1 << 2, }; bool isPresent() const { return raw() & Present; } void setPresent(bool b) { setBit(Present, b); } bool isUserAllowed() const { return raw() & UserSupervisor; } void setUserAllowed(bool b) { setBit(UserSupervisor, b); } bool isWritable() const { return raw() & ReadWrite; } void setWritable(bool b) { setBit(ReadWrite, b); } void setBit(byte bit, bool value) { if (value) *m_pte |= bit; else *m_pte &= ~bit; } dword* m_pte; }; PageTableEntry ensurePTE(LinearAddress); dword* m_pageDirectory; dword* m_pageTableZero; };