summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-06-26 21:45:56 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-06-26 21:45:56 +0200
commit183205d51cefcb68b9fd8102fe2b566212a8e59e (patch)
treeeda6663f14903d132cc888386a0bf1491d9b0829 /Kernel/Arch
parent0538adbabd255411711b4d126c0d31a66c715c00 (diff)
downloadserenity-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.h105
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();