diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-06-26 21:45:56 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-06-26 21:45:56 +0200 |
commit | 183205d51cefcb68b9fd8102fe2b566212a8e59e (patch) | |
tree | eda6663f14903d132cc888386a0bf1491d9b0829 /Kernel/Arch | |
parent | 0538adbabd255411711b4d126c0d31a66c715c00 (diff) | |
download | serenity-183205d51cefcb68b9fd8102fe2b566212a8e59e.zip |
Kernel: Make the x86 paging code slightly less insane.
Instead of PDE's and PTE's being weird wrappers around dword*, just have
MemoryManager::ensure_pte() return a PageDirectoryEntry&, which in turn has
a PageTableEntry* entries().
I've been trying to understand how things ended up this way, and I suspect
it was because I inadvertently invoked the PageDirectoryEntry copy ctor in
the original work on this, which must have made me very confused..
Anyways, now things are a bit saner and we can move forward towards a better
future, etc. :^)
Diffstat (limited to 'Kernel/Arch')
-rw-r--r-- | Kernel/Arch/i386/CPU.h | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h index bb0f7a037b..4a90bab110 100644 --- a/Kernel/Arch/i386/CPU.h +++ b/Kernel/Arch/i386/CPU.h @@ -1,11 +1,16 @@ #pragma once +#include <AK/Badge.h> +#include <AK/Noncopyable.h> #include <Kernel/VirtualAddress.h> #include <Kernel/kstdio.h> #define PAGE_SIZE 4096 #define PAGE_MASK 0xfffff000 +class MemoryManager; +class PageTableEntry; + struct [[gnu::packed]] TSS32 { word backlink, __blh; @@ -79,6 +84,106 @@ union [[gnu::packed]] Descriptor } }; +class PageDirectoryEntry { + AK_MAKE_NONCOPYABLE(PageDirectoryEntry); + +public: + PageTableEntry* page_table_base() { return reinterpret_cast<PageTableEntry*>(m_raw & 0xfffff000u); } + void set_page_table_base(dword value) + { + m_raw &= 0xfff; + m_raw |= value & 0xfffff000; + } + + dword raw() const { return m_raw; } + void copy_from(Badge<MemoryManager>, const PageDirectoryEntry& other) { m_raw = other.m_raw; } + + enum Flags { + Present = 1 << 0, + ReadWrite = 1 << 1, + UserSupervisor = 1 << 2, + WriteThrough = 1 << 3, + CacheDisabled = 1 << 4, + }; + + bool is_present() const { return raw() & Present; } + void set_present(bool b) { set_bit(Present, b); } + + bool is_user_allowed() const { return raw() & UserSupervisor; } + void set_user_allowed(bool b) { set_bit(UserSupervisor, b); } + + bool is_writable() const { return raw() & ReadWrite; } + void set_writable(bool b) { set_bit(ReadWrite, b); } + + bool is_write_through() const { return raw() & WriteThrough; } + void set_write_through(bool b) { set_bit(WriteThrough, b); } + + bool is_cache_disabled() const { return raw() & CacheDisabled; } + void set_cache_disabled(bool b) { set_bit(CacheDisabled, b); } + + void set_bit(byte bit, bool value) + { + if (value) + m_raw |= bit; + else + m_raw &= ~bit; + } + +private: + dword m_raw; +}; + +class PageTableEntry { + AK_MAKE_NONCOPYABLE(PageTableEntry); + +public: + void* physical_page_base() { return reinterpret_cast<void*>(m_raw & 0xfffff000u); } + void set_physical_page_base(dword value) + { + m_raw &= 0xfff; + m_raw |= value & 0xfffff000; + } + + dword raw() const { return m_raw; } + + enum Flags { + Present = 1 << 0, + ReadWrite = 1 << 1, + UserSupervisor = 1 << 2, + WriteThrough = 1 << 3, + CacheDisabled = 1 << 4, + }; + + bool is_present() const { return raw() & Present; } + void set_present(bool b) { set_bit(Present, b); } + + bool is_user_allowed() const { return raw() & UserSupervisor; } + void set_user_allowed(bool b) { set_bit(UserSupervisor, b); } + + bool is_writable() const { return raw() & ReadWrite; } + void set_writable(bool b) { set_bit(ReadWrite, b); } + + bool is_write_through() const { return raw() & WriteThrough; } + void set_write_through(bool b) { set_bit(WriteThrough, b); } + + bool is_cache_disabled() const { return raw() & CacheDisabled; } + void set_cache_disabled(bool b) { set_bit(CacheDisabled, b); } + + void set_bit(byte bit, bool value) + { + if (value) + m_raw |= bit; + else + m_raw &= ~bit; + } + +private: + dword m_raw; +}; + +static_assert(sizeof(PageDirectoryEntry) == 4); +static_assert(sizeof(PageTableEntry) == 4); + class IRQHandler; void gdt_init(); |