summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Arch/PageDirectory.h154
-rw-r--r--Kernel/Arch/aarch64/MMU.cpp21
-rw-r--r--Kernel/Arch/aarch64/PageDirectory.h169
-rw-r--r--Kernel/Arch/x86/PageDirectory.h154
4 files changed, 332 insertions, 166 deletions
diff --git a/Kernel/Arch/PageDirectory.h b/Kernel/Arch/PageDirectory.h
index 1fddb0ad4f..dbc8bc6c8b 100644
--- a/Kernel/Arch/PageDirectory.h
+++ b/Kernel/Arch/PageDirectory.h
@@ -1,156 +1,18 @@
/*
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2022, Timon Kruiper <timonkruiper@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
-#include <AK/Badge.h>
-#include <AK/Types.h>
-#include <Kernel/Forward.h>
-#include <Kernel/PhysicalAddress.h>
-
#include <AK/Platform.h>
-namespace Kernel {
-
-class PageDirectoryEntry {
-public:
- PhysicalPtr page_table_base() const { return PhysicalAddress::physical_page_base(m_raw); }
- void set_page_table_base(u32 value)
- {
- m_raw &= 0x8000000000000fffULL;
- m_raw |= PhysicalAddress::physical_page_base(value);
- }
-
- bool is_null() const { return m_raw == 0; }
- void clear() { m_raw = 0; }
-
- u64 raw() const { return m_raw; }
- void copy_from(Badge<Memory::PageDirectory>, PageDirectoryEntry const& other) { m_raw = other.m_raw; }
-
- enum Flags {
- Present = 1 << 0,
- ReadWrite = 1 << 1,
- UserSupervisor = 1 << 2,
- WriteThrough = 1 << 3,
- CacheDisabled = 1 << 4,
- Huge = 1 << 7,
- Global = 1 << 8,
- NoExecute = 0x8000000000000000ULL,
- };
-
- bool is_present() const { return (raw() & Present) == Present; }
- void set_present(bool b) { set_bit(Present, b); }
-
- bool is_user_allowed() const { return (raw() & UserSupervisor) == UserSupervisor; }
- void set_user_allowed(bool b) { set_bit(UserSupervisor, b); }
-
- bool is_huge() const { return (raw() & Huge) == Huge; }
- void set_huge(bool b) { set_bit(Huge, b); }
-
- bool is_writable() const { return (raw() & ReadWrite) == ReadWrite; }
- void set_writable(bool b) { set_bit(ReadWrite, b); }
-
- bool is_write_through() const { return (raw() & WriteThrough) == WriteThrough; }
- void set_write_through(bool b) { set_bit(WriteThrough, b); }
-
- bool is_cache_disabled() const { return (raw() & CacheDisabled) == CacheDisabled; }
- void set_cache_disabled(bool b) { set_bit(CacheDisabled, b); }
-
- bool is_global() const { return (raw() & Global) == Global; }
- void set_global(bool b) { set_bit(Global, b); }
-
- bool is_execute_disabled() const { return (raw() & NoExecute) == NoExecute; }
- void set_execute_disabled(bool b) { set_bit(NoExecute, b); }
-
-private:
- void set_bit(u64 bit, bool value)
- {
- if (value)
- m_raw |= bit;
- else
- m_raw &= ~bit;
- }
-
- u64 m_raw;
-};
-
-class PageTableEntry {
-public:
- PhysicalPtr physical_page_base() const { return PhysicalAddress::physical_page_base(m_raw); }
- void set_physical_page_base(PhysicalPtr value)
- {
- // FIXME: IS THIS PLATFORM SPECIFIC?
- m_raw &= 0x8000000000000fffULL;
- m_raw |= PhysicalAddress::physical_page_base(value);
- }
-
- u64 raw() const { return m_raw; }
-
- enum Flags {
- Present = 1 << 0,
- ReadWrite = 1 << 1,
- UserSupervisor = 1 << 2,
- WriteThrough = 1 << 3,
- CacheDisabled = 1 << 4,
- PAT = 1 << 7,
- Global = 1 << 8,
- NoExecute = 0x8000000000000000ULL,
- };
-
- bool is_present() const { return (raw() & Present) == Present; }
- void set_present(bool b) { set_bit(Present, b); }
-
- bool is_user_allowed() const { return (raw() & UserSupervisor) == UserSupervisor; }
- void set_user_allowed(bool b) { set_bit(UserSupervisor, b); }
-
- bool is_writable() const { return (raw() & ReadWrite) == ReadWrite; }
- void set_writable(bool b) { set_bit(ReadWrite, b); }
-
- bool is_write_through() const { return (raw() & WriteThrough) == WriteThrough; }
- void set_write_through(bool b) { set_bit(WriteThrough, b); }
-
- bool is_cache_disabled() const { return (raw() & CacheDisabled) == CacheDisabled; }
- void set_cache_disabled(bool b) { set_bit(CacheDisabled, b); }
-
- bool is_global() const { return (raw() & Global) == Global; }
- void set_global(bool b) { set_bit(Global, b); }
-
- bool is_execute_disabled() const { return (raw() & NoExecute) == NoExecute; }
- void set_execute_disabled(bool b) { set_bit(NoExecute, b); }
-
- bool is_pat() const { return (raw() & PAT) == PAT; }
- void set_pat(bool b) { set_bit(PAT, b); }
-
- bool is_null() const { return m_raw == 0; }
- void clear() { m_raw = 0; }
-
-private:
- void set_bit(u64 bit, bool value)
- {
- if (value)
- m_raw |= bit;
- else
- m_raw &= ~bit;
- }
-
- u64 m_raw;
-};
-
-static_assert(AssertSize<PageDirectoryEntry, 8>());
-static_assert(AssertSize<PageTableEntry, 8>());
-
-class PageDirectoryPointerTable {
-public:
- PageDirectoryEntry* directory(size_t index)
- {
- VERIFY(index <= (NumericLimits<size_t>::max() << 30));
- return (PageDirectoryEntry*)(PhysicalAddress::physical_page_base(raw[index]));
- }
-
- u64 raw[512];
-};
-
-}
+#if ARCH(X86_64) || ARCH(I386)
+# include <Kernel/Arch/x86/PageDirectory.h>
+#elif ARCH(AARCH64)
+# include <Kernel/Arch/aarch64/PageDirectory.h>
+#else
+# error "Unknown architecture"
+#endif
diff --git a/Kernel/Arch/aarch64/MMU.cpp b/Kernel/Arch/aarch64/MMU.cpp
index 36b5558ab2..2b4a336988 100644
--- a/Kernel/Arch/aarch64/MMU.cpp
+++ b/Kernel/Arch/aarch64/MMU.cpp
@@ -8,6 +8,7 @@
#include <Kernel/Arch/aarch64/CPU.h>
+#include <Kernel/Arch/PageDirectory.h>
#include <Kernel/Arch/aarch64/ASM_wrapper.h>
#include <Kernel/Arch/aarch64/RPi/MMIO.h>
#include <Kernel/Arch/aarch64/RPi/UART.h>
@@ -27,26 +28,6 @@ namespace Kernel {
constexpr u32 START_OF_NORMAL_MEMORY = 0x00000000;
constexpr u32 END_OF_NORMAL_MEMORY = 0x3EFFFFFF;
-// 4KiB page size was chosen for the prekernel to make this code slightly simpler
-constexpr u32 GRANULE_SIZE = 0x1000;
-constexpr u32 PAGE_TABLE_SIZE = 0x1000;
-
-// Documentation for translation table format
-// https://developer.arm.com/documentation/101811/0101/Controlling-address-translation
-constexpr u32 PAGE_DESCRIPTOR = 0b11;
-constexpr u32 TABLE_DESCRIPTOR = 0b11;
-constexpr u32 DESCRIPTOR_MASK = ~0b11;
-
-constexpr u32 ACCESS_FLAG = 1 << 10;
-
-// shareability
-constexpr u32 OUTER_SHAREABLE = (2 << 8);
-constexpr u32 INNER_SHAREABLE = (3 << 8);
-
-// these index into the MAIR attribute table
-constexpr u32 NORMAL_MEMORY = (0 << 2);
-constexpr u32 DEVICE_MEMORY = (1 << 2);
-
ALWAYS_INLINE static u64* descriptor_to_pointer(FlatPtr descriptor)
{
return (u64*)(descriptor & DESCRIPTOR_MASK);
diff --git a/Kernel/Arch/aarch64/PageDirectory.h b/Kernel/Arch/aarch64/PageDirectory.h
new file mode 100644
index 0000000000..326c017f70
--- /dev/null
+++ b/Kernel/Arch/aarch64/PageDirectory.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2022, Timon Kruiper <timonkruiper@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Badge.h>
+#include <AK/Types.h>
+#include <Kernel/Forward.h>
+#include <Kernel/PhysicalAddress.h>
+
+namespace Kernel {
+
+// 4KiB page size was chosen to make this code slightly simpler
+constexpr u32 GRANULE_SIZE = 0x1000;
+constexpr u32 PAGE_TABLE_SIZE = 0x1000;
+
+// Documentation for translation table format
+// https://developer.arm.com/documentation/101811/0101/Controlling-address-translation
+constexpr u32 PAGE_DESCRIPTOR = 0b11;
+constexpr u32 TABLE_DESCRIPTOR = 0b11;
+constexpr u32 DESCRIPTOR_MASK = ~0b11;
+
+constexpr u32 ACCESS_FLAG = 1 << 10;
+
+// shareability
+constexpr u32 OUTER_SHAREABLE = (2 << 8);
+constexpr u32 INNER_SHAREABLE = (3 << 8);
+
+// these index into the MAIR attribute table
+constexpr u32 NORMAL_MEMORY = (0 << 2);
+constexpr u32 DEVICE_MEMORY = (1 << 2);
+
+// Figure D5-15 of Arm Architecture Reference Manual Armv8 - page D5-2588
+class PageDirectoryEntry {
+public:
+ PhysicalPtr page_table_base() const { return PhysicalAddress::physical_page_base(m_raw); }
+ void set_page_table_base(u32 value)
+ {
+ m_raw &= 0xffff000000000fffULL;
+ m_raw |= PhysicalAddress::physical_page_base(value);
+
+ // FIXME: Do not hardcode this.
+ m_raw |= TABLE_DESCRIPTOR;
+ }
+
+ bool is_null() const { return m_raw == 0; }
+ void clear() { m_raw = 0; }
+
+ u64 raw() const { return m_raw; }
+ void copy_from(Badge<Memory::PageDirectory>, PageDirectoryEntry const& other) { m_raw = other.m_raw; }
+
+ enum Flags {
+ Present = 1 << 0,
+ };
+
+ bool is_present() const { return (raw() & Present) == Present; }
+ void set_present(bool) { }
+
+ bool is_user_allowed() const { VERIFY_NOT_REACHED(); }
+ void set_user_allowed(bool) { }
+
+ bool is_huge() const { VERIFY_NOT_REACHED(); }
+ void set_huge(bool) { }
+
+ bool is_writable() const { VERIFY_NOT_REACHED(); }
+ void set_writable(bool) { }
+
+ bool is_write_through() const { VERIFY_NOT_REACHED(); }
+ void set_write_through(bool) { }
+
+ bool is_cache_disabled() const { VERIFY_NOT_REACHED(); }
+ void set_cache_disabled(bool) { }
+
+ bool is_global() const { VERIFY_NOT_REACHED(); }
+ void set_global(bool) { }
+
+ bool is_execute_disabled() const { VERIFY_NOT_REACHED(); }
+ void set_execute_disabled(bool) { }
+
+private:
+ void set_bit(u64 bit, bool value)
+ {
+ if (value)
+ m_raw |= bit;
+ else
+ m_raw &= ~bit;
+ }
+
+ u64 m_raw;
+};
+
+// Figure D5-17 VMSAv8-64 level 3 descriptor format of Arm Architecture Reference Manual Armv8 - page D5-2592
+class PageTableEntry {
+public:
+ PhysicalPtr physical_page_base() const { return PhysicalAddress::physical_page_base(m_raw); }
+ void set_physical_page_base(PhysicalPtr value)
+ {
+ m_raw &= 0xffff000000000fffULL;
+ m_raw |= PhysicalAddress::physical_page_base(value);
+
+ // FIXME: For now we map everything with the same permissions.
+ u64 normal_memory_flags = ACCESS_FLAG | PAGE_DESCRIPTOR | INNER_SHAREABLE | NORMAL_MEMORY;
+ m_raw |= normal_memory_flags;
+ }
+
+ u64 raw() const { return m_raw; }
+
+ enum Flags {
+ Present = 1 << 0,
+ };
+
+ bool is_present() const { return (raw() & Present) == Present; }
+ void set_present(bool) { }
+
+ bool is_user_allowed() const { VERIFY_NOT_REACHED(); }
+ void set_user_allowed(bool) { }
+
+ bool is_writable() const { VERIFY_NOT_REACHED(); }
+ void set_writable(bool) { }
+
+ bool is_write_through() const { VERIFY_NOT_REACHED(); }
+ void set_write_through(bool) { }
+
+ bool is_cache_disabled() const { VERIFY_NOT_REACHED(); }
+ void set_cache_disabled(bool) { }
+
+ bool is_global() const { VERIFY_NOT_REACHED(); }
+ void set_global(bool) { }
+
+ bool is_execute_disabled() const { VERIFY_NOT_REACHED(); }
+ void set_execute_disabled(bool) { }
+
+ bool is_pat() const { VERIFY_NOT_REACHED(); }
+ void set_pat(bool) { }
+
+ bool is_null() const { return m_raw == 0; }
+ void clear() { m_raw = 0; }
+
+private:
+ void set_bit(u64 bit, bool value)
+ {
+ if (value)
+ m_raw |= bit;
+ else
+ m_raw &= ~bit;
+ }
+
+ u64 m_raw;
+};
+
+static_assert(AssertSize<PageDirectoryEntry, 8>());
+static_assert(AssertSize<PageTableEntry, 8>());
+
+class PageDirectoryPointerTable {
+public:
+ PageDirectoryEntry* directory(size_t index)
+ {
+ VERIFY(index <= (NumericLimits<size_t>::max() << 30));
+ return (PageDirectoryEntry*)(PhysicalAddress::physical_page_base(raw[index]));
+ }
+
+ u64 raw[512];
+};
+
+}
diff --git a/Kernel/Arch/x86/PageDirectory.h b/Kernel/Arch/x86/PageDirectory.h
new file mode 100644
index 0000000000..05fa7bade0
--- /dev/null
+++ b/Kernel/Arch/x86/PageDirectory.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Badge.h>
+#include <AK/Types.h>
+#include <Kernel/Forward.h>
+#include <Kernel/PhysicalAddress.h>
+
+namespace Kernel {
+
+class PageDirectoryEntry {
+public:
+ PhysicalPtr page_table_base() const { return PhysicalAddress::physical_page_base(m_raw); }
+ void set_page_table_base(u32 value)
+ {
+ m_raw &= 0x8000000000000fffULL;
+ m_raw |= PhysicalAddress::physical_page_base(value);
+ }
+
+ bool is_null() const { return m_raw == 0; }
+ void clear() { m_raw = 0; }
+
+ u64 raw() const { return m_raw; }
+ void copy_from(Badge<Memory::PageDirectory>, PageDirectoryEntry const& other) { m_raw = other.m_raw; }
+
+ enum Flags {
+ Present = 1 << 0,
+ ReadWrite = 1 << 1,
+ UserSupervisor = 1 << 2,
+ WriteThrough = 1 << 3,
+ CacheDisabled = 1 << 4,
+ Huge = 1 << 7,
+ Global = 1 << 8,
+ NoExecute = 0x8000000000000000ULL,
+ };
+
+ bool is_present() const { return (raw() & Present) == Present; }
+ void set_present(bool b) { set_bit(Present, b); }
+
+ bool is_user_allowed() const { return (raw() & UserSupervisor) == UserSupervisor; }
+ void set_user_allowed(bool b) { set_bit(UserSupervisor, b); }
+
+ bool is_huge() const { return (raw() & Huge) == Huge; }
+ void set_huge(bool b) { set_bit(Huge, b); }
+
+ bool is_writable() const { return (raw() & ReadWrite) == ReadWrite; }
+ void set_writable(bool b) { set_bit(ReadWrite, b); }
+
+ bool is_write_through() const { return (raw() & WriteThrough) == WriteThrough; }
+ void set_write_through(bool b) { set_bit(WriteThrough, b); }
+
+ bool is_cache_disabled() const { return (raw() & CacheDisabled) == CacheDisabled; }
+ void set_cache_disabled(bool b) { set_bit(CacheDisabled, b); }
+
+ bool is_global() const { return (raw() & Global) == Global; }
+ void set_global(bool b) { set_bit(Global, b); }
+
+ bool is_execute_disabled() const { return (raw() & NoExecute) == NoExecute; }
+ void set_execute_disabled(bool b) { set_bit(NoExecute, b); }
+
+private:
+ void set_bit(u64 bit, bool value)
+ {
+ if (value)
+ m_raw |= bit;
+ else
+ m_raw &= ~bit;
+ }
+
+ u64 m_raw;
+};
+
+class PageTableEntry {
+public:
+ PhysicalPtr physical_page_base() const { return PhysicalAddress::physical_page_base(m_raw); }
+ void set_physical_page_base(PhysicalPtr value)
+ {
+ // FIXME: IS THIS PLATFORM SPECIFIC?
+ m_raw &= 0x8000000000000fffULL;
+ m_raw |= PhysicalAddress::physical_page_base(value);
+ }
+
+ u64 raw() const { return m_raw; }
+
+ enum Flags {
+ Present = 1 << 0,
+ ReadWrite = 1 << 1,
+ UserSupervisor = 1 << 2,
+ WriteThrough = 1 << 3,
+ CacheDisabled = 1 << 4,
+ PAT = 1 << 7,
+ Global = 1 << 8,
+ NoExecute = 0x8000000000000000ULL,
+ };
+
+ bool is_present() const { return (raw() & Present) == Present; }
+ void set_present(bool b) { set_bit(Present, b); }
+
+ bool is_user_allowed() const { return (raw() & UserSupervisor) == UserSupervisor; }
+ void set_user_allowed(bool b) { set_bit(UserSupervisor, b); }
+
+ bool is_writable() const { return (raw() & ReadWrite) == ReadWrite; }
+ void set_writable(bool b) { set_bit(ReadWrite, b); }
+
+ bool is_write_through() const { return (raw() & WriteThrough) == WriteThrough; }
+ void set_write_through(bool b) { set_bit(WriteThrough, b); }
+
+ bool is_cache_disabled() const { return (raw() & CacheDisabled) == CacheDisabled; }
+ void set_cache_disabled(bool b) { set_bit(CacheDisabled, b); }
+
+ bool is_global() const { return (raw() & Global) == Global; }
+ void set_global(bool b) { set_bit(Global, b); }
+
+ bool is_execute_disabled() const { return (raw() & NoExecute) == NoExecute; }
+ void set_execute_disabled(bool b) { set_bit(NoExecute, b); }
+
+ bool is_pat() const { return (raw() & PAT) == PAT; }
+ void set_pat(bool b) { set_bit(PAT, b); }
+
+ bool is_null() const { return m_raw == 0; }
+ void clear() { m_raw = 0; }
+
+private:
+ void set_bit(u64 bit, bool value)
+ {
+ if (value)
+ m_raw |= bit;
+ else
+ m_raw &= ~bit;
+ }
+
+ u64 m_raw;
+};
+
+static_assert(AssertSize<PageDirectoryEntry, 8>());
+static_assert(AssertSize<PageTableEntry, 8>());
+
+class PageDirectoryPointerTable {
+public:
+ PageDirectoryEntry* directory(size_t index)
+ {
+ VERIFY(index <= (NumericLimits<size_t>::max() << 30));
+ return (PageDirectoryEntry*)(PhysicalAddress::physical_page_base(raw[index]));
+ }
+
+ u64 raw[512];
+};
+
+}