summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimon Kruiper <timonkruiper@gmail.com>2022-09-21 15:26:27 +0200
committerAndreas Kling <kling@serenityos.org>2022-10-01 14:09:01 +0200
commitcdf59c86ac0fa2b38af3ec0217913cab19153ab3 (patch)
tree066b50bcfadc0e83402b365f913b03a48e8d1438
parentad5e8bbb4fb827d4710cbe90c77511eee22b5d28 (diff)
downloadserenity-cdf59c86ac0fa2b38af3ec0217913cab19153ab3.zip
Kernel: Make PageDirectory.h architecture specific
The page table and page directory formats are architecture specific, so move the headers into the Arch directory. Also move the aarch64 page table constants from aarch64/MMU.cpp to aarch64/PageDirectory.h.
-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];
+};
+
+}